diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..389684e01 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,60 @@ +name: Deploy Workflow +run-name: Deploy to ${{ inputs.env }} - ${{ inputs.tag }} + +on: + workflow_dispatch: + inputs: + tag: + type: string + description: Tag to deploy + required: true + env: + type: choice + description: Environment to be deployed + required: true + options: + - dev + - staging + - perf + - prod + - client-sandbox + +env: + SERVICE_NAME: language_model_gateway + SERVICE_NAMESPACE: language_model_gateway-${{ inputs.env }} + +jobs: + deploy: + name: Deploy + runs-on: main + steps: + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Checkout icanbwell/cie.gha-deploy + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: refs/tags/v0.0.33 + repository: icanbwell/cie.gha-deploy + token: ${{ secrets.BWELL_DEV_PAT }} + path: .github/actions/cie.gha-deploy + + - name: Deploy + uses: ./.github/actions/cie.gha-deploy + with: + token: ${{ secrets.BWELL_DEV_PAT }} + service-name: $SERVICE_NAME + service-namespace: $SERVICE_NAMESPACE + env: '${{ inputs.env }}-ue1' + helm-chart-version: '1.1.8' + image-tag: ${{ github.event.inputs.tag }} + + - name: 'Cleanup build folder' + if: always() + run: | + ls -la ./ + sudo rm -rf ${{ github.workspace }}/* + ls -la ./ diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 40d3dd0c0..e8977ba9e 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -7,7 +7,7 @@ on: env: IMAGE_NAME: language_model_gateway - REPOSITORY_URL: imranq2 + REPOSITORY_URL: icanbwell jobs: push: @@ -36,6 +36,8 @@ jobs: - name: Install QEMU uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 - name: Create builder run: | @@ -51,6 +53,7 @@ jobs: run: | docker buildx build \ --platform linux/amd64,linux/arm64 \ + --target production \ -t $REPOSITORY_URL/$IMAGE_NAME:$TAG \ -t $REPOSITORY_URL/$IMAGE_NAME:latest \ --push \ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 840e58d24..7f91a9c6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,36 +1,106 @@ -exclude: (^.idea/|^notebooks/) +exclude: (^.idea/|^docsrc|^docs) + repos: + # Pre-commit hooks for basic checks - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: + # File and formatting checks - id: end-of-file-fixer types: [ python ] + - id: trailing-whitespace + types: [ python ] + + # Conflict and security checks + - id: check-case-conflict + types: [ python ] + - id: check-docstring-first + types: [ python ] + + # Security scans + - id: detect-aws-credentials + types: [ python ] + args: [ '--allow-missing-credentials' ] + - id: detect-private-key + types: [ python ] + + # Dependency and import checks + - id: check-ast + - id: check-added-large-files + - id: check-json + - id: check-toml + - id: check-yaml + + # Local hooks for Ruff (using local installation) - repo: local hooks: - id: ruff - name: ruff - language: system - types: [ python ] + name: Ruff entry: ruff - require_serial: true - args: [ 'check', '--fix'] - - id: autoflake - name: autoflake language: system types: [ python ] - entry: autoflake + args: [ check, --fix, --show-fixes, --target-version=py312 ] require_serial: true - args: [ '--in-place', '--remove-all-unused-imports', '--ignore-init-module-imports'] - - id: black - name: black + + - id: ruff-format + name: Ruff Format + entry: ruff language: system - types: [python] + types: [ python ] + args: [ format ] require_serial: true - entry: black + + # MyPy for type checking - id: mypy name: mypy language: system types: [ python ] entry: mypy require_serial: true - args: [ --strict, --python-version=3.12, --show-error-codes, --allow-untyped-decorators ] + args: [ + --strict, + --python-version=3.12, + --show-error-codes, + --allow-untyped-decorators, + --ignore-missing-imports + ] + + # Bandit for security scanning + - id: bandit + name: bandit + language: system + types: [ python ] + entry: bandit + require_serial: true + args: [ + '-q', + '--skip', 'B101,B104,B105,B106', + '-r', + '--severity-level', 'medium' + ] + + # Pygrep hooks for additional checks + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: python-use-type-annotations + - id: python-check-blanket-noqa + - id: python-check-blanket-type-ignore + - id: python-check-mock-methods + - id: python-no-eval + - id: python-no-log-warn + + # Optional: Secret scanning + - repo: https://github.com/Yelp/detect-secrets + rev: v1.4.0 + hooks: + - id: detect-secrets + args: [ 'scan' ] + exclude: > + (?x)^( + tests/.*| + docker-compose\.yml| + .helm/.*| + docker-compose-openwebui\.yml| + docker-compose-openwebui-auth\.yml + )$ diff --git a/Dockerfile b/Dockerfile index 0c515a1e0..b96bc6966 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,9 +48,10 @@ RUN python -c "import sys; print(sys.platform, sys.version, sys.maxsize > 2**32) RUN pip debug --verbose RUN pip list -v -# Stage 2: Final runtime image for the application -# This stage creates a minimal image with only the runtime dependencies and the application code. -FROM public.ecr.aws/docker/library/python:3.12-alpine3.20 + +# Stage 2: Development image with hot reload +# This stage is optimized for local development with hot reload capability +FROM public.ecr.aws/docker/library/python:3.12-alpine3.20 AS development # Set terminal width (COLUMNS) and height (LINES) ENV COLUMNS=300 @@ -58,8 +59,7 @@ ENV COLUMNS=300 # Define an argument to control whether to run pipenv lock (not used in this stage) ARG GITHUB_TOKEN -# Install runtime dependencies required by the application (e.g., for shapely, grpcio, scipy, google-crc32 and numpy) -# You can use auditwheel to check any package and identify the native library dependencies +# Install runtime dependencies required by the application RUN apk add --no-cache curl libstdc++ libffi git graphviz graphviz-dev # Install pipenv to manage and run the application @@ -76,31 +76,108 @@ RUN mkdir -p ${PROMETHEUS_MULTIPROC_DIR} # Set the working directory for the project WORKDIR ${PROJECT_DIR} -# Copy the Pipfile and Pipfile.lock files into the runtime image +# Copy the Pipfile and Pipfile.lock files into the development image COPY Pipfile* ${PROJECT_DIR} -# Copy installed Python packages from the previous stage +# Copy installed Python packages from the first stage COPY --from=python_packages /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages COPY --from=python_packages /usr/local/bin /usr/local/bin -# Copy the application code into the runtime image +# Copy the application code into the development image COPY ./language_model_gateway ${PROJECT_DIR}/language_model_gateway COPY ./setup.cfg ${PROJECT_DIR}/ -# Copy the Pipfile.lock from the previous stage in case it was locked +# Copy the Pipfile.lock from the first stage COPY --from=python_packages ${PROJECT_DIR}/Pipfile.lock ${PROJECT_DIR}/Pipfile.lock +COPY --from=python_packages ${PROJECT_DIR}/Pipfile.lock /tmp/Pipfile.lock + +# Create directories and list their contents (for debugging and verification) +RUN mkdir -p /usr/local/lib/python3.12/site-packages && ls -halt /usr/local/lib/python3.12/site-packages +RUN mkdir -p /usr/local/bin && ls -halt /usr/local/bin + +# Create the folder where we will store generated images +RUN mkdir -p ${PROJECT_DIR}/image_generation + +# Install the dependencies using pipenv in the development environment +RUN pipenv sync --dev --system --extra-pip-args="--prefer-binary" + +# Expose port 5000 for the application +EXPOSE 5000 + +# Switch to the root user to perform user management tasks +USER root + +# verify the installed version of the dot command for graphviz +RUN dot -V + +# Create a restricted user (appuser) and group (appgroup) for running the application +RUN addgroup -S appgroup && adduser -S -h /etc/appuser appuser -G appgroup + +# Ensure that the appuser owns the application files and directories +RUN chown -R appuser:appgroup ${PROJECT_DIR} /usr/local/lib/python3.12/site-packages /usr/local/bin ${PROMETHEUS_MULTIPROC_DIR} + +# Switch to the restricted user to enhance security +USER appuser + +# Development CMD with hot reload enabled +CMD ["sh", "-c", "\ + ddtrace-run uvicorn language_model_gateway.gateway.api:app \ + --host 0.0.0.0 \ + --port 5000 \ + --reload \ + --log-level $(echo ${LOG_LEVEL:-info} | tr '[:upper:]' '[:lower:]') \ + "] + +# Stage 3: Production deployment image +# This stage is optimized for deployment with multiple workers +FROM public.ecr.aws/docker/library/python:3.12-alpine3.20 AS production + +# Set terminal width (COLUMNS) and height (LINES) +ENV COLUMNS=300 + +# Define an argument to control whether to run pipenv lock (not used in this stage) +ARG GITHUB_TOKEN + +# Install runtime dependencies required by the application +RUN apk add --no-cache curl libstdc++ libffi git graphviz graphviz-dev + +# Install pipenv to manage and run the application +RUN pip install --no-cache-dir pipenv + +# Set environment variables for project configuration +ENV PROJECT_DIR=/usr/src/language_model_gateway +ENV PROMETHEUS_MULTIPROC_DIR=/tmp/prometheus +ENV PIP_ROOT_USER_ACTION=ignore + +# Create the directory for Prometheus metrics +RUN mkdir -p ${PROMETHEUS_MULTIPROC_DIR} + +# Set the working directory for the project +WORKDIR ${PROJECT_DIR} + +# Copy the Pipfile and Pipfile.lock files into the development image +COPY Pipfile* ${PROJECT_DIR} -# Copy Pipfile.lock to a temporary directory so it can be retrieved if needed +# Copy installed Python packages from the first stage +COPY --from=python_packages /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages +COPY --from=python_packages /usr/local/bin /usr/local/bin + +# Copy the application code into the development image +COPY ./language_model_gateway ${PROJECT_DIR}/language_model_gateway +COPY ./setup.cfg ${PROJECT_DIR}/ + +# Copy the Pipfile.lock from the first stage +COPY --from=python_packages ${PROJECT_DIR}/Pipfile.lock ${PROJECT_DIR}/Pipfile.lock COPY --from=python_packages ${PROJECT_DIR}/Pipfile.lock /tmp/Pipfile.lock # Create directories and list their contents (for debugging and verification) RUN mkdir -p /usr/local/lib/python3.12/site-packages && ls -halt /usr/local/lib/python3.12/site-packages RUN mkdir -p /usr/local/bin && ls -halt /usr/local/bin -# create the folder where we will store generated images +# Create the folder where we will store generated images RUN mkdir -p ${PROJECT_DIR}/image_generation -# Install the dependencies using pipenv in the final runtime environment +# Install the dependencies using pipenv in the development environment RUN pipenv sync --dev --system --extra-pip-args="--prefer-binary" # Expose port 5000 for the application @@ -124,13 +201,13 @@ USER appuser # The number of workers can be controlled using the NUM_WORKERS environment variable # Otherwise the number of workers for uvicorn (using the multiprocessing worker) is chosen based on these guidelines: # (https://sentry.io/answers/number-of-uvicorn-workers-needed-in-production/) -# basically (cores * threads + 1) +# basically (cores _threads + 1) CMD ["sh", "-c", "\ # Get CPU info \ CORE_COUNT=$(nproc) && \ THREAD_COUNT=$(nproc --all) && \ \ - # Calculate workers using formula: (cores * threads + 1) \ + # Calculate workers using formula: (cores_ threads + 1) \ WORKER_COUNT=$((CORE_COUNT * THREAD_COUNT + 1)) && \ FINAL_WORKERS=${NUM_WORKERS:-$WORKER_COUNT} && \ \ @@ -143,4 +220,4 @@ CMD ["sh", "-c", "\ --port 5000 \ --workers $FINAL_WORKERS \ --log-level $(echo ${LOG_LEVEL:-info} | tr '[:upper:]' '[:lower:]') \ - "] + "] \ No newline at end of file diff --git a/Makefile b/Makefile index 984a7a983..c7754f3c0 100644 --- a/Makefile +++ b/Makefile @@ -20,19 +20,29 @@ build: ## Builds the docker for dev .PHONY: up up: ## starts docker containers docker compose up --build -d && \ - echo "waiting for language_model_gateway service to become healthy" && \ - while [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language_model_gateway`" != "restarting" ]; do printf "." && sleep 2; done && \ - if [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway`" != "healthy" ]; then docker ps && docker logs language_model_gateway && printf "========== ERROR: language_model_gateway did not start. Run docker logs language_model_gateway =========\n" && exit 1; fi && \ + echo "waiting for language-model-gateway service to become healthy" && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language-model-gateway`" != "restarting" ]; do printf "." && sleep 2; done && \ + if [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "healthy" ]; then docker ps && docker logs language-model-gateway && printf "========== ERROR: language-model-gateway did not start. Run docker logs language-model-gateway =========\n" && exit 1; fi && \ echo "" - @echo language_model_gateway Service: http://localhost:5050/graphql + @echo language-model-gateway Service: http://localhost:5050/graphql + +.PHONY: up-integration +up-integration: ## starts docker containers + docker compose -f docker-compose.yml -f docker-compose-integration.yml up --build -d && \ + echo "waiting for language-model-gateway service to become healthy" && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language-model-gateway`" != "restarting" ]; do printf "." && sleep 2; done && \ + if [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway`" != "healthy" ]; then docker ps && docker logs language-model-gateway && printf "========== ERROR: language-model-gateway did not start. Run docker logs language-model-gateway =========\n" && exit 1; fi && \ + echo "" + @echo language-model-gateway Service: http://localhost:5050/graphql + .PHONY: up-open-webui up-open-webui: clean_database ## starts docker containers docker compose --progress=plain -f docker-compose-openwebui.yml up --build -d echo "waiting for open-webui service to become healthy" && \ - while [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ]; do printf "." && sleep 2; done && \ - while [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language_model_gateway-open-webui-1`" != "restarting" ]; do printf "." && sleep 2; done && \ - if [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ]; then docker ps && docker logs language_model_gateway-open-webui-1 && printf "========== ERROR: language_model_gateway-open-webui-1 did not start. Run docker logs language_model_gateway-open-webui-1 =========\n" && exit 1; fi && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ]; do printf "." && sleep 2; done && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language-model-gateway-open-webui-1`" != "restarting" ]; do printf "." && sleep 2; done && \ + if [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ]; then docker ps && docker logs language-model-gateway-open-webui-1 && printf "========== ERROR: language-model-gateway-open-webui-1 did not start. Run docker logs language-model-gateway-open-webui-1 =========\n" && exit 1; fi && \ echo "" @echo OpenWebUI: http://localhost:3050 @@ -40,21 +50,21 @@ up-open-webui: clean_database ## starts docker containers up-open-webui-ssl: clean_database ## starts docker containers docker compose --progress=plain -f docker-compose-openwebui.yml -f docker-compose-openwebui-ssl.yml up --build -d echo "waiting for open-webui service to become healthy" && \ - while [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ]; do printf "." && sleep 2; done && \ - while [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language_model_gateway-open-webui-1`" != "restarting" ]; do printf "." && sleep 2; done && \ - if [ "`docker inspect --format {{.State.Health.Status}} language_model_gateway-open-webui-1`" != "healthy" ]; then docker ps && docker logs language_model_gateway-open-webui-1 && printf "========== ERROR: language_model_gateway-open-webui-1 did not start. Run docker logs language_model_gateway-open-webui-1 =========\n" && exit 1; fi && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ]; do printf "." && sleep 2; done && \ + while [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} language-model-gateway-open-webui-1`" != "restarting" ]; do printf "." && sleep 2; done && \ + if [ "`docker inspect --format {{.State.Health.Status}} language-model-gateway-open-webui-1`" != "healthy" ]; then docker ps && docker logs language-model-gateway-open-webui-1 && printf "========== ERROR: language-model-gateway-open-webui-1 did not start. Run docker logs language-model-gateway-open-webui-1 =========\n" && exit 1; fi && \ echo "" @echo OpenWebUI: http://localhost:3050 https://open-webui.localhost .PHONY: up-open-webui-auth up-open-webui-auth: clean_database create-certs ## starts docker containers - docker compose --progress=plain -f docker-compose-openwebui.yml -f docker-compose-openwebui-ssl.yml -f docker-compose-openwebui-auth.yml up --build -d + docker compose --progress=plain -f docker-compose.yml -f docker-compose-openwebui.yml -f docker-compose-openwebui-ssl.yml -f docker-compose-openwebui-auth.yml -f docker-compose-mcp-server-gateway.yml up --build -d echo "waiting for open-webui service to become healthy" && \ max_attempts=30 && \ attempt=0 && \ while [ $$attempt -lt $$max_attempts ]; do \ - container_status=$$(docker inspect --format '{{.State.Health.Status}}' language_model_gateway-open-webui-1 2>/dev/null) && \ - container_state=$$(docker inspect --format '{{.State.Status}}' language_model_gateway-open-webui-1 2>/dev/null) && \ + container_status=$$(docker inspect --format '{{.State.Health.Status}}' language-model-gateway-open-webui-1 2>/dev/null) && \ + container_state=$$(docker inspect --format '{{.State.Status}}' language-model-gateway-open-webui-1 2>/dev/null) && \ if [ "$$container_status" = "healthy" ]; then \ echo "" && \ break; \ @@ -62,8 +72,8 @@ up-open-webui-auth: clean_database create-certs ## starts docker containers echo "" && \ echo "========== ERROR: Container became unhealthy ==========" && \ docker ps && \ - docker logs language_model_gateway-open-webui-1 && \ - printf "========== ERROR: language_model_gateway-open-webui-1 is unhealthy. Run docker logs language_model_gateway-open-webui-1 =========\n" && \ + docker logs language-model-gateway-open-webui-1 && \ + printf "========== ERROR: language-model-gateway-open-webui-1 is unhealthy. Run docker logs language-model-gateway-open-webui-1 =========\n" && \ exit 1; \ fi; \ printf "." && \ @@ -74,12 +84,21 @@ up-open-webui-auth: clean_database create-certs ## starts docker containers echo "" && \ echo "========== ERROR: Container did not become healthy within timeout ==========" && \ docker ps && \ - docker logs language_model_gateway-open-webui-1 && \ - printf "========== ERROR: language_model_gateway-open-webui-1 did not start. Run docker logs language_model_gateway-open-webui-1 =========\n" && \ + docker logs language-model-gateway-open-webui-1 && \ + printf "========== ERROR: language-model-gateway-open-webui-1 did not start. Run docker logs language-model-gateway-open-webui-1 =========\n" && \ exit 1; \ fi + echo "waiting for mcp-server-gateway to become healthy" && \ + while [ "`docker inspect --format {{.State.Health.Status}} mcp-server-gateway`" != "healthy" ]; do printf "." && sleep 2; done && \ + while [ "`docker inspect --format {{.State.Health.Status}} mcp-server-gateway`" != "healthy" ] && [ "`docker inspect --format {{.State.Health.Status}} mcp-server-gateway`" != "unhealthy" ] && [ "`docker inspect --format {{.State.Status}} mcp-server-gateway`" != "restarting" ]; do printf "." && sleep 2; done && \ + if [ "`docker inspect --format {{.State.Health.Status}} mcp-server-gateway`" != "healthy" ]; then docker ps && docker logs mcp-server-gateway && printf "========== ERROR: mcp-server-gateway did not start. Run docker logs mcp-server-gateway =========\n" && exit 1; fi + make insert-admin-user - @echo OpenWebUI: http://localhost:3050 https://open-webui.localhost tester/password + @echo OpenWebUI: http://localhost:3050 https://open-webui.localhost + @echo Click 'Continue with Keycloak' to login + @echo Use the following credentials: + @echo Admin User: admin/password. After login, run [make set-admin-user-role] to set admin role. + @echo Normal User: tester/password @echo Keycloak: http://keycloak:8080 admin/password @echo OIDC debugger: http://localhost:8085 @@ -106,15 +125,15 @@ help: ## Show this help. .PHONY:tests tests: ## Runs all the tests - docker compose run --rm --name language_model_gateway_tests dev pytest tests + docker compose run --rm --name language-model-gateway_tests dev pytest tests .PHONY:tests-integration tests-integration: ## Runs all the tests - docker compose run --rm -e RUN_TESTS_WITH_REAL_LLM=1 --name language_model_gateway_tests dev pytest tests + docker compose run --rm -e RUN_TESTS_WITH_REAL_LLM=1 --name language-model-gateway_tests dev pytest tests .PHONY:shell shell: ## Brings up the bash shell in dev docker - docker compose run --rm --name language_model_gateway_shell dev /bin/sh + docker compose run --rm --name language-model-gateway_shell dev /bin/sh .PHONY:clean-pre-commit clean-pre-commit: ## removes pre-commit hook @@ -132,18 +151,23 @@ run-pre-commit: setup-pre-commit clean: down clean_database ## Cleans all the local docker setup .PHONY: clean_database -clean_database: ## Cleans all the local docker setup -ifneq ($(shell docker volume ls | grep "language_model_gateway"| awk '{print $$2}'),) - docker volume ls | grep "language_model_gateway" | awk '{print $$2}' | xargs docker volume rm +clean_database: down ## Cleans all the local docker setup +ifneq ($(shell docker volume ls | grep "language-model-gateway"| awk '{print $$2}'),) + docker volume ls | grep "language-model-gateway" | awk '{print $$2}' | xargs docker volume rm endif .PHONY: insert-admin-user insert-admin-user: - docker exec -i language_model_gateway-open-webui-db-1 psql -U myapp_user -d myapp_db -p 5431 -c \ + docker exec -i language-model-gateway-open-webui-db-1 psql -U myapp_user -d myapp_db -p 5431 -c \ "INSERT INTO public.\"user\" (id,name,email,\"role\",profile_image_url,api_key,created_at,updated_at,last_active_at,settings,info,oauth_sub) \ SELECT '8d967d73-99b8-40ff-ac3b-c71ac19e1286','User','admin@localhost','admin','/user.png',NULL,1735089600,1735089600,1735089609,'{"ui": {"version": "0.4.8"}}','null',NULL \ WHERE NOT EXISTS (SELECT 1 FROM public.\"user\" WHERE id = '8d967d73-99b8-40ff-ac3b-c71ac19e1286');" +.PHONY: set-admin-user-role +set-admin-user-role: + docker exec -i language-model-gateway-open-webui-db-1 psql -U myapp_user -d myapp_db -p 5431 -c \ + "UPDATE public.\"user\" SET \"role\"='admin' WHERE name='admin@tester.com';" + CERT_DIR := certs CERT_KEY := $(CERT_DIR)/open-webui.localhost-key.pem CERT_CRT := $(CERT_DIR)/open-webui.localhost.pem diff --git a/Pipfile b/Pipfile index b5cc66636..1fe7c9d8d 100644 --- a/Pipfile +++ b/Pipfile @@ -17,9 +17,9 @@ requests = ">=2.32.3" # aridne is a Python library for building GraphQL APIs ariadne = ">=0.23.0" # fastapi is a Python library for building APIs -fastapi = ">=0.115.6" +fastapi = ">=0.115.8" # boto3 is a Python library for interacting with AWS services -boto3 = ">=1.35.84" +boto3 = ">=1.36.9" # uvicorn is a Python library for running ASGI applications uvicorn = ">=0.34.0" # ddtrace is a Python library for tracing requests @@ -33,25 +33,25 @@ httpx = ">=0.28.1" # httpx-sse is a Python library for making Server-Sent Events requests httpx-sse = ">=0.4.0" # langchain is a Python library for building language models -langchain = ">=0.3.13" +langchain = ">=0.3.17" # pydantic is a Python library for data validation pydantic = ">=2.0,<3.0.0" # needed by langchain # langchain-core is a Python library for building language models -langchain-core = ">=0.3.21" +langchain-core = ">=0.3.33" # langchain-aws is a Python library for interacting with AWS services langchain-aws = ">=0.2.9" # openai is a Python library for interacting with OpenAI -openai = ">=1.58.1" +openai = ">=1.60.2" # langchain-openai is a Python library for interacting with OpenAI -langchain-openai = ">=0.2.12" +langchain-openai = ">=0.3.3" # langchain-community is a Python library that contains ommmunity extensions -langchain-community = ">=0.3.14" +langchain-community = ">=0.3.16" # grpcio is a Python library for working with gRPC. Needed by Google Vertex AI grpcio = { version = "==1.66.0", index = "alpine-wheels" } # langchain-google-community is a Python library that contains Google community extensions langchain-google-community = ">=2.0.3" # langgraph is a Python library for building language models -langgraph = ">=0.2.60" +langgraph = ">=0.2.68" # langchainhub is a Python library for interacting with the LangChainHub API langchainhub = ">=0.1.21" # furl is a Python library for working with URLs @@ -60,7 +60,7 @@ furl = ">=2.1.3" # tiktoken 0.8.0 is missing wheel for tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl: https://pypi.org/simple/tiktoken/ tiktoken = "==0.7.0" # duckduckgo-search is a Python library for searching DuckDuckGo web results -duckduckgo-search = ">=7.2.0" +duckduckgo-search = ">=7.3.0" # xmltodict is a Python library for working with XML. It is used by the PubMed tool xmltodict = ">=0.14.2" # llm-guard is a Python library designed to protect the LLM API from abuse @@ -79,9 +79,23 @@ cachetools = ">=5.5.0" # aiofiles is a Python library for working with files asynchronously #aiofiles = ">=24.1.0" # pypdf is a Python library for working with PDFs -pypdf = ">=5.1.0" +pypdf = ">=5.2.0" # backoff is a Python library for retrying requests backoff = ">=2.2.1" +# Databricks SDK is a Python library for interacting with Databricks +databricks-sdk = ">=0.42.0" +# pandas is a Python library for working with data +pandas = ">=2.2.3" +# for testing the MCP client +mcp = ">=1.11.0" +# langchain_mcp_adapters is a Python library for working with MCP adapters in LangChain +langchain_mcp_adapters = ">=0.1.9" +# authlib is a Python library for OAuth and OpenID Connect +authlib = ">=1.6.1" +# joserfc is a Python library for working with JOSE (JSON Object Signing and Encryption) +joserfc = ">=1.2.2" +# aiocache is a Python library for caching with asyncio support +aiocache = ">=0.12.3" [dev-packages] # pre-commit is a Python library for running pre-commit checks @@ -93,9 +107,9 @@ mypy = ">=1.13.0" # pytest is a Python library for running tests pytest = ">=8.3.3" # pytest-asyncio is a Python library for running asyncio tests -pytest-asyncio = ">=0.25.0" +pytest-asyncio = ">=0.25.3" # black is a Python library for formatting code -black = ">=24.10.0" +black = ">=25.1.0" # deepdiff is a Python library for comparing objects deepdiff = { version = ">=8.1.1", extras = ["murmur"] } types-requests = "*" @@ -107,8 +121,20 @@ types-beautifulsoup4 = ">=4.12.0.20241020" types-cachetools = ">=5.5.0" # moto is a Python library for mocking AWS services moto = { version = ">=5.0.23", extras = ["s3"] } -# ruff is for linting and formatting code -ruff = ">=0.8.4" +# bandit is needed for security checks +bandit = ">=1.8.3" +# ruff is needed for linting +ruff = ">=0.11.5" +# pytest-cov is needed for measuring test coverage +pytest-cov = ">=6.1.1" +# for creating the MCP client to test +fastmcp = ">=2.10.5" +# types-boto3 provides type hints for boto3 +types-boto3 = { version = ">=1.40.0", extras = ["bedrock", "s3", "textract"] } +types-boto3-bedrock = ">=1.40.0" +types-boto3-s3 = ">=1.40.0" +types-boto3-textract = ">=1.40.0" +types-boto3-bedrock-runtime = ">=1.40.0" [requires] python_version = "3.12" diff --git a/Pipfile.lock b/Pipfile.lock index d197e0426..2749117c6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4035bfb5d4a06fd986dd43ad0f82785acc8f57c4e4e8b63085437995e2494831" + "sha256": "90321bc19c2d6a3dec556b8ac60c6c03b3e5f12a5a78c374685159aad55e4594" }, "pipfile-spec": 6, "requires": { @@ -21,103 +21,121 @@ ] }, "default": { + "aiocache": { + "hashes": [ + "sha256:889086fc24710f431937b87ad3720a289f7fc31c4fd8b68e9f918b9bacd8270d", + "sha256:f528b27bf4d436b497a1d0d1a8f59a542c153ab1e37c3621713cb376d44c4713" + ], + "index": "pypi", + "version": "==0.12.3" + }, "aiohappyeyeballs": { "hashes": [ - "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745", - "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8" + "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", + "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8" ], - "markers": "python_version >= '3.8'", - "version": "==2.4.4" + "markers": "python_version >= '3.9'", + "version": "==2.6.1" }, "aiohttp": { "hashes": [ - "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f", - "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33", - "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1", - "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", - "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9", - "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e", - "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350", - "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226", - "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", - "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a", - "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6", - "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add", - "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", - "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", - "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", - "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e", - "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", - "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1", - "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c", - "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", - "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5", - "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e", - "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9", - "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3", - "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438", - "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12", - "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3", - "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", - "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", - "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2", - "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", - "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c", - "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55", - "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", - "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e", - "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1", - "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", - "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194", - "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", - "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", - "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1", - "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d", - "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", - "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", - "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3", - "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8", - "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", - "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2", - "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff", - "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", - "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", - "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef", - "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28", - "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", - "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104", - "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", - "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", - "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", - "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", - "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5", - "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745", - "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4", - "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99", - "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43", - "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", - "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", - "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd", - "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d", - "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87", - "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", - "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", - "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", - "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d", - "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f", - "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", - "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e" - ], - "markers": "python_version >= '3.9'", - "version": "==3.11.11" + "sha256:010cc9bbd06db80fe234d9003f67e97a10fe003bfbedb40da7d71c1008eda0fe", + "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", + "sha256:098e92835b8119b54c693f2f88a1dec690e20798ca5f5fe5f0520245253ee0af", + "sha256:0a146708808c9b7a988a4af3821379e379e0f0e5e466ca31a73dbdd0325b0263", + "sha256:0a23918fedc05806966a2438489dcffccbdf83e921a1170773b6178d04ade142", + "sha256:0c643f4d75adea39e92c0f01b3fb83d57abdec8c9279b3078b68a3a52b3933b6", + "sha256:1004e67962efabbaf3f03b11b4c43b834081c9e3f9b32b16a7d97d4708a9abe6", + "sha256:14954a2988feae3987f1eb49c706bff39947605f4b6fa4027c1d75743723eb09", + "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", + "sha256:2776c7ec89c54a47029940177e75c8c07c29c66f73464784971d6a81904ce9d1", + "sha256:2abbb216a1d3a2fe86dbd2edce20cdc5e9ad0be6378455b05ec7f77361b3ab50", + "sha256:2c7d81a277fa78b2203ab626ced1487420e8c11a8e373707ab72d189fcdad20a", + "sha256:2ce13fcfb0bb2f259fb42106cdc63fa5515fb85b7e87177267d89a771a660b79", + "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", + "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", + "sha256:3b6f0af863cf17e6222b1735a756d664159e58855da99cfe965134a3ff63b0b0", + "sha256:3bdd6e17e16e1dbd3db74d7f989e8af29c4d2e025f9828e6ef45fbdee158ec75", + "sha256:3beb14f053222b391bf9cf92ae82e0171067cc9c8f52453a0f1ec7c37df12a77", + "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", + "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", + "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", + "sha256:3f9d7c55b41ed687b9d7165b17672340187f87a773c98236c987f08c858145a9", + "sha256:40b3fee496a47c3b4a39a731954c06f0bd9bd3e8258c059a4beb76ac23f8e421", + "sha256:421da6fd326460517873274875c6c5a18ff225b40da2616083c5a34a7570b685", + "sha256:4420cf9d179ec8dfe4be10e7d0fe47d6d606485512ea2265b0d8c5113372771b", + "sha256:46749be6e89cd78d6068cdf7da51dbcfa4321147ab8e4116ee6678d9a056a0cf", + "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", + "sha256:4c39e87afe48aa3e814cac5f535bc6199180a53e38d3f51c5e2530f5aa4ec58c", + "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", + "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", + "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", + "sha256:536ad7234747a37e50e7b6794ea868833d5220b49c92806ae2d7e8a9d6b5de02", + "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", + "sha256:57d16590a351dfc914670bd72530fd78344b885a00b250e992faea565b7fdc05", + "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", + "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", + "sha256:6443cca89553b7a5485331bc9bedb2342b08d073fa10b8c7d1c60579c4a7b9bd", + "sha256:691d203c2bdf4f4637792efbbcdcd157ae11e55eaeb5e9c360c1206fb03d4d98", + "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", + "sha256:6c5f40ec615e5264f44b4282ee27628cea221fcad52f27405b80abb346d9f3f8", + "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", + "sha256:74bdd8c864b36c3673741023343565d95bfbd778ffe1eb4d412c135a28a8dc89", + "sha256:74dad41b3458dbb0511e760fb355bb0b6689e0630de8a22b1b62a98777136e16", + "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", + "sha256:79b26fe467219add81d5e47b4a4ba0f2394e8b7c7c3198ed36609f9ba161aecb", + "sha256:7c7dd29c7b5bda137464dc9bfc738d7ceea46ff70309859ffde8c022e9b08ba7", + "sha256:7fbc8a7c410bb3ad5d595bb7118147dfbb6449d862cc1125cf8867cb337e8728", + "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", + "sha256:83603f881e11f0f710f8e2327817c82e79431ec976448839f3cd05d7afe8f830", + "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", + "sha256:86ceded4e78a992f835209e236617bffae649371c4a50d5e5a3987f237db84b8", + "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", + "sha256:8e995e1abc4ed2a454c731385bf4082be06f875822adc4c6d9eaadf96e20d406", + "sha256:8faa08fcc2e411f7ab91d1541d9d597d3a90e9004180edb2072238c085eac8c2", + "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", + "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", + "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", + "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", + "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", + "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", + "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", + "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", + "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", + "sha256:b5b7fe4972d48a4da367043b8e023fb70a04d1490aa7d68800e465d1b97e493b", + "sha256:b6fc902bff74d9b1879ad55f5404153e2b33a82e72a95c89cec5eb6cc9e92fbc", + "sha256:b7011a70b56facde58d6d26da4fec3280cc8e2a78c714c96b7a01a87930a9530", + "sha256:b761bac1192ef24e16706d761aefcb581438b34b13a2f069a6d343ec8fb693a5", + "sha256:b784d6ed757f27574dca1c336f968f4e81130b27595e458e69457e6878251f5d", + "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", + "sha256:bc4fbc61bb3548d3b482f9ac7ddd0f18c67e4225aaa4e8552b9f1ac7e6bda9e5", + "sha256:bc9a0f6569ff990e0bbd75506c8d8fe7214c8f6579cca32f0546e54372a3bb54", + "sha256:bd44d5936ab3193c617bfd6c9a7d8d1085a8dc8c3f44d5f1dcf554d17d04cf7d", + "sha256:ced339d7c9b5030abad5854aa5413a77565e5b6e6248ff927d3e174baf3badf7", + "sha256:d3ce17ce0220383a0f9ea07175eeaa6aa13ae5a41f30bc61d84df17f0e9b1117", + "sha256:d5f1b4ce5bc528a6ee38dbf5f39bbf11dd127048726323b72b8e85769319ffc4", + "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", + "sha256:db71ce547012a5420a39c1b744d485cfb823564d01d5d20805977f5ea1345676", + "sha256:e153e8adacfe2af562861b72f8bc47f8a5c08e010ac94eebbe33dc21d677cd5b", + "sha256:edd533a07da85baa4b423ee8839e3e91681c7bfa19b04260a469ee94b778bf6d", + "sha256:f0adb4177fa748072546fb650d9bd7398caaf0e15b370ed3317280b13f4083b0", + "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", + "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", + "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", + "sha256:fc49c4de44977aa8601a00edbf157e9a421f227aa7eb477d9e3df48343311065", + "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", + "sha256:fe086edf38b2222328cdf89af0dde2439ee173b8ad7cb659b4e4c6f385b2be3d" + ], + "markers": "python_version >= '3.9'", + "version": "==3.12.15" }, "aiosignal": { "hashes": [ - "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", - "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54" + "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", + "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7" ], "markers": "python_version >= '3.9'", - "version": "==1.3.2" + "version": "==1.4.0" }, "annotated-types": { "hashes": [ @@ -129,36 +147,46 @@ }, "anyio": { "hashes": [ - "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", - "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a" + "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", + "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1" ], "markers": "python_version >= '3.9'", - "version": "==4.8.0" + "version": "==4.10.0" }, "ariadne": { "hashes": [ - "sha256:6ea3f53d7e54d83b011e5697795ab7f8a713cb5f9423d6849e43a84f2fe81293", - "sha256:aee510e72954a84052c0705b5ed8db7f6ff82d782b9a0a8ead58b4776e3246c9" + "sha256:607617f82760c039b2137b7c1200b475ea90ccf4ca42c0994926c0d8fdede908", + "sha256:8d272c73a751d30a1c9c367318a317483588a51c335351d7342f23f109816a92" ], "index": "pypi", - "version": "==0.24.0" + "markers": "python_version >= '3.9'", + "version": "==0.26.2" }, "arxiv": { "hashes": [ - "sha256:32365221994d2cf05657c1fadf63a26efc8ccdec18590281ee03515bfef8bc4e", - "sha256:6f43673ab770a9e848d7d4fc1894824df55edeac3c3572ea280c9ba2e3c0f39f" + "sha256:545b8af5ab301efff7697cd112b5189e631b80521ccbc33fbc1e1f9cff63ca4d", + "sha256:6072a2211e95697092ef32acde0144d7de2cfa71208e2751724316c9df322cc0" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==2.1.3" + "version": "==2.2.0" }, "attrs": { "hashes": [ - "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", - "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308" + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" ], "markers": "python_version >= '3.8'", - "version": "==24.3.0" + "version": "==25.3.0" + }, + "authlib": { + "hashes": [ + "sha256:4dffdbb1460ba6ec8c17981a4c67af7d8af131231b5a36a88a1e8c80c111cdfd", + "sha256:e9d2031c34c6309373ab845afc24168fe9e93dc52d252631f52642f21f5ed06e" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.6.1" }, "backoff": { "hashes": [ @@ -171,160 +199,285 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", - "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed" + "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", + "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195" ], "index": "pypi", - "markers": "python_full_version >= '3.6.0'", - "version": "==4.12.3" + "markers": "python_full_version >= '3.7.0'", + "version": "==4.13.4" }, "boto3": { "hashes": [ - "sha256:4b6274b4fe9d7113f978abea66a1f20c8a397c268c9d1b2a6c96b14a256da4a5", - "sha256:d0224e1499d7189b47aa7f469d96522d98df6f5702fccb20a95a436582ebcd9d" + "sha256:2dfbc214fdbf94abfd61eec687ea39089d05af43bb00be792c76f3a6c1393f7b", + "sha256:3d99325ee874190e8f3bfd38823987327c826cdfbab943420851bdb7684d727c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.35.98" + "markers": "python_version >= '3.9'", + "version": "==1.40.2" }, "botocore": { "hashes": [ - "sha256:4f1c0b687488663a774ad3a5e81a5f94fae1bcada2364cfdc48482c4dbf794d5", - "sha256:d11742b3824bdeac3c89eeeaf5132351af41823bbcef8fc15e95c8250b1de09c" + "sha256:77c4710bf37b28e897833b5b1f47d6a83e45a29985cd01a560dfdb8b6ad524e5", + "sha256:a31e6269af05498f8dc1c7f2b3f34448a0f16c79a8601c0389ecddab51b2c2ab" ], - "markers": "python_version >= '3.8'", - "version": "==1.35.98" + "markers": "python_version >= '3.9'", + "version": "==1.40.2" }, "bytecode": { "hashes": [ - "sha256:06676a3c3bccc9d3dc73ee625650ea57df2bc117358826f4f290f0e1faa42292", - "sha256:76080b7c0eb9e7e17f961d61fd06e933aa47f3b753770a3249537439d8203a25" + "sha256:0a7dea0387ec5cae5ec77578690c5ca7470c8a202c50ce64a426d86380cddd7f", + "sha256:f05020b6dc1f48cdadd946f7c3a03131ba0f312bd103767c5d75559de5c308f8" ], "markers": "python_version >= '3.8'", - "version": "==0.16.0" + "version": "==0.16.2" }, "cachetools": { "hashes": [ - "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292", - "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a" + "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4", + "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==5.5.0" + "version": "==5.5.2" }, "certifi": { "hashes": [ - "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", - "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db" + "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", + "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" ], - "markers": "python_version >= '3.6'", - "version": "==2024.12.14" + "markers": "python_version >= '3.7'", + "version": "==2025.8.3" + }, + "cffi": { + "hashes": [ + "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", + "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", + "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", + "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", + "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", + "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", + "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", + "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", + "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", + "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", + "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", + "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", + "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", + "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", + "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", + "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", + "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", + "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", + "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", + "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", + "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", + "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", + "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", + "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", + "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", + "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", + "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", + "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", + "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", + "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", + "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", + "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", + "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", + "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", + "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", + "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", + "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", + "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", + "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", + "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", + "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", + "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", + "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", + "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", + "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", + "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", + "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", + "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", + "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", + "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", + "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", + "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", + "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", + "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", + "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", + "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", + "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", + "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", + "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", + "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", + "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", + "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" + ], + "markers": "python_version >= '3.8'", + "version": "==1.17.1" }, "charset-normalizer": { "hashes": [ - "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", - "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", - "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", - "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", - "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", - "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", - "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", - "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", - "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", - "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", - "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", - "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", - "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", - "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", - "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", - "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", - "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", - "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", - "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", - "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", - "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", - "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", - "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", - "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", - "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", - "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", - "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", - "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", - "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", - "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", - "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", - "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", - "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", - "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", - "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", - "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", - "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", - "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", - "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", - "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", - "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", - "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", - "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", - "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", - "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", - "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", - "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", - "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", - "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", - "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", - "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", - "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", - "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", - "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", - "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", - "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", - "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", - "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", - "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", - "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", - "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", - "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", - "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", - "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", - "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", - "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", - "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", - "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", - "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", - "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", - "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", - "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", - "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", - "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", - "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", - "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", - "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", - "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", - "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", - "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", - "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", - "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", - "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", - "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", - "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", - "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", - "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", - "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", - "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", - "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", - "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", - "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", + "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", + "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", + "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", + "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", + "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", + "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", + "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", + "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", + "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", + "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", + "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", + "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", + "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", + "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", + "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", + "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", + "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", + "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", + "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", + "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", + "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", + "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", + "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", + "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", + "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", + "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", + "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", + "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", + "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", + "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", + "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", + "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", + "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", + "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", + "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", + "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", + "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", + "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", + "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", + "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", + "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", + "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", + "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", + "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", + "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", + "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", + "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", + "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", + "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", + "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", + "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", + "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", + "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", + "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", + "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", + "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", + "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", + "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", + "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", + "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", + "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", + "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", + "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", + "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", + "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", + "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", + "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", + "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", + "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", + "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", + "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", + "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", + "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", + "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", + "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", + "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", + "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", + "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", + "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", + "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", + "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", + "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", + "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", + "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", + "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", + "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", + "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", + "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", + "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", + "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", + "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.1" + "version": "==3.4.2" }, "click": { "hashes": [ - "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", - "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" + "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", + "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b" + ], + "markers": "python_version >= '3.10'", + "version": "==8.2.1" + }, + "cryptography": { + "hashes": [ + "sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7", + "sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8", + "sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463", + "sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30", + "sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f", + "sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd", + "sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135", + "sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d", + "sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57", + "sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd", + "sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e", + "sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e", + "sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1", + "sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0", + "sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a", + "sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a", + "sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492", + "sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e", + "sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e", + "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97", + "sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174", + "sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9", + "sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18", + "sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0", + "sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27", + "sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63", + "sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e", + "sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d", + "sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6", + "sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42", + "sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097", + "sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9", + "sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d", + "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f", + "sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0", + "sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5", + "sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8" + ], + "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", + "version": "==45.0.5" + }, + "databricks-sdk": { + "hashes": [ + "sha256:06e50663c2c87e94f5e505390b74bc5c7c5330f4b4be35616b7aed06cf940af0", + "sha256:709ac7c709f843567b04fba6cea8a53ee644b79314e9a9ac4db0c1b3c1d2d5fe" ], + "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==8.1.8" + "version": "==0.61.0" }, "dataclasses-json": { "hashes": [ @@ -336,78 +489,71 @@ }, "ddtrace": { "hashes": [ - "sha256:0019ca4349cfc50116d8c1194c38de58eb0b3abdd1b253e646f09f23b4afc54c", - "sha256:04351f2bad1a02c9bc7c8459e354baedd6bd4041dc142f611375be199912449c", - "sha256:09772884c2a95bfecaa6c05644d773dcb135f04340c561a7465d6b6d28b10edf", - "sha256:0a84d60ddc11c8de13900127c5d4ef8ad450b8dd06cc8db446f024b0c6d5015b", - "sha256:0ceabfd3bc9bc772a2dfe605c16d063bf91b4ac66c2033efc4211dfe3aa0243b", - "sha256:14360fc302489f2132ee18b5f6c24debbb21f955e3cb946050398d0c1595df17", - "sha256:15a37b22ffb20071ba20f8861eda9732de91a36664d7587ad59370d17aa79d85", - "sha256:173ae0a67c502add96c4d93b6c11db22de1879017318f75fc51a0f8897f2379c", - "sha256:1b1bd03574a089d9bd7ca9e43ac12a9c685e53a01e8037649837ca437a6b6d50", - "sha256:1e9b315eb03174ed85d6eead72364b7fd99b5e004e598bbf4670759659bf367b", - "sha256:22b42396bbf23cf7d30319936e3e62ba5b571692a62eef58e8d8a10e1b50c710", - "sha256:2a0a0dbe72234b73c176d4d91aa6ddccda89e89bd554cd910cadeb9dd4500670", - "sha256:2a5ec887bce8c2718f8a3f50fb2daa708aac973105735cd3f74d55f2ce69a220", - "sha256:2e2fc0bde27c86cf25bf53152b7107b1670d45ef6395a563160de56785ee4864", - "sha256:30a93b83e75bd25be1b20217295fb6e7000f2bf34ec32ff3abe00e3a7903b471", - "sha256:328b6dc3462ca83ce9d2171eed765d8b0ed2c54e75dde10b8d9d364a00f637a4", - "sha256:32e35dba7ff39b8cd30cf27079ae2442bf57fdd1fb2f8df6977b97e6d2088b52", - "sha256:34a74acf4cdc46f075948ecf59c7a2dfa8e6aea34f1f4cb29fd5c1a0f37c95e5", - "sha256:3bc030edeed2cf37cef67b9e7a9d00c2298ac779b091574899832a7938f67f53", - "sha256:41cea5049a0115660c9484b4156ad1151c51f4e6d92251922c54f7008c1954aa", - "sha256:41f174b33d2d944dca90ff5be0bec95c98606d82f954c3acd805e4f484d2ffd5", - "sha256:4422de0e528ba965324fe96670081731eec66db2742984e3893e642e8898fa23", - "sha256:4618d0fc75f9f7b794647b7ce794e4ddd74d377467bd4e5be4f548214205ca4d", - "sha256:500a40e5501f04340e4a50c31e10788a764278bd016e7c523c455980dc0f5cb1", - "sha256:5d2f9bdc53ee00c32f4451a368c29d0173231c195a521c12524e0dfbdddefdfa", - "sha256:620d543b2dce68b6bc6cf4524378e013244938b5ea0d9d1457ec351bb7f09009", - "sha256:62c7b96d7a5dcc54e469dfcfb61bccc53019010cbd1be51bdff48988fe715a83", - "sha256:641f77eed9d5ff5fbc3078b7b11e6210a0ee96d4d7599cccb1756961c4eef948", - "sha256:686c1ec683cb28e24d8746afd00e50cdd723ce19d86af26257174c58a06a28d6", - "sha256:68db9541c238b548e769358f255e072f6311078e423e051c29e78b5fad17af15", - "sha256:6adc5faf5807b7e17a320546b3a362e36ca7e53d862f07cb8c133ec5af3216ce", - "sha256:6fd148ade68f5321358adf52c1e9a5c9a82501c10886582e4e57fca6fdfbeeb7", - "sha256:70c03403704b20b38b27dfacfd9c071a779610049449577fceefaa4fcf7fa081", - "sha256:70e1227183cd07c247326da0db7b033110d6b05b4107ee5c8541a1bd859df8fd", - "sha256:74500caa641266d8e19e9ad4259b503fc97b0855bc144f8515caf9df96855f6f", - "sha256:8394525f0f588ebd8a6b90da9916088237fe00973f462ec59514e55a232072a7", - "sha256:859d10ecf4cd2b9a58c2af38cf95d77bbaaca3c8f2527f0120f796d8afd57c53", - "sha256:88cae70b85bb10fe2d7cfdf6fab7ccfb74163ebcc8f380c3fe4e59b7ed668d82", - "sha256:8c6a860655d4e2d0b6b8ad4db0a737731198c95ee7151262e2b415d7d4e77e0b", - "sha256:8d61d5d5b2be99c711dfb19d2e7d5b9864bb9a2b1051405bc38bc707b1c8dab2", - "sha256:8d99e32c28a75dfec09fe96ac99c9d7dfc7388c55a4549f43d925aa9110b8865", - "sha256:906a1b9aa3a9c1d3565c5381f1c8793dee7e2f80292c9aa285cfa6ebff3efbb9", - "sha256:92c6d5c706f1d64e240791a365ec319a3eb51acc293b40546c501e2188b77d09", - "sha256:968117040d319e10d4128314aebd3780dd06b4757c6d6b7de78036598ff9cbc8", - "sha256:9829e01e5401823976a9c413c4a19672fcf6538444421c67ab0e719b8d83235c", - "sha256:99db67cceaacd192596bd18de78ca90be19a3ecaa5875cc0014a72905bb622e7", - "sha256:a3d3a60dfcccadad9f97c7cb9cee803b68d1e2a9160cef44f4dc907b3be22a3b", - "sha256:a90f7cb8b55e257c2db4cba612b049eaf75d65db80b4fdb3e96af1ab906813d7", - "sha256:a91efe0a1a4f758f1ad74fa6cd238f2ed5e960f15695c1062effc11c4a6bd0eb", - "sha256:ba4f5a51a02a668d7c5cd7c7a30e48ab3d28c179e5729c5425e7349e74ce5060", - "sha256:bcbd3c75fc0ac2e2f48493b6451b8f34b55c28691011ddfcd9799730a461879b", - "sha256:c55c4970868996c1c1893259e94f0233dd87a3f5342ad27c711dba8a4a18071f", - "sha256:c62a0db263944a1b8b5676e0f33e216aae7febfa134b8c99025b6bf4a1aff8d3", - "sha256:c65185a80a95114d54310c329dca3ff6c8131cf0b770b3819b9aa627749bff3e", - "sha256:c9498e544f68cabaeb9aa9bdeb974405f7bced8a5c552d0f6477b686f6ffad96", - "sha256:caf4867f702ae6b83f27c797800309c7154a8cee00cf4b97c668d995f0cf9f0d", - "sha256:ccee8a36f6fef598161299111d845a83352c2d69646b2befdd6337b307dc9962", - "sha256:d6fdeb9e2260765b496f26dcafe747ab365ddc47637b697872757db430dde6be", - "sha256:f502695c8771ffecf52a27abaffc81c832a0146aab3c397a91abf6d7b09e9528", - "sha256:f67bdeffb774e7596c22f3d6307bad9d5cd9bd6b533392f4d98e91909c2ea02a" + "sha256:09a95dea7a5bf50d4d0f1924a2d9e84f95c651cd36fadc1b41a7a94e2d578ac1", + "sha256:16707471fcc49c620ba4c967cb2867fb9a5ee89738e0781bea410dd7d0e7bc73", + "sha256:1746da0af793308bf9d7a0a1f2d9ab9037855bd7a32ced752b610ac038ec3e12", + "sha256:19bdaa594a7323d592cfc2e11ad6ee9b71541351ed445e55af06cdb7a207f471", + "sha256:1aa15632d8e2c6d485a0f875a8893778853eaa732534268fad1a27ba1f5e2c5b", + "sha256:1c7636265d2ccc63c6b63029d859a6a9de7c5a1579bfd0fe601a3cc759141f62", + "sha256:1d6c6b3900b16f87e69a0425dde4379871559017d9eb892f5523e784900f3163", + "sha256:25b2124127567fb40ba8be306d54db0a0af7d1161d3d019b59671a3fbdf9484a", + "sha256:2affa01dfe4dabe7425190b0a34c4eec237458f7a446ac990a1a178e1015505f", + "sha256:2b88ac71da5a4a2ceaa689b30b90758a41b1de23941da891c0d8259f24ff04d3", + "sha256:2de91474924362e872f47dcd7dbae257489bd9cafb71939c10338df57dffe56f", + "sha256:2e9b7169bbe46f3ba663cefb2c7cbc182425f4018ccaa23df28bc3d6a3b20a5b", + "sha256:31093942490bb2c9b94e68b49e0955a0ecc9d79f73594705c816941a3539607e", + "sha256:32c49fdb3652fbeb69af2f657c33d45a8f83d4726760887904b2cf06659524bf", + "sha256:4167262d2773301bb2e916ad4973eac2834fbd0349fadb67b569503b00754921", + "sha256:473aea359cb57d28a1f37f53229cc74b5fd49b8d7784983cbb87f08ba0c48048", + "sha256:4db17454d7f83ea5024d1d7bd1f650b3656573b055845f29576202d7e5d63189", + "sha256:5451c41368c8dfb43f93f154788c0e15865239895ab4438d514987e009abfdbb", + "sha256:556037da9ee50ba49e7836cbda108a06eab6ba3ac4d81a6e2ce188b93bfd0911", + "sha256:561881f558d4c704f359c8d28668d48b6c88b5ee0c94cb175e8f418be125f848", + "sha256:569caaef5c7222facfd9e676ce7570f6ea9131ed5f2989785dfe0392dc7933aa", + "sha256:570fbc5fb9168aadd6f4c21bd5efa2631a308e3c6c43172b3e7ec6e5ae4109a9", + "sha256:58652e6416a236cbf14ef079943887373d7b25b7e3395c2ea7fa55dfa3c59301", + "sha256:58c77dcd4e1592ab34a0e0ba2e3ceae897156fd7d62771f760554f4e132e6823", + "sha256:5e347f29217ccb00fab22a3113ab32b6a0e6895b0deaff90223e70515bd109a8", + "sha256:60ae5c669ccfeea3dcd2ad275cf50a32c9979e17c4b9cd986ea74c705b86812a", + "sha256:6130b654048f90d04677d44e11926673736fa600dcb6fa703a21a095a60aa998", + "sha256:61ca5c2bd23197757bce7fea5c9de9769d85f6f57cc4157d7709b3fe4032f6cf", + "sha256:68c0803ad311e6dd2103f94e12034e72a8e604626c47e3061576a625ad8d0037", + "sha256:6efa382507b781ddd7c3d39b97515543be1e39d2f624bdb24c3e23b76e813132", + "sha256:70ecafb9dd13aacaf318dab60fcad5f4cb9dbf8ed8f5d0314046b44026e05d38", + "sha256:748158f6fa6c97d0d62dc298ca7d2b3a5db5459facc8c7bb7348d30a554f4f72", + "sha256:79077e8ed9592080862de40068d6b05760ad3d0c25a970b407006d688537de14", + "sha256:7e425dd5b31cdb5fdbb17afba33b89acd9b35f7dace2304556945c06a60378f6", + "sha256:857d3464e8d6b19289df1336a4c5b1fb1e318319b6deef33b0606bd37c852630", + "sha256:861aac942e0ca06ccec8a9621ffdbffd3398b28d3917100dd0135d1d29e63cc7", + "sha256:87894304b73fd0d3036162edbb3a7689eee82c47433fb5d06771815920397c53", + "sha256:8e103b502257ffb0f9e4019df0a73dabf85c6f20292a83a32184c32ec109f87f", + "sha256:8e231d9a9fa8946874922973aa88862bc77a9f38979af7fca3bcd8666906fa25", + "sha256:92ea29199eaad238cf41e594af790885915c3a860ae3139e73213f3d532761c3", + "sha256:96ece8f3f112c4dd77d909f4d28ae0ad80e867442620d0b07333b3b1cb5e8624", + "sha256:986e5fbc7dfdff77f88f82781e85d5ccb1831626241e4063312095ec9ea607f2", + "sha256:a126bde2766470fabbbc617bfc118df5b8acbb7cd58a4b272ba3697fd9b955e6", + "sha256:ad4b13c847d3f9d7e422d7050a3c68bd96da3d18c927656eca081d633721c72a", + "sha256:b0f9d18c1f4e09b3e36cdf6f94ee1755e91758f1e3f0a157ded2d123a0949965", + "sha256:b6775417e11d7974117581d85053ca1037b3f49056f0f508f42bc4dbd27c7581", + "sha256:b70a4dc8ec010631da9577ceb88c02a5019415c047a51390fc1209d74da984a8", + "sha256:bb748b3017d7effce45dfcf5e7a90768423b6dabfc8f5a4df94a2c5621586e4a", + "sha256:bdd13ee56bcec1bd6eafb3b54cd75ed0f1cb3a7c6403e75a3ca451d52bd9a36a", + "sha256:c7d8066d03c0c964d302786088526f667e3ff78e9809cdaf0cb914d33ee68c21", + "sha256:ceeab9bbf2b7c1773b96840b156feb4243915f5c2ceeacc8cc4a4a4d0820039b", + "sha256:d36040f12ebebcf65a432bcadd75bdb35a326e4f5821059b0026b46a6f596f2c", + "sha256:d624172679d5a22a3b76a5db8745395ede00198f65b9308c383490d25bbd184d", + "sha256:e07a2798197d69105d841a8c79e83ae3b27cced4c5a05765fac877fc6cca750b", + "sha256:e222326e0a313408a081c43cc05db7f2af4cf93cd3a1f1176155b09edbaf630c", + "sha256:e2bd15d42ccb4ff4a074d6ba3168980fc02fd6a64119b80857bcc0563b6187c5", + "sha256:e34a07a03b9f7d9cf58481f0809a467a2e6d4ca8621fa3924893628006527367", + "sha256:f1f460525ab76bc1ac003c5a7625384354963358c77bca9d74c0cf1478d485a5", + "sha256:f215427f5bd92e76d21fec51886eb37266cbe8561bb5be5fbf7b8087eb1c36aa", + "sha256:f9119278827631e9a6afd35b974a2281db10fb2b7904bc114af2fafcd663b27f", + "sha256:fe164cf5489e41371273fc8cc8aed8006ae480c5a2999435130ef3ced034a65e" ], "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.18.1" - }, - "deprecated": { - "hashes": [ - "sha256:353bc4a8ac4bfc96800ddab349d89c25dec1079f65fd53acdcc1e0b975b21320", - "sha256:683e561a90de76239796e6b6feac66b99030d2dd3fcf61ef996330f14bbb9b0d" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.2.15" + "markers": "python_version >= '3.8'", + "version": "==3.11.2" }, "distro": { "hashes": [ @@ -419,12 +565,12 @@ }, "duckduckgo-search": { "hashes": [ - "sha256:72ebbf6ad8759e3c3c79521cd66256e7a4ac741c522fd9342db94de91745ef87", - "sha256:cb214b6cd9505a41c228445a9c254620b93519c59292662d62ef19d0220618a0" + "sha256:9da91c9eb26a17e016ea1da26235d40404b46b0565ea86d75a9f78cc9441f935", + "sha256:f48adbb06626ee05918f7e0cef3a45639e9939805c4fc179e68c48a12f1b5062" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==7.2.1" + "markers": "python_version >= '3.9'", + "version": "==8.1.1" }, "envier": { "hashes": [ @@ -436,12 +582,12 @@ }, "fastapi": { "hashes": [ - "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654", - "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305" + "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", + "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.115.6" + "version": "==0.116.1" }, "feedparser": { "hashes": [ @@ -453,133 +599,145 @@ }, "frozenlist": { "hashes": [ - "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", - "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", - "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6", - "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", - "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", - "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f", - "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", - "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", - "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", - "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", - "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec", - "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2", - "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c", - "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336", - "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4", - "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", - "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b", - "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c", - "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10", - "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08", - "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", - "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", - "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f", - "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10", - "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", - "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", - "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", - "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", - "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d", - "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923", - "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", - "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", - "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17", - "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0", - "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", - "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", - "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c", - "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a", - "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0", - "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", - "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab", - "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", - "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3", - "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", - "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", - "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604", - "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", - "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5", - "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", - "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", - "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", - "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", - "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d", - "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", - "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3", - "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", - "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", - "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", - "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf", - "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76", - "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba", - "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171", - "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb", - "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", - "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", - "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972", - "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", - "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", - "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9", - "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411", - "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723", - "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", - "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b", - "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99", - "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e", - "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", - "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", - "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb", - "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", - "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", - "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca", - "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", - "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", - "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f", - "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5", - "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307", - "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e", - "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2", - "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", - "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", - "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", - "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a" + "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", + "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", + "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", + "sha256:1073557c941395fdfcfac13eb2456cb8aad89f9de27bae29fabca8e563b12615", + "sha256:1137b78384eebaf70560a36b7b229f752fb64d463d38d1304939984d5cb887b6", + "sha256:15900082e886edb37480335d9d518cec978afc69ccbc30bd18610b7c1b22a718", + "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", + "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", + "sha256:1e63344c4e929b1a01e29bc184bbb5fd82954869033765bfe8d65d09e336a677", + "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", + "sha256:1ed8d2fa095aae4bdc7fdd80351009a48d286635edffee66bf865e37a9125c50", + "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", + "sha256:21884e23cffabb157a9dd7e353779077bf5b8f9a58e9b262c6caad2ef5f80a56", + "sha256:24c34bea555fe42d9f928ba0a740c553088500377448febecaa82cc3e88aa1fa", + "sha256:284d233a8953d7b24f9159b8a3496fc1ddc00f4db99c324bd5fb5f22d8698ea7", + "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", + "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", + "sha256:2ea2a7369eb76de2217a842f22087913cdf75f63cf1307b9024ab82dfb525938", + "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", + "sha256:34a69a85e34ff37791e94542065c8416c1afbf820b68f720452f636d5fb990cd", + "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", + "sha256:3789ebc19cb811163e70fe2bd354cea097254ce6e707ae42e56f45e31e96cb8e", + "sha256:387cbfdcde2f2353f19c2f66bbb52406d06ed77519ac7ee21be0232147c2592d", + "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", + "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", + "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", + "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", + "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", + "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", + "sha256:400ddd24ab4e55014bba442d917203c73b2846391dd42ca5e38ff52bb18c3c5e", + "sha256:41be2964bd4b15bf575e5daee5a5ce7ed3115320fb3c2b71fca05582ffa4dc9e", + "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", + "sha256:43a82fce6769c70f2f5a06248b614a7d268080a9d20f7457ef10ecee5af82b63", + "sha256:45a6f2fdbd10e074e8814eb98b05292f27bad7d1883afbe009d96abdcf3bc898", + "sha256:46d84d49e00c9429238a7ce02dc0be8f6d7cd0cd405abd1bebdc991bf27c15bd", + "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", + "sha256:4a646531fa8d82c87fe4bb2e596f23173caec9185bfbca5d583b4ccfb95183e2", + "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", + "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", + "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", + "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", + "sha256:61d1a5baeaac6c0798ff6edfaeaa00e0e412d49946c53fae8d4b8e8b3566c4ae", + "sha256:69cac419ac6a6baad202c85aaf467b65ac860ac2e7f2ac1686dc40dbb52f6577", + "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", + "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", + "sha256:6eb93efb8101ef39d32d50bce242c84bcbddb4f7e9febfa7b524532a239b4464", + "sha256:716a9973a2cc963160394f701964fe25012600f3d311f60c790400b00e568b61", + "sha256:72c1b0fe8fe451b34f12dce46445ddf14bd2a5bcad7e324987194dc8e3a74c86", + "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", + "sha256:74739ba8e4e38221d2c5c03d90a7e542cb8ad681915f4ca8f68d04f810ee0a87", + "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", + "sha256:79b2ffbba483f4ed36a0f236ccb85fbb16e670c9238313709638167670ba235f", + "sha256:7d536ee086b23fecc36c2073c371572374ff50ef4db515e4e503925361c24f71", + "sha256:7edf5c043c062462f09b6820de9854bf28cc6cc5b6714b383149745e287181a8", + "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", + "sha256:836b42f472a0e006e02499cef9352ce8097f33df43baaba3e0a28a964c26c7d2", + "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", + "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", + "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", + "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", + "sha256:960d67d0611f4c87da7e2ae2eacf7ea81a5be967861e0c63cf205215afbfac59", + "sha256:974c5336e61d6e7eb1ea5b929cb645e882aadab0095c5a6974a111e6479f8878", + "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", + "sha256:9a19e85cc503d958abe5218953df722748d87172f71b73cf3c9257a91b999890", + "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", + "sha256:9b35db7ce1cd71d36ba24f80f0c9e7cff73a28d7a74e91fe83e23d27c7828750", + "sha256:9ccec739a99e4ccf664ea0775149f2749b8a6418eb5b8384b4dc0a7d15d304cb", + "sha256:a0fd1bad056a3600047fb9462cff4c5322cebc59ebf5d0a3725e0ee78955001d", + "sha256:a26f205c9ca5829cbf82bb2a84b5c36f7184c4316617d7ef1b271a56720d6b30", + "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", + "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", + "sha256:aa51e147a66b2d74de1e6e2cf5921890de6b0f4820b257465101d7f37b49fb5a", + "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", + "sha256:ac64b6478722eeb7a3313d494f8342ef3478dff539d17002f849101b212ef97c", + "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", + "sha256:af369aa35ee34f132fcfad5be45fbfcde0e3a5f6a1ec0712857f286b7d20cca9", + "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", + "sha256:b3950f11058310008a87757f3eee16a8e1ca97979833239439586857bc25482e", + "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", + "sha256:bcacfad3185a623fa11ea0e0634aac7b691aa925d50a440f39b458e41c561d98", + "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", + "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", + "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", + "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", + "sha256:c70db4a0ab5ab20878432c40563573229a7ed9241506181bba12f6b7d0dc41cb", + "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", + "sha256:cc4df77d638aa2ed703b878dd093725b72a824c3c546c076e8fdf276f78ee84a", + "sha256:ce48b2fece5aeb45265bb7a58259f45027db0abff478e3077e12b05b17fb9da7", + "sha256:cea3dbd15aea1341ea2de490574a4a37ca080b2ae24e4b4f4b51b9057b4c3630", + "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", + "sha256:d50ac7627b3a1bd2dcef6f9da89a772694ec04d9a61b66cf87f7d9446b4a0c31", + "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", + "sha256:dfcebf56f703cb2e346315431699f00db126d158455e513bd14089d992101e44", + "sha256:e22b9a99741294b2571667c07d9f8cceec07cb92aae5ccda39ea1b6052ed4319", + "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", + "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", + "sha256:e793a9f01b3e8b5c0bc646fb59140ce0efcc580d22a3468d70766091beb81b35", + "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", + "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", + "sha256:f22dac33bb3ee8fe3e013aa7b91dc12f60d61d05b7fe32191ffa84c3aafe77bd", + "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", + "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", + "sha256:f89f65d85774f1797239693cef07ad4c97fdd0639544bad9ac4b869782eb1981", + "sha256:fe2365ae915a1fafd982c146754e1de6ab3478def8a59c86e1f7242d794f97d5" ], - "markers": "python_version >= '3.8'", - "version": "==1.5.0" + "markers": "python_version >= '3.9'", + "version": "==1.7.0" }, "furl": { "hashes": [ - "sha256:5a6188fe2666c484a12159c18be97a1977a71d632ef5bb867ef15f54af39cc4e", - "sha256:9ab425062c4217f9802508e45feb4a83e54324273ac4b202f1850363309666c0" + "sha256:877657501266c929269739fb5f5980534a41abd6bbabcb367c136d1d3b2a6015", + "sha256:da34d0b34e53ffe2d2e6851a7085a05d96922b5b578620a37377ff1dbeeb11c8" ], "index": "pypi", - "version": "==2.1.3" + "version": "==2.1.4" }, "google-api-core": { "hashes": [ - "sha256:10d82ac0fca69c82a25b3efdeefccf6f28e02ebb97925a8cce8edbfe379929d9", - "sha256:e255640547a597a4da010876d333208ddac417d60add22b6851a0c66a831fcaf" + "sha256:8a2a56c1fef82987a524371f99f3bd0143702fecc670c72e600c1cda6bf8dbb7", + "sha256:d2aaa0b13c78c61cb3f4282c464c046e45fbd75755683c9c525e6e8f7ed0a5e8" ], "markers": "python_version >= '3.7'", - "version": "==2.24.0" + "version": "==2.25.1" }, "google-api-python-client": { "hashes": [ - "sha256:55197f430f25c907394b44fa078545ffef89d33fd4dca501b7db9f0d8e224bd6", - "sha256:baef0bb631a60a0bd7c0bf12a5499e3a40cd4388484de7ee55c1950bf820a0cf" + "sha256:9ffd2b57d68f5afa7e6ac64e2c440534eaa056cbb394812a62ff94723c31b50e", + "sha256:f2f50f11105ab883eb9b6cf38ec54ea5fd4b429249f76444bec90deba5be79b3" ], "markers": "python_version >= '3.7'", - "version": "==2.159.0" + "version": "==2.177.0" }, "google-auth": { "hashes": [ - "sha256:0054623abf1f9c83492c63d3f47e77f0a544caa3d40b2d98e099a611c2dd5d00", - "sha256:42664f18290a6be591be5329a96fe30184be1a1badb7292a7f686a9659de9ca0" + "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca", + "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77" ], "markers": "python_version >= '3.7'", - "version": "==2.37.0" + "version": "==2.40.3" }, "google-auth-httplib2": { "hashes": [ @@ -590,19 +748,19 @@ }, "google-cloud-core": { "hashes": [ - "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073", - "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61" + "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", + "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e" ], "markers": "python_version >= '3.7'", - "version": "==2.4.1" + "version": "==2.4.3" }, "googleapis-common-protos": { "hashes": [ - "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c", - "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed" + "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", + "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8" ], "markers": "python_version >= '3.7'", - "version": "==1.66.0" + "version": "==1.70.0" }, "graphql-core": { "hashes": [ @@ -614,91 +772,72 @@ }, "graphviz": { "hashes": [ - "sha256:09d6bc81e6a9fa392e7ba52135a9d49f1ed62526f96499325930e87ca1b5925d", - "sha256:81f848f2904515d8cd359cc611faba817598d2feaac4027b266aa3eda7b3dde5" + "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", + "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.20.3" + "markers": "python_version >= '3.9'", + "version": "==0.21" }, "greenlet": { "hashes": [ - "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", - "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7", - "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", - "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", - "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", - "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", - "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", - "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", - "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", - "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa", - "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", - "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", - "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", - "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22", - "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9", - "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", - "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba", - "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3", - "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", - "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", - "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291", - "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", - "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", - "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", - "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", - "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef", - "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c", - "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", - "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c", - "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", - "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", - "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8", - "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d", - "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", - "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145", - "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", - "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", - "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e", - "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", - "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1", - "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef", - "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", - "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", - "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", - "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437", - "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd", - "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981", - "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", - "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", - "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798", - "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", - "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", - "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", - "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", - "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af", - "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", - "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", - "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42", - "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e", - "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81", - "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", - "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", - "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc", - "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de", - "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111", - "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", - "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", - "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", - "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", - "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", - "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803", - "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", - "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" + "sha256:003c930e0e074db83559edc8705f3a2d066d4aa8c2f198aff1e454946efd0f26", + "sha256:024571bbce5f2c1cfff08bf3fbaa43bbc7444f580ae13b0099e95d0e6e67ed36", + "sha256:02b0df6f63cd15012bed5401b47829cfd2e97052dc89da3cfaf2c779124eb892", + "sha256:0921ac4ea42a5315d3446120ad48f90c3a6b9bb93dd9b3cf4e4d84a66e42de83", + "sha256:0cc73378150b8b78b0c9fe2ce56e166695e67478550769536a6742dca3651688", + "sha256:1afd685acd5597349ee6d7a88a8bec83ce13c106ac78c196ee9dde7c04fe87be", + "sha256:22eb5ba839c4b2156f18f76768233fe44b23a31decd9cc0d4cc8141c211fd1b4", + "sha256:25ad29caed5783d4bd7a85c9251c651696164622494c00802a139c00d639242d", + "sha256:29e184536ba333003540790ba29829ac14bb645514fbd7e32af331e8202a62a5", + "sha256:2c724620a101f8170065d7dded3f962a2aea7a7dae133a009cada42847e04a7b", + "sha256:2d8aa5423cd4a396792f6d4580f88bdc6efcb9205891c9d40d20f6e670992efb", + "sha256:3d04332dddb10b4a211b68111dabaee2e1a073663d117dc10247b5b1642bac86", + "sha256:419e60f80709510c343c57b4bb5a339d8767bf9aef9b8ce43f4f143240f88b7c", + "sha256:42efc522c0bd75ffa11a71e09cd8a399d83fafe36db250a87cf1dacfaa15dc64", + "sha256:4532f0d25df67f896d137431b13f4cdce89f7e3d4a96387a41290910df4d3a57", + "sha256:49c8cfb18fb419b3d08e011228ef8a25882397f3a859b9fe1436946140b6756b", + "sha256:500b8689aa9dd1ab26872a34084503aeddefcb438e2e7317b89b11eaea1901ad", + "sha256:5035d77a27b7c62db6cf41cf786cfe2242644a7a337a0e155c80960598baab95", + "sha256:5195fb1e75e592dd04ce79881c8a22becdfa3e6f500e7feb059b1e6fdd54d3e3", + "sha256:592c12fb1165be74592f5de0d70f82bc5ba552ac44800d632214b76089945147", + "sha256:68671180e3849b963649254a882cd544a3c75bfcd2c527346ad8bb53494444db", + "sha256:706d016a03e78df129f68c4c9b4c4f963f7d73534e48a24f5f5a7101ed13dbbb", + "sha256:72e77ed69312bab0434d7292316d5afd6896192ac4327d44f3d613ecb85b037c", + "sha256:731e154aba8e757aedd0781d4b240f1225b075b4409f1bb83b05ff410582cf00", + "sha256:7454d37c740bb27bdeddfc3f358f26956a07d5220818ceb467a483197d84f849", + "sha256:751261fc5ad7b6705f5f76726567375bb2104a059454e0226e1eef6c756748ba", + "sha256:761917cac215c61e9dc7324b2606107b3b292a8349bdebb31503ab4de3f559ac", + "sha256:784ae58bba89fa1fa5733d170d42486580cab9decda3484779f4759345b29822", + "sha256:7e70ea4384b81ef9e84192e8a77fb87573138aa5d4feee541d8014e452b434da", + "sha256:8186162dffde068a465deab08fc72c767196895c39db26ab1c17c0b77a6d8b97", + "sha256:8324319cbd7b35b97990090808fdc99c27fe5338f87db50514959f8059999805", + "sha256:83a8761c75312361aa2b5b903b79da97f13f556164a7dd2d5448655425bd4c34", + "sha256:86c2d68e87107c1792e2e8d5399acec2487a4e993ab76c792408e59394d52141", + "sha256:8704b3768d2f51150626962f4b9a9e4a17d2e37c8a8d9867bbd9fa4eb938d3b3", + "sha256:873abe55f134c48e1f2a6f53f7d1419192a3d1a4e873bace00499a4e45ea6af0", + "sha256:88cd97bf37fe24a6710ec6a3a7799f3f81d9cd33317dcf565ff9950c83f55e0b", + "sha256:8b0dd8ae4c0d6f5e54ee55ba935eeb3d735a9b58a8a1e5b5cbab64e01a39f365", + "sha256:8c37ef5b3787567d322331d5250e44e42b58c8c713859b8a04c6065f27efbf72", + "sha256:8c47aae8fbbfcf82cc13327ae802ba13c9c36753b67e760023fd116bc124a62a", + "sha256:93c0bb79844a367782ec4f429d07589417052e621aa39a5ac1fb99c5aa308edc", + "sha256:93d48533fade144203816783373f27a97e4193177ebaaf0fc396db19e5d61163", + "sha256:96c20252c2f792defe9a115d3287e14811036d51e78b3aaddbee23b69b216302", + "sha256:a07d3472c2a93117af3b0136f246b2833fdc0b542d4a9799ae5f41c28323faef", + "sha256:a433dbc54e4a37e4fff90ef34f25a8c00aed99b06856f0119dcf09fbafa16392", + "sha256:aaa7aae1e7f75eaa3ae400ad98f8644bb81e1dc6ba47ce8a93d3f17274e08322", + "sha256:baeedccca94880d2f5666b4fa16fc20ef50ba1ee353ee2d7092b383a243b0b0d", + "sha256:be52af4b6292baecfa0f397f3edb3c6092ce071b499dd6fe292c9ac9f2c8f264", + "sha256:c667c0bf9d406b77a15c924ef3285e1e05250948001220368e039b6aa5b5034b", + "sha256:ce539fb52fb774d0802175d37fcff5c723e2c7d249c65916257f0a940cee8904", + "sha256:d2971d93bb99e05f8c2c0c2f4aa9484a18d98c4c3bd3c62b65b7e6ae33dfcfaf", + "sha256:d760f9bdfe79bff803bad32b4d8ffb2c1d2ce906313fc10a83976ffb73d64ca7", + "sha256:ed6cfa9200484d234d8394c70f5492f144b20d4533f69262d530a1a082f6ee9a", + "sha256:efc6dc8a792243c31f2f5674b670b3a95d46fa1c6a912b8e310d6f542e7b0712", + "sha256:f4bfbaa6096b1b7a200024784217defedf46a07c2eee1a498e94a1b5f8ec5728" ], - "markers": "python_version >= '3.7'", - "version": "==3.1.1" + "markers": "python_version >= '3.9'", + "version": "==3.2.3" }, "grpcio": { "hashes": [ @@ -710,19 +849,19 @@ }, "h11": { "hashes": [ - "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", - "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" ], - "markers": "python_version >= '3.7'", - "version": "==0.14.0" + "markers": "python_version >= '3.8'", + "version": "==0.16.0" }, "httpcore": { "hashes": [ - "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", - "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd" + "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", + "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" ], "markers": "python_version >= '3.8'", - "version": "==1.0.7" + "version": "==1.0.9" }, "httplib2": { "hashes": [ @@ -743,12 +882,12 @@ }, "httpx-sse": { "hashes": [ - "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", - "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f" + "sha256:8f44d34414bc7b21bf3602713005c5df4917884f76072479b21f68befa4ea26e", + "sha256:cba42174344c3a5b06f255ce65b350880f962d99ead85e776f23c6618a377a37" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.4.0" + "markers": "python_version >= '3.9'", + "version": "==0.4.1" }, "idna": { "hashes": [ @@ -760,93 +899,94 @@ }, "importlib-metadata": { "hashes": [ - "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", - "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7" + "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", + "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd" ], - "markers": "python_version >= '3.8'", - "version": "==8.5.0" + "markers": "python_version >= '3.9'", + "version": "==8.7.0" }, "jiter": { "hashes": [ - "sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60", - "sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841", - "sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e", - "sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c", - "sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887", - "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f", - "sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a", - "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b", - "sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6", - "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74", - "sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c", - "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566", - "sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff", - "sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105", - "sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18", - "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6", - "sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4", - "sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3", - "sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587", - "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f", - "sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1", - "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44", - "sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43", - "sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c", - "sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef", - "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44", - "sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a", - "sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6", - "sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e", - "sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc", - "sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c", - "sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9", - "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586", - "sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637", - "sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27", - "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88", - "sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d", - "sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8", - "sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9", - "sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c", - "sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5", - "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15", - "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0", - "sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865", - "sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08", - "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393", - "sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0", - "sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca", - "sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d", - "sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29", - "sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84", - "sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36", - "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b", - "sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49", - "sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6", - "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d", - "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855", - "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc", - "sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817", - "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099", - "sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1", - "sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66", - "sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d", - "sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee", - "sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b", - "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f", - "sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152", - "sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4", - "sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05", - "sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57", - "sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5", - "sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d", - "sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d", - "sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63", - "sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7", - "sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e" + "sha256:023aa0204126fe5b87ccbcd75c8a0d0261b9abdbbf46d55e7ae9f8e22424eeb8", + "sha256:03997d2f37f6b67d2f5c475da4412be584e1cec273c1cfc03d642c46db43f8cf", + "sha256:07a7142c38aacc85194391108dc91b5b57093c978a9932bd86a36862759d9500", + "sha256:0c5867d40ab716e4684858e4887489685968a47e3ba222e44cde6e4a2154f959", + "sha256:13252b58c1f4d8c5b63ab103c03d909e8e1e7842d302473f482915d95fefd605", + "sha256:13ddbc6ae311175a3b03bd8994881bc4635c923754932918e18da841632349db", + "sha256:14a4c418b1ec86a195f1ca69da8b23e8926c752b685af665ce30777233dfe070", + "sha256:15720084d90d1098ca0229352607cd68256c76991f6b374af96f36920eae13c4", + "sha256:15acb267ea5e2c64515574b06a8bf393fbfee6a50eb1673614aa45f4613c0cca", + "sha256:166f3606f11920f9a1746b2eea84fa2c0a5d50fd313c38bdea4edc072000b0af", + "sha256:1956f934dca32d7bb647ea21d06d93ca40868b505c228556d3373cbd255ce853", + "sha256:1b28302349dc65703a9e4ead16f163b1c339efffbe1049c30a44b001a2a4fff9", + "sha256:1e274728e4a5345a6dde2d343c8da018b9d4bd4350f5a472fa91f66fda44911b", + "sha256:23ba7722d6748b6920ed02a8f1726fb4b33e0fd2f3f621816a8b486c66410ab2", + "sha256:286299b74cc49e25cd42eea19b72aa82c515d2f2ee12d11392c56d8701f52224", + "sha256:28dcecbb4ba402916034fc14eba7709f250c4d24b0c43fc94d187ee0580af181", + "sha256:28ed2a4c05a1f32ef0e1d24c2611330219fed727dae01789f4a335617634b1ca", + "sha256:2e2227db6ba93cb3e2bf67c87e594adde0609f146344e8207e8730364db27041", + "sha256:31c50c40272e189d50006ad5c73883caabb73d4e9748a688b216e85a9a9ca3b9", + "sha256:32bb468e3af278f095d3fa5b90314728a6916d89ba3d0ffb726dd9bf7367285e", + "sha256:371eab43c0a288537d30e1f0b193bc4eca90439fc08a022dd83e5e07500ed026", + "sha256:395bb9a26111b60141757d874d27fdea01b17e8fac958b91c20128ba8f4acc8a", + "sha256:39de429dcaeb6808d75ffe9effefe96a4903c6a4b376b2f6d08d77c1aaee2f18", + "sha256:3aa96f2abba33dc77f79b4cf791840230375f9534e5fac927ccceb58c5e604a5", + "sha256:3bebe0c558e19902c96e99217e0b8e8b17d570906e72ed8a87170bc290b1e978", + "sha256:3c189c4f1779c05f75fc17c0c1267594ed918996a231593a21a5ca5438445216", + "sha256:48a403277ad1ee208fb930bdf91745e4d2d6e47253eedc96e2559d1e6527006d", + "sha256:4c440ea003ad10927a30521a9062ce10b5479592e8a70da27f21eeb457b4a9c5", + "sha256:4d613e4b379a07d7c8453c5712ce7014e86c6ac93d990a0b8e7377e18505e98d", + "sha256:5161e201172de298a8a1baad95eb85db4fb90e902353b1f6a41d64ea64644e25", + "sha256:520ef6d981172693786a49ff5b09eda72a42e539f14788124a07530f785c3ad6", + "sha256:52ce124f13a7a616fad3bb723f2bfb537d78239d1f7f219566dc52b6f2a9e48d", + "sha256:533efbce2cacec78d5ba73a41756beff8431dfa1694b6346ce7af3a12c42202b", + "sha256:554dedfd05937f8fc45d17ebdf298fe7e0c77458232bcb73d9fbbf4c6455f5b3", + "sha256:558cc7e44fd8e507a236bee6a02fa17199ba752874400a0ca6cd6e2196cdb7dc", + "sha256:5bc299da7789deacf95f64052d97f75c16d4fc8c4c214a22bf8d859a4288a1c2", + "sha256:5e9251a5e83fab8d87799d3e1a46cb4b7f2919b895c6f4483629ed2446f66522", + "sha256:5ed975b83a2b8639356151cef5c0d597c68376fc4922b45d0eb384ac058cfa00", + "sha256:5f51e048540dd27f204ff4a87f5d79294ea0aa3aa552aca34934588cf27023cf", + "sha256:62755d1bcea9876770d4df713d82606c8c1a3dca88ff39046b85a048566d56ea", + "sha256:66e989410b6666d3ddb27a74c7e50d0829704ede652fd4c858e91f8d64b403d0", + "sha256:6842184aed5cdb07e0c7e20e5bdcfafe33515ee1741a6835353bb45fe5d1bd95", + "sha256:6c675736059020365cebc845a820214765162728b51ab1e03a1b7b3abb70f74c", + "sha256:6ed5649ceeaeffc28d87fb012d25a4cd356dcd53eff5acff1f0466b831dda2a7", + "sha256:7202ae396446c988cb2a5feb33a543ab2165b786ac97f53b59aafb803fef0744", + "sha256:75f9eb72ecb640619c29bf714e78c9c46c9c4eaafd644bf78577ede459f330d4", + "sha256:7d1bbf3c465de4a24ab12fb7766a0003f6f9bce48b8b6a886158c4d569452dc5", + "sha256:86c5aa6910f9bebcc7bc4f8bc461aff68504388b43bfe5e5c0bd21efa33b52f4", + "sha256:8be921f0cadd245e981b964dfbcd6fd4bc4e254cdc069490416dd7a2632ecc01", + "sha256:901b92f2e2947dc6dfcb52fd624453862e16665ea909a08398dde19c0731b7f4", + "sha256:919d139cdfa8ae8945112398511cb7fca58a77382617d279556b344867a37e61", + "sha256:9ab7fd8738094139b6c1ab1822d6f2000ebe41515c537235fd45dabe13ec9324", + "sha256:9c9c1d5f10e18909e993f9641f12fe1c77b3e9b533ee94ffa970acc14ded3812", + "sha256:a7c7d785ae9dda68c2678532a5a1581347e9c15362ae9f6e68f3fdbfb64f2e49", + "sha256:a9be4d0fa2b79f7222a88aa488bd89e2ae0a0a5b189462a12def6ece2faa45f1", + "sha256:aa8b3e0068c26ddedc7abc6fac37da2d0af16b921e288a5a613f4b86f050354f", + "sha256:ac509f7eccca54b2a29daeb516fb95b6f0bd0d0d8084efaf8ed5dfc7b9f0b357", + "sha256:b2ab0051160cb758a70716448908ef14ad476c3774bd03ddce075f3c1f90a3d6", + "sha256:b532d3af9ef4f6374609a3bcb5e05a1951d3bf6190dc6b176fdb277c9bbf15ee", + "sha256:bd6292a43c0fc09ce7c154ec0fa646a536b877d1e8f2f96c19707f65355b5a4d", + "sha256:c404a99352d839fed80d6afd6c1d66071f3bacaaa5c4268983fc10f769112e90", + "sha256:cafc4628b616dc32530c20ee53d71589816cf385dd9449633e910d596b1f5c8a", + "sha256:cd2fb72b02478f06a900a5782de2ef47e0396b3e1f7d5aba30daeb1fce66f303", + "sha256:ce541693355fc6da424c08b7edf39a2895f58d6ea17d92cc2b168d20907dee12", + "sha256:ceeb52d242b315d7f1f74b441b6a167f78cea801ad7c11c36da77ff2d42e8a28", + "sha256:d0cb9a125d5a3ec971a094a845eadde2db0de85b33c9f13eb94a0c63d463879e", + "sha256:d7bfed2fe1fe0e4dda6ef682cee888ba444b21e7a6553e03252e4feb6cf0adca", + "sha256:da9be20b333970e28b72edc4dff63d4fec3398e05770fb3205f7fb460eb48dd4", + "sha256:db16e4848b7e826edca4ccdd5b145939758dadf0dc06e7007ad0e9cfb5928ae7", + "sha256:dc347c87944983481e138dea467c0551080c86b9d21de6ea9306efb12ca8f606", + "sha256:e0588107ec8e11b6f5ef0e0d656fb2803ac6cf94a96b2b9fc675c0e3ab5e8644", + "sha256:e4f2fb68e5f1cfee30e2b2a09549a00683e0fde4c6a2ab88c94072fc33cb7426", + "sha256:f59e533afed0c5b0ac3eba20d2548c4a550336d8282ee69eb07b37ea526ee4e5", + "sha256:f62cf8ba0618eda841b9bf61797f21c5ebd15a7a1e19daab76e4e4b498d515b2", + "sha256:fa3402a2ff9815960e0372a47b75c76979d74402448509ccd49a275fa983ef8a", + "sha256:fcedb049bdfc555e261d6f65a6abe1d5ad68825b7202ccb9692636c70fcced86", + "sha256:ff76d8887c8c8ee1e772274fcf8cc1071c2c58590d13e33bd12d02dc9a560397" ], - "markers": "python_version >= '3.8'", - "version": "==0.8.2" + "markers": "python_version >= '3.9'", + "version": "==0.10.0" }, "jmespath": { "hashes": [ @@ -856,6 +996,15 @@ "markers": "python_version >= '3.7'", "version": "==1.0.1" }, + "joserfc": { + "hashes": [ + "sha256:0d2a84feecef96168635fd9bf288363fc75b4afef3d99691f77833c8e025d200", + "sha256:630cc36b2f11f749980401b0cd7305fab5735ee11d830d919bc207305d011358" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.2.2" + }, "jsonpatch": { "hashes": [ "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", @@ -872,41 +1021,57 @@ "markers": "python_version >= '3.7'", "version": "==3.0.0" }, + "jsonschema": { + "hashes": [ + "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716", + "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f" + ], + "markers": "python_version >= '3.9'", + "version": "==4.25.0" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", + "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608" + ], + "markers": "python_version >= '3.9'", + "version": "==2025.4.1" + }, "langchain": { "hashes": [ - "sha256:4a5ae817b5832fa0e1fcadc5353fbf74bebd2f8e550294d4dc039f651ddcd3d1", - "sha256:5df9031702f7fe6c956e84256b4639a46d5d03a75be1ca4c1bc9479b358061a2" + "sha256:7b20c4f338826acb148d885b20a73a16e410ede9ee4f19bb02011852d5f98798", + "sha256:aa6f1e6274ff055d0fd36254176770f356ed0a8994297d1df47df341953cec62" ], "index": "pypi", "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.3.14" + "version": "==0.3.27" }, "langchain-aws": { "hashes": [ - "sha256:37e4a8d5d1a7d2f493c62ba181e5eb0eb36f4b235dc239b070507dec5b042eed", - "sha256:af733cb328e795a3b7189221b4aab694743176c00487749ff885d6297f9860a4" + "sha256:67c31f0784045a4a73ef78a2c18f392e14c1e9f7b55870e62f18039cadfb925c", + "sha256:947fe4ece30bde0a37ea721b87049d7642607bd2ba9d2d93c9890736972b4274" ], "index": "pypi", - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.2.10" + "markers": "python_version >= '3.9'", + "version": "==0.2.30" }, "langchain-community": { "hashes": [ - "sha256:cc02a0abad0551edef3e565dff643386a5b2ee45b933b6d883d4a935b9649f3c", - "sha256:d8ba0fe2dbb5795bff707684b712baa5ee379227194610af415ccdfdefda0479" + "sha256:581f97b795f9633da738ea95da9cb78f8879b538090c9b7a68c0aed49c828f0d", + "sha256:e1037c3b9da0c6d10bf06e838b034eb741e016515c79ef8f3f16e53ead33d882" ], "index": "pypi", - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.3.14" + "markers": "python_version >= '3.9'", + "version": "==0.3.27" }, "langchain-core": { "hashes": [ - "sha256:773d6aeeb612e7ce3d996c0be403433d8c6a91e77bbb7a7461c13e15cfbe5b06", - "sha256:817db1474871611a81105594a3e4d11704949661008e455a10e38ca9ff601a1a" + "sha256:4de3828909b3d7910c313242ab07b241294650f5cb6eac17738dd3638b1cd7de", + "sha256:9fa15d390600eb6b6544397a7aa84be9564939b6adf7a2b091179ea30405b240" ], "index": "pypi", - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.3.29" + "markers": "python_version >= '3.9'", + "version": "==0.3.72" }, "langchain-experimental": { "hashes": [ @@ -926,22 +1091,31 @@ "markers": "python_version >= '3.9' and python_version < '4.0'", "version": "==2.0.4" }, + "langchain-mcp-adapters": { + "hashes": [ + "sha256:0018cf7b5f7bc4c044e05ec20fcb9ebe345311c8d1060c61d411188001ab3aab", + "sha256:fd131009c60c9e5a864f96576bbe757fc1809abd604891cb2e5d6e8aebd6975c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==0.1.9" + }, "langchain-openai": { "hashes": [ - "sha256:49c921a22d272b04749a61e78bffa83aecdb8840b24b69f2909e115a357a9a5b", - "sha256:88d623eeb2aaa1fff65c2b419a4a1cfd37d3a1d504e598b87cf0bc822a3b70d0" + "sha256:4cd6d80a5b2ae471a168017bc01b2e0f01548328d83532400a001623624ede67", + "sha256:6c669548dbdea325c034ae5ef699710e2abd054c7354fdb3ef7bf909dc739d9e" ], "index": "pypi", - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.3.0" + "markers": "python_version >= '3.9'", + "version": "==0.3.28" }, "langchain-text-splitters": { "hashes": [ - "sha256:11cb7ca3694e5bdd342bc16d3875b7f7381651d4a53cbb91d34f22412ae16443", - "sha256:8c9b059827438c5fa8f327b4df857e307828a5ec815163c9b5c9569a3e82c8ee" + "sha256:7cd1e5a3aaf609979583eeca2eb34177622570b8fa8f586a605c6b1c34e7ebdb", + "sha256:cee0bb816211584ea79cc79927317c358543f40404bcfdd69e69ba3ccde54401" ], - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.3.5" + "markers": "python_version >= '3.9'", + "version": "==0.3.9" }, "langchainhub": { "hashes": [ @@ -954,450 +1128,390 @@ }, "langgraph": { "hashes": [ - "sha256:0aac9fd55ffe669bc1312203e0f9ea2733c65cc276f196e7ff0d443cf4efbb89", - "sha256:51ae9e02a52485a837642eebe7ae43269af7d7305d62f8f69ac11589b2fbba26" + "sha256:0d2280d295133dc34ccc12eae1ad4d82ee847b009c59801de418068fa9248e1b", + "sha256:733efd8c59b9915e582619da40f2ab5ebb121319a4d7718adef82d6db07547eb" ], "index": "pypi", - "markers": "python_full_version >= '3.9.0' and python_version < '4.0'", - "version": "==0.2.62" + "markers": "python_version >= '3.9'", + "version": "==0.6.3" }, "langgraph-checkpoint": { "hashes": [ - "sha256:43847d7e385a2d9d2b684155920998e44ed42d2d1780719e4f6111fe3d6db84c", - "sha256:b546ed6129929b8941ac08af6ce5cd26c8ebe1d25883d3c48638d34ade91ce42" + "sha256:5a779134fd28134a9a83d078be4450bbf0e0c79fdf5e992549658899e6fc5ea7", + "sha256:72038c0f9e22260cb9bff1f3ebe5eb06d940b7ee5c1e4765019269d4f21cf92d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.1.1" + }, + "langgraph-prebuilt": { + "hashes": [ + "sha256:5e1ca7ba98f53ce98400f34bdb0afe47f71d0167c4108b11d4aeed4c6d4a1d3d", + "sha256:cea830fc73d1a6fb871c5c6739e894bffcb7b7a07343198b56f263d3113ae8d6" ], - "markers": "python_full_version >= '3.9.0' and python_full_version < '4.0.0'", - "version": "==2.0.9" + "markers": "python_version >= '3.9'", + "version": "==0.6.3" }, "langgraph-sdk": { "hashes": [ - "sha256:ce2b58466d1700d06149782ed113157a8694a6d7932c801f316cd13fab315fe4", - "sha256:dea1363e72562cb1e82a2d156be8d5b1a69ff3fe8815eee0e1e7a2f423242ec1" + "sha256:150722264f225c4d47bbe7394676be102fdbf04c4400a0dd1bd41a70c6430cc7", + "sha256:cd8b5f6595e5571be5cbffd04cf936978ab8f5d1005517c99715947ef871e246" ], - "markers": "python_full_version >= '3.9.0' and python_full_version < '4.0.0'", - "version": "==0.1.51" + "markers": "python_version >= '3.9'", + "version": "==0.2.0" }, "langsmith": { "hashes": [ - "sha256:153c7b3ccbd823528ff5bec84801e7e50a164e388919fc583252df5b27dd7830", - "sha256:b02f2f174189ff72e54c88b1aa63343defd6f0f676c396a690c63a4b6495dcc2" + "sha256:2cb39a8af795ff4014e60ca07a73a9bcd89b67837193c9f6be22efb5c9c4c846", + "sha256:ce3a52809d37854bcb129affd8cd883025985891b82a46f2ae597c511283360d" ], - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==0.2.10" + "markers": "python_version >= '3.9'", + "version": "==0.4.11" }, "lxml": { "hashes": [ - "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e", - "sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229", - "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3", - "sha256:07da23d7ee08577760f0a71d67a861019103e4812c87e2fab26b039054594cc5", - "sha256:094cb601ba9f55296774c2d57ad68730daa0b13dc260e1f941b4d13678239e70", - "sha256:0a7056921edbdd7560746f4221dca89bb7a3fe457d3d74267995253f46343f15", - "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002", - "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd", - "sha256:0fdf3a3059611f7585a78ee10399a15566356116a4288380921a4b598d807a22", - "sha256:109fa6fede314cc50eed29e6e56c540075e63d922455346f11e4d7a036d2b8cf", - "sha256:146173654d79eb1fc97498b4280c1d3e1e5d58c398fa530905c9ea50ea849b22", - "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832", - "sha256:1483fd3358963cc5c1c9b122c80606a3a79ee0875bcac0204149fa09d6ff2727", - "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e", - "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30", - "sha256:18feb4b93302091b1541221196a2155aa296c363fd233814fa11e181adebc52f", - "sha256:1afe0a8c353746e610bd9031a630a95bcfb1a720684c3f2b36c4710a0a96528f", - "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51", - "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4", - "sha256:1ffc23010330c2ab67fac02781df60998ca8fe759e8efde6f8b756a20599c5de", - "sha256:20094fc3f21ea0a8669dc4c61ed7fa8263bd37d97d93b90f28fc613371e7a875", - "sha256:213261f168c5e1d9b7535a67e68b1f59f92398dd17a56d934550837143f79c42", - "sha256:218c1b2e17a710e363855594230f44060e2025b05c80d1f0661258142b2add2e", - "sha256:23e0553b8055600b3bf4a00b255ec5c92e1e4aebf8c2c09334f8368e8bd174d6", - "sha256:25f1b69d41656b05885aa185f5fdf822cb01a586d1b32739633679699f220391", - "sha256:2b3778cb38212f52fac9fe913017deea2fdf4eb1a4f8e4cfc6b009a13a6d3fcc", - "sha256:2bc9fd5ca4729af796f9f59cd8ff160fe06a474da40aca03fcc79655ddee1a8b", - "sha256:2c226a06ecb8cdef28845ae976da407917542c5e6e75dcac7cc33eb04aaeb237", - "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4", - "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86", - "sha256:2d9b8d9177afaef80c53c0a9e30fa252ff3036fb1c6494d427c066a4ce6a282f", - "sha256:2dec2d1130a9cda5b904696cec33b2cfb451304ba9081eeda7f90f724097300a", - "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8", - "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f", - "sha256:315f9542011b2c4e1d280e4a20ddcca1761993dda3afc7a73b01235f8641e903", - "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03", - "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e", - "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99", - "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7", - "sha256:3eb44520c4724c2e1a57c0af33a379eee41792595023f367ba3952a2d96c2aab", - "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d", - "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22", - "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492", - "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b", - "sha256:482c2f67761868f0108b1743098640fbb2a28a8e15bf3f47ada9fa59d9fe08c3", - "sha256:4b0c7a688944891086ba192e21c5229dea54382f4836a209ff8d0a660fac06be", - "sha256:4c1fefd7e3d00921c44dc9ca80a775af49698bbfd92ea84498e56acffd4c5469", - "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f", - "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a", - "sha256:516f491c834eb320d6c843156440fe7fc0d50b33e44387fcec5b02f0bc118a4c", - "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a", - "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4", - "sha256:56b9861a71575f5795bde89256e7467ece3d339c9b43141dbdd54544566b3b94", - "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442", - "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b", - "sha256:5c54afdcbb0182d06836cc3d1be921e540be3ebdf8b8a51ee3ef987537455f84", - "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c", - "sha256:609251a0ca4770e5a8768ff902aa02bf636339c5a93f9349b48eb1f606f7f3e9", - "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1", - "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be", - "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367", - "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e", - "sha256:68934b242c51eb02907c5b81d138cb977b2129a0a75a8f8b60b01cb8586c7b21", - "sha256:68b87753c784d6acb8a25b05cb526c3406913c9d988d51f80adecc2b0775d6aa", - "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16", - "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d", - "sha256:6b038cc86b285e4f9fea2ba5ee76e89f21ed1ea898e287dc277a25884f3a7dfe", - "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83", - "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba", - "sha256:6ee8c39582d2652dcd516d1b879451500f8db3fe3607ce45d7c5957ab2596040", - "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763", - "sha256:71a8dd38fbd2f2319136d4ae855a7078c69c9a38ae06e0c17c73fd70fc6caad8", - "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff", - "sha256:7437237c6a66b7ca341e868cda48be24b8701862757426852c9b3186de1da8a2", - "sha256:747a3d3e98e24597981ca0be0fd922aebd471fa99d0043a3842d00cdcad7ad6a", - "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b", - "sha256:78d9b952e07aed35fe2e1a7ad26e929595412db48535921c5013edc8aa4a35ce", - "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c", - "sha256:7d3d1ca42870cdb6d0d29939630dbe48fa511c203724820fc0fd507b2fb46577", - "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8", - "sha256:7f41026c1d64043a36fda21d64c5026762d53a77043e73e94b71f0521939cc71", - "sha256:81b4e48da4c69313192d8c8d4311e5d818b8be1afe68ee20f6385d0e96fc9512", - "sha256:86a6b24b19eaebc448dc56b87c4865527855145d851f9fc3891673ff97950540", - "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f", - "sha256:89e043f1d9d341c52bf2af6d02e6adde62e0a46e6755d5eb60dc6e4f0b8aeca2", - "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a", - "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce", - "sha256:8f0de2d390af441fe8b2c12626d103540b5d850d585b18fcada58d972b74a74e", - "sha256:92e67a0be1639c251d21e35fe74df6bcc40cba445c2cda7c4a967656733249e2", - "sha256:94d6c3782907b5e40e21cadf94b13b0842ac421192f26b84c45f13f3c9d5dc27", - "sha256:97acf1e1fd66ab53dacd2c35b319d7e548380c2e9e8c54525c6e76d21b1ae3b1", - "sha256:9ada35dd21dc6c039259596b358caab6b13f4db4d4a7f8665764d616daf9cc1d", - "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1", - "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330", - "sha256:9e4b47ac0f5e749cfc618efdf4726269441014ae1d5583e047b452a32e221920", - "sha256:9fb81d2824dff4f2e297a276297e9031f46d2682cafc484f49de182aa5e5df99", - "sha256:a0eabd0a81625049c5df745209dc7fcef6e2aea7793e5f003ba363610aa0a3ff", - "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18", - "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff", - "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c", - "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179", - "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080", - "sha256:ace2c2326a319a0bb8a8b0e5b570c764962e95818de9f259ce814ee666603f19", - "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d", - "sha256:b11a5d918a6216e521c715b02749240fb07ae5a1fefd4b7bf12f833bc8b4fe70", - "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32", - "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a", - "sha256:b710bc2b8292966b23a6a0121f7a6c51d45d2347edcc75f016ac123b8054d3f2", - "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79", - "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3", - "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5", - "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f", - "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d", - "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3", - "sha256:c300306673aa0f3ed5ed9372b21867690a17dba38c68c44b287437c362ce486b", - "sha256:c56a1d43b2f9ee4786e4658c7903f05da35b923fb53c11025712562d5cc02753", - "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9", - "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957", - "sha256:cb83f8a875b3d9b458cada4f880fa498646874ba4011dc974e071a0a84a1b033", - "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb", - "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656", - "sha256:dd5350b55f9fecddc51385463a4f67a5da829bc741e38cf689f38ec9023f54ab", - "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b", - "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d", - "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd", - "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859", - "sha256:ea2e2f6f801696ad7de8aec061044d6c8c0dd4037608c7cab38a9a4d316bfb11", - "sha256:eafa2c8658f4e560b098fe9fc54539f86528651f61849b22111a9b107d18910c", - "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a", - "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005", - "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654", - "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80", - "sha256:f2901429da1e645ce548bf9171784c0f74f0718c3f6150ce166be39e4dd66c3e", - "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec", - "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7", - "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965", - "sha256:f914c03e6a31deb632e2daa881fe198461f4d06e57ac3d0e05bbcab8eae01945", - "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8" + "sha256:013090383863b72c62a702d07678b658fa2567aa58d373d963cca245b017e065", + "sha256:032e65120339d44cdc3efc326c9f660f5f7205f3a535c1fdbf898b29ea01fb72", + "sha256:048a930eb4572829604982e39a0c7289ab5dc8abc7fc9f5aabd6fbc08c154e93", + "sha256:04d67ceee6db4bcb92987ccb16e53bef6b42ced872509f333c04fb58a3315256", + "sha256:059c4cbf3973a621b62ea3132934ae737da2c132a788e6cfb9b08d63a0ef73f9", + "sha256:0e32698462aacc5c1cf6bdfebc9c781821b7e74c79f13e5ffc8bfe27c42b1abf", + "sha256:1676b56d48048a62ef77a250428d1f31f610763636e0784ba67a9740823988ca", + "sha256:17f090a9bc0ce8da51a5632092f98a7e7f84bca26f33d161a98b57f7fb0004ca", + "sha256:185efc2fed89cdd97552585c624d3c908f0464090f4b91f7d92f8ed2f3b18f54", + "sha256:1fa377b827ca2023244a06554c6e7dc6828a10aaf74ca41965c5d8a4925aebb4", + "sha256:2181e4b1d07dde53986023482673c0f1fba5178ef800f9ab95ad791e8bdded6a", + "sha256:219e0431ea8006e15005767f0351e3f7f9143e793e58519dc97fe9e07fae5563", + "sha256:21db1ec5525780fd07251636eb5f7acb84003e9382c72c18c542a87c416ade03", + "sha256:246b40f8a4aec341cbbf52617cad8ab7c888d944bfe12a6abd2b1f6cfb6f6082", + "sha256:2793a627e95d119e9f1e19720730472f5543a6d84c50ea33313ce328d870f2dd", + "sha256:2930aa001a3776c3e2601cb8e0a15d21b8270528d89cc308be4843ade546b9ab", + "sha256:2ae06fbab4f1bb7db4f7c8ca9897dc8db4447d1a2b9bee78474ad403437bcc29", + "sha256:2b4790b558bee331a933e08883c423f65bbcd07e278f91b2272489e31ab1e2b4", + "sha256:2cfcf84f1defed7e5798ef4f88aa25fcc52d279be731ce904789aa7ccfb7e8d2", + "sha256:2dd1cc3ea7e60bfb31ff32cafe07e24839df573a5e7c2d33304082a5019bcd58", + "sha256:2f34687222b78fff795feeb799a7d44eca2477c3d9d3a46ce17d51a4f383e32e", + "sha256:310b719b695b3dd442cdfbbe64936b2f2e231bb91d998e99e6f0daf991a3eba3", + "sha256:34190a1ec4f1e84af256495436b2d196529c3f2094f0af80202947567fdbf2e7", + "sha256:35bc626eec405f745199200ccb5c6b36f202675d204aa29bb52e27ba2b71dea8", + "sha256:36531f81c8214e293097cd2b7873f178997dae33d3667caaae8bdfb9666b76c0", + "sha256:390240baeb9f415a82eefc2e13285016f9c8b5ad71ec80574ae8fa9605093cd7", + "sha256:40442e2a4456e9910875ac12951476d36c0870dcb38a68719f8c4686609897c4", + "sha256:4337e4aec93b7c011f7ee2e357b0d30562edd1955620fdd4aeab6aacd90d43c5", + "sha256:43cfbb7db02b30ad3926e8fceaef260ba2fb7df787e38fa2df890c1ca7966c3b", + "sha256:43fe5af2d590bf4691531b1d9a2495d7aab2090547eaacd224a3afec95706d76", + "sha256:46b9ed911f36bfeb6338e0b482e7fe7c27d362c52fde29f221fddbc9ee2227e7", + "sha256:4d23854ecf381ab1facc8f353dcd9adeddef3652268ee75297c1164c987c11dc", + "sha256:4d6036c3a296707357efb375cfc24bb64cd955b9ec731abf11ebb1e40063949f", + "sha256:4eb114a0754fd00075c12648d991ec7a4357f9cb873042cc9a77bf3a7e30c9db", + "sha256:4ee56288d0df919e4aac43b539dd0e34bb55d6a12a6562038e8d6f3ed07f9e36", + "sha256:51a5e4c61a4541bd1cd3ba74766d0c9b6c12d6a1a4964ef60026832aac8e79b3", + "sha256:522fe7abb41309e9543b0d9b8b434f2b630c5fdaf6482bee642b34c8c70079c8", + "sha256:54c4855eabd9fc29707d30141be99e5cd1102e7d2258d2892314cf4c110726c3", + "sha256:5592401cdf3dc682194727c1ddaa8aa0f3ddc57ca64fd03226a430b955eab6f6", + "sha256:58ffd35bd5425c3c3b9692d078bf7ab851441434531a7e517c4984d5634cd65b", + "sha256:5967fe415b1920a3877a4195e9a2b779249630ee49ece22021c690320ff07452", + "sha256:5fcd7d3b1d8ecb91445bd71b9c88bdbeae528fefee4f379895becfc72298d181", + "sha256:63b634facdfbad421d4b61c90735688465d4ab3a8853ac22c76ccac2baf98d97", + "sha256:690b20e3388a7ec98e899fd54c924e50ba6693874aa65ef9cb53de7f7de9d64a", + "sha256:6da7cd4f405fd7db56e51e96bff0865b9853ae70df0e6720624049da76bde2da", + "sha256:7488a43033c958637b1a08cddc9188eb06d3ad36582cebc7d4815980b47e27ef", + "sha256:74e748012f8c19b47f7d6321ac929a9a94ee92ef12bc4298c47e8b7219b26541", + "sha256:78718d8454a6e928470d511bf8ac93f469283a45c354995f7d19e77292f26108", + "sha256:7bf61bc4345c1895221357af8f3e89f8c103d93156ef326532d35c707e2fb19d", + "sha256:7da298e1659e45d151b4028ad5c7974917e108afb48731f4ed785d02b6818994", + "sha256:84ef591495ffd3f9dcabffd6391db7bb70d7230b5c35ef5148354a134f56f2be", + "sha256:85b14a4689d5cff426c12eefe750738648706ea2753b20c2f973b2a000d3d261", + "sha256:8a2e76efbf8772add72d002d67a4c3d0958638696f541734304c7f28217a9cab", + "sha256:8a78d6c9168f5bcb20971bf3329c2b83078611fbe1f807baadc64afc70523b3a", + "sha256:8cb26f51c82d77483cdcd2b4a53cda55bbee29b3c2f3ddeb47182a2a9064e4eb", + "sha256:8db5dc617cb937ae17ff3403c3a70a7de9df4852a046f93e71edaec678f721d0", + "sha256:9ab542c91f5a47aaa58abdd8ea84b498e8e49fe4b883d67800017757a3eb78e8", + "sha256:9da022c14baeec36edfcc8daf0e281e2f55b950249a455776f0d1adeeada4734", + "sha256:9f4b481b6cc3a897adb4279216695150bbe7a44c03daba3c894f49d2037e0a24", + "sha256:a52a4704811e2623b0324a18d41ad4b9fabf43ce5ff99b14e40a520e2190c851", + "sha256:a55da151d0b0c6ab176b4e761670ac0e2667817a1e0dadd04a01d0561a219349", + "sha256:a674c0948789e9136d69065cc28009c1b1874c6ea340253db58be7622ce6398f", + "sha256:ae74f7c762270196d2dda56f8dd7309411f08a4084ff2dfcc0b095a218df2e06", + "sha256:afd27d8629ae94c5d863e32ab0e1d5590371d296b87dae0a751fb22bf3685741", + "sha256:b2d71cdefda9424adff9a3607ba5bbfc60ee972d73c21c7e3c19e71037574816", + "sha256:b34339898bb556a2351a1830f88f751679f343eabf9cf05841c95b165152c9e7", + "sha256:b372d10d17a701b0945f67be58fae4664fd056b85e0ff0fbc1e6c951cdbc0512", + "sha256:b3c98d5b24c6095e89e03d65d5c574705be3d49c0d8ca10c17a8a4b5201b72f5", + "sha256:b8dd6dd0e9c1992613ccda2bcb74fc9d49159dbe0f0ca4753f37527749885c25", + "sha256:bd5913b4972681ffc9718bc2d4c53cde39ef81415e1671ff93e9aa30b46595e7", + "sha256:c0b5fa5eda84057a4f1bbb4bb77a8c28ff20ae7ce211588d698ae453e13c6281", + "sha256:c16304bba98f48a28ae10e32a8e75c349dd742c45156f297e16eeb1ba9287a1f", + "sha256:c24b8efd9c0f62bad0439283c2c795ef916c5a6b75f03c17799775c7ae3c0c9e", + "sha256:c2a5e8d207311a0170aca0eb6b160af91adc29ec121832e4ac151a57743a1e1e", + "sha256:c352fc8f36f7e9727db17adbf93f82499457b3d7e5511368569b4c5bd155a922", + "sha256:c86df1c9af35d903d2b52d22ea3e66db8058d21dc0f59842ca5deb0595921141", + "sha256:c907516d49f77f6cd8ead1322198bdfd902003c3c330c77a1c5f3cc32a0e4d16", + "sha256:ca50bd612438258a91b5b3788c6621c1f05c8c478e7951899f492be42defc0da", + "sha256:d18a25b19ca7307045581b18b3ec9ead2b1db5ccd8719c291f0cd0a5cec6cb81", + "sha256:d4f0c66df4386b75d2ab1e20a489f30dc7fd9a06a896d64980541506086be1f1", + "sha256:d6e200909a119626744dd81bae409fc44134389e03fbf1d68ed2a55a2fb10991", + "sha256:d7ae472f74afcc47320238b5dbfd363aba111a525943c8a34a1b657c6be934c3", + "sha256:db0efd6bae1c4730b9c863fc4f5f3c0fa3e8f05cae2c44ae141cb9dfc7d091dc", + "sha256:dbdd7679a6f4f08152818043dbb39491d1af3332128b3752c3ec5cebc0011a72", + "sha256:e0b1520ef900e9ef62e392dd3d7ae4f5fa224d1dd62897a792cf353eb20b6cae", + "sha256:e2030956cf4886b10be9a0285c6802e078ec2391e1dd7ff3eb509c2c95a69b76", + "sha256:e35e8aaaf3981489f42884b59726693de32dabfc438ac10ef4eb3409961fd402", + "sha256:e380e85b93f148ad28ac15f8117e2fd8e5437aa7732d65e260134f83ce67911b", + "sha256:edf6e4c8fe14dfe316939711e3ece3f9a20760aabf686051b537a7562f4da91a", + "sha256:f3389924581d9a770c6caa4df4e74b606180869043b9073e2cec324bad6e306e", + "sha256:f64ccf593916e93b8d36ed55401bb7fe9c7d5de3180ce2e10b08f82a8f397316", + "sha256:f720a14aa102a38907c6d5030e3d66b3b680c3e6f6bc95473931ea3c00c59967", + "sha256:f8d19565ae3eb956d84da3ef367aa7def14a2735d05bd275cd54c0301f0d0d6c", + "sha256:f97487996a39cb18278ca33f7be98198f278d0bc3c5d0fd4d7b3d63646ca3c8a" ], - "markers": "python_version >= '3.6'", - "version": "==5.3.0" + "markers": "python_version >= '3.8'", + "version": "==6.0.0" }, "markdownify": { "hashes": [ - "sha256:4c46a6c0c12c6005ddcd49b45a5a890398b002ef51380cd319db62df5e09bc2a", - "sha256:a62a7a216947ed0b8dafb95b99b2ef4a0edd1e18d5653c656f68f03db2bfb2f1" + "sha256:32a5a08e9af02c8a6528942224c91b933b4bd2c7d078f9012943776fc313eeef", + "sha256:449c0bbbf1401c5112379619524f33b63490a8fa479456d41de9dc9e37560ebd" ], "index": "pypi", - "version": "==0.14.1" + "version": "==1.1.0" }, "marshmallow": { "hashes": [ - "sha256:ec5d00d873ce473b7f2ffcb7104286a376c354cab0c2fa12f5573dab03e87210", - "sha256:f4debda3bb11153d81ac34b0d582bf23053055ee11e791b54b4b35493468040a" - ], - "markers": "python_version >= '3.9'", - "version": "==3.25.1" - }, - "msgpack": { - "hashes": [ - "sha256:06f5fd2f6bb2a7914922d935d3b8bb4a7fff3a9a91cfce6d06c13bc42bec975b", - "sha256:071603e2f0771c45ad9bc65719291c568d4edf120b44eb36324dcb02a13bfddf", - "sha256:0907e1a7119b337971a689153665764adc34e89175f9a34793307d9def08e6ca", - "sha256:0f92a83b84e7c0749e3f12821949d79485971f087604178026085f60ce109330", - "sha256:115a7af8ee9e8cddc10f87636767857e7e3717b7a2e97379dc2054712693e90f", - "sha256:13599f8829cfbe0158f6456374e9eea9f44eee08076291771d8ae93eda56607f", - "sha256:17fb65dd0bec285907f68b15734a993ad3fc94332b5bb21b0435846228de1f39", - "sha256:2137773500afa5494a61b1208619e3871f75f27b03bcfca7b3a7023284140247", - "sha256:3180065ec2abbe13a4ad37688b61b99d7f9e012a535b930e0e683ad6bc30155b", - "sha256:398b713459fea610861c8a7b62a6fec1882759f308ae0795b5413ff6a160cf3c", - "sha256:3d364a55082fb2a7416f6c63ae383fbd903adb5a6cf78c5b96cc6316dc1cedc7", - "sha256:3df7e6b05571b3814361e8464f9304c42d2196808e0119f55d0d3e62cd5ea044", - "sha256:41c991beebf175faf352fb940bf2af9ad1fb77fd25f38d9142053914947cdbf6", - "sha256:42f754515e0f683f9c79210a5d1cad631ec3d06cea5172214d2176a42e67e19b", - "sha256:452aff037287acb1d70a804ffd022b21fa2bb7c46bee884dbc864cc9024128a0", - "sha256:4676e5be1b472909b2ee6356ff425ebedf5142427842aa06b4dfd5117d1ca8a2", - "sha256:46c34e99110762a76e3911fc923222472c9d681f1094096ac4102c18319e6468", - "sha256:471e27a5787a2e3f974ba023f9e265a8c7cfd373632247deb225617e3100a3c7", - "sha256:4a1964df7b81285d00a84da4e70cb1383f2e665e0f1f2a7027e683956d04b734", - "sha256:4b51405e36e075193bc051315dbf29168d6141ae2500ba8cd80a522964e31434", - "sha256:4d1b7ff2d6146e16e8bd665ac726a89c74163ef8cd39fa8c1087d4e52d3a2325", - "sha256:53258eeb7a80fc46f62fd59c876957a2d0e15e6449a9e71842b6d24419d88ca1", - "sha256:534480ee5690ab3cbed89d4c8971a5c631b69a8c0883ecfea96c19118510c846", - "sha256:58638690ebd0a06427c5fe1a227bb6b8b9fdc2bd07701bec13c2335c82131a88", - "sha256:58dfc47f8b102da61e8949708b3eafc3504509a5728f8b4ddef84bd9e16ad420", - "sha256:59caf6a4ed0d164055ccff8fe31eddc0ebc07cf7326a2aaa0dbf7a4001cd823e", - "sha256:5dbad74103df937e1325cc4bfeaf57713be0b4f15e1c2da43ccdd836393e2ea2", - "sha256:5e1da8f11a3dd397f0a32c76165cf0c4eb95b31013a94f6ecc0b280c05c91b59", - "sha256:646afc8102935a388ffc3914b336d22d1c2d6209c773f3eb5dd4d6d3b6f8c1cb", - "sha256:64fc9068d701233effd61b19efb1485587560b66fe57b3e50d29c5d78e7fef68", - "sha256:65553c9b6da8166e819a6aa90ad15288599b340f91d18f60b2061f402b9a4915", - "sha256:685ec345eefc757a7c8af44a3032734a739f8c45d1b0ac45efc5d8977aa4720f", - "sha256:6ad622bf7756d5a497d5b6836e7fc3752e2dd6f4c648e24b1803f6048596f701", - "sha256:73322a6cc57fcee3c0c57c4463d828e9428275fb85a27aa2aa1a92fdc42afd7b", - "sha256:74bed8f63f8f14d75eec75cf3d04ad581da6b914001b474a5d3cd3372c8cc27d", - "sha256:79ec007767b9b56860e0372085f8504db5d06bd6a327a335449508bbee9648fa", - "sha256:7a946a8992941fea80ed4beae6bff74ffd7ee129a90b4dd5cf9c476a30e9708d", - "sha256:7ad442d527a7e358a469faf43fda45aaf4ac3249c8310a82f0ccff9164e5dccd", - "sha256:7c9a35ce2c2573bada929e0b7b3576de647b0defbd25f5139dcdaba0ae35a4cc", - "sha256:7e7b853bbc44fb03fbdba34feb4bd414322180135e2cb5164f20ce1c9795ee48", - "sha256:879a7b7b0ad82481c52d3c7eb99bf6f0645dbdec5134a4bddbd16f3506947feb", - "sha256:8a706d1e74dd3dea05cb54580d9bd8b2880e9264856ce5068027eed09680aa74", - "sha256:8a84efb768fb968381e525eeeb3d92857e4985aacc39f3c47ffd00eb4509315b", - "sha256:8cf9e8c3a2153934a23ac160cc4cba0ec035f6867c8013cc6077a79823370346", - "sha256:8da4bf6d54ceed70e8861f833f83ce0814a2b72102e890cbdfe4b34764cdd66e", - "sha256:8e59bca908d9ca0de3dc8684f21ebf9a690fe47b6be93236eb40b99af28b6ea6", - "sha256:914571a2a5b4e7606997e169f64ce53a8b1e06f2cf2c3a7273aa106236d43dd5", - "sha256:a51abd48c6d8ac89e0cfd4fe177c61481aca2d5e7ba42044fd218cfd8ea9899f", - "sha256:a52a1f3a5af7ba1c9ace055b659189f6c669cf3657095b50f9602af3a3ba0fe5", - "sha256:ad33e8400e4ec17ba782f7b9cf868977d867ed784a1f5f2ab46e7ba53b6e1e1b", - "sha256:b4c01941fd2ff87c2a934ee6055bda4ed353a7846b8d4f341c428109e9fcde8c", - "sha256:bce7d9e614a04d0883af0b3d4d501171fbfca038f12c77fa838d9f198147a23f", - "sha256:c40ffa9a15d74e05ba1fe2681ea33b9caffd886675412612d93ab17b58ea2fec", - "sha256:c5a91481a3cc573ac8c0d9aace09345d989dc4a0202b7fcb312c88c26d4e71a8", - "sha256:c921af52214dcbb75e6bdf6a661b23c3e6417f00c603dd2070bccb5c3ef499f5", - "sha256:d46cf9e3705ea9485687aa4001a76e44748b609d260af21c4ceea7f2212a501d", - "sha256:d8ce0b22b890be5d252de90d0e0d119f363012027cf256185fc3d474c44b1b9e", - "sha256:dd432ccc2c72b914e4cb77afce64aab761c1137cc698be3984eee260bcb2896e", - "sha256:e0856a2b7e8dcb874be44fea031d22e5b3a19121be92a1e098f46068a11b0870", - "sha256:e1f3c3d21f7cf67bcf2da8e494d30a75e4cf60041d98b3f79875afb5b96f3a3f", - "sha256:f1ba6136e650898082d9d5a5217d5906d1e138024f836ff48691784bbe1adf96", - "sha256:f3e9b4936df53b970513eac1758f3882c88658a220b58dcc1e39606dccaaf01c", - "sha256:f80bc7d47f76089633763f952e67f8214cb7b3ee6bfa489b3cb6a84cfac114cd", - "sha256:fd2906780f25c8ed5d7b323379f6138524ba793428db5d0e9d226d3fa6aa1788" + "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", + "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6" ], - "markers": "python_version >= '3.8'", - "version": "==1.1.0" + "markers": "python_version >= '3.9'", + "version": "==3.26.1" + }, + "mcp": { + "hashes": [ + "sha256:5483345bf39033b858920a5b6348a303acacf45b23936972160ff152107b850e", + "sha256:ab2e05f5e5c13e1dc90a4a9ef23ac500a6121362a564447855ef0ab643a99fed" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==1.12.3" }, "multidict": { "hashes": [ - "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", - "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056", - "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", - "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", - "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", - "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", - "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748", - "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", - "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f", - "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", - "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6", - "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada", - "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", - "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2", - "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d", - "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", - "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef", - "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", - "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", - "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60", - "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6", - "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", - "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478", - "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", - "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7", - "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56", - "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", - "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", - "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30", - "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", - "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", - "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0", - "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", - "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c", - "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", - "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", - "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", - "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", - "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", - "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2", - "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", - "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", - "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", - "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", - "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657", - "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581", - "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492", - "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43", - "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", - "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", - "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", - "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057", - "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc", - "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", - "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255", - "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1", - "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972", - "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53", - "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1", - "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", - "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a", - "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160", - "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c", - "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd", - "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", - "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5", - "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", - "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", - "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", - "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", - "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4", - "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", - "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", - "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28", - "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d", - "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a", - "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", - "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", - "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429", - "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", - "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", - "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", - "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392", - "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167", - "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c", - "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", - "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", - "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76", - "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875", - "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd", - "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", - "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db" + "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134", + "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17", + "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6", + "sha256:05db2f66c9addb10cfa226e1acb363450fab2ff8a6df73c622fefe2f5af6d4e7", + "sha256:0b9e59946b49dafaf990fd9c17ceafa62976e8471a14952163d10a7a630413a9", + "sha256:0db58da8eafb514db832a1b44f8fa7906fdd102f7d982025f816a93ba45e3dcb", + "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b", + "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55", + "sha256:12f4581d2930840295c461764b9a65732ec01250b46c6b2c510d7ee68872b140", + "sha256:1328201ee930f069961ae707d59c6627ac92e351ed5b92397cf534d1336ce557", + "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e", + "sha256:14117a41c8fdb3ee19c743b1c027da0736fdb79584d61a766da53d399b71176c", + "sha256:15332783596f227db50fb261c2c251a58ac3873c457f3a550a95d5c0aa3c770d", + "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65", + "sha256:18f4eba0cbac3546b8ae31e0bbc55b02c801ae3cbaf80c247fcdd89b456ff58c", + "sha256:1bf99b4daf908c73856bd87ee0a2499c3c9a3d19bb04b9c6025e66af3fd07462", + "sha256:1c8082e5814b662de8589d6a06c17e77940d5539080cbab9fe6794b5241b76d9", + "sha256:208b9b9757060b9faa6f11ab4bc52846e4f3c2fb8b14d5680c8aac80af3dc751", + "sha256:20c5a0c3c13a15fd5ea86c42311859f970070e4e24de5a550e99d7c271d76318", + "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b", + "sha256:233ad16999afc2bbd3e534ad8dbe685ef8ee49a37dbc2cdc9514e57b6d589ced", + "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f", + "sha256:295adc9c0551e5d5214b45cf29ca23dbc28c2d197a9c30d51aed9e037cb7c578", + "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc", + "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75", + "sha256:35712f1748d409e0707b165bf49f9f17f9e28ae85470c41615778f8d4f7d9609", + "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c", + "sha256:37b09ca60998e87734699e88c2363abfd457ed18cfbf88e4009a4e83788e63ed", + "sha256:3893a0d7d28a7fe6ca7a1f760593bc13038d1d35daf52199d431b61d2660602b", + "sha256:41bb9d1d4c303886e2d85bade86e59885112a7f4277af5ad47ab919a2251f306", + "sha256:42ca5aa9329a63be8dc49040f63817d1ac980e02eeddba763a9ae5b4027b9c9c", + "sha256:43571f785b86afd02b3855c5ac8e86ec921b760298d6f82ff2a61daf5a35330b", + "sha256:448e4a9afccbf297577f2eaa586f07067441e7b63c8362a3540ba5a38dc0f14a", + "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7", + "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3", + "sha256:531e331a2ee53543ab32b16334e2deb26f4e6b9b28e41f8e0c87e99a6c8e2d69", + "sha256:53becb01dd8ebd19d1724bebe369cfa87e4e7f29abbbe5c14c98ce4c383e16cd", + "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55", + "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10", + "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e", + "sha256:5bd8d6f793a787153956cd35e24f60485bf0651c238e207b9a54f7458b16d539", + "sha256:61af8a4b771f1d4d000b3168c12c3120ccf7284502a94aa58c68a81f5afac090", + "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e", + "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063", + "sha256:68e9e12ed00e2089725669bdc88602b0b6f8d23c0c95e52b95f0bc69f7fe9b55", + "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b", + "sha256:70b72e749a4f6e7ed8fb334fa8d8496384840319512746a5f42fa0aec79f4d61", + "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d", + "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680", + "sha256:72d8815f2cd3cf3df0f83cac3f3ef801d908b2d90409ae28102e0553af85545a", + "sha256:7394888236621f61dcdd25189b2768ae5cc280f041029a5bcf1122ac63df79f9", + "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5", + "sha256:766a4a5996f54361d8d5a9050140aa5362fe48ce51c755a50c0bc3706460c430", + "sha256:769841d70ca8bdd140a715746199fc6473414bd02efd678d75681d2d6a8986c5", + "sha256:775b464d31dac90f23192af9c291dc9f423101857e33e9ebf0020a10bfcf4144", + "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc", + "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65", + "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884", + "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2", + "sha256:877443eaaabcd0b74ff32ebeed6f6176c71850feb7d6a1d2db65945256ea535c", + "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", + "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961", + "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca", + "sha256:934796c81ea996e61914ba58064920d6cad5d99140ac3167901eb932150e2e56", + "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6", + "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b", + "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f", + "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6", + "sha256:9ed948328aec2072bc00f05d961ceadfd3e9bfc2966c1319aeaf7b7c21219183", + "sha256:9f5b28c074c76afc3e4c610c488e3493976fe0e596dd3db6c8ddfbb0134dcac5", + "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d", + "sha256:a2be5b7b35271f7fff1397204ba6708365e3d773579fe2a30625e16c4b4ce817", + "sha256:ab0a34a007704c625e25a9116c6770b4d3617a071c8a7c30cd338dfbadfe6485", + "sha256:acf6b97bd0884891af6a8b43d0f586ab2fcf8e717cbd47ab4bdddc09e20652d8", + "sha256:b1db4d2093d6b235de76932febf9d50766cf49a5692277b2c28a501c9637f616", + "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373", + "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888", + "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648", + "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1", + "sha256:bb933c891cd4da6bdcc9733d048e994e22e1883287ff7540c2a0f3b117605092", + "sha256:bc7f6fbc61b1c16050a389c630da0b32fc6d4a3d191394ab78972bf5edc568c2", + "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3", + "sha256:bf9bd1fd5eec01494e0f2e8e446a74a85d5e49afb63d75a9934e4a5423dba21d", + "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600", + "sha256:c8161b5a7778d3137ea2ee7ae8a08cce0010de3b00ac671c5ebddeaa17cefd22", + "sha256:cdf22e4db76d323bcdc733514bf732e9fb349707c98d341d40ebcc6e9318ef3d", + "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb", + "sha256:d04d01f0a913202205a598246cf77826fe3baa5a63e9f6ccf1ab0601cf56eca0", + "sha256:d25594d3b38a2e6cabfdcafef339f754ca6e81fbbdb6650ad773ea9775af35ab", + "sha256:d4e47d8faffaae822fb5cba20937c048d4f734f43572e7079298a6c39fb172cb", + "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8", + "sha256:dd7793bab517e706c9ed9d7310b06c8672fd0aeee5781bfad612f56b8e0f7d14", + "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643", + "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471", + "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0", + "sha256:e2db616467070d0533832d204c54eea6836a5e628f2cb1e6dfd8cd6ba7277cb7", + "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a", + "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d", + "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c", + "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f", + "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8", + "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9", + "sha256:e995a34c3d44ab511bfc11aa26869b9d66c2d8c799fa0e74b28a473a692532d6", + "sha256:ef43b5dd842382329e4797c46f10748d8c2b6e0614f46b4afe4aee9ac33159df", + "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b", + "sha256:f114d8478733ca7388e7c7e0ab34b72547476b97009d643644ac33d4d3fe1821", + "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37", + "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c", + "sha256:f54cb79d26d0cd420637d184af38f0668558f3c4bbe22ab7ad830e67249f2e0b", + "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1" ], - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.6.3" }, "mypy-extensions": { "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", + "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" + "markers": "python_version >= '3.8'", + "version": "==1.1.0" }, "numpy": { "hashes": [ - "sha256:059e6a747ae84fce488c3ee397cee7e5f905fd1bda5fb18c66bc41807ff119b2", - "sha256:08ef779aed40dbc52729d6ffe7dd51df85796a702afbf68a4f4e41fafdc8bda5", - "sha256:164a829b6aacf79ca47ba4814b130c4020b202522a93d7bff2202bfb33b61c60", - "sha256:26c9c4382b19fcfbbed3238a14abf7ff223890ea1936b8890f058e7ba35e8d71", - "sha256:27f5cdf9f493b35f7e41e8368e7d7b4bbafaf9660cba53fb21d2cd174ec09631", - "sha256:31b89fa67a8042e96715c68e071a1200c4e172f93b0fbe01a14c0ff3ff820fc8", - "sha256:32cb94448be47c500d2c7a95f93e2f21a01f1fd05dd2beea1ccd049bb6001cd2", - "sha256:360137f8fb1b753c5cde3ac388597ad680eccbbbb3865ab65efea062c4a1fd16", - "sha256:3683a8d166f2692664262fd4900f207791d005fb088d7fdb973cc8d663626faa", - "sha256:38efc1e56b73cc9b182fe55e56e63b044dd26a72128fd2fbd502f75555d92591", - "sha256:3d03883435a19794e41f147612a77a8f56d4e52822337844fff3d4040a142964", - "sha256:3ecc47cd7f6ea0336042be87d9e7da378e5c7e9b3c8ad0f7c966f714fc10d821", - "sha256:40f9e544c1c56ba8f1cf7686a8c9b5bb249e665d40d626a23899ba6d5d9e1484", - "sha256:4250888bcb96617e00bfa28ac24850a83c9f3a16db471eca2ee1f1714df0f957", - "sha256:4511d9e6071452b944207c8ce46ad2f897307910b402ea5fa975da32e0102800", - "sha256:45681fd7128c8ad1c379f0ca0776a8b0c6583d2f69889ddac01559dfe4390918", - "sha256:48fd472630715e1c1c89bf1feab55c29098cb403cc184b4859f9c86d4fcb6a95", - "sha256:4c86e2a209199ead7ee0af65e1d9992d1dce7e1f63c4b9a616500f93820658d0", - "sha256:4dfda918a13cc4f81e9118dea249e192ab167a0bb1966272d5503e39234d694e", - "sha256:5062dc1a4e32a10dc2b8b13cedd58988261416e811c1dc4dbdea4f57eea61b0d", - "sha256:51faf345324db860b515d3f364eaa93d0e0551a88d6218a7d61286554d190d73", - "sha256:526fc406ab991a340744aad7e25251dd47a6720a685fa3331e5c59fef5282a59", - "sha256:53c09385ff0b72ba79d8715683c1168c12e0b6e84fb0372e97553d1ea91efe51", - "sha256:55ba24ebe208344aa7a00e4482f65742969a039c2acfcb910bc6fcd776eb4355", - "sha256:5b6c390bfaef8c45a260554888966618328d30e72173697e5cabe6b285fb2348", - "sha256:5c5cc0cbabe9452038ed984d05ac87910f89370b9242371bd9079cb4af61811e", - "sha256:5edb4e4caf751c1518e6a26a83501fda79bff41cc59dac48d70e6d65d4ec4440", - "sha256:61048b4a49b1c93fe13426e04e04fdf5a03f456616f6e98c7576144677598675", - "sha256:676f4eebf6b2d430300f1f4f4c2461685f8269f94c89698d832cdf9277f30b84", - "sha256:67d4cda6fa6ffa073b08c8372aa5fa767ceb10c9a0587c707505a6d426f4e046", - "sha256:694f9e921a0c8f252980e85bce61ebbd07ed2b7d4fa72d0e4246f2f8aa6642ab", - "sha256:733585f9f4b62e9b3528dd1070ec4f52b8acf64215b60a845fa13ebd73cd0712", - "sha256:7671dc19c7019103ca44e8d94917eba8534c76133523ca8406822efdd19c9308", - "sha256:780077d95eafc2ccc3ced969db22377b3864e5b9a0ea5eb347cc93b3ea900315", - "sha256:7ba9cc93a91d86365a5d270dee221fdc04fb68d7478e6bf6af650de78a8339e3", - "sha256:89b16a18e7bba224ce5114db863e7029803c179979e1af6ad6a6b11f70545008", - "sha256:9036d6365d13b6cbe8f27a0eaf73ddcc070cae584e5ff94bb45e3e9d729feab5", - "sha256:93cf4e045bae74c90ca833cba583c14b62cb4ba2cba0abd2b141ab52548247e2", - "sha256:9ad014faa93dbb52c80d8f4d3dcf855865c876c9660cb9bd7553843dd03a4b1e", - "sha256:9b1d07b53b78bf84a96898c1bc139ad7f10fda7423f5fd158fd0f47ec5e01ac7", - "sha256:a7746f235c47abc72b102d3bce9977714c2444bdfaea7888d241b4c4bb6a78bf", - "sha256:aa3017c40d513ccac9621a2364f939d39e550c542eb2a894b4c8da92b38896ab", - "sha256:b34d87e8a3090ea626003f87f9392b3929a7bbf4104a05b6667348b6bd4bf1cd", - "sha256:b541032178a718c165a49638d28272b771053f628382d5e9d1c93df23ff58dbf", - "sha256:ba5511d8f31c033a5fcbda22dd5c813630af98c70b2661f2d2c654ae3cdfcfc8", - "sha256:bc8a37ad5b22c08e2dbd27df2b3ef7e5c0864235805b1e718a235bcb200cf1cb", - "sha256:bff7d8ec20f5f42607599f9994770fa65d76edca264a87b5e4ea5629bce12268", - "sha256:c1ad395cf254c4fbb5b2132fee391f361a6e8c1adbd28f2cd8e79308a615fe9d", - "sha256:f1d09e520217618e76396377c81fba6f290d5f926f50c35f3a5f72b01a0da780", - "sha256:f3eac17d9ec51be534685ba877b6ab5edc3ab7ec95c8f163e5d7b39859524716", - "sha256:f419290bc8968a46c4933158c91a0012b7a99bb2e465d5ef5293879742f8797e", - "sha256:f62aa6ee4eb43b024b0e5a01cf65a0bb078ef8c395e8713c6e8a12a697144528", - "sha256:f74e6fdeb9a265624ec3a3918430205dff1df7e95a230779746a6af78bc615af", - "sha256:f9b57eaa3b0cd8db52049ed0330747b0364e899e8a606a624813452b8203d5f7", - "sha256:fce4f615f8ca31b2e61aa0eb5865a21e14f5629515c9151850aa936c02a1ee51" - ], - "markers": "python_version >= '3.10'", - "version": "==2.2.1" + "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", + "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", + "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", + "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", + "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", + "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", + "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", + "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", + "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", + "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", + "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", + "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", + "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", + "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", + "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", + "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", + "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", + "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", + "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", + "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", + "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", + "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", + "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", + "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", + "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", + "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", + "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", + "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", + "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", + "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", + "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", + "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", + "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", + "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", + "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", + "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", + "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", + "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", + "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", + "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", + "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", + "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", + "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", + "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", + "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", + "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", + "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", + "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", + "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", + "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", + "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", + "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", + "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", + "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", + "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", + "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", + "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", + "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", + "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", + "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", + "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", + "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", + "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", + "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", + "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", + "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", + "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", + "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", + "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", + "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", + "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", + "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", + "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", + "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5" + ], + "markers": "python_version >= '3.11'", + "version": "==2.3.2" }, "openai": { "hashes": [ - "sha256:043603def78c00befb857df9f0a16ee76a3af5984ba40cb7ee5e2f40db4646bf", - "sha256:cfa806556226fa96df7380ab2e29814181d56fea44738c2b0e581b462c268692" + "sha256:3ee0fcc50ae95267fd22bd1ad095ba5402098f3df2162592e68109999f685427", + "sha256:b99b794ef92196829120e2df37647722104772d2a74d08305df9ced5f26eae34" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.59.7" + "version": "==1.98.0" }, "opentelemetry-api": { "hashes": [ - "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8", - "sha256:d04a6cf78aad09614f52964ecb38021e248f5714dc32c2e0d8fd99517b4d69cf" + "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c", + "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0" ], - "markers": "python_version >= '3.8'", - "version": "==1.29.0" + "markers": "python_version >= '3.9'", + "version": "==1.36.0" }, "orderedmultidict": { "hashes": [ @@ -1408,84 +1522,139 @@ }, "orjson": { "hashes": [ - "sha256:0293a88815e9bb5c90af4045f81ed364d982f955d12052d989d844d6c4e50945", - "sha256:03f61ca3674555adcb1aa717b9fc87ae936aa7a63f6aba90a474a88701278780", - "sha256:06d4ec218b1ec1467d8d64da4e123b4794c781b536203c309ca0f52819a16c03", - "sha256:07520685d408a2aba514c17ccc16199ff2934f9f9e28501e676c557f454a37fe", - "sha256:0905ca08a10f7e0e0c97d11359609300eb1437490a7f32bbaa349de757e2e0c7", - "sha256:0de4d6315cfdbd9ec803b945c23b3a68207fd47cbe43626036d97e8e9561a436", - "sha256:164ac155109226b3a2606ee6dda899ccfbe6e7e18b5bdc3fbc00f79cc074157d", - "sha256:16642f10c1ca5611251bd835de9914a4b03095e28a34c8ba6a5500b5074338bd", - "sha256:175abf3d20e737fec47261d278f95031736a49d7832a09ab684026528c4d96db", - "sha256:175cafd322e458603e8ce73510a068d16b6e6f389c13f69bf16de0e843d7d406", - "sha256:1b49e2af011c84c3f2d541bb5cd1e3c7c2df672223e7e3ea608f09cf295e5f8a", - "sha256:21d3be4132f71ef1360385770474f29ea1538a242eef72ac4934fe142800e37f", - "sha256:26336c0d4b2d44636e1e1e6ed1002f03c6aae4a8a9329561c8883f135e9ff010", - "sha256:29ca1a93e035d570e8b791b6c0feddd403c6a5388bfe870bf2aa6bba1b9d9b8e", - "sha256:2ad4b7e367efba6dc3f119c9a0fcd41908b7ec0399a696f3cdea7ec477441b09", - "sha256:33449c67195969b1a677533dee9d76e006001213a24501333624623e13c7cc8e", - "sha256:36f5bfc0399cd4811bf10ec7a759c7ab0cd18080956af8ee138097d5b5296a95", - "sha256:3871bad546aa66c155e3f36f99c459780c2a392d502a64e23fb96d9abf338511", - "sha256:397083806abd51cf2b3bbbf6c347575374d160331a2d33c5823e22249ad3118b", - "sha256:3af8e42ae4363773658b8d578d56dedffb4f05ceeb4d1d4dd3fb504950b45526", - "sha256:4ddc8c866d7467f5ee2991397d2ea94bcf60d0048bdd8ca555740b56f9042725", - "sha256:4f5007abfdbb1d866e2aa8990bd1c465f0f6da71d19e695fc278282be12cffa5", - "sha256:56ee546c2bbe9599aba78169f99d1dc33301853e897dbaf642d654248280dc6e", - "sha256:6169d3868b190d6b21adc8e61f64e3db30f50559dfbdef34a1cd6c738d409dfc", - "sha256:64410696c97a35af2432dea7bdc4ce32416458159430ef1b4beb79fd30093ad6", - "sha256:691ab9a13834310a263664313e4f747ceb93662d14a8bdf20eb97d27ed488f16", - "sha256:6b1225024cf0ef5d15934b5ffe9baf860fe8bc68a796513f5ea4f5056de30bca", - "sha256:6e2ec73b7099b6a29b40a62e08a23b936423bd35529f8f55c42e27acccde7954", - "sha256:76344269b550ea01488d19a2a369ab572c1ac4449a72e9f6ac0d70eb1cbfb953", - "sha256:7796692136a67b3e301ef9052bde6fe8e7bd5200da766811a3a608ffa62aaff0", - "sha256:7e947f70167fe18469f2023644e91ab3d24f9aed69a5e1c78e2c81b9cea553fb", - "sha256:8050a5d81c022561ee29cd2739de5b4445f3c72f39423fde80a63299c1892c52", - "sha256:83adda3db595cb1a7e2237029b3249c85afbe5c747d26b41b802e7482cb3933e", - "sha256:849ea7845a55f09965826e816cdc7689d6cf74fe9223d79d758c714af955bcb6", - "sha256:84dd83110503bc10e94322bf3ffab8bc49150176b49b4984dc1cce4c0a993bf9", - "sha256:868943660fb2a1e6b6b965b74430c16a79320b665b28dd4511d15ad5038d37d5", - "sha256:8cc8204f0b75606869c707da331058ddf085de29558b516fc43c73ee5ee2aadb", - "sha256:901e826cb2f1bdc1fcef3ef59adf0c451e8f7c0b5deb26c1a933fb66fb505eae", - "sha256:90937664e776ad316d64251e2fa2ad69265e4443067668e4727074fe39676414", - "sha256:92d13292249f9f2a3e418cbc307a9fbbef043c65f4bd8ba1eb620bc2aaba3d15", - "sha256:962c2ec0dcaf22b76dee9831fdf0c4a33d4bf9a257a2bc5d4adc00d5c8ad9034", - "sha256:96a1c0ee30fb113b3ae3c748fd75ca74a157ff4c58476c47db4d61518962a011", - "sha256:998019ef74a4997a9d741b1473533cdb8faa31373afc9849b35129b4b8ec048d", - "sha256:9a0fba3b8a587a54c18585f077dcab6dd251c170d85cfa4d063d5746cd595a0f", - "sha256:9d034abdd36f0f0f2240f91492684e5043d46f290525d1117712d5b8137784eb", - "sha256:9d3f9ed72e7458ded9a1fb1b4d4ed4c4fdbaf82030ce3f9274b4dc1bff7ace2b", - "sha256:9ed3d26c4cb4f6babaf791aa46a029265850e80ec2a566581f5c2ee1a14df4f1", - "sha256:9f1d2942605c894162252d6259b0121bf1cb493071a1ea8cb35d79cb3e6ac5bc", - "sha256:a2d1679df9f9cd9504f8dff24555c1eaabba8aad7f5914f28dab99e3c2552c9d", - "sha256:b11ed82054fce82fb74cea33247d825d05ad6a4015ecfc02af5fbce442fbf361", - "sha256:b49a28e30d3eca86db3fe6f9b7f4152fcacbb4a467953cd1b42b94b479b77956", - "sha256:b5947b139dfa33f72eecc63f17e45230a97e741942955a6c9e650069305eb73d", - "sha256:c28ed60597c149a9e3f5ad6dd9cebaee6fb2f0e3f2d159a4a2b9b862d4748860", - "sha256:c6dfbaeb7afa77ca608a50e2770a0461177b63a99520d4928e27591b142c74b1", - "sha256:c7f189bbfcded40e41a6969c1068ba305850ba016665be71a217918931416fbf", - "sha256:ca041ad20291a65d853a9523744eebc3f5a4b2f7634e99f8fe88320695ddf766", - "sha256:cde6d76910d3179dae70f164466692f4ea36da124d6fb1a61399ca589e81d69a", - "sha256:cf31f6f071a6b8e7aa1ead1fa27b935b48d00fbfa6a28ce856cfff2d5dd68eed", - "sha256:d313a2998b74bb26e9e371851a173a9b9474764916f1fc7971095699b3c6e964", - "sha256:d5075c54edf1d6ad81d4c6523ce54a748ba1208b542e54b97d8a882ecd810fd1", - "sha256:d6546e8073dc382e60fcae4a001a5a1bc46da5eab4a4878acc2d12072d6166d5", - "sha256:deaa2899dff7f03ab667e2ec25842d233e2a6a9e333efa484dfe666403f3501c", - "sha256:e2979d0f2959990620f7e62da6cd954e4620ee815539bc57a8ae46e2dacf90e3", - "sha256:e2bc525e335a8545c4e48f84dd0328bc46158c9aaeb8a1c2276546e94540ea3d", - "sha256:e4c9f60f9fb0b5be66e416dcd8c9d94c3eabff3801d875bdb1f8ffc12cf86905", - "sha256:e70a1d62b8288677d48f3bea66c21586a5f999c64ecd3878edb7393e8d1b548d", - "sha256:eca04dfd792cedad53dc9a917da1a522486255360cb4e77619343a20d9f35364", - "sha256:eee4bc767f348fba485ed9dc576ca58b0a9eac237f0e160f7a59bce628ed06b3", - "sha256:efe5fd254cfb0eeee13b8ef7ecb20f5d5a56ddda8a587f3852ab2cedfefdb5f6", - "sha256:f1c3ea52642c9714dc6e56de8a451a066f6d2707d273e07fe8a9cc1ba073813d", - "sha256:f496286fc85e93ce0f71cc84fc1c42de2decf1bf494094e188e27a53694777a7", - "sha256:f506fd666dd1ecd15a832bebc66c4df45c1902fd47526292836c339f7ba665a9", - "sha256:f77202c80e8ab5a1d1e9faf642343bee5aaf332061e1ada4e9147dbd9eb00c46", - "sha256:fa18f949d3183a8d468367056be989666ac2bef3a72eece0bade9cdb733b3c28", - "sha256:fa45e489ef80f28ff0e5ba0a72812b8cfc7c1ef8b46a694723807d1b07c89ebb" + "sha256:0085ef83a4141c2ed23bfec5fecbfdb1e95dd42fc8e8c76057bdeeec1608ea65", + "sha256:06ef26e009304bda4df42e4afe518994cde6f89b4b04c0ff24021064f83f4fbb", + "sha256:08c6a762fca63ca4dc04f66c48ea5d2428db55839fec996890e1bfaf057b658c", + "sha256:0baad413c498fc1eef568504f11ea46bc71f94b845c075e437da1e2b85b4fb86", + "sha256:0c1e394e67ced6bb16fea7054d99fbdd99a539cf4d446d40378d4c06e0a8548d", + "sha256:0eacdfeefd0a79987926476eb16e0245546bedeb8febbbbcf4b653e79257a8e4", + "sha256:0ed07faf9e4873518c60480325dcbc16d17c59a165532cccfb409b4cdbaeff24", + "sha256:0ed0fce2307843b79a0c83de49f65b86197f1e2310de07af9db2a1a77a61ce4c", + "sha256:10506cebe908542c4f024861102673db534fd2e03eb9b95b30d94438fa220abf", + "sha256:1495692f1f1ba2467df429343388a0ed259382835922e124c0cfdd56b3d1f727", + "sha256:15e2a57ce3b57c1a36acffcc02e823afefceee0a532180c2568c62213c98e3ef", + "sha256:17040a83ecaa130474af05bbb59a13cfeb2157d76385556041f945da936b1afd", + "sha256:1a68f23f09e5626cc0867a96cf618f68b91acb4753d33a80bf16111fd7f9928c", + "sha256:200c3ad7ed8b5d31d49143265dfebd33420c4b61934ead16833b5cd2c3d241be", + "sha256:2092e1d3b33f64e129ff8271642afddc43763c81f2c30823b4a4a4a5f2ea5b55", + "sha256:20b0dca94ea4ebe4628330de50975b35817a3f52954c1efb6d5d0498a3bbe581", + "sha256:22cf17ae1dae3f9b5f37bfcdba002ed22c98bbdb70306e42dc18d8cc9b50399a", + "sha256:23196b826ebc85c43f8e27bee0ab33c5fb13a29ea47fb4fcd6ebb1e660eb0252", + "sha256:26b6c821abf1ae515fbb8e140a2406c9f9004f3e52acb780b3dee9bfffddbd84", + "sha256:2b7c8be96db3a977367250c6367793a3c5851a6ca4263f92f0b48d00702f9910", + "sha256:3091dad33ac9e67c0a550cfff8ad5be156e2614d6f5d2a9247df0627751a1495", + "sha256:33aada2e6b6bc9c540d396528b91e666cedb383740fee6e6a917f561b390ecb1", + "sha256:3d593a9e0bccf2c7401ae53625b519a7ad7aa555b1c82c0042b322762dc8af4e", + "sha256:45202ee3f5494644e064c41abd1320497fb92fd31fc73af708708af664ac3b56", + "sha256:4537b0e09f45d2b74cb69c7f39ca1e62c24c0488d6bf01cd24673c74cd9596bf", + "sha256:47e07528bb6ccbd6e32a55e330979048b59bfc5518b47c89bc7ab9e3de15174a", + "sha256:48d82770a5fd88778063604c566f9c7c71820270c9cc9338d25147cbf34afd96", + "sha256:4b4b4f8f0b1d3ef8dc73e55363a0ffe012a42f4e2f1a140bf559698dca39b3fa", + "sha256:4bda5426ebb02ceb806a7d7ec9ba9ee5e0c93fca62375151a7b1c00bc634d06b", + "sha256:4cddbe41ee04fddad35d75b9cf3e3736ad0b80588280766156b94783167777af", + "sha256:4dd34e7e2518de8d7834268846f8cab7204364f427c56fb2251e098da86f5092", + "sha256:5072488fcc5cbcda2ece966d248e43ea1d222e19dd4c56d3f82747777f24d864", + "sha256:507d6012fab05465d8bf21f5d7f4635ba4b6d60132874e349beff12fb51af7fe", + "sha256:53cfefe4af059e65aabe9683f76b9c88bf34b4341a77d329227c2424e0e59b0e", + "sha256:5a31e84782a18c30abd56774c0cfa7b9884589f4d37d9acabfa0504dad59bb9d", + "sha256:5b2dc7e88da4ca201c940f5e6127998d9e89aa64264292334dad62854bc7fc27", + "sha256:5caf7f13f2e1b4e137060aed892d4541d07dabc3f29e6d891e2383c7ed483440", + "sha256:5dbf06642f3db2966df504944cdd0eb68ca2717f0353bb20b20acd78109374a6", + "sha256:5fd44d69ddfdfb4e8d0d83f09d27a4db34930fba153fbf79f8d4ae8b47914e04", + "sha256:6162a1a757a1f1f4a94bc6ffac834a3602e04ad5db022dd8395a54ed9dd51c81", + "sha256:6334d2382aff975a61f6f4d1c3daf39368b887c7de08f7c16c58f485dcf7adb2", + "sha256:6723be919c07906781b9c63cc52dc7d2fb101336c99dd7e85d3531d73fb493f7", + "sha256:68e10fd804e44e36188b9952543e3fa22f5aa8394da1b5283ca2b423735c06e8", + "sha256:72e18088f567bd4a45db5e3196677d9ed1605e356e500c8e32dd6e303167a13d", + "sha256:77c0fe28ed659b62273995244ae2aa430e432c71f86e4573ab16caa2f2e3ca5e", + "sha256:78404206977c9f946613d3f916727c189d43193e708d760ea5d4b2087d6b0968", + "sha256:7b71ef394327b3d0b39f6ea7ade2ecda2731a56c6a7cbf0d6a7301203b92a89b", + "sha256:848be553ea35aa89bfefbed2e27c8a41244c862956ab8ba00dc0b27e84fd58de", + "sha256:912579642f5d7a4a84d93c5eed8daf0aa34e1f2d3f4dc6571a8e418703f5701e", + "sha256:92d771c492b64119456afb50f2dff3e03a2db8b5af0eba32c5932d306f970532", + "sha256:93d5abed5a6f9e1b6f9b5bf6ed4423c11932b5447c2f7281d3b64e0f26c6d064", + "sha256:9e217ce3bad76351e1eb29ebe5ca630326f45cd2141f62620107a229909501a3", + "sha256:9e26794fe3976810b2c01fda29bd9ac7c91a3c1284b29cc9a383989f7b614037", + "sha256:a3d0855b643f259ee0cb76fe3df4c04483354409a520a902b067c674842eb6b8", + "sha256:b1545083b0931f754c80fd2422a73d83bea7a6d1b6de104a5f2c8dd3d64c291e", + "sha256:b1e6415c5b5ff3a616a6dafad7b6ec303a9fc625e9313c8e1268fb1370a63dcb", + "sha256:b5861c5f7acff10599132854c70ab10abf72aebf7c627ae13575e5f20b1ab8fe", + "sha256:b8ac64caba1add2c04e9cd4782d4d0c4d6c554b7a3369bdec1eed7854c98db7b", + "sha256:ba49683b87bea3ae1489a88e766e767d4f423a669a61270b6d6a7ead1c33bd65", + "sha256:bb7c36d5d3570fcbb01d24fa447a21a7fe5a41141fd88e78f7994053cc4e28f4", + "sha256:be3d0653322abc9b68e5bcdaee6cfd58fcbe9973740ab222b87f4d687232ab1f", + "sha256:c4aa13ca959ba6b15c0a98d3d204b850f9dc36c08c9ce422ffb024eb30d6e058", + "sha256:c964c29711a4b1df52f8d9966f015402a6cf87753a406c1c4405c407dd66fd45", + "sha256:d346e2ae1ce17888f7040b65a5a4a0c9734cb20ffbd228728661e020b4c8b3a5", + "sha256:d6895d32032b6362540e6d0694b19130bb4f2ad04694002dce7d8af588ca5f77", + "sha256:d6d308dd578ae3658f62bb9eba54801533225823cd3248c902be1ebc79b5e014", + "sha256:d777c57c1f86855fe5492b973f1012be776e0398571f7cc3970e9a58ecf4dc17", + "sha256:db48f8e81072e26df6cdb0e9fff808c28597c6ac20a13d595756cf9ba1fed48a", + "sha256:dbee6b050062540ae404530cacec1bf25e56e8d87d8d9b610b935afeb6725cae", + "sha256:dddf4e78747fa7f2188273f84562017a3c4f0824485b78372513c1681ea7a894", + "sha256:df146f2a14116ce80f7da669785fcb411406d8e80136558b0ecda4c924b9ac55", + "sha256:e5adaf01b92e0402a9ac5c3ebe04effe2bbb115f0914a0a53d34ea239a746289", + "sha256:e7a840752c93d4eecd1378e9bb465c3703e127b58f675cd5c620f361b6cf57a4", + "sha256:e855c1e97208133ce88b3ef6663c9a82ddf1d09390cd0856a1638deee0390c3c", + "sha256:e9a5fd589951f02ec2fcb8d69339258bbf74b41b104c556e6d4420ea5e059313", + "sha256:f2d3364cfad43003f1e3d564a069c8866237cca30f9c914b26ed2740b596ed00", + "sha256:f3807cce72bf40a9d251d689cbec28d2efd27e0f6673709f948f971afd52cb09", + "sha256:f3cf6c07f8b32127d836be8e1c55d4f34843f7df346536da768e9f73f22078a1", + "sha256:f55e557d4248322d87c4673e085c7634039ff04b47bfc823b87149ae12bef60d", + "sha256:f58ae2bcd119226fe4aa934b5880fe57b8e97b69e51d5d91c88a89477a307016", + "sha256:f716bcc166524eddfcf9f13f8209ac19a7f27b05cf591e883419079d98c8c99d", + "sha256:f857b3d134b36a8436f1e24dcb525b6b945108b30746c1b0b556200b5cb76d39", + "sha256:fa3fe8653c9f57f0e16f008e43626485b6723b84b2f741f54d1258095b655912" ], - "markers": "python_version >= '3.8'", - "version": "==3.10.14" + "markers": "python_version >= '3.9'", + "version": "==3.11.1" + }, + "ormsgpack": { + "hashes": [ + "sha256:060f67fe927582f4f63a1260726d019204b72f460cf20930e6c925a1d129f373", + "sha256:106253ac9dc08520951e556b3c270220fcb8b4fef0d30b71eedac4befa4de749", + "sha256:10f6f3509c1b0e51b15552d314b1d409321718122e90653122ce4b997f01453a", + "sha256:137aab0d5cdb6df702da950a80405eb2b7038509585e32b4e16289604ac7cb84", + "sha256:144b5e88f1999433e54db9d637bae6fe21e935888be4e3ac3daecd8260bd454e", + "sha256:1957dcadbb16e6a981cd3f9caef9faf4c2df1125e2a1b702ee8236a55837ce07", + "sha256:2190b352509d012915921cca76267db136cd026ddee42f1b0d9624613cc7058c", + "sha256:21de648a1c7ef692bdd287fb08f047bd5371d7462504c0a7ae1553c39fee35e3", + "sha256:2f345f81e852035d80232e64374d3a104139d60f8f43c6c5eade35c4bac5590e", + "sha256:33afe143a7b61ad21bb60109a86bb4e87fec70ef35db76b89c65b17e32da7935", + "sha256:35cdff6a0d3ba04e40a751129763c3b9b57a602c02944138e4b760ec99ae80a1", + "sha256:35fa9f81e5b9a0dab42e09a73f7339ecffdb978d6dbf9deb2ecf1e9fc7808722", + "sha256:3a7d844ae9cbf2112c16086dd931b2acefce14cefd163c57db161170c2bfa22b", + "sha256:3b29412558c740bf6bac156727aa85ac67f9952cd6f071318f29ee72e1a76044", + "sha256:3e666cb63030538fa5cd74b1e40cb55b6fdb6e2981f024997a288bf138ebad07", + "sha256:4bb7df307e17b36cbf7959cd642c47a7f2046ae19408c564e437f0ec323a7775", + "sha256:4e159d50cd4064d7540e2bc6a0ab66eab70b0cc40c618b485324ee17037527c0", + "sha256:51c1edafd5c72b863b1f875ec31c529f09c872a5ff6fe473b9dfaf188ccc3227", + "sha256:534d18acb805c75e5fba09598bf40abe1851c853247e61dda0c01f772234da69", + "sha256:57c4601812684024132cbb32c17a7d4bb46ffc7daf2fddf5b697391c2c4f142a", + "sha256:599ccdabc19c618ef5de6e6f2e7f5d48c1f531a625fa6772313b8515bc710681", + "sha256:6933f350c2041ec189fe739f0ba7d6117c8772f5bc81f45b97697a84d03020dd", + "sha256:7f7a27efd67ef22d7182ec3b7fa7e9d147c3ad9be2a24656b23c989077e08b16", + "sha256:86fd9c1737eaba43d3bb2730add9c9e8b5fbed85282433705dd1b1e88ea7e6fb", + "sha256:8817ae439c671779e1127ee62f0ac67afdeaeeacb5f0db45703168aa74a2e4af", + "sha256:8a52c7ce7659459f3dc8dec9fd6a6c76f855a0a7e2b61f26090982ac10b95216", + "sha256:8d816d45175a878993b7372bd5408e0f3ec5a40f48e2d5b9d8f1cc5d31b61f1f", + "sha256:9a86de06d368fcc2e58b79dece527dc8ca831e0e8b9cec5d6e633d2777ec93d0", + "sha256:a90345ccb058de0f35262893751c603b6376b05f02be2b6f6b7e05d9dd6d5643", + "sha256:b796f64fdf823dedb1e35436a4a6f889cf78b1aa42d3097c66e5adfd8c3bd72d", + "sha256:bf46f57da9364bd5eefd92365c1b78797f56c6f780581eecd60cd7b367f9b4d3", + "sha256:c28249574934534c9bd5dce5485c52f21bcea0ee44d13ece3def6e3d2c3798b5", + "sha256:c780b44107a547a9e9327270f802fa4d6b0f6667c9c03c3338c0ce812259a0f7", + "sha256:da1de515a87e339e78a3ccf60e39f5fb740edac3e9e82d3c3d209e217a13ac08", + "sha256:ddfcb30d4b1be2439836249d675f297947f4fb8efcd3eeb6fd83021d773cadc4", + "sha256:e4d80585403d86d7f800cf3d0aafac1189b403941e84e90dd5102bb2b92bf9d5", + "sha256:e7058ef6092f995561bf9f71d6c9a4da867b6cc69d2e94cb80184f579a3ceed5", + "sha256:ee0944b6ccfd880beb1ca29f9442a774683c366f17f4207f8b81c5e24cadb453", + "sha256:eeb47c85f3a866e29279d801115b554af0fefc409e2ed8aa90aabfa77efe5cc6", + "sha256:efdb25cf6d54085f7ae557268d59fd2d956f1a09a340856e282d2960fe929f32", + "sha256:f23d45080846a7b90feabec0d330a9cc1863dc956728412e4f7986c80ab3a668" + ], + "markers": "python_version >= '3.9'", + "version": "==1.10.0" }, "packaging": { "hashes": [ @@ -1495,150 +1664,213 @@ "markers": "python_version >= '3.8'", "version": "==24.2" }, + "pandas": { + "hashes": [ + "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232", + "sha256:09e3b1587f0f3b0913e21e8b32c3119174551deb4a4eba4a89bc7377947977e7", + "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", + "sha256:0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0", + "sha256:1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1", + "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956", + "sha256:1d12f618d80379fde6af007f65f0c25bd3e40251dbd1636480dfffce2cf1e6da", + "sha256:22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9", + "sha256:2323294c73ed50f612f67e2bf3ae45aea04dce5690778e08a09391897f35ff88", + "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b", + "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9", + "sha256:2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83", + "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab", + "sha256:342e59589cc454aaff7484d75b816a433350b3d7964d7847327edda4d532a2e3", + "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d", + "sha256:3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1", + "sha256:4645f770f98d656f11c69e81aeb21c6fca076a44bed3dcbb9396a4311bc7f6d8", + "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299", + "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8", + "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", + "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3", + "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a", + "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb", + "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928", + "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4", + "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a", + "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22", + "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275", + "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678", + "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e", + "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8", + "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab", + "sha256:b4b0de34dc8499c2db34000ef8baad684cfa4cbd836ecee05f323ebfba348c7d", + "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679", + "sha256:cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191", + "sha256:dd71c47a911da120d72ef173aeac0bf5241423f9bfea57320110a978457e069e", + "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12", + "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85", + "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9", + "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96", + "sha256:fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97", + "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==2.3.1" + }, "primp": { "hashes": [ - "sha256:0128453cce81552f7aa6ac2bf9b8741b7816cdb2d10536e62c77daaf6483b9af", - "sha256:7a91a089bf2962b5b56c8d83d09535eb81cf55b53c09d83208b9e5a715cf2c17", - "sha256:7fe94c3164c2efffff08f7f54c018ac445112961b3ce4f4f499315ba0a9d1ef3", - "sha256:8e711cfa019fa9bdc0cba4d5d596f319c884a4329e505bd73e92eee0b024061a", - "sha256:93142590a5a1958240ee5b74faaf2f55185ed499ccaabc622d71cb0cc8a47a0b", - "sha256:a27c5d997c37bf8237963c11e376eaa66e7eccee39164e3e259a1c3767c304d6", - "sha256:a959e9a83cff0ae7a85a02cc183e4db636f69ff41dddb7c4e32f997924923417", - "sha256:b859336d9a35669b68a29c5d8f050e0dca380452dabf6c9667bb8599f010d164", - "sha256:dc875cc9a733fe3e6344a37f2b5888e0a9605bb37807fc3009f3b03786408f34" + "sha256:1af8ea4b15f57571ff7fc5e282a82c5eb69bc695e19b8ddeeda324397965b30a", + "sha256:1b281f4ca41a0c6612d4c6e68b96e28acfe786d226a427cd944baa8d7acd644f", + "sha256:489cbab55cd793ceb8f90bb7423c6ea64ebb53208ffcf7a044138e3c66d77299", + "sha256:592f6079646bdf5abbbfc3b0a28dac8de943f8907a250ce09398cda5eaebd260", + "sha256:5a728e5a05f37db6189eb413d22c78bd143fa59dd6a8a26dacd43332b3971fe8", + "sha256:6b84a6ffa083e34668ff0037221d399c24d939b5629cd38223af860de9e17a83", + "sha256:aeb6bd20b06dfc92cfe4436939c18de88a58c640752cf7f30d9e4ae893cdec32", + "sha256:c18b45c23f94016215f62d2334552224236217aaeb716871ce0e4dcfa08eb161", + "sha256:e985a9cba2e3f96a323722e5440aa9eccaac3178e74b884778e926b5249df080" ], "markers": "python_version >= '3.8'", - "version": "==0.10.0" + "version": "==0.15.0" }, "prometheus-client": { "hashes": [ - "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb", - "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301" + "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28", + "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094" ], - "markers": "python_version >= '3.8'", - "version": "==0.21.1" + "markers": "python_version >= '3.9'", + "version": "==0.22.1" }, "prometheus-fastapi-instrumentator": { "hashes": [ - "sha256:5ba67c9212719f244ad7942d75ded80693b26331ee5dfc1e7571e4794a9ccbed", - "sha256:96030c43c776ee938a3dae58485ec24caed7e05bfc60fe067161e0d5b5757052" + "sha256:978130f3c0bb7b8ebcc90d35516a6fe13e02d2eb358c8f83887cdef7020c31e9", + "sha256:be7cd61eeea4e5912aeccb4261c6631b3f227d8924542d79eaf5af3f439cbe5e" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==7.0.0" + "markers": "python_version >= '3.8'", + "version": "==7.1.0" }, "propcache": { "hashes": [ - "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4", - "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4", - "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", - "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f", - "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9", - "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", - "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e", - "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6", - "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf", - "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034", - "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d", - "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16", - "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30", - "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba", - "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95", - "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d", - "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae", - "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348", - "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2", - "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", - "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce", - "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54", - "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629", - "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54", - "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1", - "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b", - "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf", - "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b", - "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587", - "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097", - "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea", - "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24", - "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7", - "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541", - "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6", - "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634", - "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3", - "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d", - "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034", - "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465", - "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2", - "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf", - "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1", - "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04", - "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5", - "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583", - "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb", - "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b", - "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c", - "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958", - "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc", - "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4", - "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82", - "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e", - "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce", - "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9", - "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518", - "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536", - "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505", - "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052", - "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff", - "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1", - "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f", - "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681", - "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347", - "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af", - "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246", - "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787", - "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", - "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f", - "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439", - "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3", - "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6", - "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca", - "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec", - "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d", - "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3", - "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16", - "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717", - "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6", - "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd", - "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212" - ], - "markers": "python_version >= '3.9'", - "version": "==0.2.1" + "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", + "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", + "sha256:06766d8f34733416e2e34f46fea488ad5d60726bb9481d3cddf89a6fa2d9603f", + "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", + "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", + "sha256:0b8d2f607bd8f80ddc04088bc2a037fdd17884a6fcadc47a96e334d72f3717be", + "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", + "sha256:0d0fda578d1dc3f77b6b5a5dce3b9ad69a8250a891760a548df850a5e8da87f3", + "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", + "sha256:1f43837d4ca000243fd7fd6301947d7cb93360d03cd08369969450cc6b2ce3b4", + "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", + "sha256:2183111651d710d3097338dd1893fcf09c9f54e27ff1a8795495a16a469cc90b", + "sha256:21d8759141a9e00a681d35a1f160892a36fb6caa715ba0b832f7747da48fb6ea", + "sha256:22d9962a358aedbb7a2e36187ff273adeaab9743373a272976d2e348d08c7770", + "sha256:261df2e9474a5949c46e962065d88eb9b96ce0f2bd30e9d3136bcde84befd8f2", + "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", + "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", + "sha256:2a4092e8549031e82facf3decdbc0883755d5bbcc62d3aea9d9e185549936dcf", + "sha256:2ca6d378f09adb13837614ad2754fa8afaee330254f404299611bce41a8438cb", + "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", + "sha256:31248e44b81d59d6addbb182c4720f90b44e1efdc19f58112a3c3a1615fb47ef", + "sha256:34a624af06c048946709f4278b4176470073deda88d91342665d95f7c6270fbe", + "sha256:36c8d9b673ec57900c3554264e630d45980fd302458e4ac801802a7fd2ef7897", + "sha256:3def3da3ac3ce41562d85db655d18ebac740cb3fa4367f11a52b3da9d03a5cc3", + "sha256:404d70768080d3d3bdb41d0771037da19d8340d50b08e104ca0e7f9ce55fce70", + "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", + "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", + "sha256:4927842833830942a5d0a56e6f4839bc484785b8e1ce8d287359794818633ba0", + "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", + "sha256:4ba3fef1c30f306b1c274ce0b8baaa2c3cdd91f645c48f06394068f37d3837a1", + "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", + "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", + "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", + "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", + "sha256:55ffda449a507e9fbd4aca1a7d9aa6753b07d6166140e5a18d2ac9bc49eac220", + "sha256:5745bc7acdafa978ca1642891b82c19238eadc78ba2aaa293c6863b304e552d7", + "sha256:59d61f6970ecbd8ff2e9360304d5c8876a6abd4530cb752c06586849ac8a9dc9", + "sha256:5f559e127134b07425134b4065be45b166183fdcb433cb6c24c8e4149056ad50", + "sha256:5f57aa0847730daceff0497f417c9de353c575d8da3579162cc74ac294c5369e", + "sha256:6107ddd08b02654a30fb8ad7a132021759d750a82578b94cd55ee2772b6ebea2", + "sha256:62180e0b8dbb6b004baec00a7983e4cc52f5ada9cd11f48c3528d8cfa7b96a66", + "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", + "sha256:64a67fb39229a8a8491dd42f864e5e263155e729c2e7ff723d6e25f596b1e8cb", + "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", + "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", + "sha256:70bd8b9cd6b519e12859c99f3fc9a93f375ebd22a50296c3a295028bea73b9e7", + "sha256:7435d766f978b4ede777002e6b3b6641dd229cd1da8d3d3106a45770365f9ad9", + "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", + "sha256:76cace5d6b2a54e55b137669b30f31aa15977eeed390c7cbfb1dafa8dfe9a701", + "sha256:7a2368eed65fc69a7a7a40b27f22e85e7627b74216f0846b04ba5c116e191ec9", + "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", + "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", + "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", + "sha256:85871b050f174bc0bfb437efbdb68aaf860611953ed12418e4361bc9c392749e", + "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", + "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", + "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", + "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", + "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", + "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", + "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", + "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", + "sha256:9bec58347a5a6cebf239daba9bda37dffec5b8d2ce004d9fe4edef3d2815137e", + "sha256:9da1cf97b92b51253d5b68cf5a2b9e0dafca095e36b7f2da335e27dc6172a614", + "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", + "sha256:a2dc1f4a1df4fecf4e6f68013575ff4af84ef6f478fe5344317a65d38a8e6dc9", + "sha256:a7fad897f14d92086d6b03fdd2eb844777b0c4d7ec5e3bac0fbae2ab0602bbe5", + "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", + "sha256:abb7fa19dbf88d3857363e0493b999b8011eea856b846305d8c0512dfdf8fbb1", + "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", + "sha256:aff2e4e06435d61f11a428360a932138d0ec288b0a31dd9bd78d200bd4a2b339", + "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", + "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", + "sha256:be29c4f4810c5789cf10ddf6af80b041c724e629fa51e308a7a0fb19ed1ef7bf", + "sha256:c0075bf773d66fa8c9d41f66cc132ecc75e5bb9dd7cce3cfd14adc5ca184cb95", + "sha256:c144ca294a204c470f18cf4c9d78887810d04a3e2fbb30eea903575a779159df", + "sha256:c5c2a784234c28854878d68978265617aa6dc0780e53d44b4d67f3651a17a9a2", + "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", + "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", + "sha256:cc2782eb0f7a16462285b6f8394bbbd0e1ee5f928034e941ffc444012224171b", + "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", + "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", + "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", + "sha256:d4a996adb6904f85894570301939afeee65f072b4fd265ed7e569e8d9058e4ec", + "sha256:d81ac3ae39d38588ad0549e321e6f773a4e7cc68e7751524a22885d5bbadf886", + "sha256:db429c19a6c7e8a1c320e6a13c99799450f411b02251fb1b75e6217cf4a14fcb", + "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", + "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", + "sha256:e514326b79e51f0a177daab1052bc164d9d9e54133797a3a58d24c9c87a3fe6d", + "sha256:e53af8cb6a781b02d2ea079b5b853ba9430fcbe18a8e3ce647d5982a3ff69f39", + "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", + "sha256:eef914c014bf72d18efb55619447e0aecd5fb7c2e3fa7441e2e5d6099bddff7e", + "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", + "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", + "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", + "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", + "sha256:fb075ad271405dcad8e2a7ffc9a750a3bf70e533bd86e89f0603e607b93aa64c", + "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206" + ], + "markers": "python_version >= '3.9'", + "version": "==0.3.2" }, "proto-plus": { "hashes": [ - "sha256:c91fc4a65074ade8e458e95ef8bac34d4008daa7cce4a12d6707066fca648961", - "sha256:fbb17f57f7bd05a68b7707e745e26528b0b3c34e378db91eef93912c54982d91" + "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", + "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012" ], "markers": "python_version >= '3.7'", - "version": "==1.25.0" + "version": "==1.26.1" }, "protobuf": { "hashes": [ - "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f", - "sha256:0eb32bfa5219fc8d4111803e9a690658aa2e6366384fd0851064b963b6d1f2a7", - "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888", - "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620", - "sha256:6ce8cc3389a20693bfde6c6562e03474c40851b44975c9b2bf6df7d8c4f864da", - "sha256:84a57163a0ccef3f96e4b6a20516cedcf5bb3a95a657131c5c3ac62200d23252", - "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a", - "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e", - "sha256:b89c115d877892a512f79a8114564fb435943b59067615894c3b13cd3e1fa107", - "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f", - "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84" + "sha256:0414e3aa5a5f3ff423828e1e6a6e907d6c65c1d5b7e6e975793d5590bdeecc16", + "sha256:426f59d2964864a1a366254fa703b8632dcec0790d8862d30034d8245e1cd447", + "sha256:4ee898bf66f7a8b0bd21bce523814e6fbd8c6add948045ce958b73af7e8878c6", + "sha256:6f1227473dc43d44ed644425268eb7c2e488ae245d51c6866d19fe158e207402", + "sha256:720a6c7e6b77288b85063569baae8536671b39f15cc22037ec7045658d80489e", + "sha256:7fa17d5a29c2e04b7d90e5e32388b8bfd0e7107cd8e616feef7ed3fa6bdab5c9", + "sha256:8764cf4587791e7564051b35524b72844f845ad0bb011704c3736cce762d8fe9", + "sha256:a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39", + "sha256:d8cac4c982f0b957a4dc73a80e2ea24fab08e679c0de9deb835f4a12d69aca9a" ], - "markers": "python_version >= '3.8'", - "version": "==5.29.3" + "markers": "python_version >= '3.9'", + "version": "==6.31.1" }, "pyasn1": { "hashes": [ @@ -1650,151 +1882,158 @@ }, "pyasn1-modules": { "hashes": [ - "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd", - "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c" + "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", + "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6" ], "markers": "python_version >= '3.8'", - "version": "==0.4.1" + "version": "==0.4.2" + }, + "pycparser": { + "hashes": [ + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" + ], + "markers": "python_version >= '3.8'", + "version": "==2.22" }, "pydantic": { "hashes": [ - "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", - "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53" + "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", + "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.10.5" + "markers": "python_version >= '3.9'", + "version": "==2.11.7" }, "pydantic-core": { "hashes": [ - "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278", - "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", - "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", - "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f", - "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", - "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", - "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54", - "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630", - "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", - "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", - "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", - "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", - "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", - "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", - "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", - "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", - "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", - "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd", - "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", - "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", - "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", - "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", - "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", - "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", - "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", - "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", - "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", - "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", - "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", - "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", - "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", - "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf", - "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", - "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", - "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76", - "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362", - "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", - "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", - "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320", - "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118", - "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96", - "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", - "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046", - "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", - "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", - "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", - "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", - "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67", - "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", - "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", - "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35", - "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", - "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", - "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b", - "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", - "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", - "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", - "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145", - "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", - "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", - "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", - "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", - "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", - "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", - "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5", - "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", - "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", - "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", - "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", - "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da", - "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", - "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", - "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993", - "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656", - "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4", - "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", - "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb", - "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d", - "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", - "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e", - "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", - "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc", - "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a", - "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9", - "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506", - "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b", - "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1", - "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", - "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", - "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", - "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", - "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", - "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", - "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", - "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308", - "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2", - "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228", - "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b", - "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", - "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad" + "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", + "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", + "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", + "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", + "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", + "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", + "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", + "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", + "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", + "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", + "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", + "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", + "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", + "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", + "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", + "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", + "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", + "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", + "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", + "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", + "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", + "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", + "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", + "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", + "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", + "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", + "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", + "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", + "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", + "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", + "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", + "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", + "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", + "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", + "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", + "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", + "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", + "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", + "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", + "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", + "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", + "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", + "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", + "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", + "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", + "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", + "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", + "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", + "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", + "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", + "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", + "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", + "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", + "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", + "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", + "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", + "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", + "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", + "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", + "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", + "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", + "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", + "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", + "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", + "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", + "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", + "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", + "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", + "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", + "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", + "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", + "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", + "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", + "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", + "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", + "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", + "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", + "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", + "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", + "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", + "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", + "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", + "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", + "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", + "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", + "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", + "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", + "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", + "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", + "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", + "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", + "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", + "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", + "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", + "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", + "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", + "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", + "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", + "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d" ], - "markers": "python_version >= '3.8'", - "version": "==2.27.2" + "markers": "python_version >= '3.9'", + "version": "==2.33.2" }, "pydantic-settings": { "hashes": [ - "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", - "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd" + "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", + "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796" ], - "markers": "python_version >= '3.8'", - "version": "==2.7.1" + "markers": "python_version >= '3.9'", + "version": "==2.10.1" }, "pyparsing": { "hashes": [ - "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1", - "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a" + "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", + "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be" ], "markers": "python_version >= '3.9'", - "version": "==3.2.1" + "version": "==3.2.3" }, "pypdf": { "hashes": [ - "sha256:3bd4f503f4ebc58bae40d81e81a9176c400cbbac2ba2d877367595fb524dfdfc", - "sha256:425a129abb1614183fd1aca6982f650b47f8026867c0ce7c4b9f281c443d2740" + "sha256:30f67a614d558e495e1fbb157ba58c1de91ffc1718f5e0dfeb82a029233890a1", + "sha256:be10a4c54202f46d9daceaa8788be07aa8cd5ea8c25c529c50dd509206382c35" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==5.1.0" + "version": "==5.9.0" }, "python-crfsuite": { "hashes": [ @@ -1814,11 +2053,26 @@ }, "python-dotenv": { "hashes": [ - "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", - "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" + "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", + "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" + ], + "markers": "python_version >= '3.9'", + "version": "==1.1.1" + }, + "python-multipart": { + "hashes": [ + "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", + "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13" ], "markers": "python_version >= '3.8'", - "version": "==1.0.1" + "version": "==0.0.20" + }, + "pytz": { + "hashes": [ + "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", + "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" + ], + "version": "==2025.2" }, "pyyaml": { "hashes": [ @@ -1879,114 +2133,115 @@ "markers": "python_version >= '3.8'", "version": "==6.0.2" }, + "referencing": { + "hashes": [ + "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", + "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" + ], + "markers": "python_version >= '3.9'", + "version": "==0.36.2" + }, "regex": { "hashes": [ - "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c", - "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60", - "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d", - "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d", - "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67", - "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773", - "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", - "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef", - "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad", - "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe", - "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", - "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114", - "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", - "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39", - "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e", - "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3", - "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", - "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d", - "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e", - "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", - "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7", - "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f", - "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0", - "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54", - "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b", - "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", - "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd", - "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57", - "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34", - "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", - "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f", - "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b", - "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519", - "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", - "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a", - "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638", - "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b", - "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839", - "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", - "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf", - "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", - "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0", - "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f", - "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95", - "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4", - "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e", - "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13", - "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", - "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2", - "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008", - "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9", - "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc", - "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48", - "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20", - "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89", - "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e", - "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf", - "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b", - "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd", - "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", - "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29", - "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b", - "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3", - "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45", - "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3", - "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983", - "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e", - "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", - "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4", - "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", - "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467", - "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577", - "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001", - "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", - "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55", - "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9", - "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf", - "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6", - "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e", - "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde", - "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62", - "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df", - "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51", - "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5", - "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86", - "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2", - "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2", - "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0", - "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c", - "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f", - "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", - "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2", - "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9", - "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91" + "sha256:0200a5150c4cf61e407038f4b4d5cdad13e86345dac29ff9dab3d75d905cf130", + "sha256:02e5860a250cd350c4933cf376c3bc9cb28948e2c96a8bc042aee7b985cfa26f", + "sha256:075641c94126b064c65ab86e7e71fc3d63e7ff1bea1fb794f0773c97cdad3a03", + "sha256:0a5966220b9a1a88691282b7e4350e9599cf65780ca60d914a798cb791aa1177", + "sha256:0b85241d3cfb9f8a13cefdfbd58a2843f208f2ed2c88181bf84e22e0c7fc066d", + "sha256:1a764a83128af9c1a54be81485b34dca488cbcacefe1e1d543ef11fbace191e1", + "sha256:1e4f4f62599b8142362f164ce776f19d79bdd21273e86920a7b604a4275b4f59", + "sha256:20ff8433fa45e131f7316594efe24d4679c5449c0ca69d91c2f9d21846fdf064", + "sha256:24257953d5c1d6d3c129ab03414c07fc1a47833c9165d49b954190b2b7f21a1a", + "sha256:2d15a9da5fad793e35fb7be74eec450d968e05d2e294f3e0e77ab03fa7234a83", + "sha256:3157aa512b9e606586900888cd469a444f9b898ecb7f8931996cb715f77477f0", + "sha256:32b9f9bcf0f605eb094b08e8da72e44badabb63dde6b83bd530580b488d1c6da", + "sha256:33be70d75fa05a904ee0dc43b650844e067d14c849df7e82ad673541cd465b5f", + "sha256:35e43ebf5b18cd751ea81455b19acfdec402e82fe0dc6143edfae4c5c4b3909a", + "sha256:37555e4ae0b93358fa7c2d240a4291d4a4227cc7c607d8f85596cdb08ec0a083", + "sha256:3b836eb4a95526b263c2a3359308600bd95ce7848ebd3c29af0c37c4f9627cd3", + "sha256:4494f8fd95a77eb434039ad8460e64d57baa0434f1395b7da44015bef650d0e4", + "sha256:469142fb94a869beb25b5f18ea87646d21def10fbacb0bcb749224f3509476f0", + "sha256:48fb045bbd4aab2418dc1ba2088a5e32de4bfe64e1457b948bb328a8dc2f1c2e", + "sha256:4913f52fbc7a744aaebf53acd8d3dc1b519e46ba481d4d7596de3c862e011ada", + "sha256:4b7dc33b9b48fb37ead12ffc7bdb846ac72f99a80373c4da48f64b373a7abeae", + "sha256:4b8c4d39f451e64809912c82392933d80fe2e4a87eeef8859fcc5380d0173c64", + "sha256:4f42b522259c66e918a0121a12429b2abcf696c6f967fa37bdc7b72e61469f98", + "sha256:4fef81b2f7ea6a2029161ed6dea9ae13834c28eb5a95b8771828194a026621e4", + "sha256:524c868ba527eab4e8744a9287809579f54ae8c62fbf07d62aacd89f6026b282", + "sha256:57d25b6732ea93eeb1d090e8399b6235ca84a651b52d52d272ed37d3d2efa0f1", + "sha256:5d7de1ceed5a5f84f342ba4a9f4ae589524adf9744b2ee61b5da884b5b659834", + "sha256:6164b1d99dee1dfad33f301f174d8139d4368a9fb50bf0a3603b2eaf579963ad", + "sha256:656433e5b7dccc9bc0da6312da8eb897b81f5e560321ec413500e5367fcd5d47", + "sha256:69c593ff5a24c0d5c1112b0df9b09eae42b33c014bdca7022d6523b210b69f72", + "sha256:69ed3bc611540f2ea70a4080f853741ec698be556b1df404599f8724690edbcd", + "sha256:6c053f9647e3421dd2f5dff8172eb7b4eec129df9d1d2f7133a4386319b47435", + "sha256:6cef962d7834437fe8d3da6f9bfc6f93f20f218266dcefec0560ed7765f5fe01", + "sha256:70645cad3407d103d1dbcb4841839d2946f7d36cf38acbd40120fee1682151e5", + "sha256:716a47515ba1d03f8e8a61c5013041c8c90f2e21f055203498105d7571b44531", + "sha256:72a26dcc6a59c057b292f39d41465d8233a10fd69121fa24f8f43ec6294e5415", + "sha256:7373afae7cfb716e3b8e15d0184510d518f9d21471f2d62918dbece85f2c588f", + "sha256:739a74970e736df0773788377969c9fea3876c2fc13d0563f98e5503e5185f46", + "sha256:7bf1c5503a9f2cbd2f52d7e260acb3131b07b6273c470abb78568174fe6bde3f", + "sha256:7f7211a746aced993bef487de69307a38c5ddd79257d7be83f7b202cb59ddb50", + "sha256:8283afe7042d8270cecf27cca558873168e771183d4d593e3c5fe5f12402212a", + "sha256:85c3a958ef8b3d5079c763477e1f09e89d13ad22198a37e9d7b26b4b17438b33", + "sha256:89c9504fc96268e8e74b0283e548f53a80c421182a2007e3365805b74ceef936", + "sha256:95b4639c77d414efa93c8de14ce3f7965a94d007e068a94f9d4997bb9bd9c81f", + "sha256:95d538b10eb4621350a54bf14600cc80b514211d91a019dc74b8e23d2159ace5", + "sha256:96bbae4c616726f4661fe7bcad5952e10d25d3c51ddc388189d8864fbc1b3c68", + "sha256:98d0ce170fcde1a03b5df19c5650db22ab58af375aaa6ff07978a85c9f250f0e", + "sha256:9960d162f3fecf6af252534a1ae337e9c2e20d74469fed782903b24e2cc9d3d7", + "sha256:9a9ab52a466a9b4b91564437b36417b76033e8778e5af8f36be835d8cb370d62", + "sha256:9d644de5520441e5f7e2db63aec2748948cc39ed4d7a87fd5db578ea4043d997", + "sha256:9ead9765217afd04a86822dfcd4ed2747dfe426e887da413b15ff0ac2457e21a", + "sha256:9feab78a1ffa4f2b1e27b1bcdaad36f48c2fed4870264ce32f52a393db093c78", + "sha256:a16dd56bbcb7d10e62861c3cd000290ddff28ea142ffb5eb3470f183628011ac", + "sha256:a664291c31cae9c4a30589bd8bc2ebb56ef880c9c6264cb7643633831e606a4d", + "sha256:aaef1f056d96a0a5d53ad47d019d5b4c66fe4be2da87016e0d43b7242599ffc7", + "sha256:baf2fe122a3db1c0b9f161aa44463d8f7e33eeeda47bb0309923deb743a18276", + "sha256:bca11d3c38a47c621769433c47f364b44e8043e0de8e482c5968b20ab90a3986", + "sha256:c1844be23cd40135b3a5a4dd298e1e0c0cb36757364dd6cdc6025770363e06c1", + "sha256:c3c9740a77aeef3f5e3aaab92403946a8d34437db930a0280e7e81ddcada61f5", + "sha256:c436fd1e95c04c19039668cfb548450a37c13f051e8659f40aed426e36b3765f", + "sha256:c7f663ccc4093877f55b51477522abd7299a14c5bb7626c5238599db6a0cb95d", + "sha256:c83aec91af9c6fbf7c743274fd952272403ad9a9db05fe9bfc9df8d12b45f176", + "sha256:cbe1698e5b80298dbce8df4d8d1182279fbdaf1044e864cbc9d53c20e4a2be77", + "sha256:cbfaa401d77334613cf434f723c7e8ba585df162be76474bccc53ae4e5520b3a", + "sha256:d03c6f9dcd562c56527c42b8530aad93193e0b3254a588be1f2ed378cdfdea1b", + "sha256:d428fc7731dcbb4e2ffe43aeb8f90775ad155e7db4347a639768bc6cd2df881a", + "sha256:d5273fddf7a3e602695c92716c420c377599ed3c853ea669c1fe26218867002f", + "sha256:d600e58ee6d036081c89696d2bdd55d507498a7180df2e19945c6642fac59588", + "sha256:d72765a4bff8c43711d5b0f5b452991a9947853dfa471972169b3cc0ba1d0751", + "sha256:d856164d25e2b3b07b779bfed813eb4b6b6ce73c2fd818d46f47c1eb5cd79bd6", + "sha256:da304313761b8500b8e175eb2040c4394a875837d5635f6256d6fa0377ad32c8", + "sha256:da7507d083ee33ccea1310447410c27ca11fb9ef18c95899ca57ff60a7e4d8f1", + "sha256:dde35e2afbbe2272f8abee3b9fe6772d9b5a07d82607b5788e8508974059925c", + "sha256:e154a7ee7fa18333ad90b20e16ef84daaeac61877c8ef942ec8dfa50dc38b7a1", + "sha256:e4636a7f3b65a5f340ed9ddf53585c42e3ff37101d383ed321bfe5660481744b", + "sha256:e91eb2c62c39705e17b4d42d4b86c4e86c884c0d15d9c5a47d0835f8387add8e", + "sha256:ea74cf81fe61a7e9d77989050d0089a927ab758c29dac4e8e1b6c06fccf3ebf0", + "sha256:ee38926f31f1aa61b0232a3a11b83461f7807661c062df9eb88769d86e6195c3", + "sha256:efac4db9e044d47fd3b6b0d40b6708f4dfa2d8131a5ac1d604064147c0f552fd", + "sha256:f14b36e6d4d07f1a5060f28ef3b3561c5d95eb0651741474ce4c0a4c56ba8719", + "sha256:f3e5c1e0925e77ec46ddc736b756a6da50d4df4ee3f69536ffb2373460e2dafd", + "sha256:f3f6e8e7af516a7549412ce57613e859c3be27d55341a894aacaa11703a4c31a", + "sha256:f7f3071b5faa605b0ea51ec4bb3ea7257277446b053f4fd3ad02b1dcb4e64353", + "sha256:f978ddfb6216028c8f1d6b0f7ef779949498b64117fc35a939022f67f810bdcb", + "sha256:fa1cdfb8db96ef20137de5587954c812821966c3e8b48ffc871e22d7ec0a4938", + "sha256:fb31080f2bd0681484b275461b202b5ad182f52c9ec606052020fe13eb13a72f", + "sha256:fd5edc3f453de727af267c7909d083e19f6426fc9dd149e332b6034f2a5611e6" ], - "markers": "python_version >= '3.8'", - "version": "==2024.11.6" + "markers": "python_version >= '3.9'", + "version": "==2025.7.34" }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", + "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.32.3" + "version": "==2.32.4" }, "requests-toolbelt": { "hashes": [ @@ -1996,21 +2251,171 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.0.0" }, + "rpds-py": { + "hashes": [ + "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3", + "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b", + "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5", + "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806", + "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e", + "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4", + "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f", + "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915", + "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be", + "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b", + "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696", + "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323", + "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331", + "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8", + "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c", + "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19", + "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1", + "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8", + "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0", + "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318", + "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246", + "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256", + "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b", + "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb", + "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04", + "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1", + "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19", + "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7", + "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f", + "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871", + "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84", + "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e", + "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387", + "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40", + "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958", + "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44", + "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582", + "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7", + "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292", + "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a", + "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba", + "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953", + "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51", + "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9", + "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37", + "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9", + "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137", + "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3", + "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0", + "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8", + "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1", + "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e", + "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618", + "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67", + "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1", + "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d", + "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9", + "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da", + "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0", + "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b", + "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84", + "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d", + "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11", + "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1", + "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7", + "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79", + "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f", + "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88", + "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0", + "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a", + "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158", + "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226", + "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f", + "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f", + "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1", + "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad", + "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7", + "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a", + "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae", + "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08", + "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03", + "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a", + "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d", + "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11", + "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6", + "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9", + "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb", + "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca", + "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf", + "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9", + "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15", + "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19", + "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed", + "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed", + "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6", + "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d", + "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387", + "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f", + "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8", + "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5", + "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37", + "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45", + "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72", + "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf", + "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090", + "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20", + "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e", + "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e", + "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284", + "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc", + "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8", + "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867", + "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33", + "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255", + "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8", + "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c", + "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323", + "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107", + "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d", + "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a", + "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2", + "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0", + "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41", + "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af", + "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d", + "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632", + "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d", + "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21", + "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170", + "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", + "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf", + "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd", + "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0", + "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7", + "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3", + "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35", + "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674", + "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73", + "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37", + "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f", + "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136", + "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83", + "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12", + "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9" + ], + "markers": "python_version >= '3.9'", + "version": "==0.26.0" + }, "rsa": { "hashes": [ - "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", - "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21" + "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", + "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75" ], "markers": "python_version >= '3.6' and python_version < '4'", - "version": "==4.9" + "version": "==4.9.1" }, "s3transfer": { "hashes": [ - "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", - "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7" + "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", + "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf" ], - "markers": "python_version >= '3.8'", - "version": "==0.10.4" + "markers": "python_version >= '3.9'", + "version": "==0.13.1" }, "sgmllib3k": { "hashes": [ @@ -2036,90 +2441,98 @@ }, "soupsieve": { "hashes": [ - "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", - "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9" + "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", + "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a" ], "markers": "python_version >= '3.8'", - "version": "==2.6" + "version": "==2.7" }, "sqlalchemy": { "hashes": [ - "sha256:03f0528c53ca0b67094c4764523c1451ea15959bbf0a8a8a3096900014db0278", - "sha256:12b0f1ec623cccf058cf21cb544f0e74656618165b083d78145cafde156ea7b6", - "sha256:12b28d99a9c14eaf4055810df1001557176716de0167b91026e648e65229bffb", - "sha256:1b2690456528a87234a75d1a1644cdb330a6926f455403c8e4f6cad6921f9098", - "sha256:1cdba1f73b64530c47b27118b7053b8447e6d6f3c8104e3ac59f3d40c33aa9fd", - "sha256:293f9ade06b2e68dd03cfb14d49202fac47b7bb94bffcff174568c951fbc7af2", - "sha256:2952748ecd67ed3b56773c185e85fc084f6bdcdec10e5032a7c25a6bc7d682ef", - "sha256:2f95fc8e3f34b5f6b3effb49d10ac97c569ec8e32f985612d9b25dd12d0d2e94", - "sha256:2fa2c0913f02341d25fb858e4fb2031e6b0813494cca1ba07d417674128ce11b", - "sha256:3151822aa1db0eb5afd65ccfafebe0ef5cda3a7701a279c8d0bf17781a793bb4", - "sha256:35bd2df269de082065d4b23ae08502a47255832cc3f17619a5cea92ce478b02b", - "sha256:41296bbcaa55ef5fdd32389a35c710133b097f7b2609d8218c0eabded43a1d84", - "sha256:44f569d0b1eb82301b92b72085583277316e7367e038d97c3a1a899d9a05e342", - "sha256:46954173612617a99a64aee103bcd3f078901b9a8dcfc6ae80cbf34ba23df989", - "sha256:4b12885dc85a2ab2b7d00995bac6d967bffa8594123b02ed21e8eb2205a7584b", - "sha256:4f581d365af9373a738c49e0c51e8b18e08d8a6b1b15cc556773bcd8a192fa8b", - "sha256:51bc9cfef83e0ac84f86bf2b10eaccb27c5a3e66a1212bef676f5bee6ef33ebb", - "sha256:521ef85c04c33009166777c77e76c8a676e2d8528dc83a57836b63ca9c69dcd1", - "sha256:5bc3339db84c5fb9130ac0e2f20347ee77b5dd2596ba327ce0d399752f4fce39", - "sha256:635d8a21577341dfe4f7fa59ec394b346da12420b86624a69e466d446de16aff", - "sha256:648ec5acf95ad59255452ef759054f2176849662af4521db6cb245263ae4aa33", - "sha256:650dcb70739957a492ad8acff65d099a9586b9b8920e3507ca61ec3ce650bb72", - "sha256:6b788f14c5bb91db7f468dcf76f8b64423660a05e57fe277d3f4fad7b9dcb7ce", - "sha256:6c67415258f9f3c69867ec02fea1bf6508153709ecbd731a982442a590f2b7e4", - "sha256:74bbd1d0a9bacf34266a7907d43260c8d65d31d691bb2356f41b17c2dca5b1d0", - "sha256:75311559f5c9881a9808eadbeb20ed8d8ba3f7225bef3afed2000c2a9f4d49b9", - "sha256:78361be6dc9073ed17ab380985d1e45e48a642313ab68ab6afa2457354ff692c", - "sha256:7b7e772dc4bc507fdec4ee20182f15bd60d2a84f1e087a8accf5b5b7a0dcf2ba", - "sha256:82df02816c14f8dc9f4d74aea4cb84a92f4b0620235daa76dde002409a3fbb5a", - "sha256:84b9f23b0fa98a6a4b99d73989350a94e4a4ec476b9a7dfe9b79ba5939f5e80b", - "sha256:8c4096727193762e72ce9437e2a86a110cf081241919ce3fab8e89c02f6b6658", - "sha256:8e47f1af09444f87c67b4f1bb6231e12ba6d4d9f03050d7fc88df6d075231a49", - "sha256:93d1543cd8359040c02b6614421c8e10cd7a788c40047dbc507ed46c29ae5636", - "sha256:94b564e38b344d3e67d2e224f0aec6ba09a77e4582ced41e7bfd0f757d926ec9", - "sha256:955a2a765aa1bd81aafa69ffda179d4fe3e2a3ad462a736ae5b6f387f78bfeb8", - "sha256:9d087663b7e1feabea8c578d6887d59bb00388158e8bff3a76be11aa3f748ca2", - "sha256:9df21b8d9e5c136ea6cde1c50d2b1c29a2b5ff2b1d610165c23ff250e0704087", - "sha256:a8998bf9f8658bd3839cbc44ddbe982955641863da0c1efe5b00c1ab4f5c16b1", - "sha256:b2eae3423e538c10d93ae3e87788c6a84658c3ed6db62e6a61bb9495b0ad16bb", - "sha256:b661b49d0cb0ab311a189b31e25576b7ac3e20783beb1e1817d72d9d02508bf5", - "sha256:bedee60385c1c0411378cbd4dc486362f5ee88deceea50002772912d798bb00f", - "sha256:c505edd429abdfe3643fa3b2e83efb3445a34a9dc49d5f692dd087be966020e0", - "sha256:cce918ada64c956b62ca2c2af59b125767097ec1dca89650a6221e887521bfd7", - "sha256:cf5ae8a9dcf657fd72144a7fd01f243236ea39e7344e579a121c4205aedf07bb", - "sha256:cf95a60b36997dad99692314c4713f141b61c5b0b4cc5c3426faad570b31ca01", - "sha256:d57bafbab289e147d064ffbd5cca2d7b1394b63417c0636cea1f2e93d16eb9e8", - "sha256:d70f53a0646cc418ca4853da57cf3ddddbccb8c98406791f24426f2dd77fd0e2", - "sha256:d75ead7dd4d255068ea0f21492ee67937bd7c90964c8f3c2bea83c7b7f81b95f", - "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e", - "sha256:db18ff6b8c0f1917f8b20f8eca35c28bbccb9f83afa94743e03d40203ed83de9", - "sha256:dfff7be361048244c3aa0f60b5e63221c5e0f0e509f4e47b8910e22b57d10ae7", - "sha256:e4fb5ac86d8fe8151966814f6720996430462e633d225497566b3996966b9bdb", - "sha256:e56a139bfe136a22c438478a86f8204c1eb5eed36f4e15c4224e4b9db01cb3e4", - "sha256:e6f5d254a22394847245f411a2956976401e84da4288aa70cbcd5190744062c1", - "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069", - "sha256:ea308cec940905ba008291d93619d92edaf83232ec85fbd514dcb329f3192761", - "sha256:eaa8039b6d20137a4e02603aba37d12cd2dde7887500b8855356682fc33933f4" + "sha256:09637a0872689d3eb71c41e249c6f422e3e18bbd05b4cd258193cfc7a9a50da2", + "sha256:0b718011a9d66c0d2f78e1997755cd965f3414563b31867475e9bc6efdc2281d", + "sha256:160bedd8a5c28765bd5be4dec2d881e109e33b34922e50a3b881a7681773ac5f", + "sha256:16d9b544873fe6486dddbb859501a07d89f77c61d29060bb87d0faf7519b6a4d", + "sha256:172b244753e034d91a826f80a9a70f4cbac690641207f2217f8404c261473efe", + "sha256:1aef304ada61b81f1955196f584b9e72b798ed525a7c0b46e09e98397393297b", + "sha256:1b3c117f65d64e806ce5ce9ce578f06224dc36845e25ebd2554b3e86960e1aed", + "sha256:1f092cf83ebcafba23a247f5e03f99f5436e3ef026d01c8213b5eca48ad6efa9", + "sha256:21bfdf57abf72fa89b97dd74d3187caa3172a78c125f2144764a73970810c4ee", + "sha256:260ca1d2e5910f1f1ad3fe0113f8fab28657cee2542cb48c2f342ed90046e8ec", + "sha256:27e4a7b3a7a61ff919c2e7caafd612f8626114e6e5ebbe339de3b5b1df9bc27e", + "sha256:2ddbaafe32f0dd12d64284b1c3189104b784c9f3dba8cc1ba7e642e2b14b906f", + "sha256:2eb539fd83185a85e5fcd6b19214e1c734ab0351d81505b0f987705ba0a1e231", + "sha256:37f4f42568b6c656ee177b3e111d354b5dda75eafe9fe63492535f91dfa35829", + "sha256:437c2a8b0c780ff8168a470beb22cb4a25e1c63ea6a7aec87ffeb07aa4b76641", + "sha256:45c842c94c9ad546c72225a0c0d1ae8ef3f7c212484be3d429715a062970e87f", + "sha256:480f7df62f0b3ad6aa011eefa096049dc1770208bb71f234959ee2864206eefe", + "sha256:49362193b1f43aa158deebf438062d7b5495daa9177c6c5d0f02ceeb64b544ea", + "sha256:4c94447a016f36c4da80072e6c6964713b0af3c8019e9c4daadf21f61b81ab53", + "sha256:4cf10396a8a700a0f38ccd220d940be529c8f64435c5d5b29375acab9267a6c9", + "sha256:4efbdc9754c7145a954911bfeef815fb0843e8edab0e9cecfa3417a5cbd316af", + "sha256:5651eb19cacbeb2fe7431e4019312ed00a0b3fbd2d701423e0e2ceaadb5bcd9f", + "sha256:56bc76d86216443daa2e27e6b04a9b96423f0b69b5d0c40c7f4b9a4cdf7d8d90", + "sha256:636ec3dc83b2422a7ff548d0f8abf9c23742ca50e2a5cdc492a151eac7a0248b", + "sha256:739e58879b20a179156b63aa21f05ccacfd3e28e08e9c2b630ff55cd7177c4f1", + "sha256:78548fd65cd76d4c5a2e6b5f245d7734023ee4de33ee7bb298f1ac25a9935e0d", + "sha256:78b46555b730a24901ceb4cb901c6b45c9407f8875209ed3c5d6bcd0390a6ed1", + "sha256:7ee065898359fdee83961aed5cf1fb4cfa913ba71b58b41e036001d90bebbf7a", + "sha256:88f8a8007a658dfd82c16a20bd9673ae6b33576c003b5166d42697d49e496e61", + "sha256:89143290fb94c50a8dec73b06109ccd245efd8011d24fc0ddafe89dc55b36651", + "sha256:9193fa484bf00dcc1804aecbb4f528f1123c04bad6a08d7710c909750fa76aeb", + "sha256:941804f55c7d507334da38133268e3f6e5b0340d584ba0f277dd884197f4ae8c", + "sha256:95d3d06a968a760ce2aa6a5889fefcbdd53ca935735e0768e1db046ec08cbf01", + "sha256:97978d223b11f1d161390a96f28c49a13ce48fdd2fed7683167c39bdb1b8aa09", + "sha256:98b344859d282fde388047f1710860bb23f4098f705491e06b8ab52a48aafea9", + "sha256:9cae6c2b05326d7c2c7c0519f323f90e0fb9e8afa783c6a05bb9ee92a90d0f04", + "sha256:9d88a1c0d66d24e229e3938e1ef16ebdbd2bf4ced93af6eff55225f7465cf350", + "sha256:a3cb3ec67cc08bea54e06b569398ae21623534a7b1b23c258883a7c696ae10df", + "sha256:ad59dbe4d1252448c19d171dfba14c74e7950b46dc49d015722a4a06bfdab2b0", + "sha256:b01e0dd39f96aefda5ab002d8402db4895db871eb0145836246ce0661635ce55", + "sha256:bc7347ad7a7b1c78b94177f2d57263113bb950e62c59b96ed839b131ea4234e1", + "sha256:be28f88abd74af8519a4542185ee80ca914933ca65cdfa99504d82af0e4210df", + "sha256:be3a02f963c8d66e28bb4183bebab66dc4379701d92e660f461c65fecd6ff399", + "sha256:c34100c0b7ea31fbc113c124bcf93a53094f8951c7bf39c45f39d327bad6d1e7", + "sha256:c5dd245e6502990ccf612d51f220a7b04cbea3f00f6030691ffe27def76ca79b", + "sha256:cf4bf5a174d8a679a713b7a896470ffc6baab78e80a79e7ec5668387ffeccc8b", + "sha256:d119c80c614d62d32e236ae68e21dd28a2eaf070876b2f28a6075d5bae54ef3f", + "sha256:defcdff7e661f0043daa381832af65d616e060ddb54d3fe4476f51df7eaa1835", + "sha256:e35b9b000c59fcac2867ab3a79fc368a6caca8706741beab3b799d47005b3407", + "sha256:e87e6a5ef6f9d8daeb2ce5918bf5fddecc11cae6a7d7a671fcc4616c47635e01", + "sha256:e8c7ff7ba08b375f8a8fa0511e595c9bdabb5494ec68f1cf69bb24e54c0d90f2", + "sha256:eb9905f7f1e49fd57a7ed6269bc567fcbbdac9feadff20ad6bd7707266a91577", + "sha256:ed5a6959b1668d97a32e3fd848b485f65ee3c05a759dee06d90e4545a3c77f1e", + "sha256:f50f7b20677b23cfb35b6afcd8372b2feb348a38e3033f6447ee0704540be894", + "sha256:f9187498c2149919753a7fd51766ea9c8eecdec7da47c1b955fa8090bc642eaa", + "sha256:fb57923d852d38671a17abda9a65cc59e3e5eab51fb8307b09de46ed775bcbb8", + "sha256:fc6afee7e66fdba4f5a68610b487c1f754fccdc53894a9567785932dbb6a265e" ], "markers": "python_version >= '3.7'", - "version": "==2.0.37" + "version": "==2.0.42" + }, + "sse-starlette": { + "hashes": [ + "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", + "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a" + ], + "markers": "python_version >= '3.9'", + "version": "==3.0.2" }, "starlette": { "hashes": [ - "sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835", - "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7" + "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", + "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b" ], - "markers": "python_version >= '3.8'", - "version": "==0.41.3" + "markers": "python_version >= '3.9'", + "version": "==0.47.2" }, "tenacity": { "hashes": [ - "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b", - "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539" + "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", + "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138" ], - "markers": "python_version >= '3.8'", - "version": "==9.0.0" + "markers": "python_version >= '3.9'", + "version": "==9.1.2" }, "tiktoken": { "hashes": [ @@ -2174,19 +2587,19 @@ }, "types-requests": { "hashes": [ - "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95", - "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747" + "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", + "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072" ], - "markers": "python_version >= '3.8'", - "version": "==2.32.0.20241016" + "markers": "python_version >= '3.9'", + "version": "==2.32.4.20250611" }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", + "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76" ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "markers": "python_version >= '3.9'", + "version": "==4.14.1" }, "typing-inspect": { "hashes": [ @@ -2195,30 +2608,46 @@ ], "version": "==0.9.0" }, + "typing-inspection": { + "hashes": [ + "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", + "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.1" + }, + "tzdata": { + "hashes": [ + "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", + "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" + ], + "markers": "python_version >= '2'", + "version": "==2025.2" + }, "uritemplate": { "hashes": [ - "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", - "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", + "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686" ], - "markers": "python_version >= '3.6'", - "version": "==4.1.1" + "markers": "python_version >= '3.9'", + "version": "==4.2.0" }, "urllib3": { "hashes": [ - "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", - "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" ], "markers": "python_version >= '3.9'", - "version": "==2.3.0" + "version": "==2.5.0" }, "uvicorn": { "hashes": [ - "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", - "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9" + "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", + "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.34.0" + "version": "==0.35.0" }, "wheel": { "hashes": [ @@ -2323,111 +2752,390 @@ "markers": "python_version >= '3.6'", "version": "==0.14.2" }, + "xxhash": { + "hashes": [ + "sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1", + "sha256:0691bfcc4f9c656bcb96cc5db94b4d75980b9d5589f2e59de790091028580837", + "sha256:07fda5de378626e502b42b311b049848c2ef38784d0d67b6f30bb5008642f8eb", + "sha256:08424f6648526076e28fae6ea2806c0a7d504b9ef05ae61d196d571e5c879c84", + "sha256:0a80ad0ffd78bef9509eee27b4a29e56f5414b87fb01a888353e3d5bda7038bd", + "sha256:0adfbd36003d9f86c8c97110039f7539b379f28656a04097e7434d3eaf9aa131", + "sha256:0ec70a89be933ea49222fafc3999987d7899fc676f688dd12252509434636622", + "sha256:1030a39ba01b0c519b1a82f80e8802630d16ab95dc3f2b2386a0b5c8ed5cbb10", + "sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da", + "sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166", + "sha256:1328f6d8cca2b86acb14104e381225a3d7b42c92c4b86ceae814e5c400dbb415", + "sha256:13de2b76c1835399b2e419a296d5b38dc4855385d9e96916299170085ef72f57", + "sha256:14470ace8bd3b5d51318782cd94e6f94431974f16cb3b8dc15d52f3b69df8e00", + "sha256:149b7914451eb154b3dfaa721315117ea1dac2cc55a01bfbd4df7c68c5dd683d", + "sha256:160e0c19ee500482ddfb5d5570a0415f565d8ae2b3fd69c5dcfce8a58107b1c3", + "sha256:2014c5b3ff15e64feecb6b713af12093f75b7926049e26a580e94dcad3c73d8c", + "sha256:2061188a1ba352fc699c82bff722f4baacb4b4b8b2f0c745d2001e56d0dfb514", + "sha256:220f3f896c6b8d0316f63f16c077d52c412619e475f9372333474ee15133a558", + "sha256:23241ff6423378a731d84864bf923a41649dc67b144debd1077f02e6249a0d54", + "sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2", + "sha256:297595fe6138d4da2c8ce9e72a04d73e58725bb60f3a19048bc96ab2ff31c692", + "sha256:2b4154c00eb22e4d543f472cfca430e7962a0f1d0f3778334f2e08a7ba59363c", + "sha256:2e76e83efc7b443052dd1e585a76201e40b3411fe3da7af4fe434ec51b2f163b", + "sha256:30eb2efe6503c379b7ab99c81ba4a779748e3830241f032ab46bd182bf5873af", + "sha256:3171f693dbc2cef6477054a665dc255d996646b4023fe56cb4db80e26f4cc520", + "sha256:33513d6cc3ed3b559134fb307aae9bdd94d7e7c02907b37896a6c45ff9ce51bd", + "sha256:33eac61d0796ca0591f94548dcfe37bb193671e0c9bcf065789b5792f2eda644", + "sha256:37889a0d13b0b7d739cfc128b1c902f04e32de17b33d74b637ad42f1c55101f6", + "sha256:38c384c434021e4f62b8d9ba0bc9467e14d394893077e2c66d826243025e1f81", + "sha256:392f52ebbb932db566973693de48f15ce787cabd15cf6334e855ed22ea0be5b3", + "sha256:3dbbd9892c5ebffeca1ed620cf0ade13eb55a0d8c84e0751a6653adc6ac40d0c", + "sha256:3e5b5e16c5a480fe5f59f56c30abdeba09ffd75da8d13f6b9b6fd224d0b4d0a2", + "sha256:3ff2c0a34eae7df88c868be53a8dd56fbdf592109e21d4bfa092a27b0bf4a7bf", + "sha256:42eca420c8fa072cc1dd62597635d140e78e384a79bb4944f825fbef8bfeeef6", + "sha256:4811336f1ce11cac89dcbd18f3a25c527c16311709a89313c3acaf771def2d4b", + "sha256:4cc2d67fdb4d057730c75a64c5923abfa17775ae234a71b0200346bfb0a7f482", + "sha256:4e28503dccc7d32e0b9817aa0cbfc1f45f563b2c995b7a66c4c8a0d232e840c7", + "sha256:4e2febf914ace002132aa09169cc572e0d8959d0f305f93d5828c4836f9bc5a6", + "sha256:50ac2184ffb1b999e11e27c7e3e70cc1139047e7ebc1aa95ed12f4269abe98d4", + "sha256:531af8845aaadcadf951b7e0c1345c6b9c68a990eeb74ff9acd8501a0ad6a1c9", + "sha256:53a068fe70301ec30d868ece566ac90d873e3bb059cf83c32e76012c889b8637", + "sha256:586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2", + "sha256:59aa1203de1cb96dbeab595ded0ad0c0056bb2245ae11fac11c0ceea861382b9", + "sha256:5a74f23335b9689b66eb6dbe2a931a88fcd7a4c2cc4b1cb0edba8ce381c7a1da", + "sha256:5d0d307d27099bb0cbeea7260eb39ed4fdb99c5542e21e94bb6fd29e49c57a23", + "sha256:5d2a01dcce81789cf4b12d478b5464632204f4c834dc2d064902ee27d2d1f0ee", + "sha256:5d3a10609c51da2a1c0ea0293fc3968ca0a18bd73838455b5bca3069d7f8e32b", + "sha256:5ed9ebc46f24cf91034544b26b131241b699edbfc99ec5e7f8f3d02d6eb7fba4", + "sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8", + "sha256:602d339548d35a8579c6b013339fb34aee2df9b4e105f985443d2860e4d7ffaa", + "sha256:604253b2143e13218ff1ef0b59ce67f18b8bd1c4205d2ffda22b09b426386898", + "sha256:61a1ff00674879725b194695e17f23d3248998b843eb5e933007ca743310f793", + "sha256:61c722ed8d49ac9bc26c7071eeaa1f6ff24053d553146d5df031802deffd03da", + "sha256:63107013578c8a730419adc05608756c3fa640bdc6abe806c3123a49fb829f43", + "sha256:683b94dbd1ca67557850b86423318a2e323511648f9f3f7b1840408a02b9a48c", + "sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88", + "sha256:695735deeddfb35da1677dbc16a083445360e37ff46d8ac5c6fcd64917ff9ade", + "sha256:6e5f70f6dca1d3b09bccb7daf4e087075ff776e3da9ac870f86ca316736bb4aa", + "sha256:6e93a5ad22f434d7876665444a97e713a8f60b5b1a3521e8df11b98309bff833", + "sha256:6fa0b72f2423e2aa53077e54a61c28e181d23effeaafd73fcb9c494e60930c8e", + "sha256:70dabf941dede727cca579e8c205e61121afc9b28516752fd65724be1355cc90", + "sha256:74752ecaa544657d88b1d1c94ae68031e364a4d47005a90288f3bab3da3c970f", + "sha256:7a46e1d6d2817ba8024de44c4fd79913a90e5f7265434cef97026215b7d30df6", + "sha256:7c5d3e570ef46adaf93fc81b44aca6002b5a4d8ca11bd0580c07eac537f36680", + "sha256:7cb29a034301e2982df8b1fe6328a84f4b676106a13e9135a0d7e0c3e9f806da", + "sha256:7ccb800c9418e438b44b060a32adeb8393764da7441eb52aa2aa195448935306", + "sha256:7ce379bcaa9fcc00f19affa7773084dd09f5b59947b3fb47a1ceb0179f91aaa1", + "sha256:7f85e0108d51092bdda90672476c7d909c04ada6923c14ff9d913c4f7dc8a3bc", + "sha256:80babcc30e7a1a484eab952d76a4f4673ff601f54d5142c26826502740e70b43", + "sha256:82085c2abec437abebf457c1d12fccb30cc8b3774a0814872511f0f0562c768c", + "sha256:82b833d5563fefd6fceafb1aed2f3f3ebe19f84760fdd289f8b926731c2e6e91", + "sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f", + "sha256:893074d651cf25c1cc14e3bea4fceefd67f2921b1bb8e40fcfeba56820de80c6", + "sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a", + "sha256:89e66ceed67b213dec5a773e2f7a9e8c58f64daeb38c7859d8815d2c89f39ad7", + "sha256:8d47ebd9f5d9607fd039c1fbf4994e3b071ea23eff42f4ecef246ab2b7334198", + "sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623", + "sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839", + "sha256:97a662338797c660178e682f3bc180277b9569a59abfb5925e8620fba00b9fc5", + "sha256:9bed5144c6923cc902cd14bb8963f2d5e034def4486ab0bbe1f58f03f042f9a9", + "sha256:9c770750cc80e8694492244bca7251385188bc5597b6a39d98a9f30e8da984e0", + "sha256:9d32a592cac88d18cc09a89172e1c32d7f2a6e516c3dfde1b9adb90ab5df54a6", + "sha256:a5bc08f33c4966f4eb6590d6ff3ceae76151ad744576b5fc6c4ba8edd459fdec", + "sha256:a606c8070ada8aa2a88e181773fa1ef17ba65ce5dd168b9d08038e2a61b33754", + "sha256:a6c50017518329ed65a9e4829154626f008916d36295b6a3ba336e2458824c8c", + "sha256:a7b1d8315d9b5e9f89eb2933b73afae6ec9597a258d52190944437158b49d38e", + "sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084", + "sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d", + "sha256:a9d360a792cbcce2fe7b66b8d51274ec297c53cbc423401480e53b26161a290d", + "sha256:b150b8467852e1bd844387459aa6fbe11d7f38b56e901f9f3b3e6aba0d660240", + "sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58", + "sha256:b96d559e0fcddd3343c510a0fe2b127fbff16bf346dd76280b82292567523442", + "sha256:bcd51708a633410737111e998ceb3b45d3dbc98c0931f743d9bb0a209033a326", + "sha256:bfc8cdd7f33d57f0468b0614ae634cc38ab9202c6957a60e31d285a71ebe0301", + "sha256:c0342aafd421795d740e514bc9858ebddfc705a75a8c5046ac56d85fe97bf196", + "sha256:c279f0d2b34ef15f922b77966640ade58b4ccdfef1c4d94b20f2a364617a493f", + "sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7", + "sha256:c3bc7bf8cb8806f8d1c9bf149c18708cb1c406520097d6b0a73977460ea03602", + "sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3", + "sha256:c8aa771ff2c13dd9cda8166d685d7333d389fae30a4d2bb39d63ab5775de8606", + "sha256:cc1276d369452040cbb943300dc8abeedab14245ea44056a2943183822513a18", + "sha256:cd2fd827b0ba763ac919440042302315c564fdb797294d86e8cdd4578e3bc7f3", + "sha256:d30bbc1644f726b825b3278764240f449d75f1a8bdda892e641d4a688b1494ae", + "sha256:d5e9db7ef3ecbfc0b4733579cea45713a76852b002cf605420b12ef3ef1ec148", + "sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c", + "sha256:dd86b8e7f703ec6ff4f351cfdb9f428955859537125904aa8c963604f2e9d3e7", + "sha256:dee1316133c9b463aa81aca676bc506d3f80d8f65aeb0bba2b78d0b30c51d7bd", + "sha256:e0c48b6300cd0b0106bf49169c3e0536408dfbeb1ccb53180068a18b03c662ab", + "sha256:e5d0ddaca65ecca9c10dcf01730165fd858533d0be84c75c327487c37a906a27", + "sha256:e6a4dd644d72ab316b580a1c120b375890e4c52ec392d4aef3c63361ec4d77d1", + "sha256:eade977f5c96c677035ff39c56ac74d851b1cca7d607ab3d8f23c6b859379cab", + "sha256:ec28adb204b759306a3d64358a5e5c07d7b1dd0ccbce04aa76cb9377b7b70296", + "sha256:ece616532c499ee9afbb83078b1b952beffef121d989841f7f4b3dc5ac0fd212", + "sha256:eefc37f6138f522e771ac6db71a6d4838ec7933939676f3753eafd7d3f4c40bc", + "sha256:f0b48edbebea1b7421a9c687c304f7b44d0677c46498a046079d445454504737", + "sha256:f1abffa122452481a61c3551ab3c89d72238e279e517705b8b03847b1d93d738", + "sha256:f2f2c61bee5844d41c3eb015ac652a0229e901074951ae48581d58bfb2ba01be", + "sha256:f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8", + "sha256:fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e", + "sha256:fa9f547bd98f5553d03160967866a71056a60960be00356a15ecc44efb40ba8e", + "sha256:fab81ef75003eda96239a23eda4e4543cedc22e34c373edcaf744e721a163986", + "sha256:fd1b2281d01723f076df3c8188f43f2472248a6b63118b036e641243656b1b0f", + "sha256:fe1a92cfbaa0a1253e339ccec42dbe6db262615e52df591b68726ab10338003f" + ], + "markers": "python_version >= '3.7'", + "version": "==3.5.0" + }, "yarl": { "hashes": [ - "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", - "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", - "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318", - "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee", - "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", - "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1", - "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", - "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", - "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1", - "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", - "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", - "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", - "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", - "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc", - "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5", - "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", - "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", - "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", - "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24", - "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b", - "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910", - "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", - "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", - "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed", - "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", - "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04", - "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", - "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5", - "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", - "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", - "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", - "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b", - "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c", - "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", - "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34", - "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", - "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990", - "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", - "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", - "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", - "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", - "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6", - "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", - "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", - "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", - "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", - "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8", - "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", - "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e", - "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985", - "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8", - "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", - "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5", - "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690", - "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", - "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789", - "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", - "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", - "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", - "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", - "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", - "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9", - "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", - "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db", - "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde", - "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7", - "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", - "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", - "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", - "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", - "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", - "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", - "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", - "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd", - "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", - "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760", - "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", - "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", - "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", - "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", - "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719", - "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62" - ], - "markers": "python_version >= '3.9'", - "version": "==1.18.3" + "sha256:03aa1e041727cb438ca762628109ef1333498b122e4c76dd858d186a37cec845", + "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", + "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", + "sha256:0c869f2651cc77465f6cd01d938d91a11d9ea5d798738c1dc077f3de0b5e5fed", + "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", + "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", + "sha256:12e768f966538e81e6e7550f9086a6236b16e26cd964cf4df35349970f3551cf", + "sha256:14a85f3bd2d7bb255be7183e5d7d6e70add151a98edf56a770d6140f5d5f4010", + "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", + "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", + "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", + "sha256:1f8a891e4a22a89f5dde7862994485e19db246b70bb288d3ce73a34422e55b23", + "sha256:21242b4288a6d56f04ea193adde174b7e347ac46ce6bc84989ff7c1b1ecea84e", + "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", + "sha256:26ef53a9e726e61e9cd1cda6b478f17e350fb5800b4bd1cd9fe81c4d91cfeb2e", + "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", + "sha256:2c7b34d804b8cf9b214f05015c4fee2ebe7ed05cf581e7192c06555c71f4446a", + "sha256:2c89b5c792685dd9cd3fa9761c1b9f46fc240c2a3265483acc1565769996a3f8", + "sha256:30c41ad5d717b3961b2dd785593b67d386b73feca30522048d37298fee981805", + "sha256:33f29ecfe0330c570d997bcf1afd304377f2e48f61447f37e846a6058a4d33b2", + "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", + "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", + "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", + "sha256:41493b9b7c312ac448b7f0a42a089dffe1d6e6e981a2d76205801a023ed26a2b", + "sha256:41ebd28167bc6af8abb97fec1a399f412eec5fd61a3ccbe2305a18b84fb4ca73", + "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", + "sha256:46b5e0ccf1943a9a6e766b2c2b8c732c55b34e28be57d8daa2b3c1d1d4009309", + "sha256:47ee6188fea634bdfaeb2cc420f5b3b17332e6225ce88149a17c413c77ff269e", + "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", + "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", + "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", + "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", + "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", + "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", + "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", + "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", + "sha256:57edc88517d7fc62b174fcfb2e939fbc486a68315d648d7e74d07fac42cec240", + "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", + "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", + "sha256:597f40615b8d25812f14562699e287f0dcc035d25eb74da72cae043bb884d773", + "sha256:59febc3969b0781682b469d4aca1a5cab7505a4f7b85acf6db01fa500fa3f6ba", + "sha256:6032e6da6abd41e4acda34d75a816012717000fa6839f37124a47fcefc49bec4", + "sha256:62915e6688eb4d180d93840cda4110995ad50c459bf931b8b3775b37c264af1e", + "sha256:642980ef5e0fa1de5fa96d905c7e00cb2c47cb468bfcac5a18c58e27dbf8d8d1", + "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", + "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", + "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", + "sha256:69e9b141de5511021942a6866990aea6d111c9042235de90e08f94cf972ca03d", + "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", + "sha256:6c4fbf6b02d70e512d7ade4b1f998f237137f1417ab07ec06358ea04f69134f8", + "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", + "sha256:749d73611db8d26a6281086f859ea7ec08f9c4c56cec864e52028c8b328db723", + "sha256:76d12524d05841276b0e22573f28d5fbcb67589836772ae9244d90dd7d66aa13", + "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", + "sha256:7a8900a42fcdaad568de58887c7b2f602962356908eedb7628eaf6021a6e435b", + "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", + "sha256:812303eb4aa98e302886ccda58d6b099e3576b1b9276161469c25803a8db277d", + "sha256:835ab2cfc74d5eb4a6a528c57f05688099da41cf4957cf08cad38647e4a83b30", + "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", + "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", + "sha256:8601bc010d1d7780592f3fc1bdc6c72e2b6466ea34569778422943e1a1f3c389", + "sha256:86971e2795584fe8c002356d3b97ef6c61862720eeff03db2a7c86b678d85b3e", + "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", + "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", + "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", + "sha256:8f969afbb0a9b63c18d0feecf0db09d164b7a44a053e78a7d05f5df163e43833", + "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", + "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", + "sha256:9427925776096e664c39e131447aa20ec738bdd77c049c48ea5200db2237e000", + "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", + "sha256:98c4a7d166635147924aa0bf9bfe8d8abad6fffa6102de9c99ea04a1376f91e8", + "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", + "sha256:aef6c4d69554d44b7f9d923245f8ad9a707d971e6209d51279196d8e8fe1ae16", + "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", + "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", + "sha256:b5f307337819cdfdbb40193cad84978a029f847b0a357fbe49f712063cfc4f06", + "sha256:b982fa7f74c80d5c0c7b5b38f908971e513380a10fecea528091405f519b9ebb", + "sha256:bad6d131fda8ef508b36be3ece16d0902e80b88ea7200f030a0f6c11d9e508d4", + "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", + "sha256:bea21cdae6c7eb02ba02a475f37463abfe0a01f5d7200121b03e605d6a0439f8", + "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", + "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", + "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", + "sha256:c7ddf7a09f38667aea38801da8b8d6bfe81df767d9dfc8c88eb45827b195cd1c", + "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", + "sha256:d0f6500f69e8402d513e5eedb77a4e1818691e8f45e6b687147963514d84b44b", + "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", + "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", + "sha256:d2b6fb3622b7e5bf7a6e5b679a69326b4279e805ed1699d749739a61d242449e", + "sha256:daadbdc1f2a9033a2399c42646fbd46da7992e868a5fe9513860122d7fe7a73f", + "sha256:dab096ce479d5894d62c26ff4f699ec9072269d514b4edd630a393223f45a0ee", + "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", + "sha256:dd803820d44c8853a109a34e3660e5a61beae12970da479cf44aa2954019bf70", + "sha256:df018d92fe22aaebb679a7f89fe0c0f368ec497e3dda6cb81a567610f04501f1", + "sha256:df47c55f7d74127d1b11251fe6397d84afdde0d53b90bedb46a23c0e534f9d24", + "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", + "sha256:e42ba79e2efb6845ebab49c7bf20306c4edf74a0b20fc6b2ccdd1a219d12fad3", + "sha256:eae7bfe2069f9c1c5b05fc7fe5d612e5bbc089a39309904ee8b829e322dcad00", + "sha256:f5a5928ff5eb13408c62a968ac90d43f8322fd56d87008b8f9dabf3c0f6ee983", + "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", + "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", + "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", + "sha256:fe41919b9d899661c5c28a8b4b0acf704510b88f27f0934ac7a7bebdd8938d5e", + "sha256:ff70f32aa316393eaf8222d518ce9118148eddb8a53073c2403863b41033eed5" + ], + "markers": "python_version >= '3.9'", + "version": "==1.20.1" }, "zipp": { "hashes": [ - "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", - "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931" + "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", + "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166" ], "markers": "python_version >= '3.9'", - "version": "==3.21.0" + "version": "==3.23.0" + }, + "zstandard": { + "hashes": [ + "sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473", + "sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916", + "sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15", + "sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072", + "sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4", + "sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e", + "sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26", + "sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8", + "sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5", + "sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd", + "sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c", + "sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db", + "sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5", + "sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc", + "sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152", + "sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269", + "sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045", + "sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e", + "sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d", + "sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a", + "sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb", + "sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740", + "sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105", + "sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274", + "sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2", + "sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58", + "sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b", + "sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4", + "sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db", + "sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e", + "sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9", + "sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0", + "sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813", + "sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e", + "sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512", + "sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0", + "sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b", + "sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48", + "sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a", + "sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772", + "sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed", + "sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373", + "sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea", + "sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd", + "sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f", + "sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc", + "sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23", + "sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2", + "sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db", + "sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70", + "sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259", + "sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9", + "sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700", + "sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003", + "sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba", + "sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a", + "sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c", + "sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90", + "sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690", + "sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f", + "sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840", + "sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d", + "sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9", + "sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35", + "sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd", + "sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a", + "sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea", + "sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1", + "sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573", + "sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09", + "sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094", + "sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78", + "sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9", + "sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5", + "sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9", + "sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391", + "sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847", + "sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2", + "sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c", + "sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2", + "sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057", + "sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20", + "sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d", + "sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4", + "sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54", + "sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171", + "sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e", + "sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160", + "sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b", + "sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58", + "sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8", + "sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33", + "sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a", + "sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880", + "sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca", + "sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b", + "sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69" + ], + "markers": "python_version >= '3.8'", + "version": "==0.23.0" } }, "develop": { + "annotated-types": { + "hashes": [ + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" + ], + "markers": "python_version >= '3.8'", + "version": "==0.7.0" + }, "anyio": { "hashes": [ - "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", - "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a" + "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", + "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1" + ], + "markers": "python_version >= '3.9'", + "version": "==4.10.0" + }, + "attrs": { + "hashes": [ + "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", + "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" + ], + "markers": "python_version >= '3.8'", + "version": "==25.3.0" + }, + "authlib": { + "hashes": [ + "sha256:4dffdbb1460ba6ec8c17981a4c67af7d8af131231b5a36a88a1e8c80c111cdfd", + "sha256:e9d2031c34c6309373ab845afc24168fe9e93dc52d252631f52642f21f5ed06e" ], + "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==4.8.0" + "version": "==1.6.1" }, "autoflake": { "hashes": [ @@ -2438,59 +3146,76 @@ "markers": "python_version >= '3.8'", "version": "==2.3.1" }, + "bandit": { + "hashes": [ + "sha256:3348e934d736fcdb68b6aa4030487097e23a501adf3e7827b63658df464dddd0", + "sha256:dbfe9c25fc6961c2078593de55fd19f2559f9e45b99f1272341f5b95dea4e56b" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.8.6" + }, "black": { "hashes": [ - "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f", - "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd", - "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea", - "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981", - "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b", - "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7", - "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8", - "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175", - "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d", - "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392", - "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad", - "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f", - "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f", - "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b", - "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", - "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3", - "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800", - "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65", - "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2", - "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812", - "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50", - "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==24.10.0" + "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", + "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", + "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", + "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", + "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", + "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", + "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", + "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", + "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", + "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", + "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", + "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", + "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0", + "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", + "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", + "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", + "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355", + "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", + "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e", + "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", + "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", + "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==25.1.0" }, "boto3": { "hashes": [ - "sha256:4b6274b4fe9d7113f978abea66a1f20c8a397c268c9d1b2a6c96b14a256da4a5", - "sha256:d0224e1499d7189b47aa7f469d96522d98df6f5702fccb20a95a436582ebcd9d" + "sha256:2dfbc214fdbf94abfd61eec687ea39089d05af43bb00be792c76f3a6c1393f7b", + "sha256:3d99325ee874190e8f3bfd38823987327c826cdfbab943420851bdb7684d727c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.35.98" + "markers": "python_version >= '3.9'", + "version": "==1.40.2" }, "botocore": { "hashes": [ - "sha256:4f1c0b687488663a774ad3a5e81a5f94fae1bcada2364cfdc48482c4dbf794d5", - "sha256:d11742b3824bdeac3c89eeeaf5132351af41823bbcef8fc15e95c8250b1de09c" + "sha256:77c4710bf37b28e897833b5b1f47d6a83e45a29985cd01a560dfdb8b6ad524e5", + "sha256:a31e6269af05498f8dc1c7f2b3f34448a0f16c79a8601c0389ecddab51b2c2ab" ], - "markers": "python_version >= '3.8'", - "version": "==1.35.98" + "markers": "python_version >= '3.9'", + "version": "==1.40.2" + }, + "botocore-stubs": { + "hashes": [ + "sha256:a04e69766ab8bae338911c1897492f88d05cd489cd75f06e6eb4f135f9da8c7b", + "sha256:cc21d9a7dd994bdd90872db4664d817c4719b51cda8004fd507a4bf65b085a75" + ], + "markers": "python_version >= '3.9'", + "version": "==1.38.46" }, "certifi": { "hashes": [ - "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56", - "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db" + "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", + "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5" ], - "markers": "python_version >= '3.6'", - "version": "==2024.12.14" + "markers": "python_version >= '3.7'", + "version": "==2025.8.3" }, "cffi": { "hashes": [ @@ -2575,184 +3300,348 @@ }, "charset-normalizer": { "hashes": [ - "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537", - "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa", - "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a", - "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294", - "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b", - "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", - "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", - "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", - "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4", - "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", - "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2", - "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", - "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", - "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", - "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", - "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", - "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", - "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496", - "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d", - "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", - "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e", - "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a", - "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4", - "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca", - "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78", - "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408", - "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5", - "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", - "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", - "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a", - "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765", - "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6", - "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", - "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", - "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", - "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd", - "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c", - "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", - "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", - "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176", - "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770", - "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824", - "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f", - "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf", - "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487", - "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d", - "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd", - "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", - "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534", - "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f", - "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", - "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", - "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd", - "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", - "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9", - "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de", - "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", - "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d", - "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", - "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f", - "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", - "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7", - "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a", - "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", - "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8", - "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41", - "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", - "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f", - "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", - "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", - "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", - "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", - "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", - "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247", - "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", - "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb", - "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", - "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e", - "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6", - "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037", - "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", - "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e", - "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807", - "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", - "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c", - "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", - "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", - "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089", - "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", - "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e", - "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", - "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616" + "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", + "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", + "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", + "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", + "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", + "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", + "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", + "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", + "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", + "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", + "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", + "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", + "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", + "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", + "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", + "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", + "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", + "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", + "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", + "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", + "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", + "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", + "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", + "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", + "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", + "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", + "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", + "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", + "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", + "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", + "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", + "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", + "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", + "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", + "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", + "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", + "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", + "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", + "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", + "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", + "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", + "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", + "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", + "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", + "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", + "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", + "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", + "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", + "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", + "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", + "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", + "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", + "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", + "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", + "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", + "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", + "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", + "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", + "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", + "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", + "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", + "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", + "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", + "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", + "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", + "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", + "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", + "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", + "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", + "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", + "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", + "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", + "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", + "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", + "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", + "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", + "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", + "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", + "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", + "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", + "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", + "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", + "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", + "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", + "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", + "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", + "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", + "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", + "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", + "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", + "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", + "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" ], "markers": "python_version >= '3.7'", - "version": "==3.4.1" + "version": "==3.4.2" }, "click": { "hashes": [ - "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", - "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a" + "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", + "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b" ], - "markers": "python_version >= '3.7'", - "version": "==8.1.8" + "markers": "python_version >= '3.10'", + "version": "==8.2.1" + }, + "coverage": { + "extras": [ + "toml" + ], + "hashes": [ + "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", + "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", + "sha256:069b779d03d458602bc0e27189876e7d8bdf6b24ac0f12900de22dd2154e6ad7", + "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", + "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", + "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", + "sha256:164429decd0d6b39a0582eaa30c67bf482612c0330572343042d0ed9e7f15c20", + "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", + "sha256:20f405188d28da9522b7232e51154e1b884fc18d0b3a10f382d54784715bbe01", + "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", + "sha256:22aca3e691c7709c5999ccf48b7a8ff5cf5a8bd6fe9b36efbd4993f5a36b2fcf", + "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", + "sha256:2c3b210d79925a476dfc8d74c7d53224888421edebf3a611f3adae923e212b27", + "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", + "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", + "sha256:38fd1ccfca7838c031d7a7874d4353e2f1b98eb5d2a80a2fe5732d542ae25e9c", + "sha256:3b990df23dd51dccce26d18fb09fd85a77ebe46368f387b0ffba7a74e470b31b", + "sha256:3f37516458ec1550815134937f73d6d15b434059cd10f64678a2068f65c62406", + "sha256:44329cbed24966c0b49acb386352c9722219af1f0c80db7f218af7793d251902", + "sha256:4c2de4cb80b9990e71c62c2d3e9f3ec71b804b1f9ca4784ec7e74127e0f42468", + "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", + "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", + "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", + "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", + "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", + "sha256:64586ce42bbe0da4d9f76f97235c545d1abb9b25985a8791857690f96e23dc3b", + "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", + "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", + "sha256:6c031da749a05f7a01447dd7f47beedb498edd293e31e1878c0d52db18787df0", + "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", + "sha256:6f0cbe5f7dd19f3a32bac2251b95d51c3b89621ac88a2648096ce40f9a5aa1e7", + "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", + "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", + "sha256:75bf7ab2374a7eb107602f1e07310cda164016cd60968abf817b7a0b5703e288", + "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", + "sha256:765b13b164685a2f8b2abef867ad07aebedc0e090c757958a186f64e39d63dbd", + "sha256:76c1ffaaf4f6f0f6e8e9ca06f24bb6454a7a5d4ced97a1bc466f0d6baf4bd518", + "sha256:79f0283ab5e6499fd5fe382ca3d62afa40fb50ff227676a3125d18af70eabf65", + "sha256:7f10ca4cde7b466405cce0a0e9971a13eb22e57a5ecc8b5f93a81090cc9c7eb9", + "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", + "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", + "sha256:86da8a3a84b79ead5c7d0e960c34f580bc3b231bb546627773a3f53c532c2f21", + "sha256:890ad3a26da9ec7bf69255b9371800e2a8da9bc223ae5d86daeb940b42247c83", + "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", + "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", + "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", + "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", + "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", + "sha256:98a838101321ac3089c9bb1d4bfa967e8afed58021fda72d7880dc1997f20ae1", + "sha256:99cef9731c8a39801830a604cc53c93c9e57ea8b44953d26589499eded9576e0", + "sha256:99d16f15cb5baf0729354c5bd3080ae53847a4072b9ba1e10957522fb290417f", + "sha256:9bdff88e858ee608a924acfad32a180d2bf6e13e059d6a7174abbae075f30436", + "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", + "sha256:9dd37e9ac00d5eb72f38ed93e3cdf2280b1dbda3bb9b48c6941805f265ad8d87", + "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", + "sha256:a219b70100500d0c7fd3ebb824a3302efb6b1a122baa9d4eb3f43df8f0b3d899", + "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", + "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", + "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", + "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", + "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", + "sha256:adda2268b8cf0d11f160fad3743b4dfe9813cd6ecf02c1d6397eceaa5b45b388", + "sha256:ae385e1d58fbc6a9b1c315e5510ac52281e271478b45f92ca9b5ad42cf39643f", + "sha256:bc2e69b795d97ee6d126e7e22e78a509438b46be6ff44f4dccbb5230f550d340", + "sha256:bc3945b7bad33957a9eca16e9e5eae4b17cb03173ef594fdaad228f4fc7da53b", + "sha256:be127f292496d0fbe20d8025f73221b36117b3587f890346e80a13b310712982", + "sha256:bf67d1787cd317c3f8b2e4c6ed1ae93497be7e30605a0d32237ac37a37a8a322", + "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", + "sha256:c7195444b932356055a8e287fa910bf9753a84a1bc33aeb3770e8fca521e032e", + "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", + "sha256:cc3902584d25c7eef57fb38f440aa849a26a3a9f761a029a72b69acfca4e31f8", + "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", + "sha256:d8f2d83118f25328552c728b8e91babf93217db259ca5c2cd4dd4220b8926293", + "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", + "sha256:de3c6271c482c250d3303fb5c6bdb8ca025fff20a67245e1425df04dc990ece9", + "sha256:e33e79a219105aa315439ee051bd50b6caa705dc4164a5aba6932c8ac3ce2d98", + "sha256:e4545e906f595ee8ab8e03e21be20d899bfc06647925bc5b224ad7e8c40e08b8", + "sha256:e4f5f1320f8ee0d7cfa421ceb257bef9d39fd614dd3ddcfcacd284d4824ed2c2", + "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", + "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", + "sha256:ea58b112f2966a8b91eb13f5d3b1f8bb43c180d624cd3283fb33b1cedcc2dd75", + "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", + "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", + "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", + "sha256:f2a79145a531a0e42df32d37be5af069b4a914845b6f686590739b786f2f7bce", + "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", + "sha256:fd17f427f041f6b116dc90b4049c6f3e1230524407d00daa2d8c7915037b5947", + "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb" + ], + "markers": "python_version >= '3.9'", + "version": "==7.10.2" }, "cryptography": { "hashes": [ - "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7", - "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731", - "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b", - "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc", - "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543", - "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c", - "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591", - "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede", - "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb", - "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f", - "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123", - "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c", - "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c", - "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285", - "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd", - "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092", - "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa", - "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289", - "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02", - "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64", - "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053", - "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417", - "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e", - "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e", - "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7", - "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756", - "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4" + "sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7", + "sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8", + "sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463", + "sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30", + "sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f", + "sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd", + "sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135", + "sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d", + "sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57", + "sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd", + "sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e", + "sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e", + "sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1", + "sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0", + "sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a", + "sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a", + "sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492", + "sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e", + "sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e", + "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97", + "sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174", + "sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9", + "sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18", + "sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0", + "sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27", + "sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63", + "sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e", + "sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d", + "sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6", + "sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42", + "sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097", + "sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9", + "sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d", + "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f", + "sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0", + "sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5", + "sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8" ], "markers": "python_version >= '3.7' and python_full_version not in '3.9.0, 3.9.1'", - "version": "==44.0.0" + "version": "==45.0.5" + }, + "cyclopts": { + "hashes": [ + "sha256:92efb4a094d9812718d7efe0bffa319a19cb661f230dbf24406c18cd8809fb82", + "sha256:fa2450b9840abc41c6aa37af5eaeafc7a1264e08054e3a2fe39d49aa154f592a" + ], + "markers": "python_version >= '3.9'", + "version": "==3.22.5" }, "deepdiff": { "extras": [ "murmur" ], "hashes": [ - "sha256:b0231fa3afb0f7184e82535f2b4a36636442ed21e94a0cf3aaa7982157e7ebca", - "sha256:dd7bc7d5c8b51b5b90f01b0e2fe23c801fd8b4c6a7ee7e31c5a3c3663fcc7ceb" + "sha256:a4dd3529fa8d4cd5b9cbb6e3ea9c95997eaa919ba37dac3966c1b8f872dc1cd1", + "sha256:d4599db637f36a1c285f5fdfc2cd8d38bde8d8be8636b65ab5e425b67c54df26" ], - "markers": "python_version >= '3.8'", - "version": "==8.1.1" + "markers": "python_version >= '3.9'", + "version": "==8.5.0" }, "distlib": { "hashes": [ - "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", - "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403" + "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", + "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d" ], - "version": "==0.3.9" + "version": "==0.4.0" }, - "filelock": { + "dnspython": { "hashes": [ - "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", - "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435" + "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", + "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1" + ], + "markers": "python_version >= '3.9'", + "version": "==2.7.0" + }, + "docstring-parser": { + "hashes": [ + "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912", + "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708" ], "markers": "python_version >= '3.8'", - "version": "==3.16.1" + "version": "==0.17.0" }, - "h11": { + "docutils": { "hashes": [ - "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", - "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + "sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", + "sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f" + ], + "markers": "python_version >= '3.9'", + "version": "==0.22" + }, + "email-validator": { + "hashes": [ + "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", + "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.2.0" + }, + "exceptiongroup": { + "hashes": [ + "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", + "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88" ], "markers": "python_version >= '3.7'", - "version": "==0.14.0" + "version": "==1.3.0" + }, + "fastmcp": { + "hashes": [ + "sha256:2b5af21b093d4926fef17a9a162d5729a2fcb46f3b195699762fa01f61ac3c60", + "sha256:9f0b6a3f61dcf6f688a0a24b8b507be24bfae051a00b7d590c01395d63da8c00" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==2.11.1" + }, + "filelock": { + "hashes": [ + "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", + "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18.0" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" }, "httpcore": { "hashes": [ - "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", - "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd" + "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", + "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" ], "markers": "python_version >= '3.8'", - "version": "==1.0.7" + "version": "==1.0.9" }, "httpx": { "hashes": [ @@ -2763,13 +3652,22 @@ "markers": "python_version >= '3.8'", "version": "==0.28.1" }, + "httpx-sse": { + "hashes": [ + "sha256:8f44d34414bc7b21bf3602713005c5df4917884f76072479b21f68befa4ea26e", + "sha256:cba42174344c3a5b06f255ce65b350880f962d99ead85e776f23c6618a377a37" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==0.4.1" + }, "identify": { "hashes": [ - "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566", - "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc" + "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", + "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6" ], "markers": "python_version >= '3.9'", - "version": "==2.6.5" + "version": "==2.6.12" }, "idna": { "hashes": [ @@ -2781,19 +3679,27 @@ }, "iniconfig": { "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", + "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "isodate": { + "hashes": [ + "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", + "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6" ], "markers": "python_version >= '3.7'", - "version": "==2.0.0" + "version": "==0.7.2" }, "jinja2": { "hashes": [ - "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb", - "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb" + "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", + "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" ], "markers": "python_version >= '3.7'", - "version": "==3.1.5" + "version": "==3.1.6" }, "jmespath": { "hashes": [ @@ -2803,6 +3709,58 @@ "markers": "python_version >= '3.7'", "version": "==1.0.1" }, + "jsonschema": { + "hashes": [ + "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716", + "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f" + ], + "markers": "python_version >= '3.9'", + "version": "==4.25.0" + }, + "jsonschema-path": { + "hashes": [ + "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001", + "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8" + ], + "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'", + "version": "==0.3.4" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", + "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608" + ], + "markers": "python_version >= '3.9'", + "version": "==2025.4.1" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:01261a3afd8621a1accb5682df2593dc7ec7d21d38f411011a5712dcd418fbed", + "sha256:0613116156801ab3fccb9e2b05ed83b08ea08c2517fdc6c6bc0d4697a1a376e3", + "sha256:090935756cc041e191f22f4f9c7fd4fe9a454717067adf5b1bbd2ce3046b556e", + "sha256:132bc8a34f2f2d662a851acfd1b93df769992ed1b81e2b1fda7db3e73b0d5a18", + "sha256:18874411864c9fbbbaa47f9fc1dd7aea754c86cfde21278ef427639d1dd78e9c", + "sha256:28c174db37946f94b97a97b579932ff88f07b8d73a46b6b93322b9ac06794a3b", + "sha256:76ec715017f06410f57df442c1a8d66e6b5f7035077785b129817f5ae58810a4", + "sha256:9a9f39098e93a63618a79eef2889ae3cf0605f676cd4797fdfd49fcd7ddc318b", + "sha256:a56a5093d433341ff7da0e89f9b486031ccd222ec8e52ec84d0ec1cdc819674b", + "sha256:bb03c507d96b65f617a6337dedd604399d35face2cdf01526b913fb50c4cb6e8", + "sha256:d2503427bda552d3aefcac92f81d9e7ca631e680a2268cbe62cd6a58de6409b7", + "sha256:d662f0669e27704495ff1f647070eb8816931231c44e583f4d0701b7adf6272f", + "sha256:ee13f67f4fcd044ef27bfccb1c93d39c100046fec1fad6e9a1fcdfd17492aeb3", + "sha256:fd4c84eafd8dd15ea16f7d580758bc5c2ce1f752faec877bb2b1f9f827c329cd" + ], + "markers": "python_version >= '3.9'", + "version": "==1.11.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, "markupsafe": { "hashes": [ "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", @@ -2870,69 +3828,94 @@ "markers": "python_version >= '3.9'", "version": "==3.0.2" }, + "mcp": { + "hashes": [ + "sha256:5483345bf39033b858920a5b6348a303acacf45b23936972160ff152107b850e", + "sha256:ab2e05f5e5c13e1dc90a4a9ef23ac500a6121362a564447855ef0ab643a99fed" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==1.12.3" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "more-itertools": { + "hashes": [ + "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", + "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e" + ], + "markers": "python_version >= '3.9'", + "version": "==10.7.0" + }, "moto": { "extras": [ "s3" ], "hashes": [ - "sha256:6829f58a670a087e7c5b63f8183c6b72d64a1444e420c212250b7326b69a9183", - "sha256:803831f427ca6c0452ae4fb898d731cfc19906466a33a88cbc1076abcbfcbba7" + "sha256:0c4f0387b06b5d24c0ce90f8f89f31a565cc05789189c5d59b5df02594f2e371", + "sha256:e9ba7e4764a6088ccc34e3cc846ae719861ca202409fa865573de40a3e805b9b" ], - "markers": "python_version >= '3.8'", - "version": "==5.0.26" + "markers": "python_version >= '3.9'", + "version": "==5.1.9" }, "mypy": { "hashes": [ - "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", - "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", - "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", - "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", - "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", - "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", - "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", - "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", - "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319", - "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", - "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", - "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", - "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", - "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", - "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31", - "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", - "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", - "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", - "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", - "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", - "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837", - "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6", - "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", - "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", - "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", - "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", - "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", - "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", - "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b", - "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac", - "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", - "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", - "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", - "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", - "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", - "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", - "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", - "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89" + "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", + "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", + "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", + "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", + "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", + "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", + "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", + "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", + "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", + "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972", + "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8", + "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", + "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9", + "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", + "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", + "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", + "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", + "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99", + "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7", + "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", + "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", + "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", + "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", + "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94", + "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", + "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", + "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8", + "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", + "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", + "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df", + "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", + "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d", + "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390", + "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b", + "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", + "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", + "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259", + "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.14.1" + "markers": "python_version >= '3.9'", + "version": "==1.17.1" }, "mypy-extensions": { "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", + "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" + "markers": "python_version >= '3.8'", + "version": "==1.1.0" }, "nodeenv": { "hashes": [ @@ -2942,13 +3925,45 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==1.9.1" }, + "openapi-core": { + "hashes": [ + "sha256:421e753da56c391704454e66afe4803a290108590ac8fa6f4a4487f4ec11f2d3", + "sha256:ef7210e83a59394f46ce282639d8d26ad6fc8094aa904c9c16eb1bac8908911f" + ], + "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'", + "version": "==0.19.5" + }, + "openapi-pydantic": { + "hashes": [ + "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", + "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d" + ], + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==0.5.1" + }, + "openapi-schema-validator": { + "hashes": [ + "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee", + "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3" + ], + "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'", + "version": "==0.6.3" + }, + "openapi-spec-validator": { + "hashes": [ + "sha256:4bbdc0894ec85f1d1bea1d6d9c8b2c3c8d7ccaa13577ef40da9c006c9fd0eb60", + "sha256:cc029309b5c5dbc7859df0372d55e9d1ff43e96d678b9ba087f7c56fc586f734" + ], + "markers": "python_full_version >= '3.8.0' and python_full_version < '4.0.0'", + "version": "==0.7.2" + }, "orderly-set": { "hashes": [ - "sha256:571ed97c5a5fca7ddeb6b2d26c19aca896b0ed91f334d9c109edd2f265fb3017", - "sha256:d357cedcf67f4ebff0d4cbd5b0997e98eeb65dd24fdf5c990a501ae9e82c7d34" + "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7", + "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce" ], "markers": "python_version >= '3.8'", - "version": "==5.2.3" + "version": "==5.5.0" }, "packaging": { "hashes": [ @@ -2958,6 +3973,21 @@ "markers": "python_version >= '3.8'", "version": "==24.2" }, + "parse": { + "hashes": [ + "sha256:967095588cb802add9177d0c0b6133b5ba33b1ea9007ca800e526f42a85af558", + "sha256:b41d604d16503c79d81af5165155c0b20f6c8d6c559efa66b4b695c3e5a0a0ce" + ], + "version": "==1.20.2" + }, + "pathable": { + "hashes": [ + "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", + "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2" + ], + "markers": "python_full_version >= '3.7.0' and python_full_version < '4.0.0'", + "version": "==0.4.4" + }, "pathspec": { "hashes": [ "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", @@ -2966,30 +3996,38 @@ "markers": "python_version >= '3.8'", "version": "==0.12.1" }, + "pbr": { + "hashes": [ + "sha256:38d4daea5d9fa63b3f626131b9d34947fd0c8be9b05a29276870580050a25a76", + "sha256:93ea72ce6989eb2eed99d0f75721474f69ad88128afdef5ac377eb797c4bf76b" + ], + "markers": "python_version >= '2.6'", + "version": "==6.1.1" + }, "platformdirs": { "hashes": [ - "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", - "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb" + "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", + "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4" ], - "markers": "python_version >= '3.8'", - "version": "==4.3.6" + "markers": "python_version >= '3.9'", + "version": "==4.3.8" }, "pluggy": { "hashes": [ - "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", - "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" ], - "markers": "python_version >= '3.8'", - "version": "==1.5.0" + "markers": "python_version >= '3.9'", + "version": "==1.6.0" }, "pre-commit": { "hashes": [ - "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2", - "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878" + "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", + "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==4.0.1" + "version": "==4.2.0" }, "py-partiql-parser": { "hashes": [ @@ -3006,31 +4044,176 @@ "markers": "python_version >= '3.8'", "version": "==2.22" }, + "pydantic": { + "hashes": [ + "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", + "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==2.11.7" + }, + "pydantic-core": { + "hashes": [ + "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", + "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", + "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", + "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", + "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", + "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", + "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", + "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", + "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", + "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", + "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", + "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", + "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", + "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", + "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", + "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", + "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", + "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", + "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", + "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", + "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", + "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", + "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", + "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", + "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", + "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", + "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", + "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", + "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", + "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", + "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", + "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", + "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", + "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", + "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", + "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", + "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", + "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", + "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", + "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", + "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", + "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", + "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", + "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", + "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", + "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", + "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", + "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", + "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", + "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", + "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", + "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", + "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", + "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", + "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", + "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", + "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", + "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", + "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", + "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", + "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", + "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", + "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", + "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", + "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", + "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", + "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", + "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", + "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", + "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", + "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", + "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", + "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", + "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", + "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", + "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", + "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", + "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", + "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", + "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", + "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", + "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", + "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", + "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", + "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", + "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", + "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", + "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", + "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", + "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", + "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", + "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", + "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", + "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", + "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", + "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", + "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", + "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", + "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.33.2" + }, + "pydantic-settings": { + "hashes": [ + "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", + "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796" + ], + "markers": "python_version >= '3.9'", + "version": "==2.10.1" + }, "pyflakes": { "hashes": [ - "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", - "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a" + "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", + "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f" + ], + "markers": "python_version >= '3.9'", + "version": "==3.4.0" + }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" ], "markers": "python_version >= '3.8'", - "version": "==3.2.0" + "version": "==2.19.2" + }, + "pyperclip": { + "hashes": [ + "sha256:b7de0142ddc81bfc5c7507eea19da920b92252b548b96186caf94a5e2527d310" + ], + "version": "==1.9.0" }, "pytest": { "hashes": [ - "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", - "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761" + "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", + "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==8.3.4" + "markers": "python_version >= '3.9'", + "version": "==8.4.1" }, "pytest-asyncio": { "hashes": [ - "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075", - "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f" + "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf", + "sha256:796aa822981e01b68c12e4827b8697108f7205020f24b5793b3c41555dab68ea" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.1.0" + }, + "pytest-cov": { + "hashes": [ + "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", + "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==0.25.2" + "version": "==6.2.1" }, "pytest-httpx": { "hashes": [ @@ -3049,6 +4232,22 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, + "python-dotenv": { + "hashes": [ + "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", + "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" + ], + "markers": "python_version >= '3.9'", + "version": "==1.1.1" + }, + "python-multipart": { + "hashes": [ + "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", + "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13" + ], + "markers": "python_version >= '3.8'", + "version": "==0.0.20" + }, "pyyaml": { "hashes": [ "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", @@ -3108,55 +4307,245 @@ "markers": "python_version >= '3.8'", "version": "==6.0.2" }, + "referencing": { + "hashes": [ + "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", + "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" + ], + "markers": "python_version >= '3.9'", + "version": "==0.36.2" + }, "requests": { "hashes": [ - "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", - "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", + "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.32.3" + "version": "==2.32.4" }, "responses": { "hashes": [ - "sha256:9cac8f21e1193bb150ec557875377e41ed56248aed94e4567ed644db564bacf1", - "sha256:eae7ce61a9603004e76c05691e7c389e59652d91e94b419623c12bbfb8e331d8" + "sha256:8ebae11405d7a5df79ab6fd54277f6f2bc29b2d002d0dd2d5c632594d1ddcedb", + "sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c" ], "markers": "python_version >= '3.8'", - "version": "==0.25.6" + "version": "==0.25.7" + }, + "rfc3339-validator": { + "hashes": [ + "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", + "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.1.4" + }, + "rich": { + "hashes": [ + "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", + "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==14.1.0" + }, + "rich-rst": { + "hashes": [ + "sha256:498a74e3896507ab04492d326e794c3ef76e7cda078703aa592d1853d91098c1", + "sha256:fad46e3ba42785ea8c1785e2ceaa56e0ffa32dbe5410dec432f37e4107c4f383" + ], + "markers": "python_version >= '3.6'", + "version": "==1.3.1" + }, + "rpds-py": { + "hashes": [ + "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3", + "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b", + "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5", + "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806", + "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e", + "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4", + "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f", + "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915", + "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be", + "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b", + "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696", + "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323", + "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331", + "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8", + "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c", + "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19", + "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1", + "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8", + "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0", + "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318", + "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246", + "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256", + "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b", + "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb", + "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04", + "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1", + "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19", + "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7", + "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f", + "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871", + "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84", + "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e", + "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387", + "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40", + "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958", + "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44", + "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582", + "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7", + "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292", + "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a", + "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba", + "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953", + "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51", + "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9", + "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37", + "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9", + "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137", + "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3", + "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0", + "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8", + "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1", + "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e", + "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618", + "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67", + "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1", + "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d", + "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9", + "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da", + "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0", + "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b", + "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84", + "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d", + "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11", + "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1", + "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7", + "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79", + "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f", + "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88", + "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0", + "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a", + "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158", + "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226", + "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f", + "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f", + "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1", + "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad", + "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7", + "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a", + "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae", + "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08", + "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03", + "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a", + "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d", + "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11", + "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6", + "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9", + "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb", + "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca", + "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf", + "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9", + "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15", + "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19", + "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed", + "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed", + "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6", + "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d", + "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387", + "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f", + "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8", + "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5", + "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37", + "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45", + "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72", + "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf", + "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090", + "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20", + "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e", + "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e", + "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284", + "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc", + "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8", + "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867", + "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33", + "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255", + "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8", + "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c", + "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323", + "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107", + "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d", + "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a", + "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2", + "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0", + "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41", + "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af", + "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d", + "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632", + "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d", + "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21", + "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170", + "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", + "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf", + "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd", + "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0", + "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7", + "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3", + "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35", + "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674", + "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73", + "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37", + "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f", + "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136", + "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83", + "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12", + "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9" + ], + "markers": "python_version >= '3.9'", + "version": "==0.26.0" }, "ruff": { "hashes": [ - "sha256:186c2313de946f2c22bdf5954b8dd083e124bcfb685732cfb0beae0c47233d9b", - "sha256:1cd76c7f9c679e6e8f2af8f778367dca82b95009bc7b1a85a47f1521ae524fa7", - "sha256:2f312c86fb40c5c02b44a29a750ee3b21002bd813b5233facdaf63a51d9a85e1", - "sha256:342a824b46ddbcdddd3abfbb332fa7fcaac5488bf18073e841236aadf4ad5c19", - "sha256:39d0174ccc45c439093971cc06ed3ac4dc545f5e8bdacf9f067adf879544d969", - "sha256:3cae39ba5d137054b0e5b472aee3b78a7c884e61591b100aeb544bcd1fc38d4f", - "sha256:3f94942a3bb767675d9a051867c036655fe9f6c8a491539156a6f7e6b5f31831", - "sha256:46ebf5cc106cf7e7378ca3c28ce4293b61b449cd121b98699be727d40b79ba72", - "sha256:50c647ff96f4ba288db0ad87048257753733763b409b2faf2ea78b45c8bb7fcb", - "sha256:5dc40a378a0e21b4cfe2b8a0f1812a6572fc7b230ef12cd9fac9161aa91d807f", - "sha256:69572926c0f0c9912288915214ca9b2809525ea263603370b9e00bed2ba56dbd", - "sha256:728d791b769cc28c05f12c280f99e8896932e9833fef1dd8756a6af2261fd1ab", - "sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743", - "sha256:937267afce0c9170d6d29f01fcd1f4378172dec6760a9f4dface48cdabf9610a", - "sha256:ae017c3a29bee341ba584f3823f805abbe5fe9cd97f87ed07ecbf533c4c88366", - "sha256:beb3298604540c884d8b282fe7625651378e1986c25df51dec5b2f60cafc31ce", - "sha256:f0c8b149e9c7353cace7d698e1656ffcf1e36e50f8ea3b5d5f7f87ff9986a7ca", - "sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17" + "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", + "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", + "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", + "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", + "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", + "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", + "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", + "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", + "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", + "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", + "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", + "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", + "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", + "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", + "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", + "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", + "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", + "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.9.1" + "version": "==0.12.7" }, "s3transfer": { "hashes": [ - "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e", - "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7" + "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", + "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf" ], - "markers": "python_version >= '3.8'", - "version": "==0.10.4" + "markers": "python_version >= '3.9'", + "version": "==0.13.1" + }, + "setuptools": { + "hashes": [ + "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", + "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" + ], + "markers": "python_version >= '3.9'", + "version": "==80.9.0" }, "six": { "hashes": [ @@ -3174,71 +4563,177 @@ "markers": "python_version >= '3.7'", "version": "==1.3.1" }, + "sse-starlette": { + "hashes": [ + "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a", + "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a" + ], + "markers": "python_version >= '3.9'", + "version": "==3.0.2" + }, + "starlette": { + "hashes": [ + "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", + "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b" + ], + "markers": "python_version >= '3.9'", + "version": "==0.47.2" + }, + "stevedore": { + "hashes": [ + "sha256:3135b5ae50fe12816ef291baff420acb727fcd356106e3e9cbfa9e5985cd6f4b", + "sha256:d10a31c7b86cba16c1f6e8d15416955fc797052351a56af15e608ad20811fcfe" + ], + "markers": "python_version >= '3.9'", + "version": "==5.4.1" + }, + "types-awscrt": { + "hashes": [ + "sha256:8eefe50d1709520663b77d3643a772c35ace3d8acfcb296f857627622c84cb4c", + "sha256:99ee40e787dfb92ae93a5c956251a03b847de3ac532552f7e06dd5eb6e0fd02f" + ], + "markers": "python_version >= '3.8'", + "version": "==0.27.5" + }, "types-beautifulsoup4": { "hashes": [ - "sha256:158370d08d0cd448bd11b132a50ff5279237a5d4b5837beba074de152a513059", - "sha256:c95e66ce15a4f5f0835f7fbc5cd886321ae8294f977c495424eaf4225307fd30" + "sha256:5923399d4a1ba9cc8f0096fe334cc732e130269541d66261bb42ab039c0376ee", + "sha256:aa19dd73b33b70d6296adf92da8ab8a0c945c507e6fb7d5db553415cc77b417e" ], "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==4.12.0.20250516" + }, + "types-boto3": { + "extras": [ + "bedrock", + "s3", + "textract" + ], + "hashes": [ + "sha256:4d222ca72fb70afb5d4205616dedacdafed00b416d434fbb8a57a387d582aa9a", + "sha256:578a3a47dda8d85457e23e766592f6a6d40df88f7f9cd93527d98ba2e5d46546" + ], "markers": "python_version >= '3.8'", - "version": "==4.12.0.20241020" + "version": "==1.40.2" }, - "types-cachetools": { + "types-boto3-bedrock": { "hashes": [ - "sha256:b888ab5c1a48116f7799cd5004b18474cd82b5463acb5ffb2db2fc9c7b053bc0", - "sha256:efb2ed8bf27a4b9d3ed70d33849f536362603a90b8090a328acf0cd42fda82e2" + "sha256:804cc040ed4830a58c06c50fa055216c1c87456c0f69947174f4bca56043b6a0", + "sha256:c032b0939bd939c73c91c2016edcc1396ad527d755330a8f9c991e316d7d37bc" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==5.5.0.20240820" + "version": "==1.40.0" }, - "types-html5lib": { + "types-boto3-bedrock-runtime": { + "hashes": [ + "sha256:2d2cd0c90bbc537f0b02d7855df9d49591bf4bea321d70711b8a19a761f3c1e9", + "sha256:cc393692a9b7cb9b779c4d9980adfa41a5ef68ae5c7f896890b14d7cac62eb6e" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.40.0" + }, + "types-boto3-s3": { + "hashes": [ + "sha256:c84cf5ee7168076dd4427f8f64a903fc3f1ca907887c41ca620e9fcc16758e2d", + "sha256:efc08aff95eca9b05bbc94fdb0fc1727c1259fab5ddfe68cdfa83fd43c698732" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==1.40.0" + }, + "types-boto3-textract": { "hashes": [ - "sha256:3f1e064d9ed2c289001ae6392c84c93833abb0816165c6ff0abfc304a779f403", - "sha256:98042555ff78d9e3a51c77c918b1041acbb7eb6c405408d8a9e150ff5beccafa" + "sha256:74f5e7da604dad945aaaa2a7bf782b385cfbffcc3b6ffa6b369e9c2534f8fd2a", + "sha256:ab43a80f679f7335ce0721a1b2060b32d1f62ddc2c66c497f13cd7b5811444d8" ], + "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.1.11.20241018" + "version": "==1.40.0" + }, + "types-cachetools": { + "hashes": [ + "sha256:4acc8e25de9f5f84dd176ea81dcffa7cb24393869bb2e59e692dfd0139a1e66f", + "sha256:bba4b8d42262460d24e570097d2d9040e60311934603caa642efd971f3658ed0" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==6.1.0.20250717" + }, + "types-html5lib": { + "hashes": [ + "sha256:24321720fdbac71cee50d5a4bec9b7448495b7217974cffe3fcf1ede4eef7afe", + "sha256:bb898066b155de7081cb182179e2ded31b9e0e234605e2cb46536894e68a6954" + ], + "markers": "python_version >= '3.9'", + "version": "==1.1.11.20250708" }, "types-requests": { "hashes": [ - "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95", - "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747" + "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", + "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072" + ], + "markers": "python_version >= '3.9'", + "version": "==2.32.4.20250611" + }, + "types-s3transfer": { + "hashes": [ + "sha256:203dadcb9865c2f68fb44bc0440e1dc05b79197ba4a641c0976c26c9af75ef52", + "sha256:79c8375cbf48a64bff7654c02df1ec4b20d74f8c5672fc13e382f593ca5565b3" ], "markers": "python_version >= '3.8'", - "version": "==2.32.0.20241016" + "version": "==0.13.0" }, "typing-extensions": { "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" + "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", + "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76" ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" + "markers": "python_version >= '3.9'", + "version": "==4.14.1" + }, + "typing-inspection": { + "hashes": [ + "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", + "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.1" }, "urllib3": { "hashes": [ - "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", - "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d" + "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", + "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" ], "markers": "python_version >= '3.9'", - "version": "==2.3.0" + "version": "==2.5.0" + }, + "uvicorn": { + "hashes": [ + "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", + "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==0.35.0" }, "virtualenv": { "hashes": [ - "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb", - "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329" + "sha256:106b6baa8ab1b526d5a9b71165c85c456fbd49b16976c88e2bc9352ee3bc5d3f", + "sha256:47e0c0d2ef1801fce721708ccdf2a28b9403fa2307c3268aebd03225976f61d2" ], "markers": "python_version >= '3.8'", - "version": "==20.28.1" + "version": "==20.33.0" }, "werkzeug": { "hashes": [ - "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", - "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746" + "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4", + "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5" ], "markers": "python_version >= '3.9'", - "version": "==3.1.3" + "version": "==3.1.1" }, "xmltodict": { "hashes": [ diff --git a/README.md b/README.md index fb581a652..b090655db 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ## Overview This project is a language model gateway that provides an OpenAI compatible API for language models. It is built using FastAPI and GraphQL. + ## Prerequisites - Docker @@ -19,35 +20,82 @@ To run the project locally, follow these steps: cd ``` -2. Set up the development environment: +2. Create `docker.env` file in the root of the project based on the `docker.env.example`. +Update the keys for the functionality/providers you're planning on using. +`AWS_CREDENTIALS_PROFILE` is the only one that is absolutely required to get going. Set this to the AWS profile you're part of e.g., `admin_dev`. + +3. Set up the development environment: ```sh make devsetup ``` -3. Start the Docker containers: +4. Start the Docker containers: ```sh - make up + make down; make up ``` -4. Navigate to the GraphQL endpoint: - ``` - http://localhost:5050/graphql - ``` +5. Refer to the [Running without OAuth](#running-without-oauth) or [Running with OAuth](#running-with-oauth) sections below to start OpenWebUI. + +## Project Architecture + +The project is structured into several main components: + +- **API**: Built using FastAPI, it provides endpoints for interacting with the language models. +- **GraphQL**: Used for querying and mutating data. +- **Routers**: Define the routes for different functionalities like chat completions, image generation, etc. +- **Managers**: Handle the business logic for different functionalities. +- **Utilities**: Helper functions and classes used across the project. +- **Tools**: AI Agents that perform specific tasks like querying databases, calling APIs, etc. + +## Dependencies + +The main libraries and tools used in this project are: -## Example Query +- FastAPI +- GraphQL +- Docker +- Docker Compose +- Make +- Pipenv +- Uvicorn +- Datadog + +## Usage Examples + +Here are some sample API requests and responses: -Here is a simple GraphQL query to get providers: +### Chat Completions -```graphql -query getProviders { - providers( - query_id: "foo" - ) { - total_count - results { - result_id - } +**Request:** +```sh +curl -X POST "http://localhost:5050/api/v1/chat/completions" -H "Content-Type: application/json" -d '{ + "model": "gpt-3.5-turbo", + "messages": [{"role": "user", "content": "Hello, how are you?"}] +}' +``` + +**Response:** +```json +{ + "id": "chatcmpl-123", + "object": "chat.completion", + "created": 1677652288, + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "I am fine, thank you!" + }, + "finish_reason": "stop" } + ], + "usage": { + "prompt_tokens": 9, + "completion_tokens": 7, + "total_tokens": 16 + } } ``` @@ -58,11 +106,10 @@ Just run the following commands to run OpenWebUI without OAuth: make down; make up; make up-open-webui ``` - ## Running with OAuth -Since the OpenWebUI uses Keycloak on both server side and browser side, you need to create a host mapping for `keycloak`. +Since the OpenWebUI uses Keycloak on both server side and browser side, you **MUST** create a host mapping for `keycloak`. -On Macs, this can be done by adding an entry to `/etc/hosts`: +On Macs, this is done by adding an entry to `/etc/hosts`. This is likely a `sudo` operation so you may need to run `sudo nano /etc/hosts` or `sudo vi /etc/hosts` (depending on your preferred editor) and add the following line: ```sh 127.0.0.1 keycloak @@ -72,3 +119,42 @@ Then run: ```shell make down; make up; make up-open-webui-auth ``` + +For more details and getting the models list up and running, refer to the [openwebui_functions/readme.md](openwebui_functions/readme.md). + +## Contributing + +We welcome contributions to the project! To contribute, follow these steps: + +1. Fork the repository. +2. Create a new branch for your feature or bugfix. +3. Make your changes and commit them with a clear message. +4. Push your changes to your fork. +5. Create a pull request to the main repository. + +## Reporting Issues + +If you encounter any issues, please report them by creating a new issue in the repository's issue tracker. + +## Frequently Asked Questions (FAQs) + +### How do I set up the environment variables? + +Create a `docker.env` file in the root of the project based on the `docker.env.example` file. Update the keys for the functionality/providers you're planning on using. + +### How do I run the tests? + +You can run the tests using the following command: +```sh +make tests +``` + +### How do I add a new AI Agent? + +Refer to the [add_new_agent.md](add_new_agent.md) file for detailed instructions on how to add a new AI Agent. + +## Troubleshooting Tips + +- If you encounter issues with Docker, try restarting the Docker service. +- Ensure that all environment variables are set correctly. +- Check the logs for any error messages and stack traces. diff --git a/add_new_agent.md b/add_new_agent.md new file mode 100644 index 000000000..b0ffdaf3a --- /dev/null +++ b/add_new_agent.md @@ -0,0 +1,264 @@ +from typing import Annotatedfrom pydantic import BaseModel + +# How to add a new AI Agent + +## What is an AI Agent +An AI Agent is just code that can be called by an LLM to do external tasks such as querying databases, calling APIs, running Python code etc. + +There is no data science knowledge needed to write an AI Agent. +An AI Agent is just a Python class that derives from a `BaseTool` class and implements a function to do the task. + +Note: "tools" was the old name for this functionality in OpenAI. Then OpenAI renamed it to "functions". But nowadays people call these "AI Agents". So all three are synonymous in this context. + + +## Examples +Simple example of an AI Agent that just returns the current date and time: +[language_model_gateway/gateway/tools/current_time_tool.py](language_model_gateway/gateway/tools/current_time_tool.py) + +Example of an AI Agent that talks to Jira to get list of issues: +[language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py](language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py) + +Example of an AI Agent that talks to Provider Search Service: +[language_model_gateway/gateway/tools/provider_search_tool.py](language_model_gateway/gateway/tools/provider_search_tool.py) + + +## Creating the AI Agent +### Step 1: Add a new file to hold your AI Agent class +Create a new Python file in [language_model_gateway/gateway/tools](language_model_gateway/gateway/tools). + +### Step 2: Define a Pydantic model class to specify the input parameters for your AI Agent +This class should inherit from Pydantic's BaseModel class. This class should have a list of input parameters that you want the LLM to pass to your AI Agent. + +```python +from pydantic import BaseModel, Field +from typing import Type, Optional, List, Tuple, Literal + +class JiraIssuesAnalyzerAgentInput(BaseModel): + """ + Input model for configuring GitHub Pull Request extraction and analysis. + """ + + project_name: Optional[str] = Field( + default=None, + description=( + "Optional specific project name to analyze. " + "PARSING INSTRUCTION: Extract exact project name from the query if query specifies a project name. " + ), + ) +``` +- Mark it as Optional if this is an optional parameter +- Set default if the parameter is Optional +- Provide a description to aid the LLM in knowing what to pass for this parameter +- Add any additional parameters + + +### Step 3: Define your AI Agent class +This class should inherit from `ResilientBaseTool`. ResilientBaseTool is our subclass of LangChain's BaseTool. Our subclass handles parameter naming issue. + +```python +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from typing import Type, Optional, List, Tuple, Literal +from pydantic import BaseModel, Field + +class JiraIssuesAnalyzerTool(ResilientBaseTool): + """ + A LangChain-compatible tool for comprehensive Jira issue analysis. + + This tool can be used to extract and analyze Jira issues across projects and assignees. + + """ + + name: str = "Replace with name of your AI agent" + description: str = ( + "Description of your AI Agent so the LLM knows when to call it." + "---- Sample below -----" + "Advanced Jira Issue analysis tool. " + "USAGE TIPS: " + "- Specify assignee with username " + "- If querying for a specific date range, include 'from [date] to [date]' " + "- Set 'counts_only' if you want to get counts only" + "- Set include_full_description to get full issue description" + "- Set 'sort_by' to sort by 'created', 'updated', 'popularity', or 'long-running' " + "- Set 'sort_by_direction' to 'asc' or 'desc' " + "- Set use_verbose_logging to get verbose logs" + "- Example queries: " + "'Pull issues in EFS', " + "'Issues assigned to johndoe in EFS', " + "'What issues assigned to imranq2 in EFS project'" + "'Get last 10 issues'" + ) + + args_schema: Type[BaseModel] = JiraIssuesAnalyzerAgentInput # Should be the input parameters class you created above + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + # You can define any other initialization parameters to your class. These are not passed by the LLM but we can pass them + # during initialization +``` +IMPORTANT: Your description is really important because that's what tells the LLM when and how to use your AI Agent. +If needed, just ask our AI tool what description to use for your class. + +Now implement the `_arun` method to do the actual work. +```python +from typing import Type, Optional, List, Tuple, Literal +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + +class JiraIssuesAnalyzerTool(ResilientBaseTool): + async def _arun( + self, + # add parameters here that mirror the fields in your input parameters class + # For example: + project_name: Optional[str] = None + ) -> Tuple[str, str]: + # do your actual work here + return "response to LLM", "artifact that is not given to LLM but shown in the UI" +``` +IMPORTANT: This function should take the same parameters as the fields in your input parameters class. + +You also have to implement the synchronous version of this method but you can just return `NotImplementedError`. +```python +from typing import Type, Optional, List, Tuple, Literal +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + +class JiraIssuesAnalyzerTool(ResilientBaseTool): + def _run( + self, + # add parameters here that mirror the fields in your input parameters class + # For example: + project_name: Optional[str] = None + ) -> Tuple[str, str]: + """ + Synchronous version of the tool (falls back to async implementation). + + Raises: + NotImplementedError: Always raises to enforce async usage + """ + raise NotImplementedError("Use async version of this tool") + +``` + +Recommendation: Separate your actual code into a utility class that you can test directly without having to go through the LLM. +As an example, see how `language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py` uses +the `language_model_gateway/gateway/utilities/jira/jira_issues_helper.py` class to handle all the communication with Jira. + +This allows us to test the latter with unit tests without using the LLM: +`tests/gateway/utilities/jira/test_jira_issues_helper.py` + +### Step 4: Add your new AI Agent to the tool_provider.py +Add your new AI Agent to the tool_provider.py file in the same directory: `language_model_gateway/gateway/tools/tool_provider.py`. This is where the LLM will look for all available AI Agents. + +```python +from typing import Dict +from langchain_core.tools import BaseTool +from language_model_gateway.gateway.tools.jira_issues_analyzer_tool import ( + JiraIssuesAnalyzerTool, +) +from language_model_gateway.gateway.utilities.jira.jira_issues_helper import ( + JiraIssueHelper, +) + +class ToolProvider: + def __init__( + self, + *, + jira_issues_helper: JiraIssueHelper, + ) -> None: + self.tools: Dict[str, BaseTool] = { + "jira_issues_analyzer": JiraIssuesAnalyzerTool( + jira_issues_helper=jira_issues_helper + ) + } + ``` +Match the name here with the name defined in your AI Agent class + +### Step 5: Register your agent in the container_factory +Add your new AI Agent to the container_factory.py file in the same directory: `language_model_gateway/container/container_factory.py`. This is where the LLM will look for all available AI Agents. + +```python +container.register( + JiraIssueHelper, + lambda c: JiraIssueHelper( + http_client_factory=c.resolve(HttpClientFactory), + jira_base_url=c.resolve(EnvironmentVariables).jira_base_url, + access_token=c.resolve(EnvironmentVariables).jira_token, + username=c.resolve(EnvironmentVariables).jira_username, + ), +) +``` +You may also need to register any dependencies that your AI Agent needs to the container_factory.py file. For example, the JiraIssueHelper needs a HttpClientFactory class to do the actual work. +```python +container.register(HttpClientFactory, lambda c: HttpClientFactory()) +``` + + +### Step 6: Add your agent to the configuration for task models +You can now add this to any task model configurations where you want this tool available: `language_model_gateway/configs/chat_completions/testing` + +```json +{ + "tools": [ + { + "name": "current_date" + }, + { + "name": "jira_issues_analyzer" + } + ] +} +``` + +## Unit testing your AI Agent + +### Step 1: Create unit tests for your utility class +If you created a separate utility class, as recommended above, then you can just write unit tests as normal. + + +### Step 2: Create unit test for your AI Agent +Take a look at this example unit test: `tests/gateway/tools/test_jira_issues_analyzer_tool.py`. + +Since we use Dependency Injection (DI) containers, you can override any class by supplying a new implementation in the container. + +When `RUN_TESTS_WITH_REAL_LLM` environment variable is not set, you can mock various parts of the code. +When `RUN_TESTS_WITH_REAL_LLM` is set then you can test against the real LLMs with the same code. + +## Integration testing your AI Agent using real LLMs +Change the `RUN_TESTS_WITH_REAL_LLM` environment variable to "1" in docker-compose.yml. +Now your unit tests will run using real LLMs so you can add breakpoints and step through your code. + + +## Adding Authentication +If your AI Agent needs access to the bearer token of the user, you do the following. + +Add auth_token as an input parameter to your AI Agent input model. This will be injected by our code. +```python +from langgraph.prebuilt import InjectedState +from typing import Type, Optional, List, Tuple, Literal, Dict, Annotated +from pydantic import BaseModel, Field + +class GitHubPullRequestAnalyzerAgentInput(BaseModel): + auth_token: Annotated[Optional[str], InjectedState("auth_token")] = Field( + default=None, + description="Injected state", + ) +``` + +Now you can add auth_token as a parameter to your `_arun` method and it will be passed to your code when present. +```python +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from typing import Type, Optional, List, Tuple, Literal, Dict, Annotated + +class GitHubPullRequestAnalyzerTool(ResilientBaseTool): + async def _arun( + self, + *, + auth_token: Optional[str] = None, + ) -> Tuple[str, str]: + pass +``` + +This will be the auth_token that was passed to our language model gateway when the user authenticated. + +In the case of the OpenWebUI this is the Okta access token generated when the user authenticated. + +In the case of API, this is whatever Bearer token the was passed in the Authorization header. + +``` diff --git a/docker-compose-integration.yml b/docker-compose-integration.yml new file mode 100644 index 000000000..2bc84fc75 --- /dev/null +++ b/docker-compose-integration.yml @@ -0,0 +1,4 @@ +services: + dev: + environment: + RUN_TESTS_WITH_REAL_LLM: 1 diff --git a/docker-compose-mcp-server-gateway.yml b/docker-compose-mcp-server-gateway.yml new file mode 100644 index 000000000..fb993604b --- /dev/null +++ b/docker-compose-mcp-server-gateway.yml @@ -0,0 +1,25 @@ +services: + mcp_server_gateway: + depends_on: + - keycloak + build: + dockerfile: Dockerfile + context: ../mcp-server-gateway + container_name: mcp-server-gateway + environment: + DEBUG_METRICS: 0 + DD_TRACE_ENABLED: "false" + LOG_LEVEL: DEBUG + # These define the connection to the identity provider for JWT validation + AUTH_WELL_KNOWN_URI: "http://keycloak:8080/realms/bwell-realm/.well-known/openid-configuration" + env_file: docker.env + command: ["uvicorn", "mcp_server_gateway.api:app", "--host", "0.0.0.0", "--port", "5000", "--reload", "--log-level", "debug"] + ports: + - '5051:5000' + healthcheck: + test: curl --fail -s http://localhost:5000/health || exit 1 + interval: 30s + timeout: 10s + retries: 3 + networks: + - web \ No newline at end of file diff --git a/docker-compose-openwebui-auth.yml b/docker-compose-openwebui-auth.yml index 82fcbacc3..d3984b6f6 100644 --- a/docker-compose-openwebui-auth.yml +++ b/docker-compose-openwebui-auth.yml @@ -1,4 +1,3 @@ -version: '3' services: open-webui: environment: @@ -17,63 +16,7 @@ services: OAUTH_PROVIDER_NAME: "keycloak" OAUTH_SCOPES: "openid email" OAUTH_USERNAME_CLAIM: "email" - - keycloak: - # https://github.com/keycloak/keycloak/releases - image: quay.io/keycloak/keycloak:25.0.6 - # container_name: keycloak - # build: - # dockerfile: keycloak.Dockerfile - # context: . - # depends_on: - # - postgres - environment: - KC_HEALTH_ENABLED: true - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: password - # KC_DB: postgres - # KC_DB_URL: jdbc:postgresql://postgres/pdb - # KC_DB_USERNAME: admin - # KC_DB_PASSWORD: admin - # The below settings are for test data creation - # This is the user and password that will be created in the realm - MY_ADMIN_USER_NAME: admin - MY_ADMIN_USER_PASSWORD: password - MY_ADMIN_USER_SCOPE: user/*.* access/*.* - MY_ADMIN_USER_GROUPS: user/*.* access/*.* - MY_ADMIN_USER_TOKEN_USERNAME: admin - # This is the user and password that will be created in the realm - MY_USER_NAME: tester - MY_USER_PASSWORD: password - # These groups get specified as scopes in the token - MY_USER_GROUPS: user/*.*,access/*.* launch/patient,patient/*.read - MY_USER_SCOPE: user/*.* access/*.* launch/patient patient/*.read openid profile email - MY_USER_TOKEN_USERNAME: tester - # This is the client setup - CLIENT_ID: bwell-client-id - CLIENT_SECRET: bwell-secret - # This is the service account that will be created in the realm - SERVICE_ACCOUNT_NAME: service-account - SERVICE_ACCOUNT_SCOPE: user/*.* access/*.* - SERVICE_ACCOUNT_GROUPS: user/*.* access/*.* - # These are the custom claims that will be added to any generated token - MY_USER_CLIENT_PERSON_ID: 0b2ad38a-20bc-5cf5-9739-13f242b05892 - MY_USER_CLIENT_PATIENT_ID: 22aa18af-af51-5799-bc55-367c22c85407 - MY_USER_BWELL_PERSON_ID: 0eb80391-0f61-5ce6-b221-a5428f2f38a7 - MY_USER_BWELL_PATIENT_ID: patient2 - QUARKUS_HTTP_ACCESS_LOG_PATTERN: "%r\n%{ALL_REQUEST_HEADERS}" - ports: - - "8080:8080" - command: [ "start-dev", "--import-realm", "--verbose" ] - volumes: - - ./keycloak-config/realm-import.json:/opt/keycloak/data/import/realm-import.json - healthcheck: - test: [ "CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000;echo -e \"GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3" ] - interval: 10s - timeout: 5s - retries: 5 - networks: - - web + WEBUI_URL: "https://open-webui.localhost" openid-connect-debugger: image: leplusorg/openid-connect-provider-debugger:latest diff --git a/docker-compose-openwebui-ssl.yml b/docker-compose-openwebui-ssl.yml index 7c8b1bedc..7b0f8303b 100644 --- a/docker-compose-openwebui-ssl.yml +++ b/docker-compose-openwebui-ssl.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: traefik: image: traefik:v2.10 diff --git a/docker-compose-openwebui.yml b/docker-compose-openwebui.yml index c6d9311f2..f64a6d8d1 100644 --- a/docker-compose-openwebui.yml +++ b/docker-compose-openwebui.yml @@ -1,9 +1,8 @@ -version: '3.8' - services: open-webui: # https://github.com/open-webui/open-webui/releases - image: ghcr.io/open-webui/open-webui:v0.5.4 +# image: openwebui-local:latest + image: ghcr.io/open-webui/open-webui:v0.6.18 depends_on: - open-webui-db env_file: @@ -11,7 +10,7 @@ services: ports: - "3050:8080" environment: - # https://docs.openwebui.com/getting-started/advanced-topics/env-configuration + # https://docs.openwebui.com/getting-started/env-configuration/ BYPASS_MODEL_ACCESS_CONTROL: True DEFAULT_USER_ROLE: user WEBUI_AUTH: 0 @@ -20,6 +19,8 @@ services: SRC_LOG_LEVELS: '{"SOCKET": "DEBUG", "MAIN": "DEBUG", "MODELS": "DEBUG", "OPENAI": "DEBUG", "OAUTH": "DEBUG", "CONFIG": "DEBUG", "DB": "DEBUG"}' # OPENAI_API_BASE_URL: 'http://dev:5000/api/v1' # Supports balanced OpenAI base API URLs, semicolon-separated. + # disable OEPNAI_API since we use a Pipeline to handle requests + ENABLE_OPENAI_API: 0 OPENAI_API_BASE_URL: 'http://dev:5000/api/v1' CORS_ALLOW_ORIGIN: '*' OPENAI_API_KEY: 'bedrock' @@ -52,7 +53,7 @@ services: AUDIO_TTS_VOICE: "alloy" SAFE_MODE: True ENABLE_WEBSOCKET_SUPPORT: True - # disable some unneeded stuff like RAG + # RAG requires downloading embedding models. On slow connections, this can timeout docker compose RAG_EMBEDDING_MODEL: "" # curl --silent --fail http://localhost:8081/health | jq -ne 'input.status == true' || exit 1 WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY:-$(openssl rand -hex 32)}" diff --git a/docker-compose.yml b/docker-compose.yml index 721e3d2a5..8d96a6dff 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,10 @@ -version: '3' services: dev: build: dockerfile: Dockerfile context: . - container_name: language_model_gateway + target: development + container_name: language-model-gateway environment: DEBUG_METRICS: 0 DD_TRACE_ENABLED: "false" @@ -14,7 +14,6 @@ services: DEFAULT_PATIENT_ID: "eEooRVLYdWIW753OhZUd1dgxQRny4KCo6fiH-13lY0043" # DEFAULT_WEB_SEARCH_TOOL: "duckduckgo_search" DEFAULT_WEB_SEARCH_TOOL: "google_search" - RUN_TESTS_WITH_REAL_LLM: 0 IMAGE_GENERATION_PATH: "/usr/src/language_model_gateway/image_generation" # IMAGE_GENERATION_PATH: "s3://bwell-dev-data-science-ue1/openwebui/image_generation/" IMAGE_GENERATION_URL: "http://localhost:5050/image_generation" @@ -36,12 +35,19 @@ services: DEFAULT_MODEL_PROVIDER: "bedrock" DEFAULT_MODEL_NAME: "us.anthropic.claude-3-5-haiku-20241022-v1:0" GITHUB_ORGANIZATION_NAME: "icanbwell" - GITHUB_MAXIMUM_REPOS: 100 - GITHUB_MAXIMUM_PULL_REQUESTS_PER_REPO: 100 + GITHUB_MAXIMUM_REPOS: "100" + GITHUB_MAXIMUM_PULL_REQUESTS_PER_REPO: "100" JIRA_BASE_URL: "https://icanbwell.atlassian.net" - JIRA_USERNAME: "imran.qureshi@icanbwell.com" - JIRA_MAXIMUM_PROJECTS: 100 - JIRA_MAXIMUM_ISSUES_PER_PROJECT: 100 +# JIRA_USERNAME: "imran.qureshi@icanbwell.com" + JIRA_MAXIMUM_PROJECTS: "100" + JIRA_MAXIMUM_ISSUES_PER_PROJECT: "100" + MCP_TOOLS_METADATA_CACHE_TIMEOUT_SECONDS: 30 + # These define the connection to the identity provider for JWT validation + AUTH_WELL_KNOWN_URI: "http://keycloak:8080/realms/bwell-realm/.well-known/openid-configuration" + # if well-known URI is defined then JWKS_URI, AUTH_AUDIENCE and AUTH_ISSUER are not needed +# AUTH_JWKS_URI: "http://keycloak:8080/realms/bwell-realm/protocol/openid-connect/certs" +# AUTH_AUDIENCE: "my-mcp-server" +# AUTH_ISSUER: "https://my-identity-provider.com/" env_file: docker.env ports: - '5050:5000' @@ -57,6 +63,63 @@ services: networks: - web + keycloak: + # https://github.com/keycloak/keycloak/releases + image: quay.io/keycloak/keycloak:25.0.6 + # container_name: keycloak + # build: + # dockerfile: keycloak.Dockerfile + # context: . + # depends_on: + # - postgres + environment: + KC_HEALTH_ENABLED: true + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: password + # KC_DB: postgres + # KC_DB_URL: jdbc:postgresql://postgres/pdb + # KC_DB_USERNAME: admin + # KC_DB_PASSWORD: admin + # The below settings are for test data creation + # This is the user and password that will be created in the realm + MY_ADMIN_USER_NAME: admin + MY_ADMIN_USER_PASSWORD: password + MY_ADMIN_USER_SCOPE: user/*.* access/*.* + MY_ADMIN_USER_GROUPS: user/*.* access/*.* + MY_ADMIN_USER_TOKEN_USERNAME: admin + # This is the user and password that will be created in the realm + MY_USER_NAME: tester + MY_USER_PASSWORD: password + # These groups get specified as scopes in the token + MY_USER_GROUPS: user/*.*,access/*.* launch/patient,patient/*.read + MY_USER_SCOPE: user/*.* access/*.* launch/patient patient/*.read openid profile email + MY_USER_TOKEN_USERNAME: tester + # This is the client setup + CLIENT_ID: bwell-client-id + CLIENT_SECRET: bwell-secret + # This is the service account that will be created in the realm + SERVICE_ACCOUNT_NAME: service-account + SERVICE_ACCOUNT_SCOPE: user/*.* access/*.* + SERVICE_ACCOUNT_GROUPS: user/*.* access/*.* + # These are the custom claims that will be added to any generated token + MY_USER_CLIENT_PERSON_ID: 0b2ad38a-20bc-5cf5-9739-13f242b05892 + MY_USER_CLIENT_PATIENT_ID: 22aa18af-af51-5799-bc55-367c22c85407 + MY_USER_BWELL_PERSON_ID: 0eb80391-0f61-5ce6-b221-a5428f2f38a7 + MY_USER_BWELL_PATIENT_ID: patient2 + QUARKUS_HTTP_ACCESS_LOG_PATTERN: "%r\n%{ALL_REQUEST_HEADERS}" + ports: + - "8080:8080" + command: [ "start-dev", "--import-realm", "--verbose" ] + volumes: + - ./keycloak-config/realm-import.json:/opt/keycloak/data/import/realm-import.json + healthcheck: + test: [ "CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000;echo -e \"GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n\" >&3;grep \"HTTP/1.1 200 OK\" <&3" ] + interval: 10s + timeout: 5s + retries: 5 + networks: + - web + networks: web: - driver: bridge + driver: bridge \ No newline at end of file diff --git a/docker.env.example b/docker.env.example index 4a3330e70..d64b1db3b 100644 --- a/docker.env.example +++ b/docker.env.example @@ -9,3 +9,10 @@ GOOGLE_CSE_ID= TAVILY_API_KEY= SCRAPING_BEE_API_KEY= GITHUB_TOKEN= +JIRA_TOKEN= +JIRA_USERNAME= +DATABRICKS_TOKEN= +DATABRICKS_HOST= +DATABRICKS_SQL_WAREHOUSE_ID= +GOOGLE_CREDENTIALS_JSON= +TEST_GOOGLE_DRIVE_EMAIL= \ No newline at end of file diff --git a/inspector.Dockerfile b/inspector.Dockerfile new file mode 100644 index 000000000..87fdf3a6c --- /dev/null +++ b/inspector.Dockerfile @@ -0,0 +1,33 @@ +# Inspector Dockerfile +FROM node:20-alpine + +# Install git +RUN apk add --no-cache git + +# Clone the MCP Inspector repository +RUN git clone https://github.com/modelcontextprotocol/inspector.git /app +WORKDIR /app + +# Install dependencies and build +RUN npm install && npm run build + +# Set environment variables if needed +ENV DANGEROUSLY_OMIT_AUTH=true + +# Expose the default port +EXPOSE 6277 + +# Switch to the root user to perform user management tasks +USER root + +# Create a restricted user (appuser) and group (appgroup) for running the application +RUN addgroup -S appgroup && adduser -S -h /etc/appuser appuser -G appgroup + +# Ensure that the appuser owns the application files and directories +RUN chown -R appuser:appgroup ${PROJECT_DIR} /usr/local/lib/python3.12/site-packages /usr/local/bin ${PROMETHEUS_MULTIPROC_DIR} + +# Switch to the restricted user to enhance security +USER appuser + +# Start the inspector +CMD ["npm", "start"] diff --git a/language_model_gateway/configs/chat_completions/official/general_purpose.json b/language_model_gateway/configs/chat_completions/official/general_purpose.json index a514df8ab..44a0f260e 100644 --- a/language_model_gateway/configs/chat_completions/official/general_purpose.json +++ b/language_model_gateway/configs/chat_completions/official/general_purpose.json @@ -40,6 +40,18 @@ } ] }, + { + "name": "calculator_average" + }, + { + "name": "calculator_stddev" + }, + { + "name": "calculator_length" + }, + { + "name": "calculator_sum" + }, { "name": "pubmed" }, diff --git a/language_model_gateway/configs/chat_completions/official/google_drive.json b/language_model_gateway/configs/chat_completions/official/google_drive.json new file mode 100644 index 000000000..385713a9f --- /dev/null +++ b/language_model_gateway/configs/chat_completions/official/google_drive.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", + "id": "google_drive", + "name": "Google Drive", + "description": "This is a language model that can access data in Google Drive.", + "type": "langchain", + "model": { + "provider": "bedrock", + "model": "us.anthropic.claude-3-5-haiku-20241022-v1:0" + }, + "system_prompts": [ + { + "role": "system", + "content": "You are a tool that searches and retrieves files from Google Drive. You can also download files from Google Drive given a url." + } + ], + "model_parameters": [ + { + "key": "temperature", + "value": 0.5 + } + ], + "headers": [ + { + "key": "Authorization", + "value": "Bearer OPENAI_API_KEY" + } + ], + "tools": [ + { + "name": "current_date", + "parameters": [ + { + "key": "format", + "value": "YYYY-MM-DD" + } + ] + }, + { + "name": "google_drive", + "url": "http://mcp_server_gateway:5000/google_drive/", + "auth": "jwt_token" + } + ], + "example_prompts": [ + { + "role": "user", + "content": "Summarize the contents of the file at this URL: https://drive.google.com/file/d/1a2b3c4d5e6f7g8h9i0j/view?usp=sharing" + } + ] +} diff --git a/language_model_gateway/configs/chat_completions/official/high_accuracy.json b/language_model_gateway/configs/chat_completions/official/high_accuracy.json index 92f3510da..68488da5a 100644 --- a/language_model_gateway/configs/chat_completions/official/high_accuracy.json +++ b/language_model_gateway/configs/chat_completions/official/high_accuracy.json @@ -44,6 +44,18 @@ } ] }, + { + "name": "calculator_average" + }, + { + "name": "calculator_stddev" + }, + { + "name": "calculator_length" + }, + { + "name": "calculator_sum" + }, { "name": "pubmed" }, diff --git a/language_model_gateway/configs/chat_completions/testing/confluence.json b/language_model_gateway/configs/chat_completions/testing/confluence.json new file mode 100644 index 000000000..c1dd2d3b4 --- /dev/null +++ b/language_model_gateway/configs/chat_completions/testing/confluence.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", + "id": "confluence", + "name": "Confluence", + "description": "This model allows searching through Confluence for relevant articles and retrieving specific pages based on search results.", + "owner": "Denis Chaykovskiy", + "system_prompts": [ + { + "role": "system", + "content": "You are an advanced search and information retrieval AI assistant that can search Confluence and analyze Confluence pages with the following MANDATORY source tracking and citation requirements:\\n\\n## Enhanced Search Strategy\\n\\n### Keyword Extraction Protocol\\n- Extract NO MORE than 5 most important keywords\\n- Keywords MUST be:\\n Alphanumeric only\\n Separated by single space\\n No quotes or special characters\\n Represent core query intent\\n\\n### Source Tracking Protocol\\n- EVERY search MUST create a detailed source tracking log\\n- Maintain a comprehensive source_log during entire search process\\n- Log MUST include:\\n _FULL, CLICKABLE DOCUMENT URL (e.g., https://company.atlassian.net/wiki/spaces/DEPT/pages/12345678/Specific+Page+Title)\\n _Complete document title\\n _Exact excerpt\\n _Relevance score\\n _Timestamp of retrieval\\n\\n## Keyword Extraction Example\\n\\n### Query: How do we set up continuous integration for Python projects?\\n### Extracted Keywords: continuous integration python projects devops\\n\\n## Mandatory Search Execution Rules\\n\\n1. Source Logging Requirements:\\n - Immediately log source for EVERY piece of retrieved information\\n - NO information can be used without a COMPLETE, CLICKABLE source URL\\n - Create source entry BEFORE including information in final response\\n\\n2. Search Execution Steps:\\n - Extract core keywords\\n - Perform targeted searches\\n - Capture ALL potential sources\\n - Rate and rank sources\\n - Log detailed source information WITH FULL URLs\\n - Cross-reference sources\\n - Verify source credibility\\n\\n## Strict Response Generation Guidelines\\n\\n- EVERY statement in response MUST have a corresponding source WITH A COMPLETE, CLICKABLE URL\\n- Inline citations are REQUIRED\\n- Source log must be comprehensive and transparent\\n- Confidence level must be explicitly stated for each source\\n\\n## Mandatory Output Format\\n\\n# Comprehensive Search Results\\n\\n## Extracted Keywords\\n[List of 5 max keywords used in search]\\n\\n## Source Log\\n[COMPLETE list of ALL sources, with FULL, CLICKABLE URLs and complete details]\\n\\n## Query Analysis\\n[Detailed breakdown of search strategy]\\n\\n## Answer\\n[Cited answer with MANDATORY inline source references]\\n\\n### Source Citation Format\\n- REQUIRED: [FULL, CLICKABLE Source URL] (Confidence: X%)\\n- REQUIRED: Exact page/section reference\\n- REQUIRED: Verbatim excerpt\\n\\n## Verification Mechanism\\n- Cross-reference sources\\n- Highlight potential conflicts or discrepancies\\n- Explicitly state limitations in source information\\n\\n## Ethical Source Handling\\n- Prioritize authoritative and verifiable sources\\n- Immediately discard unverifiable or low-credibility sources\\n- Maintain transparent source evaluation process\\n\\n## Failure Conditions\\n- IF no credible sources found: MUST provide detailed explanation\\n- MUST suggest alternative search strategies\\n- CANNOT generate response without proper sourcing WITH COMPLETE URLS\\n\\n## Confidence Scoring\\n- Implement 0-100 confidence scoring for:\\n _Individual sources\\n _Overall response\\n _Information reliability\\n\\n## Example Enforcement\\n\\n### Bad Response (REJECTED):\\n- Unsourced claims\\n- No citation details\\n- Vague information\\n- Missing or incomplete URLs\\n\\n### Good Response (ACCEPTED):\\n- Comprehensive source log\\n- Inline citations\\n- Transparent confidence levels\\n- Verifiable references WITH COMPLETE, CLICKABLE URLS\\n\\nAny deviation from these sourcing requirements results in response rejection and mandatory re-execution of the search with full source tracking." + } + ], + "example_prompts": [ + { + "role": "user", + "content": "is there anything documented in Confluence regarding the concept of data sets in PSS?" + } + ], + "tools": [ + { + "name": "current_date" + }, + { + "name": "confluence_search_tool" + }, + { + "name": "confluence_page_retriever" + } + ] +} \ No newline at end of file diff --git a/language_model_gateway/configs/chat_completions/testing/engineering_metrics.json b/language_model_gateway/configs/chat_completions/testing/development_tools.json similarity index 84% rename from language_model_gateway/configs/chat_completions/testing/engineering_metrics.json rename to language_model_gateway/configs/chat_completions/testing/development_tools.json index 706282876..19be5a837 100644 --- a/language_model_gateway/configs/chat_completions/testing/engineering_metrics.json +++ b/language_model_gateway/configs/chat_completions/testing/development_tools.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", - "id": "engineering_metrics", - "name": "Engineering Metrics", - "description": "This model allows searching pull requests across repos and getting git diff and getting issues from Jira.", + "id": "development_tools", + "name": "Development Tools", + "description": "This model allows searching pull requests across repos, getting git diff and getting issues from Jira.", "owner": "Imran Qureshi", "system_prompts": [ { @@ -30,4 +30,4 @@ "name": "jira_issues_analyzer" } ] -} +} \ No newline at end of file diff --git a/language_model_gateway/configs/chat_completions/testing/fhir_data_query_expert.json b/language_model_gateway/configs/chat_completions/testing/fhir_data_query_expert.json new file mode 100644 index 000000000..d601a94ad --- /dev/null +++ b/language_model_gateway/configs/chat_completions/testing/fhir_data_query_expert.json @@ -0,0 +1,68 @@ +{ + "id": "fhir_data_query_expert", + "name": "FHIR Data Query Expert", + "description": "An AI agent that transforms FHIR data requests into validated Databricks SQL queries by parsing the request, understanding the company's FHIR data flattening approach, and verifying table and field definitions.", + "type": "langchain", + "owner": "Joshua Cluff", + "model": { + "provider": "bedrock", + "model": "us.anthropic.claude-3-5-haiku-20241022-v1:0" + }, + "system_prompts": [ + { + "role": "system", + "content": "You are an expert in transforming HL7 FHIR R4B resources into a flattened database structure. Always follow these key principles:\n1. Every table must include standard fields: 'uuid', 'source_id', 'document_key', 'md5_unique_key', and 'created'. The traditional 'id' field is replaced by the 'source_id' field.\n2. Nested arrays must be exploded into separate tables\n3. All table names are prefixed with 'bronze.fhir_rpt.'\n4. References are split into 'subject_reference_name' and 'subject_reference_value'\n5. All field names must use snake_case\n6. Array of primitive types (like strings) use the type name as the column" + }, + { + "role": "system", + "content": "The Databricks Catalog is called 'bronze' and the schema is called 'fhir_rpt'. All tables names should be prefixed with 'bronze.fhir_rpt.'. For instance the pat table would be 'bronze.fhir_rpt.pat'." + }, + { + "role": "system", + "content": "When flattening FHIR resources, follow this transformation pattern:\n- Patient.name → creates 'patient_name' table\n- Patient.name.given → creates 'patient_name_given' table with a 'string' column\n- Patient.name.family → creates 'patient_name_family' table\n- Patient.telecom → creates 'patient_telecom' table\n\nExample transformations:\n- 'onsetDateTime' becomes 'onset_date_time'\n- 'Patient/123' reference becomes:\n subject_reference_name: 'Patient'\n subject_reference_value: '123'" + }, + { + "role": "system", + "content": "When processing references, always split the FHIR reference into two distinct fields:\n- subject_reference_name: The type of resource being referenced\n- subject_reference_value: The specific identifier of that resource\n\nValidate that references follow the standard 'ResourceType/ID' format and extract components accordingly." + }, + { + "role": "system", + "content": "When using time windows in SQL queries use the add_months function which is available in Databricks. For example, to get all records from the last year, use 'add_months(current_date(), -12)'" + }, + { + "role": "system", + "content": "DATABRICKS FHIR TABLE NAMING CONVENTION\n\nWhen constructing SQL queries, STRICTLY follow these table name shortening rules:\n\nParent Table Name Mapping:\n- activitydefinition: actvdfn\n- account: acct\n- adverseevent: advrsevnt\n- allergyintolerance: allrgintolr\n- appointment: appt\n- appointmentresponse: apptresp\n- basic: bsc\n- binary: bnry\n- bundle: bndl\n- bodystructure: bdystrctr\n- capabilitystatement: capstmt\n- careplan: careplan\n- careteam: careteam\n- chargeitem: chrgitm\n- claim: clm\n- claimresponse: clmresp\n- clinicalimpression: clnimprsn\n- codesystem: cdsys\n- communication: comm\n- communicationrequest: commreq\n- composition: cmpstn\n- condition: cond\n- consent: cnsnt\n- contract: cntrct\n- coverage: covrg\n- coverageeligibilityrequest: covrgelgbltyreq\n- coverageeligibilityresponse: covrgelgbltyresp\n- detectedissue: dtctdiss\n- device: dvc\n- devicemetric: dvcmtc\n- devicerequest: dvcreq\n- deviceusestatement: dvcusestmnt\n- diagnosticreport: diagrpt\n- documentmanifest: docmnfst\n- documentreference: docref\n- encounter: enctr\n- endpoint: endpnt\n- enrollmentrequest: enrlreq\n- enrollmentresponse: enrlresp\n- episodeofcare: epsofcare\n- eventdefinition: evntdfn\n- explanationofbenefit: eob\n- familymemberhistory: famlymbrhstry\n- flag: flg\n- graphdefinition: grphdfn\n- group: grp\n- guidanceresponse: gdrspns\n- healthcareservice: hlthcrsrvc\n- imagingstudy: imgstdy\n- immunization: immu\n- immunizationevaluation: immueval\n- immunizationrecommendation: immurecmndtn\n- insuranceplan: insrplan\n- invoice: invce\n- library: lib\n- linkage: lnkge\n- list: lst\n- location: loc\n- measure: msr\n- measurereport: msrrpt\n- medication: med\n- medicationadministration: medadmin\n- medicationdispense: meddisp\n- medicationknowledge: medknwldg\n- medicationrequest: medreq\n- medicationstatement: medstmnt\n- medicinalproductdefinition: medprddefn\n- messageheader: msghdr\n- molecularsequence: molsqnc\n- nutritionorder: nutrordr\n- observation: obs\n- organization: org\n- organizationaffiliation: orgaffltn\n- patient: pat\n- person: prsn\n- plandefinition: plandef\n- practitioner: pract\n- practitionerrole: practrole\n- procedure: proc\n- provenance: prvnce\n- questionnaire: questnr\n- questionnaireresponse: questnrresp\n- relatedperson: rltdprsn\n- requestgroup: reqgrp\n- researchsubject: rsrchsbjct\n- riskassessment: rskassmnt\n- schedule: schdl\n- searchparameter: srchprmtr\n- servicerequest: srvreq\n- slot: slt\n- specimen: spcmn\n- structuredefinition: strctdfn\n- subscription: subscrptn\n- subscriptionstatus: subscrptnsts\n- subscriptiontopic: subscrptntpc\n- supplydelivery: spplydlvry\n- supplyrequest: spplyreq\n- valueset: valset\n- verificationresult: vrfctnrsult\n- visionprescription: vsnprscrptn\n- extension: extnsn\n- task: tsk\n\nInstructions for Table Name Translation:\n1. Always prefix shortened names with 'fhir_'\n2. Convert full table names to their corresponding shortened forms\n3. If no mapping exists, retain the original name\n\nExamples:\n- 'fhir_patient' → 'fhir_pat'\n- 'fhir_encounter' → 'fhir_enctr'\n- 'fhir_observation' → 'fhir_obs'\n\nReasoning: This approach ensures consistency with the Databricks schema and optimizes query performance by using predefined table abbreviations. For example: 'patient_identifier' becomes 'pat_idntfr' to match the Databricks schema." + }, + { + "role": "system", + "content": "ADDITIONAL DATABRICKS FHIR TABLE NAMING SHORTENING CONVENTION\n\nWhen constructing SQL queries, STRICTLY follow these additional name shortening rules:\n\nChild table Name Mapping:\n- coding: cdng\n- identifier: idntfr\n- applicability: applcblty\n- codeable: cdabl\n- concept: cncpt\n- instruction: instrctn\n- product: prdct\n- service: srvc\n- detail: dtl\n- adjudication: adjdctn\n- category: ctgry\n- reason: rsn\n\nInstructions for Column Name Translation:\n1. Identify full column names that match the mapping\n2. Replace full column names with their corresponding shortened forms\n3. Ensure the translation is case-insensitive\n4. If no mapping exists, retain the original column name\n\nExamples:\n- 'patient_identifier' → 'patient_idntfr'\n- 'encounter_category' → 'encounter_ctgry'\n- 'medication_codeable_concept' → 'medication_cdabl_cncpt'\n\nReasoning: This approach maintains consistency in column naming across Databricks tables, reduces column name length, and improves query readability and performance. For example: 'patient_identifier' becomes 'pat_idntfr' to match the Databricks schema." + }, + { + "role": "system", + "content": "Never prefix table names with 'fhir_' when constructing SQL queries. Instead, use the shortened table names directly. For example, 'fhir_patient' should be referenced as 'pat'." + }, + { + "role": "system", + "content": "Prior to executing the requested SQL query, describe the tables you are about to query to check that your fields and table names are correctly formatted. If any issues are found, provide feedback to the user and request corrections." + }, + { + "role": "system", + "content": "Present all SQL queries in clear SQL format, ensuring that the user can easily copy and paste them into Databricks for execution. Include comments to explain the purpose of each query and any specific considerations." + } + ], + "example_prompts": [ + { + "role": "user", + "content": "Get all patient records with diabetes diagnosed in the last year limit 100" + }, + { + "role": "user", + "content": "Find medications prescribed for patients over 65 with cardiovascular conditions limit 50" + } + ], + "tools": [ + { + "name" : "databricks_query_validator" + } + ] +} \ No newline at end of file diff --git a/language_model_gateway/configs/chat_completions/testing/graphql_query_generator.json b/language_model_gateway/configs/chat_completions/testing/graphql_query_generator.json new file mode 100644 index 000000000..927b2bd2c --- /dev/null +++ b/language_model_gateway/configs/chat_completions/testing/graphql_query_generator.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", + "id": "fhir_graphql_schema_provider", + "name": "FHIR Server GraphQL Query Creator", + "description": "This is a FHIR Server GraphQL schema provider. It provides the complete SDL of GraphQL that should be used to generate graphql query", + "owner": "Mintu Sah/Shubham Goel/Darryl Cate", + "type": "langchain", + "model": { + "provider": "bedrock", + "model": "us.anthropic.claude-3-5-haiku-20241022-v1:0" + }, + "system_prompts": [ + { + "role": "system", + "content": "You are a FHIR GraphQL Query Generator with the following key responsibilities:\n\nDo not retrieve the GraphQL SDL using the fhir_graphql_schema_provider tool every time. Fetch only when required as its not changing.\n\nCore Principles:\n1. Generate precise GraphQL queries based strictly on the provided SDL\n2. Ensure 100% adherence to the SDL's exact structure and type specifications\n\nQuery Generation Guidelines:\n- Carefully examine the SDL for each resource's exact search parameter names and types\n- Use correct filter structures for complex types\n- Pay special attention to dictionary-based input types:\n * SearchDate\n * SearchExtension\n * SearchNumber\n * SearchQuantity\n * SearchReference\n * SearchString\n * SearchToken\n\nFilter Application Rules:\n- For dictionary-based input types, only one filter can be applied at a time\n- Use nested structures exactly as specified in the SDL\n- Example filter format:\n carePlans(patient: { value: \"8ba1017f-0aad-1b91-ff9e-416a96e11f0b\" })\n\nCritical Constraints:\n- NEVER add fields not present in the original resource definition\n- Verify each parameter's correct usage\n- Different resources may have unique filter parameter names\n- Search types like SearchDate have specific nested structures\n\nError Prevention:\n- Double-check query syntax against the original SDL\n- Ensure type compatibility for all filters and parameters\n- Validate that all input types are used correctly\n- Deny in case the provided command wants to make a query that is not possible through SDL.\n- When checking query, ensure that SDL rules are not broken at any point\n\nYour goal is to generate syntactically correct, resource-specific GraphQL queries that exactly match the FHIR GraphQL SDL's specifications." + } + ], + "tools": [ + { + "name": "fhir_graphql_schema_provider" + }, + { + "name": "web_search" + } + ], + "example_prompts": [ + { + "role": "user", + "content": "Show me all Patients with first name John" + }, + { + "role": "user", + "content": "Show me the Condition code for a Patient whose id is " + } + ], + "model_parameters": [ + { + "key": "max_tokens", + "value": "1000" + }, + { + "key": "temperature", + "value": "0.2" + } + ] +} diff --git a/language_model_gateway/configs/chat_completions/testing/health_summary_generator.json b/language_model_gateway/configs/chat_completions/testing/health_summary_generator.json new file mode 100644 index 000000000..f8e294097 --- /dev/null +++ b/language_model_gateway/configs/chat_completions/testing/health_summary_generator.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", + "id": "health_summary_generator", + "name": "Health Summary Generator", + "description": "An AI assistant to generate the healthcare summary from the s3 files for users.", + "owner": "Anurag Verma, Naveen Kumar Yadav", + "type": "langchain", + "model": { + "provider": "bedrock", + "model": "us.anthropic.claude-3-5-haiku-20241022-v1:0" + }, + "system_prompts": [ + { + "role": "system", + "content": "You are an expert data processor tasked with analyzing a general claims file, which may include data on Diagnoses, Procedures, Pharmaceuticals, Pharmacies, and Hospitals. Your job is to generate a health summary report for each user in the file. Follow these steps:\n\n1. **Diagnoses:**\n - Check the file for diagnosis-related columns, which may contain either diagnosis names or codes.\n - If the file contains diagnosis codes:\n - Search the web for descriptions of these codes.\n - Deduplicate the descriptions and store them.\n - If the file contains diagnosis names but not codes:\n - Collect and deduplicate the diagnosis names.\n - Print the deduplicated list of diagnosis names.\n\n2. **Procedures:**\n - Identify columns related to procedures.\n - Like diagnoses, check if columns contain procedure codes:\n - Fetch descriptions for codes and deduplicate.\n - If the columns contain procedure names only:\n - Deduplicate the procedure names.\n - Print the deduplicated list of procedure names.\n\n3. **Pharmaceuticals:**\n - Repeat the same process as Diagnoses and Procedures:\n - Check for codes, acquire descriptions, and deduplicate.\n - If names only exist, deduplicate them.\n\n4. **Output Structure:**\n - For each user (assume `user1name` as a placeholder for the given user ID in your file):\n - Create a JSON object with their health summary.\n - The JSON should include lists of deduplicated information for diagnosis and procedures.\n - Example output:\n ```json\n {\n \"user1name\": {\n \"diagnosis\": [\"diagnosis_description1\", \"diagnosis_description2\"],\n \"procedure\": [\"procedure_description1\", \"procedure_description2\"]\n }\n }\n ```\n\n5. **Final Output:**\n - Return the complete structured JSON for all users.\n - Print this JSON data." + } + ], + "tools": [ + { + "name": "health_summary_generator" + }, + { + "name": "web_search" + } + ], + "example_prompts": [ + { + "role": "user", + "content": "I am giving you the s3_url for the file 's3://test-bucket/abc.csv'. Give me the health summary for the users in the file." + }, + { + "role": "user", + "content": "I am giving you the s3_url for the file 's3://test-bucket/abc.csv'. Give me the health summary for the first 5 users in the file." + } + ], + "model_parameters": [ + { + "key": "max_tokens", + "value": "1000" + }, + { + "key": "temperature", + "value": "0.3" + } + ] +} \ No newline at end of file diff --git a/language_model_gateway/configs/chat_completions/testing/pr_reviewer.json b/language_model_gateway/configs/chat_completions/testing/pr_reviewer.json new file mode 100644 index 000000000..042deab55 --- /dev/null +++ b/language_model_gateway/configs/chat_completions/testing/pr_reviewer.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://raw.githubusercontent.com/imranq2/language_model_gateway/main/language_model_gateway/configs/config_schema.json", + "id": "pr_reviewer", + "name": "PR Reviewer", + "description": "This model allows retrieving meta data about a pull request, figuring out the corresponding Jira ticket, getting git diff of the changes, and then analyzing the quality of the code as well as whether the changes match the requirements outlined in the Jira.", + "owner": "Denis Chaykovskiy", + "system_prompts": [ + { + "role": "system", + "content": "# Advanced Pull Request Analysis Agent Workflow ## Core Objective Perform comprehensive code review and requirement validation by correlating code changes with associated Jira tickets and identifying potential Confluence documentation updates. ## I. Jira Ticket Analysis (Primary Investigation Phase) ### 1. Ticket Detection Protocol - **Ticket Pattern**: `[A-Z]{2,4}[ -]\\\\d{1,5}` - **Scanning Locations** (Prioritized): 1. Pull Request Title (Highest Priority) 2. Pull Request Description - **Valid Examples**: - ATC-1234 - Atc 6789 - EA-567 - EFS-5263 - **Extraction Method**: Strict Regex-based identification ### 2. Ticket Context Extraction - Retrieve full Jira ticket details - Analyze ticket description thoroughly - Understand complete context of the change ## II. Keyword Extraction for Confluence Search ### Keyword Extraction Process - Analyze extracted Jira ticket information - Examine pull request title and description - Extract keywords based on: - Core technical domain - Specific component or system name - Unique technical concept or feature ### Keyword Selection Criteria - Prefer precise, technical terms - Avoid generic words - Prioritize keywords that uniquely identify the context ### Examples of Good Keywords - Specific microservice name - Unique algorithm or process - Distinct system component or module ### Keyword Confidence Ranking - **High Confidence**: Directly from Jira ticket - **Medium Confidence**: From PR title - **Low Confidence**: Derived from code diff ## III. Confluence Documentation Search (Secondary Investigation Phase) ### 1. Keyword Preparation - Finalize maximum 5 most relevant keywords - Ensure keywords are specific and meaningful ### 2. Confluence Page Search - Perform search using extracted keywords - Search without using quotes on search terms - Retrieve most relevant documentation pages ### 3. Documentation Relevance Scoring - Apply confidence scoring to found pages - Prioritize pages with highest keyword match ### 4. Documentation Link Requirement - **ESSENTIAL**: Include FULL and DIRECT hyperlinks to each relevant Confluence document - Ensure links are complete and clickable - Provide links immediately after each document summary ## IV. Final Analysis and Recommendation - After retrieving relevant Jira tickets, identify 3-5 most important requirements - Create a detailed list of these requirements - Cross-reference code changes with each requirement - Mark requirements with check marks (✓) when obviously satisfied - Mark requirements with an x (x) mark when obviously missed - Provide a confidence score (0-100%) for each requirement recommendation - When you are highly confident that a Confluence documentation page needs to be updated, provide the name, full direct hyperlinks, and a brief summary of the changes. Provide a confidence score (0-100%) for such recommendation. - If you are not confident if a Confluence document should be updated as the result of the changes in the PR, simply list the names and direct links to relevant documents and indicate the developer should do a review to see if they need to be updated." + } + ], + "example_prompts": [ + { + "role": "user", + "content": "review this PR: https://github.com/icanbwell/helix.providersearch/pull/493" + } + ], + "tools": [ + { + "name": "current_date" + }, + { + "name": "github_pull_request_retriever" + }, + { + "name": "github_pull_request_diff" + }, + { + "name": "jira_issue_retriever" + }, + { + "name": "confluence_search_tool" + }, + { + "name": "confluence_page_retriever" + } + ] +} \ No newline at end of file diff --git a/language_model_gateway/configs/config_reader/config_reader.py b/language_model_gateway/configs/config_reader/config_reader.py index 73baed07c..98e1e8645 100644 --- a/language_model_gateway/configs/config_reader/config_reader.py +++ b/language_model_gateway/configs/config_reader/config_reader.py @@ -15,7 +15,9 @@ ) from language_model_gateway.configs.config_reader.s3_config_reader import S3ConfigReader from language_model_gateway.configs.config_schema import ChatModelConfig -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.gateway.utilities.url_parser import UrlParser logger = logging.getLogger(__name__) @@ -25,7 +27,7 @@ class ConfigReader: _identifier: UUID = uuid4() _lock: asyncio.Lock = asyncio.Lock() - def __init__(self, *, cache: ExpiringCache[List[ChatModelConfig]]) -> None: + def __init__(self, *, cache: ConfigExpiringCache) -> None: """ Initialize the async config reader @@ -33,15 +35,15 @@ def __init__(self, *, cache: ExpiringCache[List[ChatModelConfig]]) -> None: cache: Expiring cache for model configurations """ assert cache is not None - self._cache: ExpiringCache[List[ChatModelConfig]] = cache + self._cache: ConfigExpiringCache = cache assert self._cache is not None # noinspection PyMethodMayBeStatic async def read_model_configs_async(self) -> List[ChatModelConfig]: config_path: str = os.environ["MODELS_OFFICIAL_PATH"] - assert ( - config_path is not None - ), "MODELS_OFFICIAL_PATH environment variable is not set" + assert config_path is not None, ( + "MODELS_OFFICIAL_PATH environment variable is not set" + ) models_zip_path: Optional[str] = os.environ.get("MODELS_ZIP_PATH", "") # Check cache first @@ -83,9 +85,9 @@ async def read_model_configs_async(self) -> List[ChatModelConfig]: models = await self.read_models_from_path_async(config_path) config_testing_path = os.environ.get("MODELS_TESTING_PATH") if config_testing_path: - models_testing: List[ChatModelConfig] = ( - await self.read_models_from_path_async(config_testing_path) - ) + models_testing: List[ + ChatModelConfig + ] = await self.read_models_from_path_async(config_testing_path) if models_testing and len(models_testing) > 0: models.append( ChatModelConfig( diff --git a/language_model_gateway/configs/config_reader/github_config_reader.py b/language_model_gateway/configs/config_reader/github_config_reader.py index 55132f645..deb02be55 100644 --- a/language_model_gateway/configs/config_reader/github_config_reader.py +++ b/language_model_gateway/configs/config_reader/github_config_reader.py @@ -167,9 +167,10 @@ async def _read_model_configs( api_url = f"https://api.github.com/repos/{repo_url}/contents/{path}?ref={branch}" headers = ( - {"Authorization": f"token {github_token}"} if github_token else {} + {"Authorization": f"Bearer {github_token}"} if github_token else {} ) headers["Accept"] = "application/vnd.github.v3+json" + headers["X-GitHub-Api-Version"] = "2022-11-28" # Get the list of files with rate limit handling response = await self._make_request( @@ -187,7 +188,7 @@ async def _read_model_configs( ] async def fetch_and_parse_config( - item: Dict[str, Any] + item: Dict[str, Any], ) -> Optional[ChatModelConfig]: try: raw_url = item["download_url"] diff --git a/language_model_gateway/configs/config_reader/github_config_zip_reader.py b/language_model_gateway/configs/config_reader/github_config_zip_reader.py index de6514b2f..826ebc4ae 100644 --- a/language_model_gateway/configs/config_reader/github_config_zip_reader.py +++ b/language_model_gateway/configs/config_reader/github_config_zip_reader.py @@ -67,7 +67,10 @@ async def download_with_retry(url: str) -> bytes: """ headers = {} if self.github_token: - headers["Authorization"] = f"token {self.github_token}" + headers["Authorization"] = f"Bearer {self.github_token}" + + headers["X-GitHub-Api-Version"] = "2022-11-28" + headers["Accept"] = "application/vnd.github+json" for attempt in range(self.max_retries): try: @@ -81,13 +84,16 @@ async def download_with_retry(url: str) -> bytes: response.raise_for_status() return response.content except Exception as e1: - logger.warning(f"Download attempt {attempt + 1} failed: {str(e1)}") + logger.error( + f"Download attempt {attempt + 1} failed URL: {url}, token: {self.github_token} {type(e1)}: {str(e1)},", + exc_info=True, + ) # Exponential backoff await asyncio.sleep(self.base_delay * (2**attempt)) raise RuntimeError( - f"Failed to download ZIP after {self.max_retries} attempts" + f"Failed to download ZIP after {self.max_retries} attempts URL: {url}, token: {self.github_token}" ) try: diff --git a/language_model_gateway/configs/config_schema.json b/language_model_gateway/configs/config_schema.json index aadff0ec6..03903ad0a 100644 --- a/language_model_gateway/configs/config_schema.json +++ b/language_model_gateway/configs/config_schema.json @@ -198,6 +198,10 @@ { "enum": [ "current_date", + "calculator_stddev", + "calculator_average", + "calculator_length", + "calculator_sum", "pubmed", "web_search", "get_web_page", @@ -214,7 +218,9 @@ "pdf_text_extractor ", "github_pull_request_analyzer", "github_pull_request_diff", - "jira_issues_analyzer" + "jira_issues_analyzer", + "health_summary_generator", + "fhir_graphql_schema_provider" ] }, { @@ -223,8 +229,8 @@ ] }, "parameters": { - "type": "array", - "description": "Parameters for the tool.", + "type": ["array", "null"], + "description": "The parameters for the tool", "items": { "type": "object", "required": [ @@ -241,7 +247,31 @@ "description": "Parameter value." } } - } + }, + "default": null + }, + "url": { + "type": ["string", "null"], + "description": "The MCP (Model Context Protocol) URL to access the tool", + "default": null + }, + "headers": { + "type": ["object", "null"], + "description": "The headers to pass to the MCP tool", + "additionalProperties": { + "type": "string" + }, + "default": null + }, + "auth": { + "type": ["string", "null"], + "description": "The authentication method to use when calling the tool", + "enum": [ + "None", + "jwt_token", + "oauth" + ], + "default": null } } } @@ -262,6 +292,10 @@ { "enum": [ "current_date", + "calculator_stddev", + "calculator_average", + "calculator_length", + "calculator_sum", "pubmed", "web_search", "get_web_page", @@ -278,7 +312,9 @@ "pdf_text_extractor ", "github_pull_request_analyzer", "github_pull_request_diff", - "jira_issues_analyzer" + "jira_issues_analyzer", + "health_summary_generator", + "fhir_graphql_schema_provider" ] }, { diff --git a/language_model_gateway/configs/config_schema.py b/language_model_gateway/configs/config_schema.py index 8284279bf..2118c484a 100644 --- a/language_model_gateway/configs/config_schema.py +++ b/language_model_gateway/configs/config_schema.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict, Literal from pydantic import BaseModel @@ -68,6 +68,18 @@ class AgentConfig(BaseModel): parameters: List[AgentParameterConfig] | None = None """The parameters for the tool""" + url: str | None = None + """The MCP (Model Context Protocol) URL to access the tool""" + + headers: Dict[str, str] | None = None + """The headers to pass to the MCP tool""" + + tools: str | None = None + """The names of the tool to use in the MCP call. If none is provided then all tools at the URL will be used. Separate multiple tool names with commas.""" + + auth: Literal["None", "jwt_token", "oauth"] | None = None + """The authentication method to use when calling the tool""" + class ModelConfig(BaseModel): """Model configuration""" diff --git a/language_model_gateway/container/container_factory.py b/language_model_gateway/container/container_factory.py index 66a917fef..85f554060 100644 --- a/language_model_gateway/container/container_factory.py +++ b/language_model_gateway/container/container_factory.py @@ -26,18 +26,30 @@ from language_model_gateway.gateway.providers.image_generation_provider import ( ImageGenerationProvider, ) - from language_model_gateway.gateway.providers.langchain_chat_completions_provider import ( LangChainCompletionsProvider, ) from language_model_gateway.gateway.providers.openai_chat_completions_provider import ( OpenAiChatCompletionsProvider, ) +from language_model_gateway.gateway.tools.mcp_tool_provider import MCPToolProvider from language_model_gateway.gateway.tools.tool_provider import ToolProvider +from language_model_gateway.gateway.utilities.auth.token_verifier import TokenVerifier +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.gateway.utilities.cache.mcp_tools_expiring_cache import ( + McpToolsMetadataExpiringCache, +) +from language_model_gateway.gateway.utilities.confluence.confluence_helper import ( + ConfluenceHelper, +) +from language_model_gateway.gateway.utilities.databricks.databricks_helper import ( + DatabricksHelper, +) from language_model_gateway.gateway.utilities.environment_variables import ( EnvironmentVariables, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from language_model_gateway.gateway.utilities.github.github_pull_request_helper import ( GithubPullRequestHelper, ) @@ -56,6 +68,41 @@ async def create_container_async(self) -> SimpleContainer: container = SimpleContainer() # register services here + + # we want only one instance of the cache so we use singleton + container.singleton( + ConfigExpiringCache, + lambda c: ConfigExpiringCache( + ttl_seconds=( + int(os.environ["CONFIG_CACHE_TIMEOUT_SECONDS"]) + if os.environ.get("CONFIG_CACHE_TIMEOUT_SECONDS") + else 60 * 60 + ) + ), + ) + container.singleton( + McpToolsMetadataExpiringCache, + lambda c: McpToolsMetadataExpiringCache( + ttl_seconds=( + int(os.environ["MCP_TOOLS_METADATA_CACHE_TIMEOUT_SECONDS"]) + if os.environ.get("MCP_TOOLS_METADATA_CACHE_TIMEOUT_SECONDS") + else 60 * 60 + ), + init_value={}, + ), + ) + + container.singleton( + TokenVerifier, + lambda c: TokenVerifier( + jwks_uri=c.resolve(EnvironmentVariables).auth_jwks_uri, + issuer=c.resolve(EnvironmentVariables).auth_issuer, + audience=c.resolve(EnvironmentVariables).auth_audience, + algorithms=c.resolve(EnvironmentVariables).auth_algorithms, + well_known_uri=c.resolve(EnvironmentVariables).auth_well_known_uri, + ), + ) + container.register(HttpClientFactory, lambda c: HttpClientFactory()) container.register( @@ -120,6 +167,21 @@ async def create_container_async(self) -> SimpleContainer: ), ) + container.register( + ConfluenceHelper, + lambda c: ConfluenceHelper( + http_client_factory=c.resolve(HttpClientFactory), + confluence_base_url=c.resolve(EnvironmentVariables).jira_base_url, + access_token=c.resolve(EnvironmentVariables).jira_token, + username=c.resolve(EnvironmentVariables).jira_username, + ), + ) + + container.register( + DatabricksHelper, + lambda c: DatabricksHelper(), + ) + container.register( ToolProvider, lambda c: ToolProvider( @@ -129,30 +191,31 @@ async def create_container_async(self) -> SimpleContainer: environment_variables=c.resolve(EnvironmentVariables), github_pull_request_helper=c.resolve(GithubPullRequestHelper), jira_issues_helper=c.resolve(JiraIssueHelper), + confluence_helper=c.resolve(ConfluenceHelper), + databricks_helper=c.resolve(DatabricksHelper), + ), + ) + + container.register( + MCPToolProvider, + lambda c: MCPToolProvider( + cache=c.resolve(McpToolsMetadataExpiringCache), ), ) + container.register( LangChainCompletionsProvider, lambda c: LangChainCompletionsProvider( model_factory=c.resolve(ModelFactory), lang_graph_to_open_ai_converter=c.resolve(LangGraphToOpenAIConverter), tool_provider=c.resolve(ToolProvider), - ), - ) - # we want only one instance of the cache so we use singleton - container.singleton( - ExpiringCache, - ExpiringCache( - ttl_seconds=( - int(os.environ["CONFIG_CACHE_TIMEOUT_SECONDS"]) - if os.environ.get("CONFIG_CACHE_TIMEOUT_SECONDS") - else 60 * 60 - ) + mcp_tool_provider=c.resolve(MCPToolProvider), + token_verifier=c.resolve(TokenVerifier), ), ) container.register( - ConfigReader, lambda c: ConfigReader(cache=c.resolve(ExpiringCache)) + ConfigReader, lambda c: ConfigReader(cache=c.resolve(ConfigExpiringCache)) ) container.register( ChatCompletionManager, diff --git a/language_model_gateway/container/simple_container.py b/language_model_gateway/container/simple_container.py index e54097f49..fbb8cb676 100644 --- a/language_model_gateway/container/simple_container.py +++ b/language_model_gateway/container/simple_container.py @@ -79,9 +79,11 @@ def resolve(self, service_type: type[T]) -> T: return service - def singleton(self, service_type: type[T], instance: T) -> "SimpleContainer": + def singleton( + self, service_type: type[T], factory: ServiceFactory[T] + ) -> "SimpleContainer": """Register a singleton instance""" - self._singletons[service_type] = instance + self._factories[service_type] = factory self._singleton_types.add(service_type) return self diff --git a/language_model_gateway/gateway/api.py b/language_model_gateway/gateway/api.py index 84afb7a80..41991bb42 100644 --- a/language_model_gateway/gateway/api.py +++ b/language_model_gateway/gateway/api.py @@ -7,6 +7,7 @@ from fastapi import FastAPI, HTTPException from fastapi.params import Depends +from starlette.middleware.cors import CORSMiddleware from starlette.requests import Request from starlette.responses import FileResponse, JSONResponse from starlette.staticfiles import StaticFiles @@ -86,14 +87,27 @@ def create_app() -> FastAPI: image_generation_path: str = environ["IMAGE_GENERATION_PATH"] - assert ( - image_generation_path is not None - ), "IMAGE_GENERATION_PATH environment variable must be set" + assert image_generation_path is not None, ( + "IMAGE_GENERATION_PATH environment variable must be set" + ) makedirs(image_generation_path, exist_ok=True) app1.include_router( ImagesRouter(image_generation_path=image_generation_path).get_router() ) + + # Set up CORS middleware; adjust parameters as needed + # noinspection PyTypeChecker + allowed_origins = environ.get("ALLOWED_ORIGINS", "").split(",") + if not allowed_origins or allowed_origins == [""]: + allowed_origins = ["*"] # Allow all origins if not specified + app1.add_middleware( + CORSMiddleware, + allow_origins=allowed_origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) return app1 @@ -101,7 +115,7 @@ def create_app() -> FastAPI: app = create_app() -@app.get("/health") +@app.api_route("/health", methods=["GET", "POST"]) async def health() -> str: return "OK" diff --git a/language_model_gateway/gateway/api_container.py b/language_model_gateway/gateway/api_container.py index 84f5168d9..7384f845c 100644 --- a/language_model_gateway/gateway/api_container.py +++ b/language_model_gateway/gateway/api_container.py @@ -29,7 +29,7 @@ async def get_container_async() -> SimpleContainer: def get_chat_manager( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> ChatCompletionManager: """helper function to get the chat manager""" assert isinstance(container, SimpleContainer), type(container) @@ -37,7 +37,7 @@ def get_chat_manager( def get_model_manager( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> ModelManager: """helper function to get the model manager""" assert isinstance(container, SimpleContainer), type(container) @@ -45,7 +45,7 @@ def get_model_manager( def get_image_generation_manager( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> ImageGenerationManager: """helper function to get the model manager""" assert isinstance(container, SimpleContainer), type(container) @@ -53,7 +53,7 @@ def get_image_generation_manager( def get_config_reader( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> ConfigReader: """helper function to get the chat manager""" assert isinstance(container, SimpleContainer), type(container) @@ -61,7 +61,7 @@ def get_config_reader( def get_aws_client_factory( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> AwsClientFactory: """helper function to get the chat manager""" assert isinstance(container, SimpleContainer), type(container) @@ -69,7 +69,7 @@ def get_aws_client_factory( def get_file_manager_factory( - container: Annotated[SimpleContainer, Depends(get_container_async)] + container: Annotated[SimpleContainer, Depends(get_container_async)], ) -> FileManagerFactory: """helper function to get the chat manager""" assert isinstance(container, SimpleContainer), type(container) diff --git a/language_model_gateway/gateway/aws/aws_client_factory.py b/language_model_gateway/gateway/aws/aws_client_factory.py index daaa3e20a..d6803bf71 100644 --- a/language_model_gateway/gateway/aws/aws_client_factory.py +++ b/language_model_gateway/gateway/aws/aws_client_factory.py @@ -1,15 +1,44 @@ import os import boto3 +from boto3 import Session + +from types_boto3_bedrock_runtime.client import BedrockRuntimeClient +from types_boto3_s3.client import S3Client +from types_boto3_textract.client import TextractClient class AwsClientFactory: # noinspection PyMethodMayBeStatic - def create_client(self, *, service_name: str) -> boto3.client: + def create_bedrock_client(self) -> BedrockRuntimeClient: """Create and return a Bedrock client""" - session = boto3.Session(profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE")) - bedrock_client = session.client( - service_name=service_name, + session: Session = boto3.Session( + profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE") + ) + bedrock_client: BedrockRuntimeClient = session.client( + service_name="bedrock-runtime", region_name="us-east-1", ) return bedrock_client + + # noinspection PyMethodMayBeStatic + def create_s3_client(self) -> S3Client: + session: Session = boto3.Session( + profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE") + ) + s3_client: S3Client = session.client( + service_name="s3", + region_name="us-east-1", + ) + return s3_client + + # noinspection PyMethodMayBeStatic + def create_textract_client(self) -> TextractClient: + session: Session = boto3.Session( + profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE") + ) + textract_client: TextractClient = session.client( + service_name="textract", + region_name="us-east-1", + ) + return textract_client diff --git a/language_model_gateway/gateway/converters/langchain_to_openai_converter.py b/language_model_gateway/gateway/converters/langchain_to_openai_converter.py deleted file mode 100644 index dbb3c509f..000000000 --- a/language_model_gateway/gateway/converters/langchain_to_openai_converter.py +++ /dev/null @@ -1,397 +0,0 @@ -# import json -# import logging -# import time -# from typing import ( -# Any, -# List, -# cast, -# AsyncGenerator, -# Iterable, -# TypedDict, -# Sequence, -# Dict, -# ) -# -# from fastapi import HTTPException -# from langchain.agents import AgentExecutor -# from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser -# from langchain_core.language_models import BaseChatModel -# from langchain_core.messages import AIMessageChunk, BaseMessage, AIMessage -# from langchain_core.messages import ( -# AnyMessage, -# ) -# from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder -# from langchain_core.runnables import Runnable, RunnableSerializable, RunnablePassthrough -# from langchain_core.runnables.schema import CustomStreamEvent, StandardStreamEvent -# from langchain_core.tools import BaseTool -# from langchain_core.utils.function_calling import convert_to_openai_function -# from openai.types import CompletionUsage -# from openai.types.chat import ( -# ChatCompletionChunk, -# ChatCompletion, -# ChatCompletionMessage, -# ChatCompletionSystemMessageParam, -# ) -# from openai.types.chat import ChatCompletionMessageParam -# from openai.types.chat.chat_completion import Choice -# from openai.types.chat.chat_completion_chunk import ChoiceDelta, Choice as ChunkChoice -# from starlette.responses import StreamingResponse, JSONResponse -# -# from language_model_gateway.gateway.schema.openai.completions import ( -# ChatRequest, -# ROLE_TYPES, -# INCOMING_MESSAGE_TYPES, -# ) -# from language_model_gateway.gateway.utilities.chat_message_helpers import ( -# langchain_to_chat_message, -# ) -# -# logger = logging.getLogger(__file__) -# -# type MessageList = List[BaseMessage] -# type ToolList = Sequence[BaseTool] -# -# -# class ChainInput(TypedDict): -# input: str -# chat_history: MessageList -# -# -# class ChainOutput(TypedDict): -# output: Dict[str, Any] -# -# -# class LangChainToOpenAIConverter: -# async def _stream_resp_async_generator( -# self, -# *, -# request: ChatRequest, -# request_id: str, -# chain_input: ChainInput, -# tools: ToolList, -# llm: BaseChatModel, -# system_messages: List[ChatCompletionSystemMessageParam], -# ) -> AsyncGenerator[str, None]: -# """ -# Asynchronously generate streaming responses from the agent. -# -# Yields: -# The streaming response as a string. -# """ -# -# logger.info(f"Streaming response from generator {request_id} from agent.") -# -# # Process streamed events from the graph and yield messages over the SSE stream. -# event: StandardStreamEvent | CustomStreamEvent -# async for event in self.astream_events( -# system_messages=system_messages, -# chain_input=chain_input, -# tools=tools, -# llm=llm, -# ): -# if not event: -# continue -# -# event_type: str = event["event"] -# -# match event_type: -# case "on_chain_start": -# # Handle the start of the chain event -# pass -# case "on_chat_model_stream": -# # Handle the chat model stream event -# chunk: AIMessageChunk = event["data"]["chunk"] -# content: str | list[str | dict[str, Any]] = chunk.content -# -# content_text: str -# if isinstance(content, list): -# content_text_or_dict: str | dict[str, Any] = ( -# content[0] if len(content) > 0 else "" -# ) -# if isinstance(content_text_or_dict, dict): -# content_text = ( -# cast(str, content_text_or_dict.get("text")) -# if content_text_or_dict.get("text") -# else "" -# ) -# assert isinstance( -# content_text, str -# ), f"content_text: {content_text} (type: {type(content_text)})" -# else: -# assert isinstance(content_text_or_dict, str) -# content_text = content_text_or_dict -# else: -# assert isinstance(content, str) -# content_text = content -# -# assert isinstance( -# content_text, str -# ), f"content_text: {content_text} (type: {type(content_text)})" -# -# if content_text: -# chat_stream_response: ChatCompletionChunk = ChatCompletionChunk( -# id=request_id, -# created=int(time.time()), -# model=request["model"], -# choices=[ -# ChunkChoice( -# index=0, -# delta=ChoiceDelta( -# role="assistant", content=content_text -# ), -# ) -# ], -# usage=CompletionUsage( -# prompt_tokens=0, completion_tokens=0, total_tokens=0 -# ), -# object="chat.completion.chunk", -# ) -# yield f"data: {json.dumps(chat_stream_response.model_dump())}\n\n" -# case "on_chain_end": -# # Handle the end of the chain event -# pass -# case _: -# # Handle other event types -# pass -# -# yield "data: [DONE]\n\n" -# -# async def call_agent_with_input( -# self, -# *, -# request: ChatRequest, -# request_id: str, -# system_messages: List[ChatCompletionSystemMessageParam], -# llm: BaseChatModel, -# chain_input: ChainInput, -# tools: ToolList, -# ) -> StreamingResponse | JSONResponse: -# """ -# Call the agent with the provided input and return the response. -# -# Returns: -# The response as a StreamingResponse or JSONResponse. -# """ -# assert request is not None -# assert isinstance(request, dict) -# -# if request.get("stream"): -# return StreamingResponse( -# await self.get_streaming_response_async( -# request=request, -# request_id=request_id, -# llm=llm, -# system_messages=system_messages, -# tools=tools, -# chain_input=chain_input, -# ), -# media_type="text/event-stream", -# ) -# else: -# try: -# response: List[AnyMessage] = await self.ainvoke( -# system_messages=system_messages, -# chain_input=chain_input, -# llm=llm, -# tools=tools, -# ) -# output: ChatCompletionMessage = langchain_to_chat_message(response[-1]) -# chat_response: ChatCompletion = ChatCompletion( -# id=request_id, -# model=request["model"], -# choices=[Choice(index=0, message=output, finish_reason="stop")], -# usage=CompletionUsage( -# prompt_tokens=0, completion_tokens=0, total_tokens=0 -# ), -# created=int(time.time()), -# object="chat.completion", -# ) -# return JSONResponse(content=chat_response.model_dump()) -# except Exception as e: -# logger.error(f"An exception occurred: {e}") -# raise HTTPException(status_code=500, detail="Unexpected error") -# -# async def get_streaming_response_async( -# self, -# *, -# request: ChatRequest, -# request_id: str, -# chain_input: ChainInput, -# llm: BaseChatModel, -# system_messages: List[ChatCompletionSystemMessageParam], -# tools: ToolList, -# ) -> AsyncGenerator[str, None]: -# """ -# Get the streaming response asynchronously. -# -# Returns: -# The streaming response as an async generator. -# """ -# logger.info(f"Streaming response {request_id} from agent") -# generator: AsyncGenerator[str, None] = self._stream_resp_async_generator( -# request=request, -# request_id=request_id, -# llm=llm, -# system_messages=system_messages, -# tools=tools, -# chain_input=chain_input, -# ) -# return generator -# -# # noinspection SpellCheckingInspection,PyMethodMayBeStatic -# async def ainvoke( -# self, -# *, -# system_messages: List[ChatCompletionSystemMessageParam], -# chain_input: ChainInput, -# tools: ToolList, -# llm: BaseChatModel, -# ) -> List[AnyMessage]: -# """ -# Run the agent asynchronously. -# """ -# system_prompts: List[str] = cast( -# List[str], [s["content"] for s in system_messages] -# ) -# chain: Runnable[ChainInput, ChainOutput] = self.create_chain( -# llm=llm, system_prompts=system_prompts, tools=tools -# ) -# -# response: ChainOutput = await chain.ainvoke(chain_input) -# output: Dict[str, Any] = response["output"] -# output_text: str = output["output"] -# return [AIMessage(content=output_text)] -# -# # noinspection PyMethodMayBeStatic -# def create_chain( -# self, -# *, -# llm: BaseChatModel, -# system_prompts: List[str], -# tools: ToolList, -# ) -> Runnable[ChainInput, ChainOutput]: -# prompt: ChatPromptTemplate = ChatPromptTemplate.from_messages( -# [ -# ( -# "system", -# system_prompt, -# ) -# for system_prompt in system_prompts -# ] -# + [ -# MessagesPlaceholder(variable_name="chat_history"), -# ("human", "{input}"), -# MessagesPlaceholder(variable_name="agent_scratchpad"), -# ] -# ) -# # Create functions for the LLM -# llm_with_tools = llm.bind( -# functions=[convert_to_openai_function(t) for t in tools] -# ) -# # Create the agent -# agent: RunnableSerializable[ChainInput, ChainOutput] = ( -# { -# "input": lambda x: x["input"], -# "chat_history": lambda x: x["chat_history"], -# "agent_scratchpad": lambda x: convert_to_openai_function( -# x["intermediate_steps"] -# ), -# } -# | prompt -# | llm_with_tools -# | OpenAIFunctionsAgentOutputParser() # type: ignore[operator] -# ) -# # Create the executor -# agent_executor: AgentExecutor = AgentExecutor( -# agent=agent, tools=tools, verbose=True, return_intermediate_steps=True -# ) -# # Create the final chain -# chain: RunnableSerializable[ -# ChainInput, ChainOutput -# ] = RunnablePassthrough.assign( -# output=agent_executor -# ) | ( # type:ignore[assignment] -# lambda x: {"output": x["output"]} # type:ignore[operator] -# ) -# return chain -# -# async def astream_events( -# self, -# *, -# system_messages: List[ChatCompletionSystemMessageParam], -# chain_input: ChainInput, -# tools: ToolList, -# llm: BaseChatModel, -# ) -> AsyncGenerator[StandardStreamEvent | CustomStreamEvent, None]: -# """ -# Stream events asynchronously. -# -# Yields: -# The standard or custom stream event. -# """ -# system_prompts: List[str] = [cast(str, s["content"]) for s in system_messages] -# chain: Runnable[ChainInput, ChainOutput] = self.create_chain( -# llm=llm, system_prompts=system_prompts, tools=tools -# ) -# -# # Get response -# chunk: ChainOutput -# async for chunk in chain.astream(chain_input): -# if isinstance(chunk, dict) and "output" in chunk: -# print(chunk["output"], end="", flush=True) -# output: Dict[str, Any] = chunk["output"] -# output_text: str = output["output"] -# # noinspection PyArgumentList -# yield StandardStreamEvent( -# run_id="", -# parent_ids=[], -# name="", -# event="on_chat_model_stream", -# data={ -# "chunk": AIMessageChunk( -# content=output_text, -# ) -# }, -# ) -# -# # noinspection PyMethodMayBeStatic -# def create_messages_for_graph( -# self, *, messages: Iterable[ChatCompletionMessageParam] -# ) -> List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]]: -# """ -# Create messages for the graph. -# -# Args: -# messages: The iterable of chat completion message parameters. -# -# Returns: -# The list of role and incoming message type tuples. -# """ -# return cast( -# List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]], -# [(m["role"], m["content"]) for m in messages], -# ) -# -# async def run_graph_async( -# self, -# *, -# request: ChatRequest, -# llm: BaseChatModel, -# tools: ToolList, -# chain_input: ChainInput, -# system_messages: List[ChatCompletionSystemMessageParam], -# ) -> List[AnyMessage]: -# """ -# Run the graph asynchronously. -# -# Returns: -# The list of any messages. -# """ -# -# output_messages: List[AnyMessage] = await self.ainvoke( -# llm=llm, -# chain_input=chain_input, -# system_messages=system_messages, -# tools=tools, -# ) -# return output_messages diff --git a/language_model_gateway/gateway/converters/langgraph_to_openai_converter.py b/language_model_gateway/gateway/converters/langgraph_to_openai_converter.py index b7f4b2534..a14f3fa08 100644 --- a/language_model_gateway/gateway/converters/langgraph_to_openai_converter.py +++ b/language_model_gateway/gateway/converters/langgraph_to_openai_converter.py @@ -1,13 +1,12 @@ import json import logging import os +import re import time from typing import ( Any, List, Sequence, - Union, - Literal, cast, Optional, Tuple, @@ -18,23 +17,23 @@ Iterable, ) +from botocore.exceptions import TokenRetrievalError from fastapi import HTTPException from langchain_core.language_models import BaseChatModel from langchain_core.messages import ( AIMessage, AnyMessage, - BaseMessage, ToolMessage, + BaseMessage, + HumanMessage, + SystemMessage, ) from langchain_core.messages import AIMessageChunk from langchain_core.messages.ai import UsageMetadata -from langchain_core.prompt_values import PromptValue -from langchain_core.runnables import Runnable from langchain_core.runnables.schema import CustomStreamEvent, StandardStreamEvent from langchain_core.tools import BaseTool -from langgraph.graph import END, START, StateGraph from langgraph.graph.state import CompiledStateGraph -from langgraph.prebuilt import ToolNode +from langgraph.prebuilt import ToolNode, create_react_agent from openai import NotGiven, NOT_GIVEN from openai.types import CompletionUsage from openai.types.chat import ( @@ -75,7 +74,8 @@ async def _stream_resp_async_generator( *, request: ChatRequest, request_id: str, - compiled_state_graph: CompiledStateGraph, + headers: Dict[str, str], + compiled_state_graph: CompiledStateGraph[MyMessagesState], messages: List[ChatCompletionMessageParam], ) -> AsyncGenerator[str, None]: """ @@ -84,6 +84,7 @@ async def _stream_resp_async_generator( Args: request: The chat request. request_id: The unique request identifier. + headers: The request headers. compiled_state_graph: The compiled state graph. messages: The list of chat completion message parameters. @@ -95,6 +96,7 @@ async def _stream_resp_async_generator( event: StandardStreamEvent | CustomStreamEvent async for event in self.astream_events( request=request, + headers=headers, compiled_state_graph=compiled_state_graph, messages=messages, ): @@ -135,15 +137,15 @@ async def _stream_resp_async_generator( content ) - assert isinstance( - content_text, str - ), f"content_text: {content_text} (type: {type(content_text)})" + assert isinstance(content_text, str), ( + f"content_text: {content_text} (type: {type(content_text)})" + ) if ( os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1" and content_text ): - logger.info(f"Returning content: {content_text}") + logger.debug(f"Returning content: {content_text}") if content_text: chat_model_stream_response: ChatCompletionChunk = ( @@ -199,8 +201,19 @@ async def _stream_resp_async_generator( tool_input: Dict[str, Any] | None = event.get("data", {}).get( "input" ) + + # copy the tool_input to avoid modifying the original + tool_input_display = ( + tool_input.copy() if tool_input is not None else None + ) + # remove auth_token from tool_input + if tool_input_display and "auth_token" in tool_input_display: + tool_input_display["auth_token"] = "***" + if tool_name: - logger.debug(f"on_tool_start: {tool_name} {tool_input}") + logger.debug( + f"on_tool_start: {tool_name} {tool_input_display}" + ) chat_stream_response = ChatCompletionChunk( id=request_id, created=int(time.time()), @@ -210,7 +223,7 @@ async def _stream_resp_async_generator( index=0, delta=ChoiceDelta( role="assistant", - content=f"\n\n> Running Agent {tool_name}: {tool_input}\n", + content=f"\n\n> Running Agent {tool_name}: {tool_input_display}\n", ), ) ], @@ -261,6 +274,28 @@ async def _stream_resp_async_generator( case _: # Handle other event types pass + except TokenRetrievalError as e: + logger.exception(e, stack_info=True) + message: str = f"Token retrieval error: {e}. If you are running locally, your AWS session may have expired. Please re-authenticate using `aws sso login --profile [role]`." + chat_stream_response = ChatCompletionChunk( + id=request_id, + created=int(time.time()), + model=request["model"], + choices=[ + ChunkChoice( + index=0, + delta=ChoiceDelta( + role="assistant", + content=f"\n{message}\n", + ), + ) + ], + usage=CompletionUsage( + prompt_tokens=0, completion_tokens=0, total_tokens=0 + ), + object="chat.completion.chunk", + ) + yield f"data: {json.dumps(chat_stream_response.model_dump())}\n\n" except Exception as e: chat_stream_response = ChatCompletionChunk( id=request_id, @@ -287,9 +322,10 @@ async def _stream_resp_async_generator( async def call_agent_with_input( self, *, + headers: Dict[str, str], chat_request: ChatRequest, request_id: str, - compiled_state_graph: CompiledStateGraph, + compiled_state_graph: CompiledStateGraph[MyMessagesState], system_messages: List[ChatCompletionSystemMessageParam], ) -> StreamingResponse | JSONResponse: """ @@ -297,6 +333,7 @@ async def call_agent_with_input( Args: chat_request: The chat request. + headers: request headers request_id: The unique request identifier. compiled_state_graph: The compiled state graph. system_messages: The list of chat completion message parameters. @@ -305,11 +342,11 @@ async def call_agent_with_input( The response as a StreamingResponse or JSONResponse. """ assert chat_request is not None - assert isinstance(chat_request, dict) if chat_request.get("stream"): return StreamingResponse( await self.get_streaming_response_async( + headers=headers, request=chat_request, request_id=request_id, compiled_state_graph=compiled_state_graph, @@ -326,6 +363,7 @@ async def call_agent_with_input( responses: List[AnyMessage] = await self.ainvoke( compiled_state_graph=compiled_state_graph, + headers=headers, request=chat_request, system_messages=system_messages, ) @@ -387,9 +425,25 @@ async def call_agent_with_input( object="chat.completion", ) return JSONResponse(content=chat_response.model_dump()) - except Exception as e: + except* TokenRetrievalError as e: logger.exception(e, stack_info=True) - raise HTTPException(status_code=500, detail=f"Unexpected error: {e}") + raise HTTPException( + status_code=401, + detail=f"Token retrieval error: {type(e)} {e}. If you are running locally, your AWS session may have expired. Please re-authenticate using `aws sso login --profile [role]`.", + ) + except* Exception as e: + logger.exception(e, stack_info=True) + # print type of first exception in ExceptionGroup + # if there is just one exception, we can log it directly + if len(e.exceptions) > 0: + logger.error( + f"ExceptionGroup in call_agent_with_input: {type(e.exceptions[0])} {e.exceptions[0]}", + exc_info=True, + ) + + raise HTTPException( + status_code=500, detail=f"Unexpected error: {type(e)} {e}" + ) @staticmethod def add_system_messages_for_json( @@ -415,9 +469,9 @@ def add_system_messages_for_json( return chat_request, json_response_requested case "json_object": json_response_requested = True - json_object_system_message_text: str = """ + json_object_system_message_text: str = """ Respond only with a JSON object or array. - + Output follows this example format: json here @@ -430,6 +484,7 @@ def add_system_messages_for_json( chat_request["messages"] = [r for r in chat_request["messages"]] + [ json_object_system_message ] + return chat_request, json_response_requested case "json_schema": json_response_requested = True json_response_format: ResponseFormatJSONSchema = cast( @@ -437,13 +492,13 @@ def add_system_messages_for_json( response_format, ) json_schema: JSONSchema | None = json_response_format.get("json_schema") - assert ( - json_schema is not None - ), "json_schema should be specified in response_format if type is json_schema" - json_schema_system_message_text: str = f""" + assert json_schema is not None, ( + "json_schema should be specified in response_format if type is json_schema" + ) + json_schema_system_message_text: str = f""" Respond only with a JSON object or array using the provided schema: - ```{json_schema}``` - + ```{json_schema}``` + Output follows this example format: json here @@ -456,11 +511,11 @@ def add_system_messages_for_json( chat_request["messages"] = [r for r in chat_request["messages"]] + [ json_schema_system_message ] + return chat_request, json_response_requested case _: - assert ( - False - ), f"Unexpected response format type: {response_format.get('type', None)}" - return chat_request, json_response_requested + raise ValueError( + f"Unexpected response format type: {response_format.get('type', None)}" + ) # noinspection PyMethodMayBeStatic def convert_usage_meta_data_to_openai( @@ -479,9 +534,10 @@ def convert_usage_meta_data_to_openai( async def get_streaming_response_async( self, *, + headers: Dict[str, str], request: ChatRequest, request_id: str, - compiled_state_graph: CompiledStateGraph, + compiled_state_graph: CompiledStateGraph[MyMessagesState], system_messages: List[ChatCompletionSystemMessageParam], ) -> AsyncGenerator[str, None]: """ @@ -489,6 +545,7 @@ async def get_streaming_response_async( Args: request: The chat request. + headers: The request headers. request_id: The unique request identifier. compiled_state_graph: The compiled state graph. system_messages: The list of chat completion message parameters. @@ -508,6 +565,7 @@ async def get_streaming_response_async( generator: AsyncGenerator[str, None] = self._stream_resp_async_generator( request=request, request_id=request_id, + headers=headers, compiled_state_graph=compiled_state_graph, messages=messages, ) @@ -517,8 +575,10 @@ async def get_streaming_response_async( async def _run_graph_with_messages_async( self, *, - messages: List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]], - compiled_state_graph: CompiledStateGraph, + chat_request: ChatRequest, + headers: Dict[str, str], + messages: List[BaseMessage], + compiled_state_graph: CompiledStateGraph[MyMessagesState], ) -> List[AnyMessage]: """ Run the graph with the provided messages asynchronously. @@ -530,10 +590,12 @@ async def _run_graph_with_messages_async( Returns: The list of any messages. """ - input1: Dict[str, List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]]] = { - "messages": messages - } - output: Dict[str, Any] = await compiled_state_graph.ainvoke(input=input1) + + output: Dict[str, Any] = await compiled_state_graph.ainvoke( + input=self.create_state( + chat_request=chat_request, headers=headers, messages=messages + ) + ) out_messages: List[AnyMessage] = output["messages"] return out_messages @@ -542,26 +604,29 @@ async def _stream_graph_with_messages_async( self, *, request: ChatRequest, - messages: List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]], - compiled_state_graph: CompiledStateGraph, + headers: Dict[str, str], + messages: List[BaseMessage], + compiled_state_graph: CompiledStateGraph[MyMessagesState], ) -> AsyncGenerator[StandardStreamEvent | CustomStreamEvent, None]: """ Stream the graph with the provided messages asynchronously. Args: request: The chat request. + headers: The request headers. messages: The list of role and incoming message type tuples. compiled_state_graph: The compiled state graph. Yields: The standard or custom stream event. """ - input1: Dict[str, List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]]] = { - "messages": messages - } + event: StandardStreamEvent | CustomStreamEvent async for event in compiled_state_graph.astream_events( - input=input1, version="v2" + input=self.create_state( + chat_request=request, headers=headers, messages=messages + ), + version="v2", ): yield event @@ -570,7 +635,8 @@ async def ainvoke( self, *, request: ChatRequest, - compiled_state_graph: CompiledStateGraph, + headers: Dict[str, str], + compiled_state_graph: CompiledStateGraph[MyMessagesState], system_messages: Iterable[ChatCompletionSystemMessageParam], ) -> List[AnyMessage]: """ @@ -578,6 +644,7 @@ async def ainvoke( Args: request: The chat request. + headers: The request headers. compiled_state_graph: The compiled state graph. system_messages: The iterable of chat completion message parameters. @@ -585,7 +652,6 @@ async def ainvoke( The list of any messages. """ assert request is not None - assert isinstance(request, dict) new_messages: List[ChatCompletionMessageParam] = [ m for m in request["messages"] @@ -595,6 +661,8 @@ async def ainvoke( ] + new_messages return await self._run_graph_with_messages_async( + chat_request=request, + headers=headers, compiled_state_graph=compiled_state_graph, messages=self.create_messages_for_graph(messages=messages), ) @@ -603,7 +671,8 @@ async def astream_events( self, *, request: ChatRequest, - compiled_state_graph: CompiledStateGraph, + headers: Dict[str, str], + compiled_state_graph: CompiledStateGraph[MyMessagesState], messages: Iterable[ChatCompletionMessageParam], ) -> AsyncGenerator[StandardStreamEvent | CustomStreamEvent, None]: """ @@ -611,6 +680,7 @@ async def astream_events( Args: request: The chat request. + headers: The request headers. compiled_state_graph: The compiled state graph. messages: The iterable of chat completion message parameters. @@ -620,6 +690,7 @@ async def astream_events( event: StandardStreamEvent | CustomStreamEvent async for event in self._stream_graph_with_messages_async( request=request, + headers=headers, compiled_state_graph=compiled_state_graph, messages=self.create_messages_for_graph(messages=messages), ): @@ -628,7 +699,7 @@ async def astream_events( # noinspection PyMethodMayBeStatic def create_messages_for_graph( self, *, messages: Iterable[ChatCompletionMessageParam] - ) -> List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]]: + ) -> List[BaseMessage]: """ Create messages for the graph. @@ -638,40 +709,89 @@ def create_messages_for_graph( Returns: The list of role and incoming message type tuples. """ - return cast( + chat_messages: List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]] = cast( List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]], [(m["role"], m["content"]) for m in messages], ) + messages_: List[BaseMessage] = [] + for role, content in chat_messages: + match role: + case "system": + messages_.append( + SystemMessage( + content=self.convert_incoming_message_content_to_string( + content + ), + role="system", + ) + ) + case "user": + messages_.append( + HumanMessage( + content=self.convert_incoming_message_content_to_string( + content + ), + role="user", + ) + ) + case "assistant": + messages_.append( + AIMessage( + content=self.convert_incoming_message_content_to_string( + content + ), + role="assistant", + ) + ) + case "tool": + messages_.append( + ToolMessage( + content=self.convert_incoming_message_content_to_string( + content + ), + role="tool", + ) + ) + case _: + raise ValueError(f"Unexpected role: {role}") + + return messages_ + async def run_graph_async( self, *, request: ChatRequest, - compiled_state_graph: CompiledStateGraph, + headers: Dict[str, Any], + compiled_state_graph: CompiledStateGraph[MyMessagesState], ) -> List[AnyMessage]: """ Run the graph asynchronously. Args: request: The chat request. + headers: The request headers. compiled_state_graph: The compiled state graph. Returns: The list of any messages. """ - messages: List[tuple[ROLE_TYPES, INCOMING_MESSAGE_TYPES]] = ( - self.create_messages_for_graph(messages=request["messages"]) + messages: List[BaseMessage] = self.create_messages_for_graph( + messages=request["messages"] ) output_messages: List[AnyMessage] = await self._run_graph_with_messages_async( - compiled_state_graph=compiled_state_graph, messages=messages + chat_request=request, + headers=headers, + compiled_state_graph=compiled_state_graph, + messages=messages, ) return output_messages # noinspection PyMethodMayBeStatic async def create_graph_for_llm_async( self, *, llm: BaseChatModel, tools: Sequence[BaseTool] - ) -> CompiledStateGraph: + ) -> CompiledStateGraph[MyMessagesState]: """ Create a graph for the language model asynchronously. @@ -687,7 +807,7 @@ async def create_graph_for_llm_async( # noinspection PyMethodMayBeStatic async def _create_graph_for_llm_with_tools_async( self, *, llm: BaseChatModel, tools: Sequence[BaseTool] - ) -> CompiledStateGraph: + ) -> CompiledStateGraph[MyMessagesState]: """ Create a graph for the language model asynchronously. @@ -697,59 +817,14 @@ async def _create_graph_for_llm_with_tools_async( :return: compiled state graph """ tool_node: ToolNode | None = None - model_with_tools: Runnable[ - PromptValue - | str - | Sequence[ - BaseMessage | list[str] | tuple[str, str] | str | dict[str, Any] - ], - BaseMessage, - ] if len(tools) > 0: tool_node = StreamingToolNode(tools) - model_with_tools = llm.bind_tools(tools) - else: - model_with_tools = llm - - def should_continue( - state: MyMessagesState, - ) -> Union[Literal["tools"], str]: - messages: List[AnyMessage] = state["messages"] - last_message: AnyMessage = messages[-1] - # Check if it's an AIMessage and has tool calls - if isinstance(last_message, AIMessage) and getattr( - last_message, "tool_calls", None - ): - return "tools" - return END - - async def call_model(state: MyMessagesState) -> MyMessagesState: - messages: List[AnyMessage] = state["messages"] - response: AnyMessage - usage_metadata: Optional[UsageMetadata] = None - base_message: BaseMessage = await model_with_tools.ainvoke(messages) - # assert isinstance(base_message, AnyMessage) - response = cast(AnyMessage, base_message) - usage_metadata = ( - response.usage_metadata if hasattr(response, "usage_metadata") else None - ) - return MyMessagesState(messages=[response], usage_metadata=usage_metadata) - - workflow = StateGraph(MyMessagesState) - - # Define the two nodes we will cycle between - workflow.add_node("agent", call_model) # Now using async call_model - if len(tools) > 0: - assert tool_node is not None - workflow.add_node("tools", tool_node) - - workflow.add_edge(START, "agent") - if len(tools) > 0: - workflow.add_conditional_edges("agent", should_continue, ["tools", END]) - workflow.add_edge("tools", "agent") - workflow.add_edge("agent", END) - compiled_state_graph: CompiledStateGraph = workflow.compile() + compiled_state_graph: CompiledStateGraph[MyMessagesState] = create_react_agent( + model=llm, + tools=tool_node if tool_node is not None else [], + state_schema=MyMessagesState, + ) return compiled_state_graph @staticmethod @@ -771,3 +846,79 @@ def add_completion_usage( completion_tokens=original.completion_tokens + new_one.completion_tokens, total_tokens=original.total_tokens + new_one.total_tokens, ) + + @staticmethod + def create_state( + *, + chat_request: ChatRequest, + headers: Dict[str, Any], + messages: List[BaseMessage], + ) -> MyMessagesState: + """ + Create the state. + """ + + input1: MyMessagesState = MyMessagesState( + messages=messages, + auth_token=LangGraphToOpenAIConverter.get_auth_token_from_headers( + headers=headers + ), + usage_metadata=None, + remaining_steps=0, + ) + return input1 + + @staticmethod + def get_auth_token_from_headers(headers: Dict[str, str]) -> Optional[str]: + """ + Get the auth token from the headers. + + Args: + headers: The headers. + + Returns: + The auth token. + """ + # Normalize headers to handle case-insensitive matching + normalized_headers = {k.lower(): v for k, v in headers.items()} + + # Check for authorization header variations + auth_headers = ["authorization"] + + for header_key in auth_headers: + header_value = normalized_headers.get(header_key.lower()) + + if header_value: + # Use regex to extract bearer token + match = re.search(r"Bearer\s+(\S+)", str(header_value), re.IGNORECASE) + if match: + return match.group(1) + + return None + + @staticmethod + def convert_incoming_message_content_to_string( + content_: INCOMING_MESSAGE_TYPES, + ) -> str: + """ + Convert the message content to a string. + + Args: + content_: The message content. + + Returns: + The message content as a string. + """ + text: List[str] = [] + if isinstance(content_, str): + text.append(content_) + elif isinstance(content_, list): + for content_item in content_: + content_item_type: Optional[str] = content_item.get("type") + if content_item_type == "text": + text.append(content_item.get("text") or "") + else: + raise ValueError( + f"Unsupported content item type: {type(content_item)}: {content_item}" + ) + return "".join(text) diff --git a/language_model_gateway/gateway/converters/my_messages_state.py b/language_model_gateway/gateway/converters/my_messages_state.py index 644422dce..8c29cf263 100644 --- a/language_model_gateway/gateway/converters/my_messages_state.py +++ b/language_model_gateway/gateway/converters/my_messages_state.py @@ -1,8 +1,9 @@ from typing import Optional from langchain_core.messages.ai import UsageMetadata -from langgraph.graph import MessagesState +from langgraph.prebuilt.chat_agent_executor import AgentState -class MyMessagesState(MessagesState): +class MyMessagesState(AgentState): usage_metadata: Optional[UsageMetadata] + auth_token: Optional[str] diff --git a/language_model_gateway/gateway/file_managers/aws_s3_file_manager.py b/language_model_gateway/gateway/file_managers/aws_s3_file_manager.py index 57561108b..8fe645456 100644 --- a/language_model_gateway/gateway/file_managers/aws_s3_file_manager.py +++ b/language_model_gateway/gateway/file_managers/aws_s3_file_manager.py @@ -1,9 +1,9 @@ import logging from typing import Optional, Generator, override -import boto3 from botocore.exceptions import ClientError from starlette.responses import Response, StreamingResponse +from types_boto3_s3.client import S3Client from language_model_gateway.gateway.aws.aws_client_factory import AwsClientFactory from language_model_gateway.gateway.file_managers.file_manager import FileManager @@ -46,7 +46,8 @@ async def save_file_async( s3_full_path: str = s3_url.url - s3_client = self.aws_client_factory.create_client(service_name="s3") + s3_client: S3Client = self.aws_client_factory.create_s3_client() + if not file_data: logger.error("No file to save") return None @@ -90,16 +91,14 @@ def get_bucket(self, *, filename: str, folder: str) -> S3Url: async def read_file_async( self, *, folder: str, file_path: str ) -> StreamingResponse | Response: - s3_client: boto3.client = self.aws_client_factory.create_client( - service_name="s3" - ) + s3_client: S3Client = self.aws_client_factory.create_s3_client() - assert ( - "s3://" not in folder - ), "folder should not contain s3://. It should be the bucket name" - assert ( - "s3://" not in file_path - ), "file_path should not contain s3://. It should be the file path" + assert "s3://" not in folder, ( + "folder should not contain s3://. It should be the bucket name" + ) + assert "s3://" not in file_path, ( + "file_path should not contain s3://. It should be the file path" + ) s3_url: S3Url = self.get_bucket(folder=f"s3://{folder}", filename=file_path) try: s3_full_path: str = self.get_full_path( diff --git a/language_model_gateway/gateway/file_managers/file_manager.py b/language_model_gateway/gateway/file_managers/file_manager.py index 2a0359dc9..96ed6b2de 100644 --- a/language_model_gateway/gateway/file_managers/file_manager.py +++ b/language_model_gateway/gateway/file_managers/file_manager.py @@ -14,7 +14,7 @@ async def save_file_async( file_data: bytes, folder: str, filename: str, - content_type: str = "image/png" + content_type: str = "image/png", ) -> Optional[str]: raise NotImplementedError("Must be implemented in a subclass") @@ -26,3 +26,18 @@ async def read_file_async( self, *, folder: str, file_path: str ) -> StreamingResponse | Response: raise NotImplementedError("Must be implemented in a subclass") + + @staticmethod + async def extract_content(response: StreamingResponse) -> str: + """ + Extracts and returns content from a streaming response. + :param response: (StreamingResponse) s3 response for the file + :return: returns the file content in string format. + """ + extracted_content = "" + async for chunk in response.body_iterator: + # Decode the chunk, assuming it is UTF-8 encoded + assert isinstance(chunk, bytes) + extracted_content += chunk.decode("utf-8") + + return extracted_content diff --git a/language_model_gateway/gateway/image_generation/aws_image_generator.py b/language_model_gateway/gateway/image_generation/aws_image_generator.py index efbd28bbd..a1e18b7d2 100644 --- a/language_model_gateway/gateway/image_generation/aws_image_generator.py +++ b/language_model_gateway/gateway/image_generation/aws_image_generator.py @@ -6,7 +6,8 @@ from concurrent.futures.thread import ThreadPoolExecutor from typing import override, Dict, Any, Literal -import boto3 +from types_boto3_bedrock_runtime.client import BedrockRuntimeClient +from types_boto3_bedrock_runtime.type_defs import InvokeModelResponseTypeDef from language_model_gateway.gateway.aws.aws_client_factory import AwsClientFactory from language_model_gateway.gateway.image_generation.image_generator import ( @@ -23,13 +24,11 @@ def __init__(self, *, aws_client_factory: AwsClientFactory) -> None: assert self.aws_client_factory is not None assert isinstance(self.aws_client_factory, AwsClientFactory) - def _invoke_model(self, request_body: Dict[str, Any]) -> Dict[str, Any]: + def _invoke_model(self, request_body: Dict[str, Any]) -> InvokeModelResponseTypeDef: """Synchronous model invocation""" - client: boto3.client = self.aws_client_factory.create_client( - service_name="bedrock-runtime" - ) - response: Dict[str, Any] = client.invoke_model( + client: BedrockRuntimeClient = self.aws_client_factory.create_bedrock_client() + response: InvokeModelResponseTypeDef = client.invoke_model( modelId="amazon.titan-image-generator-v2:0", body=json.dumps(request_body), ) @@ -67,7 +66,7 @@ async def generate_image_async( loop = asyncio.get_running_loop() # Run model invocation in executor - response = await loop.run_in_executor( + response: InvokeModelResponseTypeDef = await loop.run_in_executor( self.executor, self._invoke_model, request_body ) diff --git a/language_model_gateway/gateway/image_generation/image_generator.py b/language_model_gateway/gateway/image_generation/image_generator.py index 149f2311a..6aea2748e 100644 --- a/language_model_gateway/gateway/image_generation/image_generator.py +++ b/language_model_gateway/gateway/image_generation/image_generator.py @@ -9,6 +9,6 @@ async def generate_image_async( style: Literal["natural", "cinematic", "digital-art", "pop-art"] = "natural", image_size: Literal[ "256x256", "512x512", "1024x1024", "1792x1024", "1024x1792" - ] = "1024x1024" + ] = "1024x1024", ) -> bytes: raise NotImplementedError("Must be implemented by subclass") diff --git a/language_model_gateway/gateway/image_generation/openai_image_generator.py b/language_model_gateway/gateway/image_generation/openai_image_generator.py index 51abcd9f0..1e935144f 100644 --- a/language_model_gateway/gateway/image_generation/openai_image_generator.py +++ b/language_model_gateway/gateway/image_generation/openai_image_generator.py @@ -15,7 +15,6 @@ class OpenAIImageGenerator(ImageGenerator): - @staticmethod async def _invoke_model_async( prompt: str, @@ -26,9 +25,9 @@ async def _invoke_model_async( """Synchronous OpenAI image generation""" openai_api_key: Optional[str] = os.environ.get("OPENAI_API_KEY") - assert ( - openai_api_key is not None - ), "OPENAI_API_KEY environment variable is not set" + assert openai_api_key is not None, ( + "OPENAI_API_KEY environment variable is not set" + ) client = AsyncOpenAI(api_key=openai_api_key) @@ -42,6 +41,10 @@ async def _invoke_model_async( ) # Extract the base64 encoded image and decode + assert response.data is not None and len(response.data) > 0, ( + "Base64 image is None" + ) + base64_image: Optional[str] = response.data[0].b64_json assert base64_image is not None, "Base64 image is None" return base64.b64decode(base64_image) diff --git a/language_model_gateway/configs/models.json b/language_model_gateway/gateway/langchain_overrides/__init__.py similarity index 100% rename from language_model_gateway/configs/models.json rename to language_model_gateway/gateway/langchain_overrides/__init__.py diff --git a/language_model_gateway/gateway/langchain_overrides/multiserver_mcp_client_with_caching.py b/language_model_gateway/gateway/langchain_overrides/multiserver_mcp_client_with_caching.py new file mode 100644 index 000000000..03031de6b --- /dev/null +++ b/language_model_gateway/gateway/langchain_overrides/multiserver_mcp_client_with_caching.py @@ -0,0 +1,278 @@ +import asyncio +import logging +from typing import override, List, Dict +from uuid import UUID, uuid4 + +from httpx import HTTPStatusError +from langchain_core.tools import BaseTool +from langchain_mcp_adapters.client import MultiServerMCPClient +from langchain_mcp_adapters.sessions import Connection +from langchain_mcp_adapters.sessions import create_session + +# noinspection PyProtectedMember +from langchain_mcp_adapters.tools import ( + _list_all_tools, + convert_mcp_tool_to_langchain_tool, +) +from mcp import ClientSession, Tool + +from language_model_gateway.gateway.utilities.cache.mcp_tools_expiring_cache import ( + McpToolsMetadataExpiringCache, +) + +logger = logging.getLogger(__name__) + + +class MultiServerMCPClientWithCaching(MultiServerMCPClient): # type: ignore[misc] + """A MultiServerMCPClient that caches tool metadata to avoid repeated calls to the MCP server. + + This class extends the MultiServerMCPClient to cache the metadata of tools + across multiple calls to `get_tools`. It allows for efficient retrieval of tools + without needing to repeatedly query the MCP server for the same tool metadata. + """ + + _identifier: UUID = uuid4() + _lock: asyncio.Lock = asyncio.Lock() + + def __init__( + self, + *, + connections: dict[str, Connection] | None = None, + cache: McpToolsMetadataExpiringCache, + tool_names: List[str] | None, + ) -> None: + """ + Initialize the async config reader + + Args: + cache: Expiring cache for model configurations + """ + assert cache is not None + self._cache: McpToolsMetadataExpiringCache = cache + assert self._cache is not None + self._tool_names: List[str] | None = tool_names + super().__init__(connections=connections) + + async def load_tools_metadata_cache( + self, *, server_name: str | None = None, tool_names: List[str] | None + ) -> None: + """Get a list of all tools from all connected servers. + + Args: + server_name: Optional name of the server to get tools from. + If None, all tools from all servers will be returned (default). + tool_names: Optional list of tool names to filter the tools. + + NOTE: a new session will be created for each tool call + + Returns: + A list of LangChain tools + + """ + async with self._lock: + cache: Dict[str, List[Tool]] | None = await self._cache.get() + if cache is None: + cache = await self._cache.create() + assert cache is not None, ( + "Cache must be initialized before getting tools" + ) + + if server_name is not None: + if server_name not in self.connections: + msg = f"Couldn't find a server with name '{server_name}', expected one of '{list(self.connections.keys())}'" + raise ValueError(msg) + connection_for_server = self.connections[server_name] + if connection_for_server["url"] not in cache: + cache[ + connection_for_server["url"] + ] = await self.load_metadata_for_mcp_tools( + session=None, + connection=connection_for_server, + tool_names=tool_names, + ) + logger.info( + f"Loaded tools for connection {connection_for_server['url']}" + ) + else: + logger.debug( + f"Tools for connection {connection_for_server['url']} are already cached" + ) + else: + for connection in self.connections.values(): + # if the tools for this connection are already cached, skip loading them + if connection["url"] not in cache: + cache[ + connection["url"] + ] = await self.load_metadata_for_mcp_tools( + session=None, + connection=connection, + tool_names=self._tool_names, + ) + logger.info(f"Loaded tools for connection {connection['url']}") + else: + # see if we are missing any tools in the cache + if self._tool_names: + cached_tool_names = [ + tool.name for tool in cache[connection["url"]] + ] + missing_tools = set(self._tool_names) - set( + cached_tool_names + ) + if missing_tools: + logger.info( + f"Missing tools {missing_tools} for connection {connection['url']}, loading them" + ) + tools = await self.load_metadata_for_mcp_tools( + session=None, + connection=connection, + tool_names=list(missing_tools), + ) + cache[connection["url"]].extend(tools) + else: + logger.debug( + f"Tools for connection {connection['url']} are already cached and all tools are present" + ) + else: + logger.debug( + f"Tools for connection {connection['url']} are already cached" + ) + # set the cache with the loaded tools + await self._cache.set(cache) + + @override + async def get_tools(self, *, server_name: str | None = None) -> list[BaseTool]: + """Get a list of all tools from all connected servers. + + Args: + server_name: Optional name of the server to get tools from. + If None, all tools from all servers will be returned (default). + + NOTE: a new session will be created for each tool call + + Returns: + A list of LangChain tools + + """ + + await self.load_tools_metadata_cache( + server_name=server_name, tool_names=self._tool_names + ) + + async with self._lock: + cache: Dict[str, List[Tool]] | None = await self._cache.get() + assert cache is not None, "Cache must be initialized before getting tools" + + # create LangChain tools from the loaded MCP tools + all_tools: List[BaseTool] = [] + for connection in self.connections.values(): + tools_for_connection = cache[connection["url"]] + all_tools.extend( + self.create_tools_from_list( + tools=tools_for_connection, session=None, connection=connection + ) + ) + return all_tools + + @staticmethod + async def load_metadata_for_mcp_tools( + *, + session: ClientSession | None, + connection: Connection | None = None, + tool_names: List[str] | None, + ) -> list[Tool]: + """Load all available MCP tools and convert them to LangChain tools. + + Args: + session: The MCP client session. If None, connection must be provided. + connection: Connection config to create a new session if session is None. + tool_names: Optional list of tool names to filter the tools. + If None, all tools will be returned. + + Returns: + List of LangChain tools. Tool annotations are returned as part + of the tool metadata object. + + Raises: + ValueError: If neither session nor connection is provided. + """ + if session is None and connection is None: + msg = "Either a session or a connection config must be provided" + raise ValueError(msg) + + tools: List[Tool] = [] + try: + if session is None: + # If a session is not provided, we will create one on the fly + async with create_session(connection) as tool_session: + await tool_session.initialize() + tools = await _list_all_tools(tool_session) + else: + tools = await _list_all_tools(session) + except* HTTPStatusError as exc: + # if there is + # exc is a ExceptionGroup, so we can catch it with a wildcard + # and log the type of the exception + # if there is just one exception then check if it is 401 and then return a custom error + if len(exc.exceptions) == 1 and isinstance( + exc.exceptions[0], HTTPStatusError + ): + http_status_exception: HTTPStatusError = exc.exceptions[0] + if http_status_exception.response.status_code == 401: + logger.error( + f"load_metadata_for_mcp_tools Unauthorized access to MCP tools: {http_status_exception}" + ) + # Read response text before the stream is closed + if not http_status_exception.response.is_closed: + response_bytes = await http_status_exception.response.aread() + response_text = ( + response_bytes.decode() + if isinstance(response_bytes, bytes) + else str(response_bytes) + ) + else: + response_text = http_status_exception.response.reason_phrase + raise ValueError( + f"Not allowed to access MCP tool at {http_status_exception.request.url}." + + " Perhaps your login token has expired. Please reload to login again." + + f" Response: {response_text}" + ) from exc + logger.error( + f"load_metadata_for_mcp_tools Failed to load MCP tools: {type(exc)}" + ) + except* Exception as e: + url: str = connection.get("url") if connection else "unknown" + logger.error( + f"load_metadata_for_mcp_tools Failed to load MCP tools from {url}: {type(e)} {e}" + ) + raise e + + if tool_names is not None: + # Filter tools by names if provided + tools = [tool for tool in tools if tool.name in tool_names] + return tools + + @staticmethod + def create_tools_from_list( + *, + tools: list[Tool], + session: ClientSession | None = None, + connection: Connection | None = None, + ) -> List[BaseTool]: + """ + Create LangChain tools from a list of MCP tools. + Args: + tools: List of MCP tools to convert. + session: The MCP client session. If None, connection must be provided. + connection: Connection config to create a new session if session is None. + """ + try: + return [ + convert_mcp_tool_to_langchain_tool(session, tool, connection=connection) + for tool in tools + ] + except Exception as e: + url: str = connection.get("url") if connection else "unknown" + logger.error( + f"Failed to convert MCP tools to LangChain tools from {url}, tools={[t.name for t in tools]}: {e}" + ) + raise e diff --git a/language_model_gateway/gateway/managers/chat_completion_manager.py b/language_model_gateway/gateway/managers/chat_completion_manager.py index 163bdde29..f6d5d3c47 100644 --- a/language_model_gateway/gateway/managers/chat_completion_manager.py +++ b/language_model_gateway/gateway/managers/chat_completion_manager.py @@ -31,6 +31,8 @@ from language_model_gateway.gateway.schema.openai.completions import ChatRequest from openai.types.chat.chat_completion_chunk import ChoiceDelta, Choice as ChunkChoice +from language_model_gateway.gateway.utilities.exception_logger import ExceptionLogger + logger = logging.getLogger(__name__) @@ -80,9 +82,9 @@ async def chat_completions( model: str = chat_request["model"] assert model is not None - configs: List[ChatModelConfig] = ( - await self.config_reader.read_model_configs_async() - ) + configs: List[ + ChatModelConfig + ] = await self.config_reader.read_model_configs_async() # Find the model config model_config: ChatModelConfig | None = next( @@ -124,14 +126,25 @@ async def chat_completions( f"Running chat completion for {chat_request} with headers {headers}" ) # Use the provider to get the completions - response: StreamingResponse | JSONResponse = ( - await provider.chat_completions( - model_config=model_config, - headers=headers, - chat_request=chat_request, - ) + response: ( + StreamingResponse | JSONResponse + ) = await provider.chat_completions( + model_config=model_config, + headers=headers, + chat_request=chat_request, ) return response + except ExceptionGroup as e: + # if there is just one exception, we can log it directly + if len(e.exceptions) == 1: + logger.error( + f"ExceptionGroup in chat completion: {e.exceptions[0]}", + exc_info=True, + ) + return await self.handle_exception( + chat_request=chat_request, e=e.exceptions[0] + ) + return await self.handle_exception(chat_request=chat_request, e=e) except Exception as e: return await self.handle_exception(chat_request=chat_request, e=e) @@ -241,7 +254,7 @@ def write_response( ) if should_stream_response: - async def foo( + async def stream_response( response_messages1: List[ChatCompletionMessage], ) -> AsyncGenerator[str, None]: for response_message in response_messages1: @@ -270,7 +283,7 @@ async def foo( yield "data: [DONE]\n\n" return StreamingResponse( - content=foo(response_messages1=response_messages), + content=stream_response(response_messages1=response_messages), media_type="text/event-stream", ) else: @@ -298,8 +311,14 @@ async def foo( async def handle_exception( self, *, chat_request: ChatRequest, e: Exception ) -> StreamingResponse | JSONResponse: - logger.error(f"Error in chat completion: {e}") + logger.error( + f"Error in chat completion: {e} {type(e)} {e.__dict__.keys()}", + exc_info=True, + ) + content = ExceptionLogger.extract_error_details(e) return self.write_response( chat_request=chat_request, - response_messages=[ChatCompletionMessage(role="assistant", content=str(e))], + response_messages=[ + ChatCompletionMessage(role="assistant", content=content) + ], ) diff --git a/language_model_gateway/gateway/managers/image_generation_manager.py b/language_model_gateway/gateway/managers/image_generation_manager.py index 20dd4b685..6d1af44be 100644 --- a/language_model_gateway/gateway/managers/image_generation_manager.py +++ b/language_model_gateway/gateway/managers/image_generation_manager.py @@ -23,7 +23,7 @@ async def generate_image_async( self, *, image_generation_request: ImageGenerationRequest, - headers: Dict[str, str] + headers: Dict[str, str], ) -> StreamingResponse | JSONResponse: """ Implements the image generation manager @@ -39,10 +39,10 @@ async def generate_image_async( assert isinstance(headers, dict) assert isinstance(image_generation_request, dict) - response: StreamingResponse | JSONResponse = ( - await self.image_generation_provider.generate_image_async( - image_generation_request=image_generation_request, headers=headers - ) + response: ( + StreamingResponse | JSONResponse + ) = await self.image_generation_provider.generate_image_async( + image_generation_request=image_generation_request, headers=headers ) return response diff --git a/language_model_gateway/gateway/managers/model_manager.py b/language_model_gateway/gateway/managers/model_manager.py index 5df3aaa15..4a25852a6 100644 --- a/language_model_gateway/gateway/managers/model_manager.py +++ b/language_model_gateway/gateway/managers/model_manager.py @@ -20,9 +20,9 @@ async def get_models( *, headers: Dict[str, str], ) -> Dict[str, str | List[Dict[str, str | int]]]: - configs: List[ChatModelConfig] = ( - await self.config_reader.read_model_configs_async() - ) + configs: List[ + ChatModelConfig + ] = await self.config_reader.read_model_configs_async() logger = logging.getLogger(__name__) logger.info("Received request for models") # get time in seconds since epoch from ten minutes ago diff --git a/language_model_gateway/gateway/ocr/aws_ocr_extractor.py b/language_model_gateway/gateway/ocr/aws_ocr_extractor.py index 2ca964e23..4b5fef97c 100644 --- a/language_model_gateway/gateway/ocr/aws_ocr_extractor.py +++ b/language_model_gateway/gateway/ocr/aws_ocr_extractor.py @@ -4,8 +4,8 @@ from typing import Optional, List from uuid import uuid4 -import boto3 from pypdf import PdfReader, PdfWriter +from types_boto3_textract.client import TextractClient from language_model_gateway.gateway.aws.aws_client_factory import AwsClientFactory from language_model_gateway.gateway.file_managers.file_manager import FileManager @@ -41,8 +41,8 @@ async def extract_text_with_textract_async(self, pdf_bytes: bytes) -> str: """ try: # Create Textract client - textract_client: boto3.client = self.aws_client_factory.create_client( - service_name="textract" + textract_client: TextractClient = ( + self.aws_client_factory.create_textract_client() ) # Open PDF from memory @@ -108,9 +108,9 @@ async def extract_text_with_textract_save_to_s3_async( # first save the file to s3 # Save the file to S3 image_generation_path_ = os.environ["IMAGE_GENERATION_PATH"] - assert ( - image_generation_path_ - ), "IMAGE_GENERATION_PATH environment variable is not set" + assert image_generation_path_, ( + "IMAGE_GENERATION_PATH environment variable is not set" + ) image_file_name: str = f"{uuid4()}.pdf" file_manager: FileManager = self.file_manager_factory.get_file_manager( @@ -125,8 +125,8 @@ async def extract_text_with_textract_save_to_s3_async( assert file_path is not None # Call Textract API - textract_client: boto3.client = self.aws_client_factory.create_client( - service_name="textract" + textract_client: TextractClient = ( + self.aws_client_factory.create_textract_client() ) s3_bucket, s3_object_key = UrlParser.parse_s3_uri(file_path) diff --git a/language_model_gateway/gateway/providers/base_chat_completions_provider.py b/language_model_gateway/gateway/providers/base_chat_completions_provider.py index 0c3e0ce54..37a9463b1 100644 --- a/language_model_gateway/gateway/providers/base_chat_completions_provider.py +++ b/language_model_gateway/gateway/providers/base_chat_completions_provider.py @@ -1,4 +1,4 @@ -from abc import abstractmethod +from abc import abstractmethod, ABCMeta from typing import Dict from starlette.responses import StreamingResponse, JSONResponse @@ -7,7 +7,7 @@ from language_model_gateway.gateway.schema.openai.completions import ChatRequest -class BaseChatCompletionsProvider: +class BaseChatCompletionsProvider(metaclass=ABCMeta): @abstractmethod async def chat_completions( self, diff --git a/language_model_gateway/gateway/providers/base_image_generation_provider.py b/language_model_gateway/gateway/providers/base_image_generation_provider.py index 8ecb5d1af..088491656 100644 --- a/language_model_gateway/gateway/providers/base_image_generation_provider.py +++ b/language_model_gateway/gateway/providers/base_image_generation_provider.py @@ -14,5 +14,5 @@ async def generate_image_async( self, *, image_generation_request: ImageGenerationRequest, - headers: Dict[str, str] + headers: Dict[str, str], ) -> StreamingResponse | JSONResponse: ... diff --git a/language_model_gateway/gateway/providers/image_generation_provider.py b/language_model_gateway/gateway/providers/image_generation_provider.py index cb8b2bb1c..e46bedf86 100644 --- a/language_model_gateway/gateway/providers/image_generation_provider.py +++ b/language_model_gateway/gateway/providers/image_generation_provider.py @@ -90,9 +90,9 @@ async def generate_image_async( response_data = [Image(b64_json=image_b64_json)] else: image_generation_path_ = os.environ["IMAGE_GENERATION_PATH"] - assert ( - image_generation_path_ - ), "IMAGE_GENERATION_PATH environment variable is not set" + assert image_generation_path_, ( + "IMAGE_GENERATION_PATH environment variable is not set" + ) image_file_name: str = f"{uuid4()}.png" file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ diff --git a/language_model_gateway/gateway/providers/langchain_chat_completions_provider.py b/language_model_gateway/gateway/providers/langchain_chat_completions_provider.py index ecdfcec2e..71b463557 100644 --- a/language_model_gateway/gateway/providers/langchain_chat_completions_provider.py +++ b/language_model_gateway/gateway/providers/langchain_chat_completions_provider.py @@ -1,6 +1,6 @@ import datetime import random -from typing import Dict, Any, Sequence +from typing import Dict, Any, Sequence, List from langchain_core.language_models import BaseChatModel from langchain_core.tools import BaseTool @@ -11,12 +11,15 @@ from language_model_gateway.gateway.converters.langgraph_to_openai_converter import ( LangGraphToOpenAIConverter, ) +from language_model_gateway.gateway.converters.my_messages_state import MyMessagesState from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.providers.base_chat_completions_provider import ( BaseChatCompletionsProvider, ) from language_model_gateway.gateway.schema.openai.completions import ChatRequest +from language_model_gateway.gateway.tools.mcp_tool_provider import MCPToolProvider from language_model_gateway.gateway.tools.tool_provider import ToolProvider +from language_model_gateway.gateway.utilities.auth.token_verifier import TokenVerifier class LangChainCompletionsProvider(BaseChatCompletionsProvider): @@ -25,7 +28,9 @@ def __init__( *, model_factory: ModelFactory, lang_graph_to_open_ai_converter: LangGraphToOpenAIConverter, - tool_provider: ToolProvider + tool_provider: ToolProvider, + mcp_tool_provider: MCPToolProvider, + token_verifier: TokenVerifier, ) -> None: self.model_factory: ModelFactory = model_factory assert self.model_factory is not None @@ -41,14 +46,21 @@ def __init__( assert self.tool_provider is not None assert isinstance(self.tool_provider, ToolProvider) + self.mcp_tool_provider: MCPToolProvider = mcp_tool_provider + assert self.mcp_tool_provider is not None + assert isinstance(self.mcp_tool_provider, MCPToolProvider) + + self.token_verifier: TokenVerifier = token_verifier + assert self.token_verifier is not None + assert isinstance(self.token_verifier, TokenVerifier) + async def chat_completions( self, *, model_config: ChatModelConfig, headers: Dict[str, str], - chat_request: ChatRequest + chat_request: ChatRequest, ) -> StreamingResponse | JSONResponse: - # noinspection PyArgumentList llm: BaseChatModel = self.model_factory.get_model( chat_model_config=model_config @@ -62,21 +74,70 @@ def get_current_time(*args: Any, **kwargs: Any) -> str: # Initialize tools tools: Sequence[BaseTool] = ( - self.tool_provider.get_tools(tools=[t for t in model_config.get_agents()]) + self.tool_provider.get_tools( + tools=[t for t in model_config.get_agents()], headers=headers + ) if model_config.get_agents() is not None else [] ) - compiled_state_graph: CompiledStateGraph = ( - await self.lang_graph_to_open_ai_converter.create_graph_for_llm_async( - llm=llm, - tools=tools, + # Load MCP tools if they are enabled + await self.mcp_tool_provider.load_async() + # check if any of the MCP tools require authentication + tools_using_authentication: List[str] = [ + a.name for a in model_config.get_agents() if a.auth == "jwt_token" + ] + if any(tools_using_authentication): + # check that we have a valid Authorization header + auth_header: str | None = next( + (headers.get(key) for key in headers if key.lower() == "authorization"), + None, ) + if not auth_header: + raise ValueError( + "Authorization header is required for MCP tools with JWT authentication." + + f"Following tools require authentication: {tools_using_authentication}" + ) + else: + token = self.token_verifier.extract_token(auth_header) + if not token: + raise ValueError( + "Invalid Authorization header format. Expected 'Bearer '" + + f"Following tools require authentication: {tools_using_authentication}" + ) + # verify the token + try: + access_token = await self.token_verifier.verify_token_async( + token=token + ) + if not access_token: + raise ValueError( + "Invalid or expired token provided in Authorization header" + + f"Following tools require authentication: {tools_using_authentication}" + ) + except Exception as e: + raise ValueError( + "Invalid or expired token provided in Authorization header." + + f" Following tools require authentication: {tools_using_authentication}" + ) from e + + # add MCP tools + tools = [t for t in tools] + await self.mcp_tool_provider.get_tools_async( + tools=[t for t in model_config.get_agents()], + headers=headers, + ) + + compiled_state_graph: CompiledStateGraph[ + MyMessagesState + ] = await self.lang_graph_to_open_ai_converter.create_graph_for_llm_async( + llm=llm, + tools=tools, ) request_id = random.randint(1, 1000) return await self.lang_graph_to_open_ai_converter.call_agent_with_input( request_id=str(request_id), + headers=headers, compiled_state_graph=compiled_state_graph, chat_request=chat_request, system_messages=[], diff --git a/language_model_gateway/gateway/providers/openai_chat_completions_provider.py b/language_model_gateway/gateway/providers/openai_chat_completions_provider.py index cfa6db1b9..8878a4699 100644 --- a/language_model_gateway/gateway/providers/openai_chat_completions_provider.py +++ b/language_model_gateway/gateway/providers/openai_chat_completions_provider.py @@ -126,7 +126,6 @@ async def _stream_resp_async_generator( chat_request: ChatRequest, headers: Dict[str, str], ) -> AsyncGenerator[str, None]: - logger.info(f"Streaming response {request_id} from agent") async with self.http_client_factory.create_http_client( base_url="http://test" diff --git a/language_model_gateway/gateway/routers/chat_completion_router.py b/language_model_gateway/gateway/routers/chat_completion_router.py index 78eeb1e26..ee6e5d0c4 100644 --- a/language_model_gateway/gateway/routers/chat_completion_router.py +++ b/language_model_gateway/gateway/routers/chat_completion_router.py @@ -58,6 +58,16 @@ def _register_routes(self) -> None: response_description="Chat completions", status_code=200, ) + self.router.add_api_route( + "/chat/completion", + self.chat_completions, + methods=["POST"], + response_model=None, + summary="Complete a chat prompt", + description="Completes a chat prompt using the specified model", + response_description="Chat completions", + status_code=200, + ) # noinspection PyMethodMayBeStatic async def chat_completions( @@ -85,7 +95,8 @@ async def chat_completions( try: return await chat_manager.chat_completions( - headers={k: v for k, v in request.headers.items()}, + # convert headers to lowercase to match OpenAI API expectations + headers={k.lower(): v for k, v in request.headers.items()}, chat_request=cast(ChatRequest, chat_request), ) except* TokenRetrievalError as e: diff --git a/language_model_gateway/gateway/tools/calculator_average_tool.py b/language_model_gateway/gateway/tools/calculator_average_tool.py new file mode 100644 index 000000000..7b3a4d82a --- /dev/null +++ b/language_model_gateway/gateway/tools/calculator_average_tool.py @@ -0,0 +1,46 @@ +import asyncio +from typing import List +import logging + +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + +logger = logging.getLogger(__name__) + + +class CalculatorAverageTool(ResilientBaseTool): + """ + LangChain-compatible tool for calculating the average of a list of numbers. + + Example usage: + - Input: [10, 20, 30] + - Output: "The average of the provided numbers is: 20.0" + """ + + logger.info("Initializing CalculatorAverageTool") + + name: str = "CalculatorAverageTool" + description: str = ( + "Useful for when you need to calculate the average of a list of numbers" + ) + + async def _arun(self, numbers: List[float]) -> str: + """Run the tool to calculate the average of a list of numbers""" + logger.info(f"CalculatorAverageTool _arun called with numbers: {numbers}") + + if not numbers: + logger.warning("No numbers provided to calculate the average.") + return "No numbers provided to calculate the average." + + try: + # Ensure all inputs are convertible to float + numbers = [float(num) for num in numbers] + average = sum(numbers) / len(numbers) + logger.info(f"Calculated average: {average}") + return f"The average of the provided numbers is: {average}" + except (TypeError, ValueError) as e: + logger.error(f"Error converting numbers: {e}") + return f"Error: Could not convert all inputs to numbers. {e}" + + def _run(self, numbers: List[float]) -> str: + """Async implementation of the tool (in this case, just calls _run)""" + return asyncio.run(self._arun(numbers=numbers)) diff --git a/language_model_gateway/gateway/tools/calculator_length_tool.py b/language_model_gateway/gateway/tools/calculator_length_tool.py new file mode 100644 index 000000000..407c090e8 --- /dev/null +++ b/language_model_gateway/gateway/tools/calculator_length_tool.py @@ -0,0 +1,37 @@ +import asyncio +from typing import Any +import logging + +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + + +logger = logging.getLogger(__name__) + + +class CalculatorLengthTool(ResilientBaseTool): + """ + LangChain-compatible tool for calculating the length (count) of a list of items. + + Example usage: + - Input: ["apple", "banana", "cherry"] + - Output: "The length of the provided list is: 3" + """ + + name: str = "CalculatorLengthTool" + description: str = ( + "Useful for when you need to calculate the length (count) of a list of items" + ) + + async def _arun(self, items: list[Any]) -> str: + """Run the tool to calculate the length of a list of items""" + if items is None: + logger.warning("No list provided to calculate the length.") + return "No list provided to calculate the length." + + length = len(items) + logger.info("Calculated length: %d for items: %s", length, items) + return f"The length of the provided list is: {length}" + + def _run(self, items: list[Any]) -> str: + """Async implementation of the tool (in this case, just calls _run)""" + return asyncio.run(self._arun(items=items)) diff --git a/language_model_gateway/gateway/tools/calculator_stddev_tool.py b/language_model_gateway/gateway/tools/calculator_stddev_tool.py new file mode 100644 index 000000000..71449e763 --- /dev/null +++ b/language_model_gateway/gateway/tools/calculator_stddev_tool.py @@ -0,0 +1,53 @@ +import asyncio + +import math +import logging + +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + + +logger = logging.getLogger(__name__) + + +class CalculatorStddevTool(ResilientBaseTool): + """ + LangChain-compatible tool for calculating the standard deviation of a list of numbers. + + Example usage: + - Input: [10, 20, 30] + - Output: "The standard deviation of the provided numbers is: 8.16" + """ + + name: str = "CalculatorStddevTool" + description: str = "Useful for when you need to calculate the standard deviation of a list of numbers" + + async def _arun(self, numbers: list[float]) -> str: + """Run the tool to calculate the standard deviation of a list of numbers""" + logger.info("Starting standard deviation calculation.") + logger.debug(f"Input numbers: {numbers}") + + if not numbers: + logger.warning("No numbers provided to calculate the standard deviation.") + return "No numbers provided to calculate the standard deviation." + + if len(numbers) == 1: + logger.info("Only one number provided. Standard deviation is 0.0.") + return "Standard deviation of a single number is: 0.0" + + # Calculate mean + mean = sum(numbers) / len(numbers) + logger.debug(f"Calculated mean: {mean}") + + # Calculate variance (average of squared differences from mean) + variance = sum((x - mean) ** 2 for x in numbers) / len(numbers) + logger.debug(f"Calculated variance: {variance}") + + # Standard deviation is square root of variance + stddev = math.sqrt(variance) + logger.info(f"Calculated standard deviation: {stddev:.2f}") + + return f"The standard deviation of the provided numbers is: {stddev:.2f}" + + def _run(self, numbers: list[float]) -> str: + """Async implementation of the tool (in this case, just calls _run)""" + return asyncio.run(self._arun(numbers=numbers)) diff --git a/language_model_gateway/gateway/tools/calculator_sum_tool.py b/language_model_gateway/gateway/tools/calculator_sum_tool.py new file mode 100644 index 000000000..c1d498656 --- /dev/null +++ b/language_model_gateway/gateway/tools/calculator_sum_tool.py @@ -0,0 +1,39 @@ +import asyncio +from typing import List +import logging + +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + + +logger = logging.getLogger(__name__) + + +class CalculatorSumTool(ResilientBaseTool): + """ + LangChain-compatible tool for calculating the sum of a list of numbers. + + Example usage: + - Input: [10, 20, 30] + - Output: "The sum of the provided numbers is: 60.0" + """ + + name: str = "CalculatorSumTool" + description: str = ( + "Useful for when you need to calculate the sum of a list of numbers" + ) + + async def _arun(self, numbers: List[float]) -> str: + """Run the tool to calculate the sum of a list of numbers""" + logger.debug(f"Received numbers for sum: {numbers}") + + if not numbers: + logger.warning("No numbers provided to calculate the sum.") + return "No numbers provided to calculate the sum." + + total = sum(numbers) + logger.info(f"Calculated sum: {total}") + return f"The sum of the provided numbers is: {total}" + + def _run(self, numbers: List[float]) -> str: + """Async implementation of the tool (in this case, just calls _run)""" + return asyncio.run(self._arun(numbers=numbers)) diff --git a/language_model_gateway/gateway/tools/confluence_page_retriever.py b/language_model_gateway/gateway/tools/confluence_page_retriever.py new file mode 100644 index 000000000..a51dc744c --- /dev/null +++ b/language_model_gateway/gateway/tools/confluence_page_retriever.py @@ -0,0 +1,99 @@ +import logging +from typing import Optional, Type, Tuple, Literal +from pydantic import BaseModel, Field +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.confluence.confluence_document import ( + ConfluenceDocument, +) +from language_model_gateway.gateway.utilities.confluence.confluence_helper import ( + ConfluenceHelper, +) + +logger = logging.getLogger(__name__) + + +class ConfluencePageRetrieverAgentInput(BaseModel): + """ + Input model for retrieving a specific Confluence page by ID. + """ + + page_id: str = Field( + default="", description="The ID of the Confluence page to retrieve." + ) + + +class ConfluencePageRetriever(ResilientBaseTool): + """ + A LangChain-compatible tool for retrieving a specific Confluence page by ID. + """ + + name: str = "confluence_page_retriever" + description: str = ( + "Tool to retrieve a specific Confluence page by ID. " + "USAGE TIPS: " + "- Provide the Confluence page ID to retrieve the page details." + ) + + args_schema: Type[BaseModel] = ConfluencePageRetrieverAgentInput + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + confluence_helper: ConfluenceHelper + + async def _arun( + self, + page_id: str, + ) -> Tuple[str, str]: + """ + Asynchronous version of the Confluence Page by ID tool. + + Returns: + Tuple of Confluence page text and artifact description + """ + log_prefix: str = f"ConfluencePageRetriever: page_id={page_id}" + + try: + confluence_page: Optional[ + ConfluenceDocument + ] = await self.confluence_helper.retrieve_page_by_id(page_id=page_id) + + if not confluence_page: + error_msg = "Error retrieving Confluence page: Page not found" + error_artifact = log_prefix + " Retrieval Failed: Page not found" + logger.error(error_msg) + return error_msg, error_artifact + + full_text_display = ( + f"**Title**: {confluence_page.title}\n" + f"**URL**: {confluence_page.url}\n" + f"**Updated**: {confluence_page.updated_at}\n" + f"**Author**: {confluence_page.author_name}\n" + ) + + full_text = ( + f"Id: {confluence_page.id}\n" + f"{full_text_display}" + f"Content: {confluence_page.content}\n" + ) + + artifact = log_prefix + f", Retrieved page {confluence_page.id}.\n\n" + artifact += f"\n{full_text_display}" + + return full_text, artifact + + except Exception as e: + error_msg = f"Error retrieving Confluence page: {str(e)}" + error_artifact = log_prefix + " Retrieval Failed: " + str(e) + logger.error(error_msg) + return error_msg, error_artifact + + def _run( + self, + page_id: str, + ) -> Tuple[str, str]: + """ + Synchronous version of the Confluence Page by ID tool. + + Returns: + Tuple of Confluence page text and artifact description + """ + raise NotImplementedError("Use async version of this tool") diff --git a/language_model_gateway/gateway/tools/confluence_search_tool.py b/language_model_gateway/gateway/tools/confluence_search_tool.py new file mode 100644 index 000000000..f73474453 --- /dev/null +++ b/language_model_gateway/gateway/tools/confluence_search_tool.py @@ -0,0 +1,76 @@ +import logging +from typing import Type, Literal, Optional, Tuple +from pydantic import BaseModel, Field + +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.confluence.confluence_helper import ( + ConfluenceHelper, +) +from language_model_gateway.gateway.utilities.csv_to_markdown_converter import ( + CsvToMarkdownConverter, +) + +logger = logging.getLogger(__name__) + + +class ConfluenceSearchToolInput(BaseModel): + """ + Input model for configuring Confluence search and analysis. + + """ + + search_string: str = Field( + ..., description="The search string to use for querying Confluence content." + ) + limit: Optional[int] = Field( + default=10, description="Maximum number of search results to retrieve." + ) + + +class ConfluenceSearchTool(ResilientBaseTool): + name: str = "confluence_search_tool" + description: str = ( + "Tool for searching content in Confluence. " + "USAGE TIPS: " + "- Provide a search string to search content in Confluence." + "- Indicate the Confluence space to limit the search results." + ) + + args_schema: Type[BaseModel] = ConfluenceSearchToolInput + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + confluence_helper: ConfluenceHelper + + async def _arun(self, search_string: str, limit: int = 10) -> Tuple[str, str]: + try: + search_results = await self.confluence_helper.search_content( + search_string, limit + ) + + logger.info(f"CONFLUENCE SEARCH TOOL, RESULTS:\n{search_results}") + + if not search_results: + return "No results found.", "No results found." + + csv_results = self.confluence_helper.format_results_as_csv(search_results) + csv_results_display = ( + self.confluence_helper.format_results_as_csv_for_display(search_results) + ) + markdown_results = CsvToMarkdownConverter.csv_to_markdown_table( + csv_results_display + ) + + artifact = f"Search results for query: {search_string}\n\nResults:\n{markdown_results}" + return csv_results, artifact + except Exception as e: + error_msg = f"Error searching Confluence content: {str(e)}" + return error_msg, error_msg + + def _run(self, search_string: str, limit: Optional[int] = 10) -> Tuple[str, str]: + """ + Synchronous version of the tool (falls back to async implementation). + + Raises: + NotImplementedError: Always raises to enforce async usage + """ + raise NotImplementedError("Use async version of this tool") diff --git a/language_model_gateway/gateway/tools/databricks_sql_tool.py b/language_model_gateway/gateway/tools/databricks_sql_tool.py new file mode 100644 index 000000000..423335319 --- /dev/null +++ b/language_model_gateway/gateway/tools/databricks_sql_tool.py @@ -0,0 +1,54 @@ +from pydantic import BaseModel, Field +from typing import Type, Optional, Tuple, Literal, Any +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.databricks.databricks_helper import ( + DatabricksHelper, +) + + +class DatabricksSQLInput(BaseModel): + """ + Enhanced input model for Databricks with API validation + """ + + fhir_request: Optional[str] = Field( + default=None, + description=("Request to be created into a query. "), + ) + + +class DatabricksSQLTool(ResilientBaseTool): + """ + Enhanced Databricks Agent Tool with API Validation + """ + + name: str = "databricks_tool" + description: str = ( + "A tool for querying FHIR data from Databricks. " + "USAGE TIPS: " + "- If you believe a query will return a large amount of data, please use the 'limit' keyword in the query. For example: 'Get all patients with diabetes diagnosis' would return a lot of results. If you are limiting, tell the user beforehand. " + "- Check the query before running it. Make sure if calling nested fields that you have accounted for proper explosion of those fields into new tables. Join accordingly. " + "- Take the natural language query, convert it into SQL, and present that SQL in clear SQL format to the user prior to sending to Databricks. " + "Example queries: " + "'Get all patients with diabetes diagnosis'. " + "'Get demographics of patients'. " + "'Get all patients with diabetes and a count of their encounters'. " + ) + args_schema: Type[DatabricksSQLInput] = DatabricksSQLInput + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + databricks_helper: DatabricksHelper + + def _run( + self, + fhir_request: Optional[str] = None, + ) -> Tuple[str, Any]: + raise NotImplementedError("Use async version of this tool") + + async def _arun(self, fhir_request: str) -> Tuple[str, str]: + if not fhir_request or not fhir_request.strip(): + raise ValueError("Query cannot be empty or None") + results = self.databricks_helper.execute_query(fhir_request) + artifact = f"\n\nDatabricksSQLTool: Query Results\n {results}" + + return results, artifact diff --git a/language_model_gateway/gateway/tools/er_diagram_generator_tool.py b/language_model_gateway/gateway/tools/er_diagram_generator_tool.py index 0646aab86..f3df5d2a9 100644 --- a/language_model_gateway/gateway/tools/er_diagram_generator_tool.py +++ b/language_model_gateway/gateway/tools/er_diagram_generator_tool.py @@ -1,5 +1,6 @@ import logging import os +import tempfile from typing import Type, Literal, Tuple, Optional, List, Dict, Union, Any from uuid import uuid4 @@ -143,7 +144,9 @@ async def _arun( for attr in attributes: attr_name = attr["name"] # type: ignore[index] # Mark primary key with * - attr_display = f"{'*' if attr.get('primary', False) else ''}{attr_name}" # type: ignore[union-attr] + attr_display = ( + f"{'*' if attr.get('primary', False) else ''}{attr_name}" # type: ignore[union-attr] + ) attribute_lines.append(attr_display) # Combine attributes into label @@ -183,7 +186,9 @@ async def _arun( image_file_name: str = f"{uuid4()}.png" # Use file manager to save the file (if needed) - image_generation_path_ = os.environ.get("IMAGE_GENERATION_PATH", "/tmp") + image_generation_path_ = os.environ.get( + "IMAGE_GENERATION_PATH", tempfile.gettempdir() + ) file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ ) @@ -210,9 +215,7 @@ async def _arun( "ERDiagramGeneratorTool: Failed to save image to disk", ) - artifact: str = ( - f"ERDiagramGeneratorTool: Generated ER diagram with {len(entities)} entities <{url}> " - ) + artifact: str = f"ERDiagramGeneratorTool: Generated ER diagram with {len(entities)} entities <{url}> " # Return the image bytes and a description return url, artifact diff --git a/language_model_gateway/gateway/tools/fhir_graphql_schema_provider.py b/language_model_gateway/gateway/tools/fhir_graphql_schema_provider.py new file mode 100644 index 000000000..4bc1ddd2c --- /dev/null +++ b/language_model_gateway/gateway/tools/fhir_graphql_schema_provider.py @@ -0,0 +1,22061 @@ +from typing import Tuple, Literal +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool + + +class GraphqlSchemaProviderTool(ResilientBaseTool): + """ + A tool for providing FHIR GraphQL schema. + """ + + name: str = "fhir_graphql_schema_provider" + description: str = ( + "This is a FHIR GraphQL schema provider that provides the GraphQL SDL for needed for generating correct query" + "Example queries: " + "'Make query for getting all patients with ids 1,2', " + "'Get conditions for patients whose name is John'" + ) + + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + async def _arun(self) -> Tuple[str, str]: + graphql_schema = ''' +directive @key(fields: _FieldSet!, resolvable: Boolean = true) on OBJECT | INTERFACE + +directive @requires(fields: _FieldSet!) on FIELD_DEFINITION + +directive @provides(fields: _FieldSet!) on FIELD_DEFINITION + +directive @external(reason: String) on OBJECT | FIELD_DEFINITION + +directive @tag(name: String!) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +directive @extends on OBJECT | INTERFACE + +""" +Indicates exactly one field must be supplied and this field must not be `null`. +""" +directive @oneOf on INPUT_OBJECT + +enum TotalType { + accurate + estimate +} + +type Query { + id: String + accounts(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, name: SearchString, owner: SearchReference, patient: SearchReference, period: SearchDate, status: SearchToken, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AccountBundle + activityDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ActivityDefinitionBundle + administrableProductDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, device: SearchReference, dose_form: SearchToken, form_of: SearchReference, identifier: SearchToken, ingredient: SearchToken, manufactured_item: SearchReference, route: SearchToken, target_species: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AdministrableProductDefinitionBundle + adverseEvents(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, actuality: SearchToken, category: SearchToken, date: SearchDate, event: SearchToken, location: SearchReference, recorder: SearchReference, resultingcondition: SearchReference, seriousness: SearchToken, severity: SearchToken, study: SearchReference, subject: SearchReference, substance: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AdverseEventBundle + allergyIntolerances(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, asserter: SearchReference, category: SearchToken, clinical_status: SearchToken, code: SearchToken, criticality: SearchToken, date: SearchDate, identifier: SearchToken, last_date: SearchDate, manifestation: SearchToken, onset: SearchDate, patient: SearchReference, recorder: SearchReference, route: SearchToken, severity: SearchToken, type: SearchToken, verification_status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AllergyIntoleranceBundle + appointments(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, actor: SearchReference, appointment_type: SearchToken, based_on: SearchReference, date: SearchDate, identifier: SearchToken, location: SearchReference, part_status: SearchToken, patient: SearchReference, practitioner: SearchReference, reason_code: SearchToken, reason_reference: SearchReference, service_category: SearchToken, service_type: SearchToken, slot: SearchReference, specialty: SearchToken, status: SearchToken, supporting_info: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AppointmentBundle + appointmentResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, actor: SearchReference, appointment: SearchReference, identifier: SearchToken, location: SearchReference, part_status: SearchToken, patient: SearchReference, practitioner: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AppointmentResponseBundle + auditEvents(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, action: SearchToken, address: SearchString, agent: SearchReference, agent_name: SearchString, agent_role: SearchToken, altid: SearchToken, date: SearchDate, entity: SearchReference, entity_name: SearchString, entity_role: SearchToken, entity_type: SearchToken, outcome: SearchToken, patient: SearchReference, policy: SearchString, site: SearchToken, source: SearchReference, subtype: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): AuditEventBundle + basics(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, code: SearchToken, created: SearchDate, identifier: SearchToken, patient: SearchReference, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): BasicBundle + binaries(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): BinaryBundle + biologicallyDerivedProducts(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): BiologicallyDerivedProductBundle + bodyStructures(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, location: SearchToken, morphology: SearchToken, patient: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): BodyStructureBundle + bundles(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, composition: SearchReference, identifier: SearchToken, message: SearchReference, timestamp: SearchDate, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): BundleBundle + capabilityStatements(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, fhirversion: SearchToken, format: SearchToken, guide: SearchReference, jurisdiction: SearchToken, mode: SearchToken, name: SearchString, publisher: SearchString, resource: SearchToken, resource_profile: SearchReference, security_service: SearchToken, software: SearchString, status: SearchToken, supported_profile: SearchReference, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CapabilityStatementBundle + carePlans(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, activity_code: SearchToken, activity_date: SearchDate, activity_reference: SearchReference, based_on: SearchReference, care_team: SearchReference, category: SearchToken, condition: SearchReference, date: SearchDate, encounter: SearchReference, goal: SearchReference, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, intent: SearchToken, part_of: SearchReference, patient: SearchReference, performer: SearchReference, replaces: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CarePlanBundle + careTeams(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, date: SearchDate, encounter: SearchReference, identifier: SearchToken, participant: SearchReference, patient: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CareTeamBundle + catalogEntries(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CatalogEntryBundle + chargeItems(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, account: SearchReference, code: SearchToken, context: SearchReference, entered_date: SearchDate, enterer: SearchReference, factor_override: SearchNumber, identifier: SearchToken, occurrence: SearchDate, patient: SearchReference, performer_actor: SearchReference, performer_function: SearchToken, performing_organization: SearchReference, price_override: SearchQuantity, quantity: SearchQuantity, requesting_organization: SearchReference, service: SearchReference, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ChargeItemBundle + chargeItemDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ChargeItemDefinitionBundle + citations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CitationBundle + claims(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, care_team: SearchReference, created: SearchDate, detail_udi: SearchReference, encounter: SearchReference, enterer: SearchReference, facility: SearchReference, identifier: SearchToken, insurer: SearchReference, item_udi: SearchReference, patient: SearchReference, payee: SearchReference, priority: SearchToken, procedure_udi: SearchReference, provider: SearchReference, status: SearchToken, subdetail_udi: SearchReference, use: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ClaimBundle + claimResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, created: SearchDate, disposition: SearchString, identifier: SearchToken, insurer: SearchReference, outcome: SearchToken, patient: SearchReference, payment_date: SearchDate, request: SearchReference, requestor: SearchReference, status: SearchToken, use: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ClaimResponseBundle + clinicalImpressions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, assessor: SearchReference, date: SearchDate, encounter: SearchReference, finding_code: SearchToken, finding_ref: SearchReference, identifier: SearchToken, investigation: SearchReference, patient: SearchReference, previous: SearchReference, problem: SearchReference, status: SearchToken, subject: SearchReference, supporting_info: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ClinicalImpressionBundle + clinicalUseDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, contraindication: SearchToken, contraindication_reference: SearchReference, effect: SearchToken, effect_reference: SearchReference, identifier: SearchToken, indication: SearchToken, indication_reference: SearchReference, interaction: SearchToken, product: SearchReference, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ClinicalUseDefinitionBundle + codeSystems(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, content_mode: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, identifier: SearchToken, jurisdiction: SearchToken, language: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, supplements: SearchReference, system: SearchString, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CodeSystemBundle + communications(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, based_on: SearchReference, category: SearchToken, encounter: SearchReference, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, medium: SearchToken, part_of: SearchReference, patient: SearchReference, received: SearchDate, recipient: SearchReference, sender: SearchReference, sent: SearchDate, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CommunicationBundle + communicationRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authored: SearchDate, based_on: SearchReference, category: SearchToken, encounter: SearchReference, group_identifier: SearchToken, identifier: SearchToken, medium: SearchToken, occurrence: SearchDate, patient: SearchReference, priority: SearchToken, recipient: SearchReference, replaces: SearchReference, requester: SearchReference, sender: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CommunicationRequestBundle + compartmentDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, name: SearchString, publisher: SearchString, resource: SearchToken, status: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CompartmentDefinitionBundle + compositions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, attester: SearchReference, author: SearchReference, category: SearchToken, confidentiality: SearchToken, context: SearchToken, date: SearchDate, encounter: SearchReference, entry: SearchReference, identifier: SearchToken, patient: SearchReference, period: SearchDate, related_id: SearchToken, related_ref: SearchReference, section: SearchToken, status: SearchToken, subject: SearchReference, title: SearchString, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CompositionBundle + conceptMaps(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, dependson: SearchString, description: SearchString, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, other: SearchReference, product: SearchString, publisher: SearchString, source: SearchReference, source_code: SearchToken, source_system: SearchString, source_uri: SearchReference, status: SearchToken, target: SearchReference, target_code: SearchToken, target_system: SearchString, target_uri: SearchReference, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ConceptMapBundle + conditions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, abatement_age: SearchQuantity, abatement_date: SearchDate, abatement_string: SearchString, asserter: SearchReference, body_site: SearchToken, category: SearchToken, clinical_status: SearchToken, code: SearchToken, encounter: SearchReference, evidence: SearchToken, evidence_detail: SearchReference, identifier: SearchToken, onset_age: SearchQuantity, onset_date: SearchDate, onset_info: SearchString, patient: SearchReference, recorded_date: SearchDate, severity: SearchToken, stage: SearchToken, subject: SearchReference, verification_status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ConditionBundle + consents(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, action: SearchToken, actor: SearchReference, category: SearchToken, consentor: SearchReference, data: SearchReference, date: SearchDate, identifier: SearchToken, organization: SearchReference, patient: SearchReference, period: SearchDate, purpose: SearchToken, scope: SearchToken, security_label: SearchToken, source_reference: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ConsentBundle + contracts(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authority: SearchReference, domain: SearchReference, identifier: SearchToken, instantiates: SearchString, issued: SearchDate, patient: SearchReference, signer: SearchReference, status: SearchToken, subject: SearchReference, url: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ContractBundle + coverages(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, beneficiary: SearchReference, class_type: SearchToken, class_value: SearchString, dependent: SearchString, identifier: SearchToken, patient: SearchReference, payor: SearchReference, policy_holder: SearchReference, status: SearchToken, subscriber: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CoverageBundle + coverageEligibilityRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, created: SearchDate, enterer: SearchReference, facility: SearchReference, identifier: SearchToken, patient: SearchReference, provider: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CoverageEligibilityRequestBundle + coverageEligibilityResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, created: SearchDate, disposition: SearchString, identifier: SearchToken, insurer: SearchReference, outcome: SearchToken, patient: SearchReference, request: SearchReference, requestor: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): CoverageEligibilityResponseBundle + detectedIssues(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, code: SearchToken, identified: SearchDate, identifier: SearchToken, implicated: SearchReference, patient: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DetectedIssueBundle + devices(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, device_name: SearchString, identifier: SearchToken, location: SearchReference, manufacturer: SearchString, model: SearchString, organization: SearchReference, patient: SearchReference, status: SearchToken, type: SearchToken, udi_carrier: SearchString, udi_di: SearchString, url: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DeviceBundle + deviceDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, parent: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DeviceDefinitionBundle + deviceMetrics(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, identifier: SearchToken, parent: SearchReference, source: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DeviceMetricBundle + deviceRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authored_on: SearchDate, based_on: SearchReference, code: SearchToken, device: SearchReference, encounter: SearchReference, event_date: SearchDate, group_identifier: SearchToken, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, insurance: SearchReference, intent: SearchToken, patient: SearchReference, performer: SearchReference, prior_request: SearchReference, requester: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DeviceRequestBundle + deviceUseStatements(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, device: SearchReference, identifier: SearchToken, patient: SearchReference, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DeviceUseStatementBundle + diagnosticReports(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, based_on: SearchReference, category: SearchToken, code: SearchToken, conclusion: SearchToken, date: SearchDate, encounter: SearchReference, identifier: SearchToken, issued: SearchDate, media: SearchReference, patient: SearchReference, performer: SearchReference, result: SearchReference, results_interpreter: SearchReference, specimen: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DiagnosticReportBundle + documentManifests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, created: SearchDate, description: SearchString, identifier: SearchToken, item: SearchReference, patient: SearchReference, recipient: SearchReference, related_id: SearchToken, related_ref: SearchReference, source: SearchString, status: SearchToken, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DocumentManifestBundle + documentReferences(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authenticator: SearchReference, author: SearchReference, category: SearchToken, contenttype: SearchToken, custodian: SearchReference, date: SearchDate, description: SearchString, encounter: SearchReference, event: SearchToken, facility: SearchToken, format: SearchToken, identifier: SearchToken, language: SearchToken, location: SearchString, patient: SearchReference, period: SearchDate, related: SearchReference, relatesto: SearchReference, relation: SearchToken, security_label: SearchToken, setting: SearchToken, status: SearchToken, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): DocumentReferenceBundle + encounters(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, account: SearchReference, appointment: SearchReference, based_on: SearchReference, class: SearchToken, date: SearchDate, diagnosis: SearchReference, episode_of_care: SearchReference, identifier: SearchToken, length: SearchQuantity, location: SearchReference, location_period: SearchDate, part_of: SearchReference, participant: SearchReference, participant_type: SearchToken, patient: SearchReference, practitioner: SearchReference, reason_code: SearchToken, reason_reference: SearchReference, service_provider: SearchReference, special_arrangement: SearchToken, status: SearchToken, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EncounterBundle + endpoints(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, connection_type: SearchToken, identifier: SearchToken, name: SearchString, organization: SearchReference, payload_type: SearchToken, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EndpointBundle + enrollmentRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, patient: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EnrollmentRequestBundle + enrollmentResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, request: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EnrollmentResponseBundle + episodesOfCare(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, care_manager: SearchReference, condition: SearchReference, date: SearchDate, identifier: SearchToken, incoming_referral: SearchReference, organization: SearchReference, patient: SearchReference, status: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EpisodeOfCareBundle + eventDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EventDefinitionBundle + evidences(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, identifier: SearchToken, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EvidenceBundle + evidenceReports(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, identifier: SearchToken, publisher: SearchString, status: SearchToken, url: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EvidenceReportBundle + evidenceVariables(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, identifier: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): EvidenceVariableBundle + exampleScenarios(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ExampleScenarioBundle + explanationOfBenefits(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, care_team: SearchReference, claim: SearchReference, coverage: SearchReference, created: SearchDate, detail_udi: SearchReference, disposition: SearchString, encounter: SearchReference, enterer: SearchReference, facility: SearchReference, identifier: SearchToken, item_udi: SearchReference, patient: SearchReference, payee: SearchReference, procedure_udi: SearchReference, provider: SearchReference, status: SearchToken, subdetail_udi: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ExplanationOfBenefitBundle + familyMemberHistories(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, date: SearchDate, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, patient: SearchReference, relationship: SearchToken, sex: SearchToken, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): FamilyMemberHistoryBundle + flags(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, date: SearchDate, encounter: SearchReference, identifier: SearchToken, patient: SearchReference, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): FlagBundle + goals(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, achievement_status: SearchToken, category: SearchToken, identifier: SearchToken, lifecycle_status: SearchToken, patient: SearchReference, start_date: SearchDate, subject: SearchReference, target_date: SearchDate, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): GoalBundle + graphDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, start: SearchToken, status: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): GraphDefinitionBundle + groups(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, actual: SearchToken, characteristic: SearchToken, code: SearchToken, exclude: SearchToken, identifier: SearchToken, managing_entity: SearchReference, member: SearchReference, type: SearchToken, value: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): GroupBundle + guidanceResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, patient: SearchReference, request: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): GuidanceResponseBundle + healthcareServices(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, characteristic: SearchToken, coverage_area: SearchReference, endpoint: SearchReference, identifier: SearchToken, location: SearchReference, name: SearchString, organization: SearchReference, program: SearchToken, service_category: SearchToken, service_type: SearchToken, specialty: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): HealthcareServiceBundle + imagingStudies(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, basedon: SearchReference, bodysite: SearchToken, dicom_class: SearchToken, encounter: SearchReference, endpoint: SearchReference, identifier: SearchToken, instance: SearchToken, interpreter: SearchReference, modality: SearchToken, patient: SearchReference, performer: SearchReference, reason: SearchToken, referrer: SearchReference, series: SearchToken, started: SearchDate, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ImagingStudyBundle + immunizations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, identifier: SearchToken, location: SearchReference, lot_number: SearchString, manufacturer: SearchReference, patient: SearchReference, performer: SearchReference, reaction: SearchReference, reaction_date: SearchDate, reason_code: SearchToken, reason_reference: SearchReference, series: SearchString, status: SearchToken, status_reason: SearchToken, target_disease: SearchToken, vaccine_code: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ImmunizationBundle + immunizationEvaluations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, dose_status: SearchToken, identifier: SearchToken, immunization_event: SearchReference, patient: SearchReference, status: SearchToken, target_disease: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ImmunizationEvaluationBundle + immunizationRecommendations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, identifier: SearchToken, information: SearchReference, patient: SearchReference, status: SearchToken, support: SearchReference, target_disease: SearchToken, vaccine_type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ImmunizationRecommendationBundle + implementationGuides(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, description: SearchString, experimental: SearchToken, global: SearchReference, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, resource: SearchReference, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ImplementationGuideBundle + ingredients(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, for: SearchReference, function: SearchToken, identifier: SearchToken, manufacturer: SearchReference, role: SearchToken, substance: SearchReference, substance_code: SearchToken, substance_definition: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): IngredientBundle + insurancePlans(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, administered_by: SearchReference, endpoint: SearchReference, identifier: SearchToken, name: SearchString, owned_by: SearchReference, phonetic: SearchString, status: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): InsurancePlanBundle + invoices(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, account: SearchReference, date: SearchDate, identifier: SearchToken, issuer: SearchReference, participant: SearchReference, participant_role: SearchToken, patient: SearchReference, recipient: SearchReference, status: SearchToken, subject: SearchReference, totalgross: SearchQuantity, totalnet: SearchQuantity, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): InvoiceBundle + libraries(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, content_type: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, type: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): LibraryBundle + linkages(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, item: SearchReference, source: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): LinkageBundle + lists(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, date: SearchDate, empty_reason: SearchToken, encounter: SearchReference, identifier: SearchToken, item: SearchReference, notes: SearchString, patient: SearchReference, source: SearchReference, status: SearchToken, subject: SearchReference, title: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ListBundle + locations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, endpoint: SearchReference, identifier: SearchToken, name: SearchString, near: String, operational_status: SearchToken, organization: SearchReference, partof: SearchReference, status: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): LocationBundle + manufacturedItemDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, dose_form: SearchToken, identifier: SearchToken, ingredient: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ManufacturedItemDefinitionBundle + measures(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MeasureBundle + measureReports(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, evaluated_resource: SearchReference, identifier: SearchToken, measure: SearchReference, patient: SearchReference, period: SearchDate, reporter: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MeasureReportBundle + media(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, based_on: SearchReference, created: SearchDate, device: SearchReference, encounter: SearchReference, identifier: SearchToken, modality: SearchToken, operator: SearchReference, patient: SearchReference, site: SearchToken, status: SearchToken, subject: SearchReference, type: SearchToken, view: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MediaBundle + medications(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, expiration_date: SearchDate, form: SearchToken, identifier: SearchToken, ingredient: SearchReference, ingredient_code: SearchToken, lot_number: SearchToken, manufacturer: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationBundle + medicationAdministrations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, context: SearchReference, device: SearchReference, effective_time: SearchDate, identifier: SearchToken, medication: SearchReference, patient: SearchReference, performer: SearchReference, reason_given: SearchToken, reason_not_given: SearchToken, request: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationAdministrationBundle + medicationDispenses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, context: SearchReference, destination: SearchReference, identifier: SearchToken, medication: SearchReference, patient: SearchReference, performer: SearchReference, prescription: SearchReference, receiver: SearchReference, responsibleparty: SearchReference, status: SearchToken, subject: SearchReference, type: SearchToken, whenhandedover: SearchDate, whenprepared: SearchDate, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationDispenseBundle + medicationKnowledges(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, classification: SearchToken, classification_type: SearchToken, code: SearchToken, doseform: SearchToken, ingredient: SearchReference, ingredient_code: SearchToken, manufacturer: SearchReference, monitoring_program_name: SearchToken, monitoring_program_type: SearchToken, monograph: SearchReference, monograph_type: SearchToken, source_cost: SearchToken, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationKnowledgeBundle + medicationRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authoredon: SearchDate, category: SearchToken, code: SearchToken, date: SearchDate, encounter: SearchReference, identifier: SearchToken, intended_dispenser: SearchReference, intended_performer: SearchReference, intended_performertype: SearchToken, intent: SearchToken, medication: SearchReference, patient: SearchReference, priority: SearchToken, requester: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationRequestBundle + medicationStatements(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, code: SearchToken, context: SearchReference, effective: SearchDate, identifier: SearchToken, medication: SearchReference, part_of: SearchReference, patient: SearchReference, source: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicationStatementBundle + medicinalProductDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, characteristic: SearchToken, characteristic_type: SearchToken, contact: SearchReference, domain: SearchToken, identifier: SearchToken, ingredient: SearchToken, master_file: SearchReference, name: SearchString, name_language: SearchToken, product_classification: SearchToken, status: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MedicinalProductDefinitionBundle + messageDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, event: SearchToken, focus: SearchToken, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, parent: SearchReference, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MessageDefinitionBundle + messageHeaders(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, code: SearchToken, destination: SearchString, destination_uri: SearchString, enterer: SearchReference, event: SearchToken, focus: SearchReference, receiver: SearchReference, response_id: SearchToken, responsible: SearchReference, sender: SearchReference, source: SearchString, source_uri: SearchString, target: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MessageHeaderBundle + molecularSequences(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, chromosome: SearchToken, identifier: SearchToken, patient: SearchReference, referenceseqid: SearchToken, type: SearchToken, variant_end: SearchNumber, variant_start: SearchNumber, window_end: SearchNumber, window_start: SearchNumber, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): MolecularSequenceBundle + namingSystems(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, contact: SearchString, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, id_type: SearchToken, jurisdiction: SearchToken, kind: SearchToken, name: SearchString, period: SearchDate, publisher: SearchString, responsible: SearchString, status: SearchToken, telecom: SearchToken, type: SearchToken, value: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): NamingSystemBundle + nutritionOrders(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, additive: SearchToken, datetime: SearchDate, encounter: SearchReference, formula: SearchToken, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, oraldiet: SearchToken, patient: SearchReference, provider: SearchReference, status: SearchToken, supplement: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): NutritionOrderBundle + nutritionProducts(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): NutritionProductBundle + observations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, based_on: SearchReference, category: SearchToken, code: SearchToken, combo_code: SearchToken, combo_data_absent_reason: SearchToken, combo_value_concept: SearchToken, combo_value_quantity: SearchQuantity, component_code: SearchToken, component_data_absent_reason: SearchToken, component_value_concept: SearchToken, component_value_quantity: SearchQuantity, data_absent_reason: SearchToken, date: SearchDate, derived_from: SearchReference, device: SearchReference, encounter: SearchReference, focus: SearchReference, has_member: SearchReference, identifier: SearchToken, method: SearchToken, part_of: SearchReference, patient: SearchReference, performer: SearchReference, specimen: SearchReference, status: SearchToken, subject: SearchReference, value_concept: SearchToken, value_date: SearchDate, value_quantity: SearchQuantity, value_string: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ObservationBundle + observationDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ObservationDefinitionBundle + operationDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, base: SearchReference, code: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, input_profile: SearchReference, instance: SearchToken, jurisdiction: SearchToken, kind: SearchToken, name: SearchString, output_profile: SearchReference, publisher: SearchString, status: SearchToken, system: SearchToken, title: SearchString, type: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): OperationDefinitionBundle + operationOutcomes(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): OperationOutcomeBundle + organizations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, endpoint: SearchReference, identifier: SearchToken, name: SearchString, partof: SearchReference, phonetic: SearchString, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): OrganizationBundle + organizationAffiliations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, date: SearchDate, email: SearchToken, endpoint: SearchReference, identifier: SearchToken, location: SearchReference, network: SearchReference, participating_organization: SearchReference, phone: SearchToken, primary_organization: SearchReference, role: SearchToken, service: SearchReference, specialty: SearchToken, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): OrganizationAffiliationBundle + packagedProductDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, biological: SearchReference, contained_item: SearchReference, device: SearchReference, identifier: SearchToken, manufactured_item: SearchReference, medication: SearchReference, name: SearchToken, nutrition: SearchReference, package: SearchReference, package_for: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PackagedProductDefinitionBundle + parameters(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ParametersBundle + patients(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, birthdate: SearchDate, death_date: SearchDate, deceased: SearchToken, email: SearchToken, family: SearchString, gender: SearchToken, general_practitioner: SearchReference, given: SearchString, identifier: SearchToken, language: SearchToken, link: SearchReference, name: SearchString, organization: SearchReference, phone: SearchToken, phonetic: SearchString, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PatientBundle + paymentNotices(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, created: SearchDate, identifier: SearchToken, payment_status: SearchToken, provider: SearchReference, request: SearchReference, response: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PaymentNoticeBundle + paymentReconciliations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, created: SearchDate, disposition: SearchString, identifier: SearchToken, outcome: SearchToken, payment_issuer: SearchReference, request: SearchReference, requestor: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PaymentReconciliationBundle + persons(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, birthdate: SearchDate, email: SearchToken, family: SearchString, gender: SearchToken, given: SearchString, identifier: SearchToken, link: SearchReference, name: SearchString, organization: SearchReference, patient: SearchReference, phone: SearchToken, phonetic: SearchString, practitioner: SearchReference, relatedperson: SearchReference, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PersonBundle + planDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, definition: SearchReference, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, type: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PlanDefinitionBundle + practitioners(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, communication: SearchToken, email: SearchToken, family: SearchString, gender: SearchToken, given: SearchString, identifier: SearchToken, name: SearchString, phone: SearchToken, phonetic: SearchString, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PractitionerBundle + practitionerRoles(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, date: SearchDate, email: SearchToken, endpoint: SearchReference, identifier: SearchToken, location: SearchReference, organization: SearchReference, phone: SearchToken, practitioner: SearchReference, role: SearchToken, service: SearchReference, specialty: SearchToken, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): PractitionerRoleBundle + procedures(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, based_on: SearchReference, category: SearchToken, code: SearchToken, date: SearchDate, encounter: SearchReference, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, location: SearchReference, part_of: SearchReference, patient: SearchReference, performer: SearchReference, reason_code: SearchToken, reason_reference: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ProcedureBundle + provenances(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, agent: SearchReference, agent_role: SearchToken, agent_type: SearchToken, entity: SearchReference, location: SearchReference, patient: SearchReference, recorded: SearchDate, signature_type: SearchToken, target: SearchReference, when: SearchDate, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ProvenanceBundle + questionnaires(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, definition: SearchString, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, subject_type: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): QuestionnaireBundle + questionnaireResponses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, authored: SearchDate, based_on: SearchReference, encounter: SearchReference, identifier: SearchToken, part_of: SearchReference, patient: SearchReference, questionnaire: SearchReference, source: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): QuestionnaireResponseBundle + regulatedAuthorizations(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, case: SearchToken, case_type: SearchToken, holder: SearchReference, identifier: SearchToken, region: SearchToken, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): RegulatedAuthorizationBundle + relatedPersons(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, address: SearchString, address_city: SearchString, address_country: SearchString, address_postalcode: SearchString, address_state: SearchString, address_use: SearchToken, birthdate: SearchDate, email: SearchToken, gender: SearchToken, identifier: SearchToken, name: SearchString, patient: SearchReference, phone: SearchToken, phonetic: SearchString, relationship: SearchToken, telecom: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): RelatedPersonBundle + requestGroups(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, author: SearchReference, authored: SearchDate, code: SearchToken, encounter: SearchReference, group_identifier: SearchToken, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, intent: SearchToken, participant: SearchReference, patient: SearchReference, priority: SearchToken, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): RequestGroupBundle + researchDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ResearchDefinitionBundle + researchElementDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, composed_of: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, depends_on: SearchReference, derived_from: SearchReference, description: SearchString, effective: SearchDate, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, predecessor: SearchReference, publisher: SearchString, status: SearchToken, successor: SearchReference, title: SearchString, topic: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ResearchElementDefinitionBundle + researchStudies(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, date: SearchDate, focus: SearchToken, identifier: SearchToken, keyword: SearchToken, location: SearchToken, partof: SearchReference, principalinvestigator: SearchReference, protocol: SearchReference, site: SearchReference, sponsor: SearchReference, status: SearchToken, title: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ResearchStudyBundle + researchSubjects(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, identifier: SearchToken, individual: SearchReference, patient: SearchReference, status: SearchToken, study: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ResearchSubjectBundle + riskAssessments(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, condition: SearchReference, date: SearchDate, encounter: SearchReference, identifier: SearchToken, method: SearchToken, patient: SearchReference, performer: SearchReference, probability: SearchNumber, risk: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): RiskAssessmentBundle + schedules(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, active: SearchToken, actor: SearchReference, date: SearchDate, identifier: SearchToken, service_category: SearchToken, service_type: SearchToken, specialty: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ScheduleBundle + searchParameters(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, base: SearchToken, code: SearchToken, component: SearchReference, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, derived_from: SearchReference, description: SearchString, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, target: SearchToken, type: SearchToken, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SearchParameterBundle + serviceRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authored: SearchDate, based_on: SearchReference, body_site: SearchToken, category: SearchToken, code: SearchToken, encounter: SearchReference, identifier: SearchToken, instantiates_canonical: SearchReference, instantiates_uri: SearchString, intent: SearchToken, occurrence: SearchDate, patient: SearchReference, performer: SearchReference, performer_type: SearchToken, priority: SearchToken, replaces: SearchReference, requester: SearchReference, requisition: SearchToken, specimen: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ServiceRequestBundle + slots(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, appointment_type: SearchToken, identifier: SearchToken, schedule: SearchReference, service_category: SearchToken, service_type: SearchToken, specialty: SearchToken, start: SearchDate, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SlotBundle + specimens(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, accession: SearchToken, bodysite: SearchToken, collected: SearchDate, collector: SearchReference, container: SearchToken, container_id: SearchToken, identifier: SearchToken, parent: SearchReference, patient: SearchReference, status: SearchToken, subject: SearchReference, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SpecimenBundle + specimenDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, container: SearchToken, identifier: SearchToken, type: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SpecimenDefinitionBundle + structureDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, abstract: SearchToken, base: SearchReference, base_path: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, derivation: SearchToken, description: SearchString, experimental: SearchToken, ext_context: SearchToken, identifier: SearchToken, jurisdiction: SearchToken, keyword: SearchToken, kind: SearchToken, name: SearchString, path: SearchToken, publisher: SearchString, status: SearchToken, title: SearchString, type: SearchString, url: SearchString, valueset: SearchReference, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): StructureDefinitionBundle + structureMaps(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): StructureMapBundle + subscriptions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, contact: SearchToken, criteria: SearchString, payload: SearchToken, status: SearchToken, type: SearchToken, url: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SubscriptionBundle + subscriptionStatuses(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SubscriptionStatusBundle + subscriptionTopics(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, date: SearchDate, derived_or_self: SearchString, identifier: SearchToken, resource: SearchString, status: SearchToken, title: SearchString, trigger_description: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SubscriptionTopicBundle + substances(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, code: SearchToken, container_identifier: SearchToken, expiry: SearchDate, identifier: SearchToken, quantity: SearchQuantity, status: SearchToken, substance_reference: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SubstanceBundle + substanceDefinitions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, classification: SearchToken, code: SearchToken, domain: SearchToken, identifier: SearchToken, name: SearchString, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SubstanceDefinitionBundle + supplyDeliveries(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, patient: SearchReference, receiver: SearchReference, status: SearchToken, supplier: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SupplyDeliveryBundle + supplyRequests(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, category: SearchToken, date: SearchDate, identifier: SearchToken, requester: SearchReference, status: SearchToken, subject: SearchReference, supplier: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): SupplyRequestBundle + tasks(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, authored_on: SearchDate, based_on: SearchReference, business_status: SearchToken, code: SearchToken, encounter: SearchReference, focus: SearchReference, group_identifier: SearchToken, identifier: SearchToken, intent: SearchToken, modified: SearchDate, owner: SearchReference, part_of: SearchReference, patient: SearchReference, performer: SearchToken, period: SearchDate, priority: SearchToken, requester: SearchReference, status: SearchToken, subject: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): TaskBundle + terminologyCapabilities(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): TerminologyCapabilitiesBundle + testReports(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, identifier: SearchToken, issued: SearchDate, participant: SearchString, result: SearchToken, tester: SearchString, testscript: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): TestReportBundle + testScripts(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, status: SearchToken, testscript_capability: SearchString, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): TestScriptBundle + valueSets(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, code: SearchToken, context: SearchToken, context_quantity: SearchQuantity, context_type: SearchToken, date: SearchDate, description: SearchString, expansion: SearchString, identifier: SearchToken, jurisdiction: SearchToken, name: SearchString, publisher: SearchString, reference: SearchString, status: SearchToken, title: SearchString, url: SearchString, version: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): ValueSetBundle + verificationResults(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, target: SearchReference, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): VerificationResultBundle + visionPrescriptions(id: SearchString, _lastUpdated: SearchDate, _profile: SearchString, _security: SearchToken, _source: SearchString, _tag: SearchToken, extension: SearchExtension, datewritten: SearchDate, encounter: SearchReference, identifier: SearchToken, patient: SearchReference, prescriber: SearchReference, status: SearchToken, _total: TotalType, _sort: [String], _count: Int, _getpagesoffset: Int, _debug: Boolean, _explain: Boolean, _setIndexHint: String): VisionPrescriptionBundle + _entities(representations: [_Any!]!): [_Entity]! + _service: _Service! +} + +type AccountCoverageCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type AccountCoverage { + id: String + extension: [Extension] + modifierExtension: [Extension] + coverage: AccountCoverageCoverageReference + priority: Int +} + +union AccountGuarantorParty = Patient | RelatedPerson | Organization + +type AccountGuarantorPartyReference { + id: String + extension: [Extension] + reference: String + resource: AccountGuarantorParty + type: URI + identifier: Identifier + display: String +} + +type AccountGuarantor { + id: String + extension: [Extension] + modifierExtension: [Extension] + party: AccountGuarantorPartyReference + onHold: Boolean + period: Period +} + +type ActivityDefinitionDynamicValue { + id: String + extension: [Extension] + modifierExtension: [Extension] + path: String + expression: Expression +} + +type ActivityDefinitionParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + role: CodeableConcept +} + +type AdministrableProductDefinitionProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueDate: Date + valueBoolean: Boolean + valueAttachment: Attachment + status: CodeableConcept +} + +type AdministrableProductDefinitionRouteOfAdministration { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + firstDose: Quantity + maxSingleDose: Quantity + maxDosePerDay: Quantity + maxDosePerTreatmentPeriod: Ratio + maxTreatmentPeriod: Quantity + targetSpecies: [AdministrableProductDefinitionTargetSpecies] +} + +type AdministrableProductDefinitionTargetSpecies { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + withdrawalPeriod: [AdministrableProductDefinitionWithdrawalPeriod] +} + +type AdministrableProductDefinitionWithdrawalPeriod { + id: String + extension: [Extension] + modifierExtension: [Extension] + tissue: CodeableConcept + value: Quantity + supportingInformation: String +} + +union AdverseEventCausalityAuthor = Practitioner | PractitionerRole + +type AdverseEventCausalityAuthorReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventCausalityAuthor + type: URI + identifier: Identifier + display: String +} + +type AdverseEventCausality { + id: String + extension: [Extension] + modifierExtension: [Extension] + assessment: CodeableConcept + productRelatedness: String + author: AdverseEventCausalityAuthorReference + method: CodeableConcept +} + +union AdverseEventSuspectEntityInstance = Immunization | Procedure | Substance | Medication | MedicationAdministration | MedicationStatement | Device + +type AdverseEventSuspectEntityInstanceReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventSuspectEntityInstance + type: URI + identifier: Identifier + display: String +} + +type AdverseEventSuspectEntity { + id: String + extension: [Extension] + modifierExtension: [Extension] + instance: AdverseEventSuspectEntityInstanceReference + causality: [AdverseEventCausality] +} + +type AllergyIntoleranceReaction { + id: String + extension: [Extension] + modifierExtension: [Extension] + substance: CodeableConcept + manifestation: [CodeableConcept] + description: String + onset: DateTime + severity: Code + exposureRoute: CodeableConcept + note: [Annotation] +} + +union AppointmentParticipantActor = Patient | Practitioner | PractitionerRole | RelatedPerson | Device | HealthcareService | Location + +type AppointmentParticipantActorReference { + id: String + extension: [Extension] + reference: String + resource: AppointmentParticipantActor + type: URI + identifier: Identifier + display: String +} + +type AppointmentParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: [CodeableConcept] + actor: AppointmentParticipantActorReference + required: Code + status: Code + period: Period +} + +union AuditEventAgentWho = PractitionerRole | Practitioner | Organization | Device | Patient | RelatedPerson + +type AuditEventAgentWhoReference { + id: String + extension: [Extension] + reference: String + resource: AuditEventAgentWho + type: URI + identifier: Identifier + display: String +} + +type AuditEventAgentLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type AuditEventAgent { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + role: [CodeableConcept] + who: AuditEventAgentWhoReference + altId: String + name: String + requestor: Boolean + location: AuditEventAgentLocationReference + policy: [URI] + media: Coding + network: AuditEventNetwork + purposeOfUse: [CodeableConcept] +} + +type AuditEventDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: String + valueString: String + valueBase64Binary: Base64Binary +} + +type AuditEventEntityWhatReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type AuditEventEntity { + id: String + extension: [Extension] + modifierExtension: [Extension] + what: AuditEventEntityWhatReference + type: Coding + role: Coding + lifecycle: Coding + securityLabel: [Coding] + name: String + description: String + query: Base64Binary + detail: [AuditEventDetail] +} + +type AuditEventNetwork { + id: String + extension: [Extension] + modifierExtension: [Extension] + address: String + type: Code +} + +union AuditEventSourceObserver = PractitionerRole | Practitioner | Organization | Device | Patient | RelatedPerson + +type AuditEventSourceObserverReference { + id: String + extension: [Extension] + reference: String + resource: AuditEventSourceObserver + type: URI + identifier: Identifier + display: String +} + +type AuditEventSource { + id: String + extension: [Extension] + modifierExtension: [Extension] + site: String + observer: AuditEventSourceObserverReference + type: [Coding] +} + +union BiologicallyDerivedProductCollectionCollector = Practitioner | PractitionerRole + +type BiologicallyDerivedProductCollectionCollectorReference { + id: String + extension: [Extension] + reference: String + resource: BiologicallyDerivedProductCollectionCollector + type: URI + identifier: Identifier + display: String +} + +union BiologicallyDerivedProductCollectionSource = Patient | Organization + +type BiologicallyDerivedProductCollectionSourceReference { + id: String + extension: [Extension] + reference: String + resource: BiologicallyDerivedProductCollectionSource + type: URI + identifier: Identifier + display: String +} + +type BiologicallyDerivedProductCollection { + id: String + extension: [Extension] + modifierExtension: [Extension] + collector: BiologicallyDerivedProductCollectionCollectorReference + source: BiologicallyDerivedProductCollectionSourceReference + collectedDateTime: DateTime + collectedPeriod: Period +} + +type BiologicallyDerivedProductManipulation { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + timeDateTime: DateTime + timePeriod: Period +} + +type BiologicallyDerivedProductProcessingAdditiveReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type BiologicallyDerivedProductProcessing { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + procedure: CodeableConcept + additive: BiologicallyDerivedProductProcessingAdditiveReference + timeDateTime: DateTime + timePeriod: Period +} + +type BiologicallyDerivedProductStorage { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + temperature: Float + scale: Code + duration: Period +} + +type BundleEntry { + id: String + extension: [Extension] + modifierExtension: [Extension] + link: [BundleLink] + fullUrl: URI + resource: Resource + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BundleLink { + id: String + extension: [Extension] + modifierExtension: [Extension] + relation: String + url: URI +} + +type BundleRequest { + id: String + extension: [Extension] + modifierExtension: [Extension] + method: Code + url: URI + ifNoneMatch: String + ifModifiedSince: Instant + ifMatch: String + ifNoneExist: String +} + +type BundleResponse { + id: String + extension: [Extension] + modifierExtension: [Extension] + status: String + location: URI + etag: String + lastModified: Instant + outcome: Resource +} + +type BundleSearch { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + score: Float +} + +type CapabilityStatementDocument { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + documentation: Markdown + profile: Canonical +} + +type CapabilityStatementEndpoint { + id: String + extension: [Extension] + modifierExtension: [Extension] + protocol: Coding + address: URL +} + +type CapabilityStatementImplementationCustodianReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CapabilityStatementImplementation { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + url: URL + custodian: CapabilityStatementImplementationCustodianReference +} + +type CapabilityStatementInteraction { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + documentation: Markdown +} + +type CapabilityStatementInteraction1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + documentation: Markdown +} + +type CapabilityStatementMessaging { + id: String + extension: [Extension] + modifierExtension: [Extension] + endpoint: [CapabilityStatementEndpoint] + reliableCache: Int + documentation: Markdown + supportedMessage: [CapabilityStatementSupportedMessage] +} + +type CapabilityStatementOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + definition: Canonical + documentation: Markdown +} + +type CapabilityStatementResource { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + profile: Canonical + supportedProfile: [Canonical] + documentation: Markdown + interaction: [CapabilityStatementInteraction] + versioning: Code + readHistory: Boolean + updateCreate: Boolean + conditionalCreate: Boolean + conditionalRead: Code + conditionalUpdate: Boolean + conditionalDelete: Code + referencePolicy: [Code] + searchInclude: [String] + searchRevInclude: [String] + searchParam: [CapabilityStatementSearchParam] + operation: [CapabilityStatementOperation] +} + +type CapabilityStatementRest { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + documentation: Markdown + security: CapabilityStatementSecurity + resource: [CapabilityStatementResource] + interaction: [CapabilityStatementInteraction1] + searchParam: [CapabilityStatementSearchParam] + operation: [CapabilityStatementOperation] + compartment: [Canonical] +} + +type CapabilityStatementSearchParam { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + definition: Canonical + type: Code + documentation: Markdown +} + +type CapabilityStatementSecurity { + id: String + extension: [Extension] + modifierExtension: [Extension] + cors: Boolean + service: [CodeableConcept] + description: Markdown +} + +type CapabilityStatementSoftware { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + version: String + releaseDate: DateTime +} + +type CapabilityStatementSupportedMessage { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + definition: Canonical +} + +type CarePlanActivityOutcomeReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union CarePlanActivityReference = Appointment | CommunicationRequest | DeviceRequest | MedicationRequest | NutritionOrder | Task | ServiceRequest | VisionPrescription | RequestGroup + +type CarePlanActivityReferenceReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanActivityReference + type: URI + identifier: Identifier + display: String +} + +type CarePlanActivity { + id: String + extension: [Extension] + modifierExtension: [Extension] + outcomeCodeableConcept: [CodeableConcept] + outcomeReference: [CarePlanActivityOutcomeReferenceReference] + progress: [Annotation] + reference: CarePlanActivityReferenceReference + detail: CarePlanDetail +} + +union CarePlanDetailReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type CarePlanDetailReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanDetailReasonReference + type: URI + identifier: Identifier + display: String +} + +type CarePlanDetailGoalReference { + id: String + extension: [Extension] + reference: String + resource: Goal + type: URI + identifier: Identifier + display: String +} + +type CarePlanDetailLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union CarePlanDetailPerformer = Practitioner | PractitionerRole | Organization | RelatedPerson | Patient | CareTeam | HealthcareService | Device + +type CarePlanDetailPerformerReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanDetailPerformer + type: URI + identifier: Identifier + display: String +} + +union CarePlanDetailProductReference = Medication | Substance + +type CarePlanDetailProductReferenceReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanDetailProductReference + type: URI + identifier: Identifier + display: String +} + +type CarePlanDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + kind: Code + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + code: CodeableConcept + reasonCode: [CodeableConcept] + reasonReference: [CarePlanDetailReasonReferenceReference] + goal: [CarePlanDetailGoalReference] + status: Code + statusReason: CodeableConcept + doNotPerform: Boolean + scheduledTiming: Timing + scheduledPeriod: Period + scheduledString: String + location: CarePlanDetailLocationReference + performer: [CarePlanDetailPerformerReference] + productCodeableConcept: CodeableConcept + productReference: CarePlanDetailProductReferenceReference + dailyAmount: Quantity + quantity: Quantity + description: String +} + +union CareTeamParticipantMember = Practitioner | PractitionerRole | RelatedPerson | Patient | Organization | CareTeam + +type CareTeamParticipantMemberReference { + id: String + extension: [Extension] + reference: String + resource: CareTeamParticipantMember + type: URI + identifier: Identifier + display: String +} + +type CareTeamParticipantOnBehalfOfReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CareTeamParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: [CodeableConcept] + member: CareTeamParticipantMemberReference + onBehalfOf: CareTeamParticipantOnBehalfOfReference + period: Period +} + +type CatalogEntryRelatedEntryItemReference { + id: String + extension: [Extension] + reference: String + resource: CatalogEntry + type: URI + identifier: Identifier + display: String +} + +type CatalogEntryRelatedEntry { + id: String + extension: [Extension] + modifierExtension: [Extension] + relationtype: Code + item: CatalogEntryRelatedEntryItemReference +} + +type ChargeItemDefinitionApplicability { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + language: String + expression: String +} + +type ChargeItemDefinitionPriceComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + code: CodeableConcept + factor: Float + amount: Money +} + +type ChargeItemDefinitionPropertyGroup { + id: String + extension: [Extension] + modifierExtension: [Extension] + applicability: [ChargeItemDefinitionApplicability] + priceComponent: [ChargeItemDefinitionPriceComponent] +} + +union ChargeItemPerformerActor = Practitioner | PractitionerRole | Organization | CareTeam | Patient | Device | RelatedPerson + +type ChargeItemPerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemPerformerActor + type: URI + identifier: Identifier + display: String +} + +type ChargeItemPerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: ChargeItemPerformerActorReference +} + +type CitationAbstract { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + language: CodeableConcept + text: Markdown + copyright: Markdown +} + +type CitationAffiliationInfo { + id: String + extension: [Extension] + modifierExtension: [Extension] + affiliation: String + role: String + identifier: [Identifier] +} + +type CitationCitedArtifact { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + relatedIdentifier: [Identifier] + dateAccessed: DateTime + version: CitationVersion + currentState: [CodeableConcept] + statusDate: [CitationStatusDate1] + title: [CitationTitle] + abstract: [CitationAbstract] + part: CitationPart + relatesTo: [CitationRelatesTo1] + publicationForm: [CitationPublicationForm] + webLocation: [CitationWebLocation] + classification: [CitationClassification1] + contributorship: CitationContributorship + note: [Annotation] +} + +type CitationClassification { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + classifier: [CodeableConcept] +} + +type CitationClassification1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + classifier: [CodeableConcept] + whoClassified: CitationWhoClassified +} + +type CitationContributionInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + time: DateTime +} + +type CitationContributorship { + id: String + extension: [Extension] + modifierExtension: [Extension] + complete: Boolean + entry: [CitationEntry] + summary: [CitationSummary1] +} + +type CitationDateOfPublication { + id: String + extension: [Extension] + modifierExtension: [Extension] + date: Date + year: String + month: String + day: String + season: String + text: String +} + +type CitationEntry { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: HumanName + initials: String + collectiveName: String + identifier: [Identifier] + affiliationInfo: [CitationAffiliationInfo] + address: [Address] + telecom: [ContactPoint] + contributionType: [CodeableConcept] + role: CodeableConcept + contributionInstance: [CitationContributionInstance] + correspondingContact: Boolean + listOrder: Int +} + +type CitationPartBaseCitationReference { + id: String + extension: [Extension] + reference: String + resource: Citation + type: URI + identifier: Identifier + display: String +} + +type CitationPart { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + value: String + baseCitation: CitationPartBaseCitationReference +} + +type CitationPeriodicRelease { + id: String + extension: [Extension] + modifierExtension: [Extension] + citedMedium: CodeableConcept + volume: String + issue: String + dateOfPublication: CitationDateOfPublication +} + +type CitationPublicationForm { + id: String + extension: [Extension] + modifierExtension: [Extension] + publishedIn: CitationPublishedIn + periodicRelease: CitationPeriodicRelease + articleDate: DateTime + lastRevisionDate: DateTime + language: [CodeableConcept] + accessionNumber: String + pageString: String + firstPage: String + lastPage: String + pageCount: String + copyright: Markdown +} + +type CitationPublishedInPublisherReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CitationPublishedIn { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + identifier: [Identifier] + title: String + publisher: CitationPublishedInPublisherReference + publisherLocation: String +} + +type CitationRelatesToTargetReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CitationRelatesTo { + id: String + extension: [Extension] + modifierExtension: [Extension] + relationshipType: CodeableConcept + targetClassifier: [CodeableConcept] + targetUri: URI + targetIdentifier: Identifier + targetReference: CitationRelatesToTargetReferenceReference + targetAttachment: Attachment +} + +type CitationRelatesTo1TargetReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CitationRelatesTo1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + relationshipType: CodeableConcept + targetClassifier: [CodeableConcept] + targetUri: URI + targetIdentifier: Identifier + targetReference: CitationRelatesTo1TargetReferenceReference + targetAttachment: Attachment +} + +type CitationStatusDate { + id: String + extension: [Extension] + modifierExtension: [Extension] + activity: CodeableConcept + actual: Boolean + period: Period +} + +type CitationStatusDate1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + activity: CodeableConcept + actual: Boolean + period: Period +} + +type CitationSummary { + id: String + extension: [Extension] + modifierExtension: [Extension] + style: CodeableConcept + text: Markdown +} + +type CitationSummary1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + style: CodeableConcept + source: CodeableConcept + value: Markdown +} + +type CitationTitle { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: [CodeableConcept] + language: CodeableConcept + text: Markdown +} + +type CitationVersionBaseCitationReference { + id: String + extension: [Extension] + reference: String + resource: Citation + type: URI + identifier: Identifier + display: String +} + +type CitationVersion { + id: String + extension: [Extension] + modifierExtension: [Extension] + value: String + baseCitation: CitationVersionBaseCitationReference +} + +type CitationWebLocation { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + url: URI +} + +union CitationWhoClassifiedPerson = Person | Practitioner + +type CitationWhoClassifiedPersonReference { + id: String + extension: [Extension] + reference: String + resource: CitationWhoClassifiedPerson + type: URI + identifier: Identifier + display: String +} + +type CitationWhoClassifiedOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CitationWhoClassifiedPublisherReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CitationWhoClassified { + id: String + extension: [Extension] + modifierExtension: [Extension] + person: CitationWhoClassifiedPersonReference + organization: CitationWhoClassifiedOrganizationReference + publisher: CitationWhoClassifiedPublisherReference + classifierCopyright: String + freeToShare: Boolean +} + +type ClaimAccidentLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ClaimAccident { + id: String + extension: [Extension] + modifierExtension: [Extension] + date: Date + type: CodeableConcept + locationAddress: Address + locationReference: ClaimAccidentLocationReferenceReference +} + +union ClaimCareTeamProvider = Practitioner | PractitionerRole | Organization + +type ClaimCareTeamProviderReference { + id: String + extension: [Extension] + reference: String + resource: ClaimCareTeamProvider + type: URI + identifier: Identifier + display: String +} + +type ClaimCareTeam { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + provider: ClaimCareTeamProviderReference + responsible: Boolean + role: CodeableConcept + qualification: CodeableConcept +} + +type ClaimDetailUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ClaimDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ClaimDetailUdiReference] + subDetail: [ClaimSubDetail] +} + +type ClaimDiagnosisDiagnosisReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type ClaimDiagnosis { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + diagnosisCodeableConcept: CodeableConcept + diagnosisReference: ClaimDiagnosisDiagnosisReferenceReference + type: [CodeableConcept] + onAdmission: CodeableConcept + packageCode: CodeableConcept +} + +type ClaimInsuranceCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type ClaimInsuranceClaimResponseReference { + id: String + extension: [Extension] + reference: String + resource: ClaimResponse + type: URI + identifier: Identifier + display: String +} + +type ClaimInsurance { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + focal: Boolean + identifier: Identifier + coverage: ClaimInsuranceCoverageReference + businessArrangement: String + preAuthRef: [String] + claimResponse: ClaimInsuranceClaimResponseReference +} + +type ClaimItemLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ClaimItemUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ClaimItemEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type ClaimItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + careTeamSequence: [Int] + diagnosisSequence: [Int] + procedureSequence: [Int] + informationSequence: [Int] + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + servicedDate: Date + servicedPeriod: Period + locationCodeableConcept: CodeableConcept + locationAddress: Address + locationReference: ClaimItemLocationReferenceReference + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ClaimItemUdiReference] + bodySite: CodeableConcept + subSite: [CodeableConcept] + encounter: [ClaimItemEncounterReference] + detail: [ClaimDetail] +} + +union ClaimPayeeParty = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson + +type ClaimPayeePartyReference { + id: String + extension: [Extension] + reference: String + resource: ClaimPayeeParty + type: URI + identifier: Identifier + display: String +} + +type ClaimPayee { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + party: ClaimPayeePartyReference +} + +type ClaimProcedureProcedureReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Procedure + type: URI + identifier: Identifier + display: String +} + +type ClaimProcedureUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ClaimProcedure { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + type: [CodeableConcept] + date: DateTime + procedureCodeableConcept: CodeableConcept + procedureReference: ClaimProcedureProcedureReferenceReference + udi: [ClaimProcedureUdiReference] +} + +type ClaimRelatedClaimReference { + id: String + extension: [Extension] + reference: String + resource: Claim + type: URI + identifier: Identifier + display: String +} + +type ClaimRelated { + id: String + extension: [Extension] + modifierExtension: [Extension] + claim: ClaimRelatedClaimReference + relationship: CodeableConcept + reference: Identifier +} + +union ClaimResponseAddItemProvider = Practitioner | PractitionerRole | Organization + +type ClaimResponseAddItemProviderReference { + id: String + extension: [Extension] + reference: String + resource: ClaimResponseAddItemProvider + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseAddItemLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseAddItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemSequence: [Int] + detailSequence: [Int] + subdetailSequence: [Int] + provider: [ClaimResponseAddItemProviderReference] + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + servicedDate: Date + servicedPeriod: Period + locationCodeableConcept: CodeableConcept + locationAddress: Address + locationReference: ClaimResponseAddItemLocationReferenceReference + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + bodySite: CodeableConcept + subSite: [CodeableConcept] + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] + detail: [ClaimResponseDetail1] +} + +type ClaimResponseAdjudication { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + reason: CodeableConcept + amount: Money + value: Float +} + +type ClaimResponseDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + detailSequence: Int + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] + subDetail: [ClaimResponseSubDetail] +} + +type ClaimResponseDetail1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + productOrService: CodeableConcept + modifier: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] + subDetail: [ClaimResponseSubDetail1] +} + +type ClaimResponseError { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemSequence: Int + detailSequence: Int + subDetailSequence: Int + code: CodeableConcept +} + +type ClaimResponseInsuranceCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseInsuranceClaimResponseReference { + id: String + extension: [Extension] + reference: String + resource: ClaimResponse + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseInsurance { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + focal: Boolean + coverage: ClaimResponseInsuranceCoverageReference + businessArrangement: String + claimResponse: ClaimResponseInsuranceClaimResponseReference +} + +type ClaimResponseItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemSequence: Int + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] + detail: [ClaimResponseDetail] +} + +type ClaimResponsePayment { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + adjustment: Money + adjustmentReason: CodeableConcept + date: Date + amount: Money + identifier: Identifier +} + +type ClaimResponseProcessNote { + id: String + extension: [Extension] + modifierExtension: [Extension] + number: Int + type: Code + text: String + language: CodeableConcept +} + +type ClaimResponseSubDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + subDetailSequence: Int + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] +} + +type ClaimResponseSubDetail1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + productOrService: CodeableConcept + modifier: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + noteNumber: [Int] + adjudication: [ClaimResponseAdjudication] +} + +type ClaimResponseTotal { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + amount: Money +} + +type ClaimSubDetailUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ClaimSubDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ClaimSubDetailUdiReference] +} + +type ClaimSupportingInfoValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ClaimSupportingInfo { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + category: CodeableConcept + code: CodeableConcept + timingDate: Date + timingPeriod: Period + valueBoolean: Boolean + valueString: String + valueQuantity: Quantity + valueAttachment: Attachment + valueReference: ClaimSupportingInfoValueReferenceReference + reason: CodeableConcept +} + +union ClinicalImpressionFindingItemReference = Condition | Observation | Media + +type ClinicalImpressionFindingItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpressionFindingItemReference + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionFinding { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemCodeableConcept: CodeableConcept + itemReference: ClinicalImpressionFindingItemReferenceReference + basis: String +} + +union ClinicalImpressionInvestigationItem = Observation | QuestionnaireResponse | FamilyMemberHistory | DiagnosticReport | RiskAssessment | ImagingStudy | Media + +type ClinicalImpressionInvestigationItemReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpressionInvestigationItem + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionInvestigation { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + item: [ClinicalImpressionInvestigationItemReference] +} + +type ClinicalUseDefinitionContraindicationDiseaseSymptomProcedureReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionContraindicationDiseaseStatusReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionContraindicationComorbidityReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionContraindicationIndicationReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionContraindication { + id: String + extension: [Extension] + modifierExtension: [Extension] + diseaseSymptomProcedure: ClinicalUseDefinitionContraindicationDiseaseSymptomProcedureReference + diseaseStatus: ClinicalUseDefinitionContraindicationDiseaseStatusReference + comorbidity: [ClinicalUseDefinitionContraindicationComorbidityReference] + indication: [ClinicalUseDefinitionContraindicationIndicationReference] + otherTherapy: [ClinicalUseDefinitionOtherTherapy] +} + +type ClinicalUseDefinitionIndicationDiseaseSymptomProcedureReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionIndicationDiseaseStatusReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionIndicationComorbidityReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionIndicationIntendedEffectReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionIndicationUndesirableEffectReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionIndication { + id: String + extension: [Extension] + modifierExtension: [Extension] + diseaseSymptomProcedure: ClinicalUseDefinitionIndicationDiseaseSymptomProcedureReference + diseaseStatus: ClinicalUseDefinitionIndicationDiseaseStatusReference + comorbidity: [ClinicalUseDefinitionIndicationComorbidityReference] + intendedEffect: ClinicalUseDefinitionIndicationIntendedEffectReference + durationRange: Range + durationString: String + undesirableEffect: [ClinicalUseDefinitionIndicationUndesirableEffectReference] + otherTherapy: [ClinicalUseDefinitionOtherTherapy] +} + +union ClinicalUseDefinitionInteractantItemReference = MedicinalProductDefinition | Medication | Substance | ObservationDefinition + +type ClinicalUseDefinitionInteractantItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinitionInteractantItemReference + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionInteractant { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemReference: ClinicalUseDefinitionInteractantItemReferenceReference + itemCodeableConcept: CodeableConcept +} + +type ClinicalUseDefinitionInteractionEffectReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionInteraction { + id: String + extension: [Extension] + modifierExtension: [Extension] + interactant: [ClinicalUseDefinitionInteractant] + type: CodeableConcept + effect: ClinicalUseDefinitionInteractionEffectReference + incidence: CodeableConcept + management: [CodeableConcept] +} + +union ClinicalUseDefinitionOtherTherapyTherapy = MedicinalProductDefinition | Medication | Substance | SubstanceDefinition | ActivityDefinition + +type ClinicalUseDefinitionOtherTherapyTherapyReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinitionOtherTherapyTherapy + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionOtherTherapy { + id: String + extension: [Extension] + modifierExtension: [Extension] + relationshipType: CodeableConcept + therapy: ClinicalUseDefinitionOtherTherapyTherapyReference +} + +type ClinicalUseDefinitionUndesirableEffectSymptomConditionEffectReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionUndesirableEffect { + id: String + extension: [Extension] + modifierExtension: [Extension] + symptomConditionEffect: ClinicalUseDefinitionUndesirableEffectSymptomConditionEffectReference + classification: CodeableConcept + frequencyOfOccurrence: CodeableConcept +} + +type ClinicalUseDefinitionWarning { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: Markdown + code: CodeableConcept +} + +type CodeSystemConcept { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + display: String + definition: String + designation: [CodeSystemDesignation] + property: [CodeSystemProperty1] + concept: [CodeSystemConcept] +} + +type CodeSystemDesignation { + id: String + extension: [Extension] + modifierExtension: [Extension] + language: Code + use: Coding + value: String +} + +type CodeSystemFilter { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + description: String + operator: [Code] + value: String +} + +type CodeSystemProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + uri: URI + description: String + type: Code +} + +type CodeSystemProperty1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + valueCode: Code + valueCoding: Coding + valueString: String + valueInteger: Int + valueBoolean: Boolean + valueDateTime: DateTime + valueDecimal: Float +} + +type CommunicationPayloadContentReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationPayload { + id: String + extension: [Extension] + modifierExtension: [Extension] + contentString: String + contentAttachment: Attachment + contentReference: CommunicationPayloadContentReferenceReference +} + +type CommunicationRequestPayloadContentReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationRequestPayload { + id: String + extension: [Extension] + modifierExtension: [Extension] + contentString: String + contentAttachment: Attachment + contentReference: CommunicationRequestPayloadContentReferenceReference +} + +type CompartmentDefinitionResource { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + param: [String] + documentation: String +} + +union CompositionAttesterParty = Patient | RelatedPerson | Practitioner | PractitionerRole | Organization + +type CompositionAttesterPartyReference { + id: String + extension: [Extension] + reference: String + resource: CompositionAttesterParty + type: URI + identifier: Identifier + display: String +} + +type CompositionAttester { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + time: DateTime + party: CompositionAttesterPartyReference +} + +type CompositionEventDetailReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CompositionEvent { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: [CodeableConcept] + period: Period + detail: [CompositionEventDetailReference] +} + +type CompositionRelatesToTargetReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Composition + type: URI + identifier: Identifier + display: String +} + +type CompositionRelatesTo { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + targetIdentifier: Identifier + targetReference: CompositionRelatesToTargetReferenceReference +} + +union CompositionSectionAuthor = Practitioner | PractitionerRole | Device | Patient | RelatedPerson | Organization + +type CompositionSectionAuthorReference { + id: String + extension: [Extension] + reference: String + resource: CompositionSectionAuthor + type: URI + identifier: Identifier + display: String +} + +type CompositionSectionFocusReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CompositionSectionEntryReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CompositionSection { + id: String + extension: [Extension] + modifierExtension: [Extension] + title: String + code: CodeableConcept + author: [CompositionSectionAuthorReference] + focus: CompositionSectionFocusReference + text: Narrative + mode: Code + orderedBy: CodeableConcept + entry: [CompositionSectionEntryReference] + emptyReason: CodeableConcept + section: [CompositionSection] +} + +type ConceptMapDependsOn { + id: String + extension: [Extension] + modifierExtension: [Extension] + property: URI + system: Canonical + value: String + display: String +} + +type ConceptMapElement { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + display: String + target: [ConceptMapTarget] +} + +type ConceptMapGroup { + id: String + extension: [Extension] + modifierExtension: [Extension] + source: URI + sourceVersion: String + target: URI + targetVersion: String + element: [ConceptMapElement] + unmapped: ConceptMapUnmapped +} + +type ConceptMapTarget { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + display: String + equivalence: Code + comment: String + dependsOn: [ConceptMapDependsOn] + product: [ConceptMapDependsOn] +} + +type ConceptMapUnmapped { + id: String + extension: [Extension] + modifierExtension: [Extension] + mode: Code + code: Code + display: String + url: Canonical +} + +type ConditionEvidenceDetailReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ConditionEvidence { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: [CodeableConcept] + detail: [ConditionEvidenceDetailReference] +} + +union ConditionStageAssessment = ClinicalImpression | DiagnosticReport | Observation + +type ConditionStageAssessmentReference { + id: String + extension: [Extension] + reference: String + resource: ConditionStageAssessment + type: URI + identifier: Identifier + display: String +} + +type ConditionStage { + id: String + extension: [Extension] + modifierExtension: [Extension] + summary: CodeableConcept + assessment: [ConditionStageAssessmentReference] + type: CodeableConcept +} + +union ConsentActorReference = Device | Group | CareTeam | Organization | Patient | Practitioner | RelatedPerson | PractitionerRole + +type ConsentActorReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ConsentActorReference + type: URI + identifier: Identifier + display: String +} + +type ConsentActor { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: CodeableConcept + reference: ConsentActorReferenceReference +} + +type ConsentDataReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ConsentData { + id: String + extension: [Extension] + modifierExtension: [Extension] + meaning: Code + reference: ConsentDataReferenceReference +} + +type ConsentPolicy { + id: String + extension: [Extension] + modifierExtension: [Extension] + authority: URI + uri: URI +} + +type ConsentProvision { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + period: Period + actor: [ConsentActor] + action: [CodeableConcept] + securityLabel: [Coding] + purpose: [Coding] + class: [Coding] + code: [CodeableConcept] + dataPeriod: Period + data: [ConsentData] + provision: [ConsentProvision] +} + +union ConsentVerificationVerifiedWith = Patient | RelatedPerson + +type ConsentVerificationVerifiedWithReference { + id: String + extension: [Extension] + reference: String + resource: ConsentVerificationVerifiedWith + type: URI + identifier: Identifier + display: String +} + +type ConsentVerification { + id: String + extension: [Extension] + modifierExtension: [Extension] + verified: Boolean + verifiedWith: ConsentVerificationVerifiedWithReference + verificationDate: DateTime +} + +union ContractActionContext = Encounter | EpisodeOfCare + +type ContractActionContextReference { + id: String + extension: [Extension] + reference: String + resource: ContractActionContext + type: URI + identifier: Identifier + display: String +} + +union ContractActionRequester = Patient | RelatedPerson | Practitioner | PractitionerRole | Device | Group | Organization + +type ContractActionRequesterReference { + id: String + extension: [Extension] + reference: String + resource: ContractActionRequester + type: URI + identifier: Identifier + display: String +} + +union ContractActionPerformer = RelatedPerson | Patient | Practitioner | PractitionerRole | CareTeam | Device | Substance | Organization | Location + +type ContractActionPerformerReference { + id: String + extension: [Extension] + reference: String + resource: ContractActionPerformer + type: URI + identifier: Identifier + display: String +} + +union ContractActionReasonReference = Condition | Observation | DiagnosticReport | DocumentReference | Questionnaire | QuestionnaireResponse + +type ContractActionReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractActionReasonReference + type: URI + identifier: Identifier + display: String +} + +type ContractAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + doNotPerform: Boolean + type: CodeableConcept + subject: [ContractSubject] + intent: CodeableConcept + linkId: [String] + status: CodeableConcept + context: ContractActionContextReference + contextLinkId: [String] + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + requester: [ContractActionRequesterReference] + requesterLinkId: [String] + performerType: [CodeableConcept] + performerRole: CodeableConcept + performer: ContractActionPerformerReference + performerLinkId: [String] + reasonCode: [CodeableConcept] + reasonReference: [ContractActionReasonReferenceReference] + reason: [String] + reasonLinkId: [String] + note: [Annotation] + securityLabelNumber: [Int] +} + +type ContractAnswerValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractAnswer { + id: String + extension: [Extension] + modifierExtension: [Extension] + valueBoolean: Boolean + valueDecimal: Float + valueInteger: Int + valueDate: Date + valueDateTime: DateTime + valueTime: Time + valueString: String + valueUri: URI + valueAttachment: Attachment + valueCoding: Coding + valueQuantity: Quantity + valueReference: ContractAnswerValueReferenceReference +} + +type ContractAssetTypeReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractAsset { + id: String + extension: [Extension] + modifierExtension: [Extension] + scope: CodeableConcept + type: [CodeableConcept] + typeReference: [ContractAssetTypeReferenceReference] + subtype: [CodeableConcept] + relationship: Coding + context: [ContractContext] + condition: String + periodType: [CodeableConcept] + period: [Period] + usePeriod: [Period] + text: String + linkId: [String] + answer: [ContractAnswer] + securityLabelNumber: [Int] + valuedItem: [ContractValuedItem] +} + +union ContractContentDefinitionPublisher = Practitioner | PractitionerRole | Organization + +type ContractContentDefinitionPublisherReference { + id: String + extension: [Extension] + reference: String + resource: ContractContentDefinitionPublisher + type: URI + identifier: Identifier + display: String +} + +type ContractContentDefinition { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + subType: CodeableConcept + publisher: ContractContentDefinitionPublisherReference + publicationDate: DateTime + publicationStatus: Code + copyright: Markdown +} + +type ContractContextReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractContext { + id: String + extension: [Extension] + modifierExtension: [Extension] + reference: ContractContextReferenceReference + code: [CodeableConcept] + text: String +} + +union ContractFriendlyContentReference = Composition | DocumentReference | QuestionnaireResponse + +type ContractFriendlyContentReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractFriendlyContentReference + type: URI + identifier: Identifier + display: String +} + +type ContractFriendly { + id: String + extension: [Extension] + modifierExtension: [Extension] + contentAttachment: Attachment + contentReference: ContractFriendlyContentReferenceReference +} + +union ContractLegalContentReference = Composition | DocumentReference | QuestionnaireResponse + +type ContractLegalContentReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractLegalContentReference + type: URI + identifier: Identifier + display: String +} + +type ContractLegal { + id: String + extension: [Extension] + modifierExtension: [Extension] + contentAttachment: Attachment + contentReference: ContractLegalContentReferenceReference +} + +type ContractOfferTopicReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractOffer { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + party: [ContractParty] + topic: ContractOfferTopicReference + type: CodeableConcept + decision: CodeableConcept + decisionMode: [CodeableConcept] + answer: [ContractAnswer] + text: String + linkId: [String] + securityLabelNumber: [Int] +} + +union ContractPartyReference = Patient | RelatedPerson | Practitioner | PractitionerRole | Device | Group | Organization + +type ContractPartyReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractPartyReference + type: URI + identifier: Identifier + display: String +} + +type ContractParty { + id: String + extension: [Extension] + modifierExtension: [Extension] + reference: [ContractPartyReferenceReference] + role: CodeableConcept +} + +type ContractRuleContentReferenceReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type ContractRule { + id: String + extension: [Extension] + modifierExtension: [Extension] + contentAttachment: Attachment + contentReference: ContractRuleContentReferenceReference +} + +type ContractSecurityLabel { + id: String + extension: [Extension] + modifierExtension: [Extension] + number: [Int] + classification: Coding + category: [Coding] + control: [Coding] +} + +union ContractSignerParty = Organization | Patient | Practitioner | PractitionerRole | RelatedPerson + +type ContractSignerPartyReference { + id: String + extension: [Extension] + reference: String + resource: ContractSignerParty + type: URI + identifier: Identifier + display: String +} + +type ContractSigner { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Coding + party: ContractSignerPartyReference + signature: [Signature] +} + +union ContractSubjectReference = Patient | RelatedPerson | Practitioner | PractitionerRole | Device | Group | Organization + +type ContractSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractSubjectReference + type: URI + identifier: Identifier + display: String +} + +type ContractSubject { + id: String + extension: [Extension] + modifierExtension: [Extension] + reference: [ContractSubjectReferenceReference] + role: CodeableConcept +} + +type ContractTermTopicReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractTerm { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + issued: DateTime + applies: Period + topicCodeableConcept: CodeableConcept + topicReference: ContractTermTopicReferenceReference + type: CodeableConcept + subType: CodeableConcept + text: String + securityLabel: [ContractSecurityLabel] + offer: ContractOffer + asset: [ContractAsset] + action: [ContractAction] + group: [ContractTerm] +} + +type ContractValuedItemEntityReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union ContractValuedItemResponsible = Organization | Patient | Practitioner | PractitionerRole | RelatedPerson + +type ContractValuedItemResponsibleReference { + id: String + extension: [Extension] + reference: String + resource: ContractValuedItemResponsible + type: URI + identifier: Identifier + display: String +} + +union ContractValuedItemRecipient = Organization | Patient | Practitioner | PractitionerRole | RelatedPerson + +type ContractValuedItemRecipientReference { + id: String + extension: [Extension] + reference: String + resource: ContractValuedItemRecipient + type: URI + identifier: Identifier + display: String +} + +type ContractValuedItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + entityCodeableConcept: CodeableConcept + entityReference: ContractValuedItemEntityReferenceReference + identifier: Identifier + effectiveTime: DateTime + quantity: Quantity + unitPrice: Money + factor: Float + points: Float + net: Money + payment: String + paymentDate: DateTime + responsible: ContractValuedItemResponsibleReference + recipient: ContractValuedItemRecipientReference + linkId: [String] + securityLabelNumber: [Int] +} + +type CoverageClass { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + value: String + name: String +} + +type CoverageCostToBeneficiary { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueQuantity: Quantity + valueMoney: Money + exception: [CoverageException] +} + +type CoverageEligibilityRequestDiagnosisDiagnosisReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestDiagnosis { + id: String + extension: [Extension] + modifierExtension: [Extension] + diagnosisCodeableConcept: CodeableConcept + diagnosisReference: CoverageEligibilityRequestDiagnosisDiagnosisReferenceReference +} + +type CoverageEligibilityRequestInsuranceCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestInsurance { + id: String + extension: [Extension] + modifierExtension: [Extension] + focal: Boolean + coverage: CoverageEligibilityRequestInsuranceCoverageReference + businessArrangement: String +} + +union CoverageEligibilityRequestItemProvider = Practitioner | PractitionerRole + +type CoverageEligibilityRequestItemProviderReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityRequestItemProvider + type: URI + identifier: Identifier + display: String +} + +union CoverageEligibilityRequestItemFacility = Location | Organization + +type CoverageEligibilityRequestItemFacilityReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityRequestItemFacility + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestItemDetailReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + supportingInfoSequence: [Int] + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + provider: CoverageEligibilityRequestItemProviderReference + quantity: Quantity + unitPrice: Money + facility: CoverageEligibilityRequestItemFacilityReference + diagnosis: [CoverageEligibilityRequestDiagnosis] + detail: [CoverageEligibilityRequestItemDetailReference] +} + +type CoverageEligibilityRequestSupportingInfoInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestSupportingInfo { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + information: CoverageEligibilityRequestSupportingInfoInformationReference + appliesToAll: Boolean +} + +type CoverageEligibilityResponseBenefit { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + allowedUnsignedInt: Int + allowedString: String + allowedMoney: Money + usedUnsignedInt: Int + usedString: String + usedMoney: Money +} + +type CoverageEligibilityResponseError { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept +} + +type CoverageEligibilityResponseInsuranceCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityResponseInsurance { + id: String + extension: [Extension] + modifierExtension: [Extension] + coverage: CoverageEligibilityResponseInsuranceCoverageReference + inforce: Boolean + benefitPeriod: Period + item: [CoverageEligibilityResponseItem] +} + +union CoverageEligibilityResponseItemProvider = Practitioner | PractitionerRole + +type CoverageEligibilityResponseItemProviderReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityResponseItemProvider + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityResponseItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + provider: CoverageEligibilityResponseItemProviderReference + excluded: Boolean + name: String + description: String + network: CodeableConcept + unit: CodeableConcept + term: CodeableConcept + benefit: [CoverageEligibilityResponseBenefit] + authorizationRequired: Boolean + authorizationSupporting: [CodeableConcept] + authorizationUrl: URI +} + +type CoverageException { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + period: Period +} + +type DetectedIssueEvidenceDetailReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DetectedIssueEvidence { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: [CodeableConcept] + detail: [DetectedIssueEvidenceDetailReference] +} + +union DetectedIssueMitigationAuthor = Practitioner | PractitionerRole + +type DetectedIssueMitigationAuthorReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssueMitigationAuthor + type: URI + identifier: Identifier + display: String +} + +type DetectedIssueMitigation { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: CodeableConcept + date: DateTime + author: DetectedIssueMitigationAuthorReference +} + +type DeviceDefinitionCapability { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + description: [CodeableConcept] +} + +type DeviceDefinitionDeviceName { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + type: Code +} + +type DeviceDefinitionMaterial { + id: String + extension: [Extension] + modifierExtension: [Extension] + substance: CodeableConcept + alternate: Boolean + allergenicIndicator: Boolean +} + +type DeviceDefinitionProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueQuantity: [Quantity] + valueCode: [CodeableConcept] +} + +type DeviceDefinitionSpecialization { + id: String + extension: [Extension] + modifierExtension: [Extension] + systemType: String + version: String +} + +type DeviceDefinitionUdiDeviceIdentifier { + id: String + extension: [Extension] + modifierExtension: [Extension] + deviceIdentifier: String + issuer: URI + jurisdiction: URI +} + +type DeviceDeviceName { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + type: Code +} + +type DeviceMetricCalibration { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + state: Code + time: Instant +} + +type DeviceProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueQuantity: [Quantity] + valueCode: [CodeableConcept] +} + +type DeviceRequestParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueRange: Range + valueBoolean: Boolean +} + +type DeviceSpecialization { + id: String + extension: [Extension] + modifierExtension: [Extension] + systemType: CodeableConcept + version: String +} + +type DeviceUdiCarrier { + id: String + extension: [Extension] + modifierExtension: [Extension] + deviceIdentifier: String + issuer: URI + jurisdiction: URI + carrierAIDC: Base64Binary + carrierHRF: String + entryType: Code +} + +type DeviceVersion { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + component: Identifier + value: String +} + +type DiagnosticReportMediaLinkReference { + id: String + extension: [Extension] + reference: String + resource: Media + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReportMedia { + id: String + extension: [Extension] + modifierExtension: [Extension] + comment: String + link: DiagnosticReportMediaLinkReference +} + +type DocumentManifestRelatedRefReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DocumentManifestRelated { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + ref: DocumentManifestRelatedRefReference +} + +type DocumentReferenceContent { + id: String + extension: [Extension] + modifierExtension: [Extension] + attachment: DocumentReferenceAttachment + format: Coding +} + +union DocumentReferenceContextEncounter = Encounter | EpisodeOfCare + +type DocumentReferenceContextEncounterReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReferenceContextEncounter + type: URI + identifier: Identifier + display: String +} + +type DocumentReferenceContextSourcePatientInfoReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type DocumentReferenceContextRelatedReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DocumentReferenceContext { + id: String + extension: [Extension] + modifierExtension: [Extension] + encounter: [DocumentReferenceContextEncounterReference] + event: [CodeableConcept] + period: Period + facilityType: CodeableConcept + practiceSetting: CodeableConcept + sourcePatientInfo: DocumentReferenceContextSourcePatientInfoReference + related: [DocumentReferenceContextRelatedReference] +} + +type DocumentReferenceRelatesToTargetReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type DocumentReferenceRelatesTo { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + target: DocumentReferenceRelatesToTargetReference +} + +type Dosage { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + text: String + additionalInstruction: [CodeableConcept] + patientInstruction: String + timing: Timing + asNeededBoolean: Boolean + asNeededCodeableConcept: CodeableConcept + site: CodeableConcept + route: CodeableConcept + method: CodeableConcept + doseAndRate: [DosageDoseAndRate] + maxDosePerPeriod: Ratio + maxDosePerAdministration: Quantity + maxDosePerLifetime: Quantity +} + +type DosageDoseAndRate { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + doseRange: Range + doseQuantity: Quantity + rateRatio: Ratio + rateRange: Range + rateQuantity: Quantity +} + +type ElementDefinitionDefaultValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ElementDefinitionFixedReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ElementDefinitionPatternReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ElementDefinition { + id: String + extension: [Extension] + modifierExtension: [Extension] + path: String + representation: [Code] + sliceName: String + sliceIsConstraining: Boolean + label: String + code: [Coding] + slicing: ElementDefinitionSlicing + short: String + definition: Markdown + comment: Markdown + requirements: Markdown + alias: [String] + min: Int + max: String + base: ElementDefinitionBase + contentReference: URI + type: [ElementDefinitionType] + defaultValueBase64Binary: Base64Binary + defaultValueBoolean: Boolean + defaultValueCanonical: Canonical + defaultValueCode: Code + defaultValueDate: Date + defaultValueDateTime: DateTime + defaultValueDecimal: Float + defaultValueId: ID + defaultValueInstant: Instant + defaultValueInteger: Int + defaultValueMarkdown: Markdown + defaultValueOid: OID + defaultValuePositiveInt: Int + defaultValueString: String + defaultValueTime: Time + defaultValueUnsignedInt: Int + defaultValueUri: URI + defaultValueUrl: URL + defaultValueUuid: UUID + defaultValueAddress: Address + defaultValueAge: Quantity + defaultValueAnnotation: Annotation + defaultValueAttachment: Attachment + defaultValueCodeableConcept: CodeableConcept + defaultValueCodeableReference: CodeableReference + defaultValueCoding: Coding + defaultValueContactPoint: ContactPoint + defaultValueCount: Quantity + defaultValueDistance: Quantity + defaultValueDuration: Quantity + defaultValueHumanName: HumanName + defaultValueIdentifier: Identifier + defaultValueMoney: Money + defaultValuePeriod: Period + defaultValueQuantity: Quantity + defaultValueRange: Range + defaultValueRatio: Ratio + defaultValueRatioRange: RatioRange + defaultValueReference: ElementDefinitionDefaultValueReferenceReference + defaultValueSampledData: SampledData + defaultValueSignature: Signature + defaultValueTiming: Timing + defaultValueContactDetail: ContactDetail + defaultValueContributor: Contributor + defaultValueDataRequirement: DataRequirement + defaultValueExpression: Expression + defaultValueParameterDefinition: ParameterDefinition + defaultValueRelatedArtifact: RelatedArtifact + defaultValueTriggerDefinition: TriggerDefinition + defaultValueUsageContext: UsageContext + defaultValueDosage: Dosage + meaningWhenMissing: Markdown + orderMeaning: String + fixedBase64Binary: Base64Binary + fixedBoolean: Boolean + fixedCanonical: Canonical + fixedCode: Code + fixedDate: Date + fixedDateTime: DateTime + fixedDecimal: Float + fixedId: ID + fixedInstant: Instant + fixedInteger: Int + fixedMarkdown: Markdown + fixedOid: OID + fixedPositiveInt: Int + fixedString: String + fixedTime: Time + fixedUnsignedInt: Int + fixedUri: URI + fixedUrl: URL + fixedUuid: UUID + fixedAddress: Address + fixedAge: Quantity + fixedAnnotation: Annotation + fixedAttachment: Attachment + fixedCodeableConcept: CodeableConcept + fixedCodeableReference: CodeableReference + fixedCoding: Coding + fixedContactPoint: ContactPoint + fixedCount: Quantity + fixedDistance: Quantity + fixedDuration: Quantity + fixedHumanName: HumanName + fixedIdentifier: Identifier + fixedMoney: Money + fixedPeriod: Period + fixedQuantity: Quantity + fixedRange: Range + fixedRatio: Ratio + fixedRatioRange: RatioRange + fixedReference: ElementDefinitionFixedReferenceReference + fixedSampledData: SampledData + fixedSignature: Signature + fixedTiming: Timing + fixedContactDetail: ContactDetail + fixedContributor: Contributor + fixedDataRequirement: DataRequirement + fixedExpression: Expression + fixedParameterDefinition: ParameterDefinition + fixedRelatedArtifact: RelatedArtifact + fixedTriggerDefinition: TriggerDefinition + fixedUsageContext: UsageContext + fixedDosage: Dosage + patternBase64Binary: Base64Binary + patternBoolean: Boolean + patternCanonical: Canonical + patternCode: Code + patternDate: Date + patternDateTime: DateTime + patternDecimal: Float + patternId: ID + patternInstant: Instant + patternInteger: Int + patternMarkdown: Markdown + patternOid: OID + patternPositiveInt: Int + patternString: String + patternTime: Time + patternUnsignedInt: Int + patternUri: URI + patternUrl: URL + patternUuid: UUID + patternAddress: Address + patternAge: Quantity + patternAnnotation: Annotation + patternAttachment: Attachment + patternCodeableConcept: CodeableConcept + patternCodeableReference: CodeableReference + patternCoding: Coding + patternContactPoint: ContactPoint + patternCount: Quantity + patternDistance: Quantity + patternDuration: Quantity + patternHumanName: HumanName + patternIdentifier: Identifier + patternMoney: Money + patternPeriod: Period + patternQuantity: Quantity + patternRange: Range + patternRatio: Ratio + patternRatioRange: RatioRange + patternReference: ElementDefinitionPatternReferenceReference + patternSampledData: SampledData + patternSignature: Signature + patternTiming: Timing + patternContactDetail: ContactDetail + patternContributor: Contributor + patternDataRequirement: DataRequirement + patternExpression: Expression + patternParameterDefinition: ParameterDefinition + patternRelatedArtifact: RelatedArtifact + patternTriggerDefinition: TriggerDefinition + patternUsageContext: UsageContext + patternDosage: Dosage + example: [ElementDefinitionExample] + minValueDate: Date + minValueDateTime: DateTime + minValueInstant: Instant + minValueTime: Time + minValueDecimal: Float + minValueInteger: Int + minValuePositiveInt: Int + minValueUnsignedInt: Int + minValueQuantity: Quantity + maxValueDate: Date + maxValueDateTime: DateTime + maxValueInstant: Instant + maxValueTime: Time + maxValueDecimal: Float + maxValueInteger: Int + maxValuePositiveInt: Int + maxValueUnsignedInt: Int + maxValueQuantity: Quantity + maxLength: Int + condition: [ID] + constraint: [ElementDefinitionConstraint] + mustSupport: Boolean + isModifier: Boolean + isModifierReason: String + isSummary: Boolean + binding: ElementDefinitionBinding + mapping: [ElementDefinitionMapping] +} + +type ElementDefinitionBase { + id: String + extension: [Extension] + modifierExtension: [Extension] + path: String + min: Int + max: String +} + +type ElementDefinitionBinding { + id: String + extension: [Extension] + modifierExtension: [Extension] + strength: Code + description: String + valueSet: Canonical +} + +type ElementDefinitionConstraint { + id: String + extension: [Extension] + modifierExtension: [Extension] + key: ID + requirements: String + severity: Code + human: String + expression: String + xpath: String + source: Canonical +} + +type ElementDefinitionDiscriminator { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + path: String +} + +type ElementDefinitionExampleValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ElementDefinitionExample { + id: String + extension: [Extension] + modifierExtension: [Extension] + label: String + valueBase64Binary: Base64Binary + valueBoolean: Boolean + valueCanonical: Canonical + valueCode: Code + valueDate: Date + valueDateTime: DateTime + valueDecimal: Float + valueId: ID + valueInstant: Instant + valueInteger: Int + valueMarkdown: Markdown + valueOid: OID + valuePositiveInt: Int + valueString: String + valueTime: Time + valueUnsignedInt: Int + valueUri: URI + valueUrl: URL + valueUuid: UUID + valueAddress: Address + valueAge: Quantity + valueAnnotation: Annotation + valueAttachment: Attachment + valueCodeableConcept: CodeableConcept + valueCodeableReference: CodeableReference + valueCoding: Coding + valueContactPoint: ContactPoint + valueCount: Quantity + valueDistance: Quantity + valueDuration: Quantity + valueHumanName: HumanName + valueIdentifier: Identifier + valueMoney: Money + valuePeriod: Period + valueQuantity: Quantity + valueRange: Range + valueRatio: Ratio + valueRatioRange: RatioRange + valueReference: ElementDefinitionExampleValueReferenceReference + valueSampledData: SampledData + valueSignature: Signature + valueTiming: Timing + valueContactDetail: ContactDetail + valueContributor: Contributor + valueDataRequirement: DataRequirement + valueExpression: Expression + valueParameterDefinition: ParameterDefinition + valueRelatedArtifact: RelatedArtifact + valueTriggerDefinition: TriggerDefinition + valueUsageContext: UsageContext + valueDosage: Dosage +} + +type ElementDefinitionMapping { + id: String + extension: [Extension] + modifierExtension: [Extension] + identity: ID + language: Code + map: String + comment: String +} + +type ElementDefinitionSlicing { + id: String + extension: [Extension] + modifierExtension: [Extension] + discriminator: [ElementDefinitionDiscriminator] + description: String + ordered: Boolean + rules: Code +} + +type ElementDefinitionType { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: URI + profile: [Canonical] + targetProfile: [Canonical] + aggregation: [Code] + versioning: Code +} + +type EncounterClassHistory { + id: String + extension: [Extension] + modifierExtension: [Extension] + class: Coding + period: Period +} + +union EncounterDiagnosisCondition = Condition | Procedure + +type EncounterDiagnosisConditionReference { + id: String + extension: [Extension] + reference: String + resource: EncounterDiagnosisCondition + type: URI + identifier: Identifier + display: String +} + +type EncounterDiagnosis { + id: String + extension: [Extension] + modifierExtension: [Extension] + condition: EncounterDiagnosisConditionReference + use: CodeableConcept + rank: Int +} + +union EncounterHospitalizationOrigin = Location | Organization + +type EncounterHospitalizationOriginReference { + id: String + extension: [Extension] + reference: String + resource: EncounterHospitalizationOrigin + type: URI + identifier: Identifier + display: String +} + +union EncounterHospitalizationDestination = Location | Organization + +type EncounterHospitalizationDestinationReference { + id: String + extension: [Extension] + reference: String + resource: EncounterHospitalizationDestination + type: URI + identifier: Identifier + display: String +} + +type EncounterHospitalization { + id: String + extension: [Extension] + modifierExtension: [Extension] + preAdmissionIdentifier: Identifier + origin: EncounterHospitalizationOriginReference + admitSource: CodeableConcept + reAdmission: CodeableConcept + dietPreference: [CodeableConcept] + specialCourtesy: [CodeableConcept] + specialArrangement: [CodeableConcept] + destination: EncounterHospitalizationDestinationReference + dischargeDisposition: CodeableConcept +} + +type EncounterLocationLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type EncounterLocation { + id: String + extension: [Extension] + modifierExtension: [Extension] + location: EncounterLocationLocationReference + status: Code + physicalType: CodeableConcept + period: Period +} + +union EncounterParticipantIndividual = Practitioner | PractitionerRole | RelatedPerson + +type EncounterParticipantIndividualReference { + id: String + extension: [Extension] + reference: String + resource: EncounterParticipantIndividual + type: URI + identifier: Identifier + display: String +} + +type EncounterParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: [CodeableConcept] + period: Period + individual: EncounterParticipantIndividualReference +} + +type EncounterStatusHistory { + id: String + extension: [Extension] + modifierExtension: [Extension] + status: Code + period: Period +} + +type EpisodeOfCareDiagnosisConditionReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCareDiagnosis { + id: String + extension: [Extension] + modifierExtension: [Extension] + condition: EpisodeOfCareDiagnosisConditionReference + role: CodeableConcept + rank: Int +} + +type EpisodeOfCareStatusHistory { + id: String + extension: [Extension] + modifierExtension: [Extension] + status: Code + period: Period +} + +type EvidenceAttributeEstimate { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + note: [Annotation] + type: CodeableConcept + quantity: Quantity + level: Float + range: Range + attributeEstimate: [EvidenceAttributeEstimate] +} + +type EvidenceCertainty { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + note: [Annotation] + type: CodeableConcept + rating: CodeableConcept + rater: String + subcomponent: [EvidenceCertainty] +} + +type EvidenceModelCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + value: Quantity + variable: [BackboneEvidenceVariable] + attributeEstimate: [EvidenceAttributeEstimate] +} + +type EvidenceReportCharacteristicValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type EvidenceReportCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + valueReference: EvidenceReportCharacteristicValueReferenceReference + valueCodeableConcept: CodeableConcept + valueBoolean: Boolean + valueQuantity: Quantity + valueRange: Range + exclude: Boolean + period: Period +} + +type EvidenceReportRelatesToTargetReferenceReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceReport + type: URI + identifier: Identifier + display: String +} + +type EvidenceReportRelatesTo { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + targetIdentifier: Identifier + targetReference: EvidenceReportRelatesToTargetReferenceReference +} + +type EvidenceReportSectionFocusReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union EvidenceReportSectionAuthor = Person | Device | Group | Organization + +type EvidenceReportSectionAuthorReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceReportSectionAuthor + type: URI + identifier: Identifier + display: String +} + +type EvidenceReportSectionEntryReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type EvidenceReportSection { + id: String + extension: [Extension] + modifierExtension: [Extension] + title: String + focus: CodeableConcept + focusReference: EvidenceReportSectionFocusReferenceReference + author: [EvidenceReportSectionAuthorReference] + text: Narrative + mode: Code + orderedBy: CodeableConcept + entryClassifier: [CodeableConcept] + entryReference: [EvidenceReportSectionEntryReferenceReference] + entryQuantity: [Quantity] + emptyReason: CodeableConcept + section: [EvidenceReportSection] +} + +type EvidenceReportSubject { + id: String + extension: [Extension] + modifierExtension: [Extension] + characteristic: [EvidenceReportCharacteristic] + note: [Annotation] +} + +type EvidenceSampleSize { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + note: [Annotation] + numberOfStudies: Int + numberOfParticipants: Int + knownDataCount: Int +} + +type EvidenceStatistic { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + note: [Annotation] + statisticType: CodeableConcept + category: CodeableConcept + quantity: Quantity + numberOfEvents: Int + numberAffected: Int + sampleSize: EvidenceSampleSize + attributeEstimate: [EvidenceAttributeEstimate] + modelCharacteristic: [EvidenceModelCharacteristic] +} + +union EvidenceVariableVariableDefinition = Group | EvidenceVariable + +type EvidenceVariableVariableDefinitionReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceVariableVariableDefinition + type: URI + identifier: Identifier + display: String +} + +type BackboneEvidenceVariable { + id: String + extension: [Extension] + modifierExtension: [Extension] + variableDefinition: EvidenceVariableVariableDefinitionReference + handling: Code + valueCategory: [CodeableConcept] + valueQuantity: [Quantity] + valueRange: [Range] +} + +type EvidenceVariableCategory { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueRange: Range +} + +union EvidenceVariableCharacteristicDefinitionReference = Group | EvidenceVariable + +type EvidenceVariableCharacteristicDefinitionReferenceReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceVariableCharacteristicDefinitionReference + type: URI + identifier: Identifier + display: String +} + +union EvidenceVariableCharacteristicDevice = Device | DeviceMetric + +type EvidenceVariableCharacteristicDeviceReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceVariableCharacteristicDevice + type: URI + identifier: Identifier + display: String +} + +type EvidenceVariableCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + definitionReference: EvidenceVariableCharacteristicDefinitionReferenceReference + definitionCanonical: Canonical + definitionCodeableConcept: CodeableConcept + definitionExpression: Expression + method: CodeableConcept + device: EvidenceVariableCharacteristicDeviceReference + exclude: Boolean + timeFromStart: EvidenceVariableTimeFromStart + groupMeasure: Code +} + +union EvidenceVariableDefinitionObserved = Group | EvidenceVariable + +type EvidenceVariableDefinitionObservedReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceVariableDefinitionObserved + type: URI + identifier: Identifier + display: String +} + +union EvidenceVariableDefinitionIntended = Group | EvidenceVariable + +type EvidenceVariableDefinitionIntendedReference { + id: String + extension: [Extension] + reference: String + resource: EvidenceVariableDefinitionIntended + type: URI + identifier: Identifier + display: String +} + +type EvidenceVariableDefinition { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: Markdown + note: [Annotation] + variableRole: CodeableConcept + observed: EvidenceVariableDefinitionObservedReference + intended: EvidenceVariableDefinitionIntendedReference + directnessMatch: CodeableConcept +} + +type EvidenceVariableTimeFromStart { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + quantity: Quantity + range: Range + note: [Annotation] +} + +type ExampleScenarioActor { + id: String + extension: [Extension] + modifierExtension: [Extension] + actorId: String + type: Code + name: String + description: Markdown +} + +type ExampleScenarioAlternative { + id: String + extension: [Extension] + modifierExtension: [Extension] + title: String + description: Markdown + step: [ExampleScenarioStep] +} + +type ExampleScenarioContainedInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + resourceId: String + versionId: String +} + +type ExampleScenarioInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + resourceId: String + resourceType: Code + name: String + description: Markdown + version: [ExampleScenarioVersion] + containedInstance: [ExampleScenarioContainedInstance] +} + +type ExampleScenarioOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + number: String + type: String + name: String + initiator: String + receiver: String + description: Markdown + initiatorActive: Boolean + receiverActive: Boolean + request: ExampleScenarioContainedInstance + response: ExampleScenarioContainedInstance +} + +type ExampleScenarioProcess { + id: String + extension: [Extension] + modifierExtension: [Extension] + title: String + description: Markdown + preConditions: Markdown + postConditions: Markdown + step: [ExampleScenarioStep] +} + +type ExampleScenarioStep { + id: String + extension: [Extension] + modifierExtension: [Extension] + process: [ExampleScenarioProcess] + pause: Boolean + operation: ExampleScenarioOperation + alternative: [ExampleScenarioAlternative] +} + +type ExampleScenarioVersion { + id: String + extension: [Extension] + modifierExtension: [Extension] + versionId: String + description: Markdown +} + +type ExplanationOfBenefitAccidentLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitAccident { + id: String + extension: [Extension] + modifierExtension: [Extension] + date: Date + type: CodeableConcept + locationAddress: Address + locationReference: ExplanationOfBenefitAccidentLocationReferenceReference +} + +union ExplanationOfBenefitAddItemProvider = Practitioner | PractitionerRole | Organization + +type ExplanationOfBenefitAddItemProviderReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitAddItemProvider + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitAddItemLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitAddItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemSequence: [Int] + detailSequence: [Int] + subDetailSequence: [Int] + provider: [ExplanationOfBenefitAddItemProviderReference] + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + servicedDate: Date + servicedPeriod: Period + locationCodeableConcept: CodeableConcept + locationAddress: Address + locationReference: ExplanationOfBenefitAddItemLocationReferenceReference + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + bodySite: CodeableConcept + subSite: [CodeableConcept] + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] + detail: [ExplanationOfBenefitDetail1] +} + +type ExplanationOfBenefitAdjudication { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + reason: CodeableConcept + amount: Money + value: Float +} + +type ExplanationOfBenefitBenefitBalance { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + excluded: Boolean + name: String + description: String + network: CodeableConcept + unit: CodeableConcept + term: CodeableConcept + financial: [ExplanationOfBenefitFinancial] +} + +union ExplanationOfBenefitCareTeamProvider = Practitioner | PractitionerRole | Organization + +type ExplanationOfBenefitCareTeamProviderReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitCareTeamProvider + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitCareTeam { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + provider: ExplanationOfBenefitCareTeamProviderReference + responsible: Boolean + role: CodeableConcept + qualification: CodeableConcept +} + +type ExplanationOfBenefitDetailUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ExplanationOfBenefitDetailUdiReference] + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] + subDetail: [ExplanationOfBenefitSubDetail] +} + +type ExplanationOfBenefitDetail1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + productOrService: CodeableConcept + modifier: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] + subDetail: [ExplanationOfBenefitSubDetail1] +} + +type ExplanationOfBenefitDiagnosisDiagnosisReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitDiagnosis { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + diagnosisCodeableConcept: CodeableConcept + diagnosisReference: ExplanationOfBenefitDiagnosisDiagnosisReferenceReference + type: [CodeableConcept] + onAdmission: CodeableConcept + packageCode: CodeableConcept +} + +type ExplanationOfBenefitFinancial { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + allowedUnsignedInt: Int + allowedString: String + allowedMoney: Money + usedUnsignedInt: Int + usedMoney: Money +} + +type ExplanationOfBenefitInsuranceCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitInsurance { + id: String + extension: [Extension] + modifierExtension: [Extension] + focal: Boolean + coverage: ExplanationOfBenefitInsuranceCoverageReference + preAuthRef: [String] +} + +type ExplanationOfBenefitItemLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitItemUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitItemEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + careTeamSequence: [Int] + diagnosisSequence: [Int] + procedureSequence: [Int] + informationSequence: [Int] + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + servicedDate: Date + servicedPeriod: Period + locationCodeableConcept: CodeableConcept + locationAddress: Address + locationReference: ExplanationOfBenefitItemLocationReferenceReference + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ExplanationOfBenefitItemUdiReference] + bodySite: CodeableConcept + subSite: [CodeableConcept] + encounter: [ExplanationOfBenefitItemEncounterReference] + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] + detail: [ExplanationOfBenefitDetail] +} + +union ExplanationOfBenefitPayeeParty = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson + +type ExplanationOfBenefitPayeePartyReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitPayeeParty + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitPayee { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + party: ExplanationOfBenefitPayeePartyReference +} + +type ExplanationOfBenefitPayment { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + adjustment: Money + adjustmentReason: CodeableConcept + date: Date + amount: Money + identifier: Identifier +} + +type ExplanationOfBenefitProcedureProcedureReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Procedure + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitProcedureUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitProcedure { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + type: [CodeableConcept] + date: DateTime + procedureCodeableConcept: CodeableConcept + procedureReference: ExplanationOfBenefitProcedureProcedureReferenceReference + udi: [ExplanationOfBenefitProcedureUdiReference] +} + +type ExplanationOfBenefitProcessNote { + id: String + extension: [Extension] + modifierExtension: [Extension] + number: Int + type: Code + text: String + language: CodeableConcept +} + +type ExplanationOfBenefitRelatedClaimReference { + id: String + extension: [Extension] + reference: String + resource: Claim + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitRelated { + id: String + extension: [Extension] + modifierExtension: [Extension] + claim: ExplanationOfBenefitRelatedClaimReference + relationship: CodeableConcept + reference: Identifier +} + +type ExplanationOfBenefitSubDetailUdiReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitSubDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + revenue: CodeableConcept + category: CodeableConcept + productOrService: CodeableConcept + modifier: [CodeableConcept] + programCode: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + udi: [ExplanationOfBenefitSubDetailUdiReference] + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] +} + +type ExplanationOfBenefitSubDetail1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + productOrService: CodeableConcept + modifier: [CodeableConcept] + quantity: Quantity + unitPrice: Money + factor: Float + net: Money + noteNumber: [Int] + adjudication: [ExplanationOfBenefitAdjudication] +} + +type ExplanationOfBenefitSupportingInfoValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitSupportingInfo { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + category: CodeableConcept + code: CodeableConcept + timingDate: Date + timingPeriod: Period + valueBoolean: Boolean + valueString: String + valueQuantity: Quantity + valueAttachment: Attachment + valueReference: ExplanationOfBenefitSupportingInfoValueReferenceReference + reason: Coding +} + +type ExplanationOfBenefitTotal { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + amount: Money +} + +type FamilyMemberHistoryCondition { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + outcome: CodeableConcept + contributedToDeath: Boolean + onsetAge: Quantity + onsetRange: Range + onsetPeriod: Period + onsetString: String + note: [Annotation] +} + +type GoalTarget { + id: String + extension: [Extension] + modifierExtension: [Extension] + measure: CodeableConcept + detailQuantity: Quantity + detailRange: Range + detailCodeableConcept: CodeableConcept + detailString: String + detailBoolean: Boolean + detailInteger: Int + detailRatio: Ratio + dueDate: Date + dueDuration: Quantity +} + +type GraphDefinitionCompartment { + id: String + extension: [Extension] + modifierExtension: [Extension] + use: Code + code: Code + rule: Code + expression: String + description: String +} + +type GraphDefinitionLink { + id: String + extension: [Extension] + modifierExtension: [Extension] + path: String + sliceName: String + min: Int + max: String + description: String + target: [GraphDefinitionTarget] +} + +type GraphDefinitionTarget { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + params: String + profile: Canonical + compartment: [GraphDefinitionCompartment] + link: [GraphDefinitionLink] +} + +type GroupCharacteristicValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type GroupCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + valueCodeableConcept: CodeableConcept + valueBoolean: Boolean + valueQuantity: Quantity + valueRange: Range + valueReference: GroupCharacteristicValueReferenceReference + exclude: Boolean + period: Period +} + +union GroupMemberEntity = Patient | RelatedPerson | Practitioner | PractitionerRole | Device | Medication | Substance | Group + +type GroupMemberEntityReference { + id: String + extension: [Extension] + reference: String + resource: GroupMemberEntity + type: URI + identifier: Identifier + display: String +} + +type GroupMember { + id: String + extension: [Extension] + modifierExtension: [Extension] + entity: GroupMemberEntityReference + period: Period + inactive: Boolean +} + +type HealthcareServiceAvailableTime { + id: String + extension: [Extension] + modifierExtension: [Extension] + daysOfWeek: [Code] + allDay: Boolean + availableStartTime: Time + availableEndTime: Time +} + +type HealthcareServiceEligibility { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + comment: Markdown +} + +type HealthcareServiceNotAvailable { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + during: Period +} + +type ImagingStudyInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + uid: ID + sopClass: Coding + number: Int + title: String +} + +union ImagingStudyPerformerActor = Practitioner | PractitionerRole | Organization | CareTeam | Patient | Device | RelatedPerson + +type ImagingStudyPerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudyPerformerActor + type: URI + identifier: Identifier + display: String +} + +type ImagingStudyPerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: ImagingStudyPerformerActorReference +} + +type ImagingStudySeriesEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type ImagingStudySeriesSpecimenReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +type ImagingStudySeries { + id: String + extension: [Extension] + modifierExtension: [Extension] + uid: ID + number: Int + modality: Coding + description: String + numberOfInstances: Int + endpoint: [ImagingStudySeriesEndpointReference] + bodySite: Coding + laterality: Coding + specimen: [ImagingStudySeriesSpecimenReference] + started: DateTime + performer: [ImagingStudyPerformer] + instance: [ImagingStudyInstance] +} + +type ImmunizationEducation { + id: String + extension: [Extension] + modifierExtension: [Extension] + documentType: String + reference: URI + publicationDate: DateTime + presentationDate: DateTime +} + +union ImmunizationPerformerActor = Practitioner | PractitionerRole | Organization + +type ImmunizationPerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: ImmunizationPerformerActor + type: URI + identifier: Identifier + display: String +} + +type ImmunizationPerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: ImmunizationPerformerActorReference +} + +type ImmunizationProtocolAppliedAuthorityReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ImmunizationProtocolApplied { + id: String + extension: [Extension] + modifierExtension: [Extension] + series: String + authority: ImmunizationProtocolAppliedAuthorityReference + targetDisease: [CodeableConcept] + doseNumberPositiveInt: Int + doseNumberString: String + seriesDosesPositiveInt: Int + seriesDosesString: String +} + +type ImmunizationReactionDetailReference { + id: String + extension: [Extension] + reference: String + resource: Observation + type: URI + identifier: Identifier + display: String +} + +type ImmunizationReaction { + id: String + extension: [Extension] + modifierExtension: [Extension] + date: DateTime + detail: ImmunizationReactionDetailReference + reported: Boolean +} + +type ImmunizationRecommendationDateCriterion { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + value: DateTime +} + +union ImmunizationRecommendationRecommendationSupportingImmunization = Immunization | ImmunizationEvaluation + +type ImmunizationRecommendationRecommendationSupportingImmunizationReference { + id: String + extension: [Extension] + reference: String + resource: ImmunizationRecommendationRecommendationSupportingImmunization + type: URI + identifier: Identifier + display: String +} + +type ImmunizationRecommendationRecommendationSupportingPatientInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ImmunizationRecommendationRecommendation { + id: String + extension: [Extension] + modifierExtension: [Extension] + vaccineCode: [CodeableConcept] + targetDisease: CodeableConcept + contraindicatedVaccineCode: [CodeableConcept] + forecastStatus: CodeableConcept + forecastReason: [CodeableConcept] + dateCriterion: [ImmunizationRecommendationDateCriterion] + description: String + series: String + doseNumberPositiveInt: Int + doseNumberString: String + seriesDosesPositiveInt: Int + seriesDosesString: String + supportingImmunization: [ImmunizationRecommendationRecommendationSupportingImmunizationReference] + supportingPatientInformation: [ImmunizationRecommendationRecommendationSupportingPatientInformationReference] +} + +type ImplementationGuideDefinition { + id: String + extension: [Extension] + modifierExtension: [Extension] + grouping: [ImplementationGuideGrouping] + resource: [ImplementationGuideResource] + page: ImplementationGuidePage + parameter: [ImplementationGuideParameter] + template: [ImplementationGuideTemplate] +} + +type ImplementationGuideDependsOn { + id: String + extension: [Extension] + modifierExtension: [Extension] + uri: Canonical + packageId: ID + version: String +} + +type ImplementationGuideGlobal { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + profile: Canonical +} + +type ImplementationGuideGrouping { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + description: String +} + +type ImplementationGuideManifest { + id: String + extension: [Extension] + modifierExtension: [Extension] + rendering: URL + resource: [ImplementationGuideResource1] + page: [ImplementationGuidePage1] + image: [String] + other: [String] +} + +type ImplementationGuidePageNameReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Binary + type: URI + identifier: Identifier + display: String +} + +type ImplementationGuidePage { + id: String + extension: [Extension] + modifierExtension: [Extension] + nameUrl: URL + nameReference: ImplementationGuidePageNameReferenceReference + title: String + generation: Code + page: [ImplementationGuidePage] +} + +type ImplementationGuidePage1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + title: String + anchor: [String] +} + +type ImplementationGuideParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + value: String +} + +type ImplementationGuideResourceReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ImplementationGuideResource { + id: String + extension: [Extension] + modifierExtension: [Extension] + reference: ImplementationGuideResourceReferenceReference + fhirVersion: [Code] + name: String + description: String + exampleBoolean: Boolean + exampleCanonical: Canonical + groupingId: ID +} + +type ImplementationGuideResource1ReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ImplementationGuideResource1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + reference: ImplementationGuideResource1ReferenceReference + exampleBoolean: Boolean + exampleCanonical: Canonical + relativePath: URL +} + +type ImplementationGuideTemplate { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + source: String + scope: String +} + +type IngredientManufacturerManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type IngredientManufacturer { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: Code + manufacturer: IngredientManufacturerManufacturerReference +} + +type IngredientReferenceStrengthSubstanceReference { + id: String + extension: [Extension] + reference: String + resource: SubstanceDefinition + type: URI + identifier: Identifier + display: String +} + +type IngredientReferenceStrength { + id: String + extension: [Extension] + modifierExtension: [Extension] + substance: IngredientReferenceStrengthSubstanceReference + strengthRatio: Ratio + strengthRatioRange: RatioRange + measurementPoint: String + country: [CodeableConcept] +} + +type IngredientStrength { + id: String + extension: [Extension] + modifierExtension: [Extension] + presentationRatio: Ratio + presentationRatioRange: RatioRange + textPresentation: String + concentrationRatio: Ratio + concentrationRatioRange: RatioRange + textConcentration: String + measurementPoint: String + country: [CodeableConcept] + referenceStrength: [IngredientReferenceStrength] +} + +type IngredientSubstanceCodeReference { + id: String + extension: [Extension] + reference: String + resource: SubstanceDefinition + type: URI + identifier: Identifier + display: String +} + +type IngredientSubstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: IngredientSubstanceCodeReference + strength: [IngredientStrength] +} + +type InsurancePlanBenefit { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + requirement: String + limit: [InsurancePlanLimit] +} + +type InsurancePlanBenefit1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + cost: [InsurancePlanCost] +} + +type InsurancePlanContact { + id: String + extension: [Extension] + modifierExtension: [Extension] + purpose: CodeableConcept + name: HumanName + telecom: [ContactPoint] + address: Address +} + +type InsurancePlanCost { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + applicability: CodeableConcept + qualifiers: [CodeableConcept] + value: Quantity +} + +type InsurancePlanCoverageNetworkReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanCoverage { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + network: [InsurancePlanCoverageNetworkReference] + benefit: [InsurancePlanBenefit] +} + +type InsurancePlanGeneralCost { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + groupSize: Int + cost: Money + comment: String +} + +type InsurancePlanLimit { + id: String + extension: [Extension] + modifierExtension: [Extension] + value: Quantity + code: CodeableConcept +} + +type InsurancePlanPlanCoverageAreaReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanPlanNetworkReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanPlan { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: CodeableConcept + coverageArea: [InsurancePlanPlanCoverageAreaReference] + network: [InsurancePlanPlanNetworkReference] + generalCost: [InsurancePlanGeneralCost] + specificCost: [InsurancePlanSpecificCost] +} + +type InsurancePlanSpecificCost { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + benefit: [InsurancePlanBenefit1] +} + +type InvoiceLineItemChargeItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItem + type: URI + identifier: Identifier + display: String +} + +type InvoiceLineItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + sequence: Int + chargeItemReference: InvoiceLineItemChargeItemReferenceReference + chargeItemCodeableConcept: CodeableConcept + priceComponent: [InvoicePriceComponent] +} + +union InvoiceParticipantActor = Practitioner | Organization | Patient | PractitionerRole | Device | RelatedPerson + +type InvoiceParticipantActorReference { + id: String + extension: [Extension] + reference: String + resource: InvoiceParticipantActor + type: URI + identifier: Identifier + display: String +} + +type InvoiceParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: CodeableConcept + actor: InvoiceParticipantActorReference +} + +type InvoicePriceComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + code: CodeableConcept + factor: Float + amount: Money +} + +type LinkageItemResourceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type LinkageItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + resource: LinkageItemResourceReference +} + +type ListEntryItemReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ListEntry { + id: String + extension: [Extension] + modifierExtension: [Extension] + flag: CodeableConcept + deleted: Boolean + date: DateTime + item: ListEntryItemReference +} + +type LocationHoursOfOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + daysOfWeek: [Code] + allDay: Boolean + openingTime: Time + closingTime: Time +} + +type LocationPosition { + id: String + extension: [Extension] + modifierExtension: [Extension] + longitude: Float + latitude: Float + altitude: Float +} + +type ManufacturedItemDefinitionProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueDate: Date + valueBoolean: Boolean + valueAttachment: Attachment +} + +type MarketingStatus { + id: String + extension: [Extension] + modifierExtension: [Extension] + country: CodeableConcept + jurisdiction: CodeableConcept + status: CodeableConcept + dateRange: Period + restoreDate: DateTime +} + +type MeasureComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + description: String + criteria: Expression +} + +type MeasureGroup { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + description: String + population: [MeasurePopulation] + stratifier: [MeasureStratifier] +} + +type MeasurePopulation { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + description: String + criteria: Expression +} + +type MeasureReportComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + value: CodeableConcept +} + +type MeasureReportGroup { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + population: [MeasureReportPopulation] + measureScore: Quantity + stratifier: [MeasureReportStratifier] +} + +type MeasureReportPopulationSubjectResultsReference { + id: String + extension: [Extension] + reference: String + resource: List + type: URI + identifier: Identifier + display: String +} + +type MeasureReportPopulation { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + count: Int + subjectResults: MeasureReportPopulationSubjectResultsReference +} + +type MeasureReportPopulation1SubjectResultsReference { + id: String + extension: [Extension] + reference: String + resource: List + type: URI + identifier: Identifier + display: String +} + +type MeasureReportPopulation1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + count: Int + subjectResults: MeasureReportPopulation1SubjectResultsReference +} + +type MeasureReportStratifier { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: [CodeableConcept] + stratum: [MeasureReportStratum] +} + +type MeasureReportStratum { + id: String + extension: [Extension] + modifierExtension: [Extension] + value: CodeableConcept + component: [MeasureReportComponent] + population: [MeasureReportPopulation1] + measureScore: Quantity +} + +type MeasureStratifier { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + description: String + criteria: Expression + component: [MeasureComponent] +} + +type MeasureSupplementalData { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + usage: [CodeableConcept] + description: String + criteria: Expression +} + +type MedicationAdministrationDosage { + id: String + extension: [Extension] + modifierExtension: [Extension] + text: String + site: CodeableConcept + route: CodeableConcept + method: CodeableConcept + dose: Quantity + rateRatio: Ratio + rateQuantity: Quantity +} + +union MedicationAdministrationPerformerActor = Practitioner | PractitionerRole | Patient | RelatedPerson | Device + +type MedicationAdministrationPerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: MedicationAdministrationPerformerActor + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationPerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: MedicationAdministrationPerformerActorReference +} + +type MedicationBatch { + id: String + extension: [Extension] + modifierExtension: [Extension] + lotNumber: String + expirationDate: DateTime +} + +union MedicationDispensePerformerActor = Practitioner | PractitionerRole | Organization | Patient | Device | RelatedPerson + +type MedicationDispensePerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: MedicationDispensePerformerActor + type: URI + identifier: Identifier + display: String +} + +type MedicationDispensePerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: MedicationDispensePerformerActorReference +} + +union MedicationDispenseSubstitutionResponsibleParty = Practitioner | PractitionerRole + +type MedicationDispenseSubstitutionResponsiblePartyReference { + id: String + extension: [Extension] + reference: String + resource: MedicationDispenseSubstitutionResponsibleParty + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseSubstitution { + id: String + extension: [Extension] + modifierExtension: [Extension] + wasSubstituted: Boolean + type: CodeableConcept + reason: [CodeableConcept] + responsibleParty: [MedicationDispenseSubstitutionResponsiblePartyReference] +} + +union MedicationIngredientItemReference = Substance | Medication + +type MedicationIngredientItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationIngredientItemReference + type: URI + identifier: Identifier + display: String +} + +type MedicationIngredient { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemCodeableConcept: CodeableConcept + itemReference: MedicationIngredientItemReferenceReference + isActive: Boolean + strength: Ratio +} + +type MedicationKnowledgeAdministrationGuidelinesIndicationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeAdministrationGuidelines { + id: String + extension: [Extension] + modifierExtension: [Extension] + dosage: [MedicationKnowledgeDosage] + indicationCodeableConcept: CodeableConcept + indicationReference: MedicationKnowledgeAdministrationGuidelinesIndicationReferenceReference + patientCharacteristics: [MedicationKnowledgePatientCharacteristics] +} + +type MedicationKnowledgeCost { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + source: String + cost: Money +} + +type MedicationKnowledgeDosage { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + dosage: [Dosage] +} + +type MedicationKnowledgeDrugCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueString: String + valueQuantity: Quantity + valueBase64Binary: Base64Binary +} + +type MedicationKnowledgeIngredientItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeIngredient { + id: String + extension: [Extension] + modifierExtension: [Extension] + itemCodeableConcept: CodeableConcept + itemReference: MedicationKnowledgeIngredientItemReferenceReference + isActive: Boolean + strength: Ratio +} + +type MedicationKnowledgeKinetics { + id: String + extension: [Extension] + modifierExtension: [Extension] + areaUnderCurve: [Quantity] + lethalDose50: [Quantity] + halfLifePeriod: Quantity +} + +type MedicationKnowledgeMaxDispense { + id: String + extension: [Extension] + modifierExtension: [Extension] + quantity: Quantity + period: Quantity +} + +type MedicationKnowledgeMedicineClassification { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + classification: [CodeableConcept] +} + +type MedicationKnowledgeMonitoringProgram { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + name: String +} + +union MedicationKnowledgeMonographSource = DocumentReference | Media + +type MedicationKnowledgeMonographSourceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationKnowledgeMonographSource + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeMonograph { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + source: MedicationKnowledgeMonographSourceReference +} + +type MedicationKnowledgePackaging { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + quantity: Quantity +} + +type MedicationKnowledgePatientCharacteristics { + id: String + extension: [Extension] + modifierExtension: [Extension] + characteristicCodeableConcept: CodeableConcept + characteristicQuantity: Quantity + value: [String] +} + +type MedicationKnowledgeRegulatoryRegulatoryAuthorityReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeRegulatory { + id: String + extension: [Extension] + modifierExtension: [Extension] + regulatoryAuthority: MedicationKnowledgeRegulatoryRegulatoryAuthorityReference + substitution: [MedicationKnowledgeSubstitution] + schedule: [MedicationKnowledgeSchedule] + maxDispense: MedicationKnowledgeMaxDispense +} + +type MedicationKnowledgeRelatedMedicationKnowledgeReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationKnowledge + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeRelatedMedicationKnowledge { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + reference: [MedicationKnowledgeRelatedMedicationKnowledgeReferenceReference] +} + +type MedicationKnowledgeSchedule { + id: String + extension: [Extension] + modifierExtension: [Extension] + schedule: CodeableConcept +} + +type MedicationKnowledgeSubstitution { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + allowed: Boolean +} + +type MedicationRequestDispenseRequestPerformerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestDispenseRequest { + id: String + extension: [Extension] + modifierExtension: [Extension] + initialFill: MedicationRequestInitialFill + dispenseInterval: Quantity + validityPeriod: Period + numberOfRepeatsAllowed: Int + quantity: Quantity + expectedSupplyDuration: Quantity + performer: MedicationRequestDispenseRequestPerformerReference +} + +type MedicationRequestInitialFill { + id: String + extension: [Extension] + modifierExtension: [Extension] + quantity: Quantity + duration: Quantity +} + +type MedicationRequestSubstitution { + id: String + extension: [Extension] + modifierExtension: [Extension] + allowedBoolean: Boolean + allowedCodeableConcept: CodeableConcept + reason: CodeableConcept +} + +type MedicinalProductDefinitionCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueDate: Date + valueBoolean: Boolean + valueAttachment: Attachment +} + +union MedicinalProductDefinitionContactContact = Organization | PractitionerRole + +type MedicinalProductDefinitionContactContactReference { + id: String + extension: [Extension] + reference: String + resource: MedicinalProductDefinitionContactContact + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionContact { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + contact: MedicinalProductDefinitionContactContactReference +} + +type MedicinalProductDefinitionCountryLanguage { + id: String + extension: [Extension] + modifierExtension: [Extension] + country: CodeableConcept + jurisdiction: CodeableConcept + language: CodeableConcept +} + +type MedicinalProductDefinitionCrossReferenceProductReference { + id: String + extension: [Extension] + reference: String + resource: MedicinalProductDefinition + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionCrossReference { + id: String + extension: [Extension] + modifierExtension: [Extension] + product: MedicinalProductDefinitionCrossReferenceProductReference + type: CodeableConcept +} + +type MedicinalProductDefinitionName { + id: String + extension: [Extension] + modifierExtension: [Extension] + productName: String + type: CodeableConcept + namePart: [MedicinalProductDefinitionNamePart] + countryLanguage: [MedicinalProductDefinitionCountryLanguage] +} + +type MedicinalProductDefinitionNamePart { + id: String + extension: [Extension] + modifierExtension: [Extension] + part: String + type: CodeableConcept +} + +union MedicinalProductDefinitionOperationType = ActivityDefinition | PlanDefinition + +type MedicinalProductDefinitionOperationTypeReference { + id: String + extension: [Extension] + reference: String + resource: MedicinalProductDefinitionOperationType + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionOperationOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: MedicinalProductDefinitionOperationTypeReference + effectiveDate: Period + organization: [MedicinalProductDefinitionOperationOrganizationReference] + confidentialityIndicator: CodeableConcept +} + +type MessageDefinitionAllowedResponse { + id: String + extension: [Extension] + modifierExtension: [Extension] + message: Canonical + situation: Markdown +} + +type MessageDefinitionFocus { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + profile: Canonical + min: Int + max: String +} + +type MessageHeaderDestinationTargetReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +union MessageHeaderDestinationReceiver = Practitioner | PractitionerRole | Organization + +type MessageHeaderDestinationReceiverReference { + id: String + extension: [Extension] + reference: String + resource: MessageHeaderDestinationReceiver + type: URI + identifier: Identifier + display: String +} + +type MessageHeaderDestination { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + target: MessageHeaderDestinationTargetReference + endpoint: URL + receiver: MessageHeaderDestinationReceiverReference +} + +type MessageHeaderResponseDetailsReference { + id: String + extension: [Extension] + reference: String + resource: OperationOutcome + type: URI + identifier: Identifier + display: String +} + +type MessageHeaderResponse { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: ID + code: Code + details: MessageHeaderResponseDetailsReference +} + +type MessageHeaderSource { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + software: String + version: String + contact: ContactPoint + endpoint: URL +} + +type MolecularSequenceInner { + id: String + extension: [Extension] + modifierExtension: [Extension] + start: Int + end: Int +} + +type MolecularSequenceOuter { + id: String + extension: [Extension] + modifierExtension: [Extension] + start: Int + end: Int +} + +type MolecularSequenceQuality { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + standardSequence: CodeableConcept + start: Int + end: Int + score: Quantity + method: CodeableConcept + truthTP: Float + queryTP: Float + truthFN: Float + queryFP: Float + gtFP: Float + precision: Float + recall: Float + fScore: Float + roc: MolecularSequenceRoc +} + +type MolecularSequenceReferenceSeqReferenceSeqPointerReference { + id: String + extension: [Extension] + reference: String + resource: MolecularSequence + type: URI + identifier: Identifier + display: String +} + +type MolecularSequenceReferenceSeq { + id: String + extension: [Extension] + modifierExtension: [Extension] + chromosome: CodeableConcept + genomeBuild: String + orientation: Code + referenceSeqId: CodeableConcept + referenceSeqPointer: MolecularSequenceReferenceSeqReferenceSeqPointerReference + referenceSeqString: String + strand: Code + windowStart: Int + windowEnd: Int +} + +type MolecularSequenceRepository { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + url: URI + name: String + datasetId: String + variantsetId: String + readsetId: String +} + +type MolecularSequenceRoc { + id: String + extension: [Extension] + modifierExtension: [Extension] + score: [Int] + numTP: [Int] + numFP: [Int] + numFN: [Int] + precision: [Float] + sensitivity: [Float] + fMeasure: [Float] +} + +type MolecularSequenceStructureVariant { + id: String + extension: [Extension] + modifierExtension: [Extension] + variantType: CodeableConcept + exact: Boolean + length: Int + outer: MolecularSequenceOuter + inner: MolecularSequenceInner +} + +type MolecularSequenceVariantVariantPointerReference { + id: String + extension: [Extension] + reference: String + resource: Observation + type: URI + identifier: Identifier + display: String +} + +type MolecularSequenceVariant { + id: String + extension: [Extension] + modifierExtension: [Extension] + start: Int + end: Int + observedAllele: String + referenceAllele: String + cigar: String + variantPointer: MolecularSequenceVariantVariantPointerReference +} + +type NamingSystemUniqueId { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + value: String + preferred: Boolean + comment: String + period: Period +} + +type NutritionOrderAdministration { + id: String + extension: [Extension] + modifierExtension: [Extension] + schedule: Timing + quantity: Quantity + rateQuantity: Quantity + rateRatio: Ratio +} + +type NutritionOrderEnteralFormula { + id: String + extension: [Extension] + modifierExtension: [Extension] + baseFormulaType: CodeableConcept + baseFormulaProductName: String + additiveType: CodeableConcept + additiveProductName: String + caloricDensity: Quantity + routeofAdministration: CodeableConcept + administration: [NutritionOrderAdministration] + maxVolumeToDeliver: Quantity + administrationInstruction: String +} + +type NutritionOrderNutrient { + id: String + extension: [Extension] + modifierExtension: [Extension] + modifier: CodeableConcept + amount: Quantity +} + +type NutritionOrderOralDiet { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: [CodeableConcept] + schedule: [Timing] + nutrient: [NutritionOrderNutrient] + texture: [NutritionOrderTexture] + fluidConsistencyType: [CodeableConcept] + instruction: String +} + +type NutritionOrderSupplement { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + productName: String + schedule: [Timing] + quantity: Quantity + instruction: String +} + +type NutritionOrderTexture { + id: String + extension: [Extension] + modifierExtension: [Extension] + modifier: CodeableConcept + foodType: CodeableConcept +} + +type NutritionProductIngredientItemReference { + id: String + extension: [Extension] + reference: String + resource: NutritionProduct + type: URI + identifier: Identifier + display: String +} + +type NutritionProductIngredient { + id: String + extension: [Extension] + modifierExtension: [Extension] + item: NutritionProductIngredientItemReference + amount: [Ratio] +} + +type NutritionProductInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + quantity: Quantity + identifier: [Identifier] + lotNumber: String + expiry: DateTime + useBy: DateTime +} + +type NutritionProductNutrientItemReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type NutritionProductNutrient { + id: String + extension: [Extension] + modifierExtension: [Extension] + item: NutritionProductNutrientItemReference + amount: [Ratio] +} + +type NutritionProductProductCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueString: String + valueQuantity: Quantity + valueBase64Binary: Base64Binary + valueAttachment: Attachment + valueBoolean: Boolean +} + +type ObservationComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + valueQuantity: Quantity + valueCodeableConcept: CodeableConcept + valueString: String + valueBoolean: Boolean + valueInteger: Int + valueRange: Range + valueRatio: Ratio + valueSampledData: SampledData + valueTime: Time + valueDateTime: DateTime + valuePeriod: Period + dataAbsentReason: CodeableConcept + interpretation: [CodeableConcept] + referenceRange: [ObservationReferenceRange] +} + +type ObservationDefinitionQualifiedInterval { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: Code + range: Range + context: CodeableConcept + appliesTo: [CodeableConcept] + gender: Code + age: Range + gestationalAge: Range + condition: String +} + +type ObservationDefinitionQuantitativeDetails { + id: String + extension: [Extension] + modifierExtension: [Extension] + customaryUnit: CodeableConcept + unit: CodeableConcept + conversionFactor: Float + decimalPrecision: Int +} + +type ObservationReferenceRange { + id: String + extension: [Extension] + modifierExtension: [Extension] + low: Quantity + high: Quantity + type: CodeableConcept + appliesTo: [CodeableConcept] + age: Range + text: String +} + +type OperationDefinitionBinding { + id: String + extension: [Extension] + modifierExtension: [Extension] + strength: Code + valueSet: Canonical +} + +type OperationDefinitionOverload { + id: String + extension: [Extension] + modifierExtension: [Extension] + parameterName: [String] + comment: String +} + +type OperationDefinitionParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: Code + use: Code + min: Int + max: String + documentation: String + type: Code + targetProfile: [Canonical] + searchType: Code + binding: OperationDefinitionBinding + referencedFrom: [OperationDefinitionReferencedFrom] + part: [OperationDefinitionParameter] +} + +type OperationDefinitionReferencedFrom { + id: String + extension: [Extension] + modifierExtension: [Extension] + source: String + sourceId: String +} + +type OperationOutcomeIssue { + id: String + extension: [Extension] + modifierExtension: [Extension] + severity: Code + code: Code + details: CodeableConcept + diagnostics: String + location: [String] + expression: [String] +} + +type OrganizationContact { + id: String + extension: [Extension] + modifierExtension: [Extension] + purpose: CodeableConcept + name: HumanName + telecom: [ContactPoint] + address: Address +} + +union PackagedProductDefinitionContainedItemItem = ManufacturedItemDefinition | DeviceDefinition | PackagedProductDefinition | BiologicallyDerivedProduct | NutritionProduct + +type PackagedProductDefinitionContainedItemItemReference { + id: String + extension: [Extension] + reference: String + resource: PackagedProductDefinitionContainedItemItem + type: URI + identifier: Identifier + display: String +} + +type PackagedProductDefinitionContainedItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + item: PackagedProductDefinitionContainedItemItemReference + amount: Quantity +} + +type PackagedProductDefinitionLegalStatusOfSupply { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + jurisdiction: CodeableConcept +} + +type PackagedProductDefinitionPackageManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PackagedProductDefinitionPackage { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: CodeableConcept + quantity: Int + material: [CodeableConcept] + alternateMaterial: [CodeableConcept] + shelfLifeStorage: [PackagedProductDefinitionShelfLifeStorage] + manufacturer: [PackagedProductDefinitionPackageManufacturerReference] + property: [PackagedProductDefinitionProperty] + containedItem: [PackagedProductDefinitionContainedItem] + package: [PackagedProductDefinitionPackage] +} + +type PackagedProductDefinitionProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueDate: Date + valueBoolean: Boolean + valueAttachment: Attachment +} + +type PackagedProductDefinitionShelfLifeStorage { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + periodDuration: Quantity + periodString: String + specialPrecautionsForStorage: [CodeableConcept] +} + +type ParametersParameterValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ParametersParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + valueBase64Binary: Base64Binary + valueBoolean: Boolean + valueCanonical: Canonical + valueCode: Code + valueDate: Date + valueDateTime: DateTime + valueDecimal: Float + valueId: ID + valueInstant: Instant + valueInteger: Int + valueMarkdown: Markdown + valueOid: OID + valuePositiveInt: Int + valueString: String + valueTime: Time + valueUnsignedInt: Int + valueUri: URI + valueUrl: URL + valueUuid: UUID + valueAddress: Address + valueAge: Quantity + valueAnnotation: Annotation + valueAttachment: Attachment + valueCodeableConcept: CodeableConcept + valueCoding: Coding + valueContactPoint: ContactPoint + valueCount: Quantity + valueDistance: Quantity + valueDuration: Quantity + valueHumanName: HumanName + valueIdentifier: Identifier + valueMoney: Money + valuePeriod: Period + valueQuantity: Quantity + valueRange: Range + valueRatio: Ratio + valueReference: ParametersParameterValueReferenceReference + valueSampledData: SampledData + valueSignature: Signature + valueTiming: Timing + valueContactDetail: ContactDetail + valueContributor: Contributor + valueDataRequirement: DataRequirement + valueExpression: Expression + valueParameterDefinition: ParameterDefinition + valueRelatedArtifact: RelatedArtifact + valueTriggerDefinition: TriggerDefinition + valueUsageContext: UsageContext + valueDosage: Dosage + valueMeta: Meta + resource: Resource + part: [ParametersParameter] +} + +type PatientCommunication { + id: String + extension: [Extension] + modifierExtension: [Extension] + language: CodeableConcept + preferred: Boolean +} + +type PatientContactOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PatientContact { + id: String + extension: [Extension] + modifierExtension: [Extension] + relationship: [CodeableConcept] + name: HumanName + telecom: [ContactPoint] + address: Address + gender: Code + organization: PatientContactOrganizationReference + period: Period +} + +union PatientLinkOther = Patient | RelatedPerson + +type PatientLinkOtherReference { + id: String + extension: [Extension] + reference: String + resource: PatientLinkOther + type: URI + identifier: Identifier + display: String +} + +type PatientLink { + id: String + extension: [Extension] + modifierExtension: [Extension] + other: PatientLinkOtherReference + type: Code +} + +type PaymentReconciliationDetailRequestReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union PaymentReconciliationDetailSubmitter = Practitioner | PractitionerRole | Organization + +type PaymentReconciliationDetailSubmitterReference { + id: String + extension: [Extension] + reference: String + resource: PaymentReconciliationDetailSubmitter + type: URI + identifier: Identifier + display: String +} + +type PaymentReconciliationDetailResponseReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type PaymentReconciliationDetailResponsibleReference { + id: String + extension: [Extension] + reference: String + resource: PractitionerRole + type: URI + identifier: Identifier + display: String +} + +union PaymentReconciliationDetailPayee = Practitioner | PractitionerRole | Organization + +type PaymentReconciliationDetailPayeeReference { + id: String + extension: [Extension] + reference: String + resource: PaymentReconciliationDetailPayee + type: URI + identifier: Identifier + display: String +} + +type PaymentReconciliationDetail { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + predecessor: Identifier + type: CodeableConcept + request: PaymentReconciliationDetailRequestReference + submitter: PaymentReconciliationDetailSubmitterReference + response: PaymentReconciliationDetailResponseReference + date: Date + responsible: PaymentReconciliationDetailResponsibleReference + payee: PaymentReconciliationDetailPayeeReference + amount: Money +} + +type PaymentReconciliationProcessNote { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + text: String +} + +union PersonLinkTarget = Patient | Practitioner | RelatedPerson | Person + +type PersonLinkTargetReference { + id: String + extension: [Extension] + reference: String + resource: PersonLinkTarget + type: URI + identifier: Identifier + display: String +} + +type PersonLink { + id: String + extension: [Extension] + modifierExtension: [Extension] + target: PersonLinkTargetReference + assurance: Code +} + +type PlanDefinitionActionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type PlanDefinitionAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + prefix: String + title: String + description: String + textEquivalent: String + priority: Code + code: [CodeableConcept] + reason: [CodeableConcept] + documentation: [RelatedArtifact] + goalId: [ID] + subjectCodeableConcept: CodeableConcept + subjectReference: PlanDefinitionActionSubjectReferenceReference + subjectCanonical: Canonical + trigger: [TriggerDefinition] + condition: [PlanDefinitionCondition] + input: [DataRequirement] + output: [DataRequirement] + relatedAction: [PlanDefinitionRelatedAction] + timingDateTime: DateTime + timingAge: Quantity + timingPeriod: Period + timingDuration: Quantity + timingRange: Range + timingTiming: Timing + participant: [PlanDefinitionParticipant] + type: CodeableConcept + groupingBehavior: Code + selectionBehavior: Code + requiredBehavior: Code + precheckBehavior: Code + cardinalityBehavior: Code + definitionCanonical: Canonical + definitionUri: URI + transform: Canonical + dynamicValue: [PlanDefinitionDynamicValue] + action: [PlanDefinitionAction] +} + +type PlanDefinitionCondition { + id: String + extension: [Extension] + modifierExtension: [Extension] + kind: Code + expression: Expression +} + +type PlanDefinitionDynamicValue { + id: String + extension: [Extension] + modifierExtension: [Extension] + path: String + expression: Expression +} + +type PlanDefinitionGoal { + id: String + extension: [Extension] + modifierExtension: [Extension] + category: CodeableConcept + description: CodeableConcept + priority: CodeableConcept + start: CodeableConcept + addresses: [CodeableConcept] + documentation: [RelatedArtifact] + target: [PlanDefinitionTarget] +} + +type PlanDefinitionParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + role: CodeableConcept +} + +type PlanDefinitionRelatedAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + actionId: ID + relationship: Code + offsetDuration: Quantity + offsetRange: Range +} + +type PlanDefinitionTarget { + id: String + extension: [Extension] + modifierExtension: [Extension] + measure: CodeableConcept + detailQuantity: Quantity + detailRange: Range + detailCodeableConcept: CodeableConcept + due: Quantity +} + +type Population { + id: String + extension: [Extension] + modifierExtension: [Extension] + ageRange: Range + ageCodeableConcept: CodeableConcept + gender: CodeableConcept + race: CodeableConcept + physiologicalCondition: CodeableConcept +} + +type PractitionerQualificationIssuerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PractitionerQualification { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + code: CodeableConcept + period: Period + issuer: PractitionerQualificationIssuerReference +} + +type PractitionerRoleAvailableTime { + id: String + extension: [Extension] + modifierExtension: [Extension] + daysOfWeek: [Code] + allDay: Boolean + availableStartTime: Time + availableEndTime: Time +} + +type PractitionerRoleNotAvailable { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + during: Period +} + +type ProcedureFocalDeviceManipulatedReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type ProcedureFocalDevice { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: CodeableConcept + manipulated: ProcedureFocalDeviceManipulatedReference +} + +union ProcedurePerformerActor = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device + +type ProcedurePerformerActorReference { + id: String + extension: [Extension] + reference: String + resource: ProcedurePerformerActor + type: URI + identifier: Identifier + display: String +} + +type ProcedurePerformerOnBehalfOfReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ProcedurePerformer { + id: String + extension: [Extension] + modifierExtension: [Extension] + function: CodeableConcept + actor: ProcedurePerformerActorReference + onBehalfOf: ProcedurePerformerOnBehalfOfReference +} + +type ProdCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + height: Quantity + width: Quantity + depth: Quantity + weight: Quantity + nominalVolume: Quantity + externalDiameter: Quantity + shape: String + color: [String] + imprint: [String] + image: [Attachment] + scoring: CodeableConcept +} + +type ProductShelfLife { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + type: CodeableConcept + period: Quantity + specialPrecautionsForStorage: [CodeableConcept] +} + +union ProvenanceAgentWho = Practitioner | PractitionerRole | RelatedPerson | Patient | Device | Organization + +type ProvenanceAgentWhoReference { + id: String + extension: [Extension] + reference: String + resource: ProvenanceAgentWho + type: URI + identifier: Identifier + display: String +} + +union ProvenanceAgentOnBehalfOf = Practitioner | PractitionerRole | RelatedPerson | Patient | Device | Organization + +type ProvenanceAgentOnBehalfOfReference { + id: String + extension: [Extension] + reference: String + resource: ProvenanceAgentOnBehalfOf + type: URI + identifier: Identifier + display: String +} + +type ProvenanceAgent { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + role: [CodeableConcept] + who: ProvenanceAgentWhoReference + onBehalfOf: ProvenanceAgentOnBehalfOfReference +} + +type ProvenanceEntityWhatReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ProvenanceEntity { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: Code + what: ProvenanceEntityWhatReference + agent: [ProvenanceAgent] +} + +type QuestionnaireAnswerOptionValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireAnswerOption { + id: String + extension: [Extension] + modifierExtension: [Extension] + valueInteger: Int + valueDate: Date + valueTime: Time + valueString: String + valueCoding: Coding + valueReference: QuestionnaireAnswerOptionValueReferenceReference + initialSelected: Boolean +} + +type QuestionnaireEnableWhenAnswerReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireEnableWhen { + id: String + extension: [Extension] + modifierExtension: [Extension] + question: String + operator: Code + answerBoolean: Boolean + answerDecimal: Float + answerInteger: Int + answerDate: Date + answerDateTime: DateTime + answerTime: Time + answerString: String + answerCoding: Coding + answerQuantity: Quantity + answerReference: QuestionnaireEnableWhenAnswerReferenceReference +} + +type QuestionnaireInitialValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireInitial { + id: String + extension: [Extension] + modifierExtension: [Extension] + valueBoolean: Boolean + valueDecimal: Float + valueInteger: Int + valueDate: Date + valueDateTime: DateTime + valueTime: Time + valueString: String + valueUri: URI + valueAttachment: Attachment + valueCoding: Coding + valueQuantity: Quantity + valueReference: QuestionnaireInitialValueReferenceReference +} + +type QuestionnaireItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + linkId: String + definition: URI + code: [Coding] + prefix: String + text: String + type: Code + enableWhen: [QuestionnaireEnableWhen] + enableBehavior: Code + required: Boolean + repeats: Boolean + readOnly: Boolean + maxLength: Int + answerValueSet: Canonical + answerOption: [QuestionnaireAnswerOption] + initial: [QuestionnaireInitial] + item: [QuestionnaireItem] +} + +type QuestionnaireResponseAnswerValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireResponseAnswer { + id: String + extension: [Extension] + modifierExtension: [Extension] + valueBoolean: Boolean + valueDecimal: Float + valueInteger: Int + valueDate: Date + valueDateTime: DateTime + valueTime: Time + valueString: String + valueUri: URI + valueAttachment: Attachment + valueCoding: Coding + valueQuantity: Quantity + valueReference: QuestionnaireResponseAnswerValueReferenceReference + item: [QuestionnaireResponseItem] +} + +type QuestionnaireResponseItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + linkId: String + definition: URI + text: String + answer: [QuestionnaireResponseAnswer] + item: [QuestionnaireResponseItem] +} + +type RegulatedAuthorizationCase { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + type: CodeableConcept + status: CodeableConcept + datePeriod: Period + dateDateTime: DateTime + application: [RegulatedAuthorizationCase] +} + +type RelatedPersonCommunication { + id: String + extension: [Extension] + modifierExtension: [Extension] + language: CodeableConcept + preferred: Boolean +} + +union RequestGroupActionParticipant = Patient | Practitioner | PractitionerRole | RelatedPerson | Device + +type RequestGroupActionParticipantReference { + id: String + extension: [Extension] + reference: String + resource: RequestGroupActionParticipant + type: URI + identifier: Identifier + display: String +} + +type RequestGroupActionResourceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type RequestGroupAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + prefix: String + title: String + description: String + textEquivalent: String + priority: Code + code: [CodeableConcept] + documentation: [RelatedArtifact] + condition: [RequestGroupCondition] + relatedAction: [RequestGroupRelatedAction] + timingDateTime: DateTime + timingAge: Quantity + timingPeriod: Period + timingDuration: Quantity + timingRange: Range + timingTiming: Timing + participant: [RequestGroupActionParticipantReference] + type: CodeableConcept + groupingBehavior: Code + selectionBehavior: Code + requiredBehavior: Code + precheckBehavior: Code + cardinalityBehavior: Code + resource: RequestGroupActionResourceReference + action: [RequestGroupAction] +} + +type RequestGroupCondition { + id: String + extension: [Extension] + modifierExtension: [Extension] + kind: Code + expression: Expression +} + +type RequestGroupRelatedAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + actionId: ID + relationship: Code + offsetDuration: Quantity + offsetRange: Range +} + +type ResearchElementDefinitionCharacteristic { + id: String + extension: [Extension] + modifierExtension: [Extension] + definitionCodeableConcept: CodeableConcept + definitionCanonical: Canonical + definitionExpression: Expression + definitionDataRequirement: DataRequirement + usageContext: [UsageContext] + exclude: Boolean + unitOfMeasure: CodeableConcept + studyEffectiveDescription: String + studyEffectiveDateTime: DateTime + studyEffectivePeriod: Period + studyEffectiveDuration: Quantity + studyEffectiveTiming: Timing + studyEffectiveTimeFromStart: Quantity + studyEffectiveGroupMeasure: Code + participantEffectiveDescription: String + participantEffectiveDateTime: DateTime + participantEffectivePeriod: Period + participantEffectiveDuration: Quantity + participantEffectiveTiming: Timing + participantEffectiveTimeFromStart: Quantity + participantEffectiveGroupMeasure: Code +} + +type ResearchStudyArm { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + type: CodeableConcept + description: String +} + +type ResearchStudyObjective { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + type: CodeableConcept +} + +type RiskAssessmentPrediction { + id: String + extension: [Extension] + modifierExtension: [Extension] + outcome: CodeableConcept + probabilityDecimal: Float + probabilityRange: Range + qualitativeRisk: CodeableConcept + relativeRisk: Float + whenPeriod: Period + whenRange: Range + rationale: String +} + +type SearchParameterComponent { + id: String + extension: [Extension] + modifierExtension: [Extension] + definition: Canonical + expression: String +} + +union SpecimenCollectionCollector = Practitioner | PractitionerRole + +type SpecimenCollectionCollectorReference { + id: String + extension: [Extension] + reference: String + resource: SpecimenCollectionCollector + type: URI + identifier: Identifier + display: String +} + +type SpecimenCollection { + id: String + extension: [Extension] + modifierExtension: [Extension] + collector: SpecimenCollectionCollectorReference + collectedDateTime: DateTime + collectedPeriod: Period + duration: Quantity + quantity: Quantity + method: CodeableConcept + bodySite: CodeableConcept + fastingStatusCodeableConcept: CodeableConcept + fastingStatusDuration: Quantity +} + +type SpecimenContainerAdditiveReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type SpecimenContainer { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + description: String + type: CodeableConcept + capacity: Quantity + specimenQuantity: Quantity + additiveCodeableConcept: CodeableConcept + additiveReference: SpecimenContainerAdditiveReferenceReference +} + +type SpecimenDefinitionAdditiveAdditiveReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type SpecimenDefinitionAdditive { + id: String + extension: [Extension] + modifierExtension: [Extension] + additiveCodeableConcept: CodeableConcept + additiveReference: SpecimenDefinitionAdditiveAdditiveReferenceReference +} + +type SpecimenDefinitionContainer { + id: String + extension: [Extension] + modifierExtension: [Extension] + material: CodeableConcept + type: CodeableConcept + cap: CodeableConcept + description: String + capacity: Quantity + minimumVolumeQuantity: Quantity + minimumVolumeString: String + additive: [SpecimenDefinitionAdditive] + preparation: String +} + +type SpecimenDefinitionHandling { + id: String + extension: [Extension] + modifierExtension: [Extension] + temperatureQualifier: CodeableConcept + temperatureRange: Range + maxDuration: Quantity + instruction: String +} + +type SpecimenDefinitionTypeTested { + id: String + extension: [Extension] + modifierExtension: [Extension] + isDerived: Boolean + type: CodeableConcept + preference: Code + container: SpecimenDefinitionContainer + requirement: String + retentionTime: Quantity + rejectionCriterion: [CodeableConcept] + handling: [SpecimenDefinitionHandling] +} + +type SpecimenProcessingAdditiveReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type SpecimenProcessing { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + procedure: CodeableConcept + additive: [SpecimenProcessingAdditiveReference] + timeDateTime: DateTime + timePeriod: Period +} + +type StructureDefinitionContext { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + expression: String +} + +type StructureDefinitionDifferential { + id: String + extension: [Extension] + modifierExtension: [Extension] + element: [ElementDefinition] +} + +type StructureDefinitionMapping { + id: String + extension: [Extension] + modifierExtension: [Extension] + identity: ID + uri: URI + name: String + comment: String +} + +type StructureDefinitionSnapshot { + id: String + extension: [Extension] + modifierExtension: [Extension] + element: [ElementDefinition] +} + +type StructureMapDependent { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: ID + variable: [String] +} + +type StructureMapGroup { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: ID + extends: ID + typeMode: Code + documentation: String + input: [StructureMapInput] + rule: [StructureMapRule] +} + +type StructureMapInput { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: ID + type: String + mode: Code + documentation: String +} + +type StructureMapParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + valueId: ID + valueString: String + valueBoolean: Boolean + valueInteger: Int + valueDecimal: Float +} + +type StructureMapRule { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: ID + source: [StructureMapSource] + target: [StructureMapTarget] + rule: [StructureMapRule] + dependent: [StructureMapDependent] + documentation: String +} + +type StructureMapSourceDefaultValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type StructureMapSource { + id: String + extension: [Extension] + modifierExtension: [Extension] + context: ID + min: Int + max: String + type: String + defaultValueBase64Binary: Base64Binary + defaultValueBoolean: Boolean + defaultValueCanonical: Canonical + defaultValueCode: Code + defaultValueDate: Date + defaultValueDateTime: DateTime + defaultValueDecimal: Float + defaultValueId: ID + defaultValueInstant: Instant + defaultValueInteger: Int + defaultValueMarkdown: Markdown + defaultValueOid: OID + defaultValuePositiveInt: Int + defaultValueString: String + defaultValueTime: Time + defaultValueUnsignedInt: Int + defaultValueUri: URI + defaultValueUrl: URL + defaultValueUuid: UUID + defaultValueAddress: Address + defaultValueAge: Quantity + defaultValueAnnotation: Annotation + defaultValueAttachment: Attachment + defaultValueCodeableConcept: CodeableConcept + defaultValueCoding: Coding + defaultValueContactPoint: ContactPoint + defaultValueCount: Quantity + defaultValueDistance: Quantity + defaultValueDuration: Quantity + defaultValueHumanName: HumanName + defaultValueIdentifier: Identifier + defaultValueMoney: Money + defaultValuePeriod: Period + defaultValueQuantity: Quantity + defaultValueRange: Range + defaultValueRatio: Ratio + defaultValueReference: StructureMapSourceDefaultValueReferenceReference + defaultValueSampledData: SampledData + defaultValueSignature: Signature + defaultValueTiming: Timing + defaultValueContactDetail: ContactDetail + defaultValueContributor: Contributor + defaultValueDataRequirement: DataRequirement + defaultValueExpression: Expression + defaultValueParameterDefinition: ParameterDefinition + defaultValueRelatedArtifact: RelatedArtifact + defaultValueTriggerDefinition: TriggerDefinition + defaultValueUsageContext: UsageContext + defaultValueDosage: Dosage + defaultValueMeta: Meta + element: String + listMode: Code + variable: ID + condition: String + check: String + logMessage: String +} + +type StructureMapStructure { + id: String + extension: [Extension] + modifierExtension: [Extension] + url: Canonical + mode: Code + alias: String + documentation: String +} + +type StructureMapTarget { + id: String + extension: [Extension] + modifierExtension: [Extension] + context: ID + contextType: Code + element: String + variable: ID + listMode: [Code] + listRuleId: ID + transform: Code + parameter: [StructureMapParameter] +} + +type SubscriptionChannel { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + endpoint: URL + payload: Code + header: [String] +} + +type SubscriptionStatusNotificationEventFocusReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type SubscriptionStatusNotificationEventAdditionalContextReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type SubscriptionStatusNotificationEvent { + id: String + extension: [Extension] + modifierExtension: [Extension] + eventNumber: String + timestamp: Instant + focus: SubscriptionStatusNotificationEventFocusReference + additionalContext: [SubscriptionStatusNotificationEventAdditionalContextReference] +} + +type SubscriptionTopicCanFilterBy { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: Markdown + resource: URI + filterParameter: String + filterDefinition: URI + modifier: [Code] +} + +type SubscriptionTopicEventTrigger { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: Markdown + event: CodeableConcept + resource: URI +} + +type SubscriptionTopicNotificationShape { + id: String + extension: [Extension] + modifierExtension: [Extension] + resource: URI + include: [String] + revInclude: [String] +} + +type SubscriptionTopicQueryCriteria { + id: String + extension: [Extension] + modifierExtension: [Extension] + previous: String + resultForCreate: Code + current: String + resultForDelete: Code + requireBoth: Boolean +} + +type SubscriptionTopicResourceTrigger { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: Markdown + resource: URI + supportedInteraction: [Code] + queryCriteria: SubscriptionTopicQueryCriteria + fhirPathCriteria: String +} + +type SubstanceDefinitionCodeSourceReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionCode { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + status: CodeableConcept + statusDate: DateTime + note: [Annotation] + source: [SubstanceDefinitionCodeSourceReference] +} + +type SubstanceDefinitionMoiety { + id: String + extension: [Extension] + modifierExtension: [Extension] + role: CodeableConcept + identifier: Identifier + name: String + stereochemistry: CodeableConcept + opticalActivity: CodeableConcept + molecularFormula: String + amountQuantity: Quantity + amountString: String + measurementType: CodeableConcept +} + +type SubstanceDefinitionMolecularWeight { + id: String + extension: [Extension] + modifierExtension: [Extension] + method: CodeableConcept + type: CodeableConcept + amount: Quantity +} + +type SubstanceDefinitionNameSourceReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionName { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + type: CodeableConcept + status: CodeableConcept + preferred: Boolean + language: [CodeableConcept] + domain: [CodeableConcept] + jurisdiction: [CodeableConcept] + synonym: [SubstanceDefinitionName] + translation: [SubstanceDefinitionName] + official: [SubstanceDefinitionOfficial] + source: [SubstanceDefinitionNameSourceReference] +} + +type SubstanceDefinitionOfficial { + id: String + extension: [Extension] + modifierExtension: [Extension] + authority: CodeableConcept + status: CodeableConcept + date: DateTime +} + +type SubstanceDefinitionProperty { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueDate: Date + valueBoolean: Boolean + valueAttachment: Attachment +} + +type SubstanceDefinitionRelationshipSubstanceDefinitionReferenceReference { + id: String + extension: [Extension] + reference: String + resource: SubstanceDefinition + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionRelationshipSourceReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionRelationship { + id: String + extension: [Extension] + modifierExtension: [Extension] + substanceDefinitionReference: SubstanceDefinitionRelationshipSubstanceDefinitionReferenceReference + substanceDefinitionCodeableConcept: CodeableConcept + type: CodeableConcept + isDefining: Boolean + amountQuantity: Quantity + amountRatio: Ratio + amountString: String + ratioHighLimitAmount: Ratio + comparator: CodeableConcept + source: [SubstanceDefinitionRelationshipSourceReference] +} + +type SubstanceDefinitionRepresentationDocumentReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionRepresentation { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + representation: String + format: CodeableConcept + document: SubstanceDefinitionRepresentationDocumentReference +} + +type SubstanceDefinitionSourceMaterial { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + genus: CodeableConcept + species: CodeableConcept + part: CodeableConcept + countryOfOrigin: [CodeableConcept] +} + +type SubstanceDefinitionStructureSourceDocumentReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionStructure { + id: String + extension: [Extension] + modifierExtension: [Extension] + stereochemistry: CodeableConcept + opticalActivity: CodeableConcept + molecularFormula: String + molecularFormulaByMoiety: String + molecularWeight: SubstanceDefinitionMolecularWeight + technique: [CodeableConcept] + sourceDocument: [SubstanceDefinitionStructureSourceDocumentReference] + representation: [SubstanceDefinitionRepresentation] +} + +type SubstanceIngredientSubstanceReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type SubstanceIngredient { + id: String + extension: [Extension] + modifierExtension: [Extension] + quantity: Ratio + substanceCodeableConcept: CodeableConcept + substanceReference: SubstanceIngredientSubstanceReferenceReference +} + +type SubstanceInstance { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + expiry: DateTime + quantity: Quantity +} + +union SupplyDeliverySuppliedItemItemReference = Medication | Substance | Device + +type SupplyDeliverySuppliedItemItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: SupplyDeliverySuppliedItemItemReference + type: URI + identifier: Identifier + display: String +} + +type SupplyDeliverySuppliedItem { + id: String + extension: [Extension] + modifierExtension: [Extension] + quantity: Quantity + itemCodeableConcept: CodeableConcept + itemReference: SupplyDeliverySuppliedItemItemReferenceReference +} + +type SupplyRequestParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueRange: Range + valueBoolean: Boolean +} + +type TaskInputValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TaskInput { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueBase64Binary: Base64Binary + valueBoolean: Boolean + valueCanonical: Canonical + valueCode: Code + valueDate: Date + valueDateTime: DateTime + valueDecimal: Float + valueId: ID + valueInstant: Instant + valueInteger: Int + valueMarkdown: Markdown + valueOid: OID + valuePositiveInt: Int + valueString: String + valueTime: Time + valueUnsignedInt: Int + valueUri: URI + valueUrl: URL + valueUuid: UUID + valueAddress: Address + valueAge: Quantity + valueAnnotation: Annotation + valueAttachment: Attachment + valueCodeableConcept: CodeableConcept + valueCoding: Coding + valueContactPoint: ContactPoint + valueCount: Quantity + valueDistance: Quantity + valueDuration: Quantity + valueHumanName: HumanName + valueIdentifier: Identifier + valueMoney: Money + valuePeriod: Period + valueQuantity: Quantity + valueRange: Range + valueRatio: Ratio + valueReference: TaskInputValueReferenceReference + valueSampledData: SampledData + valueSignature: Signature + valueTiming: Timing + valueContactDetail: ContactDetail + valueContributor: Contributor + valueDataRequirement: DataRequirement + valueExpression: Expression + valueParameterDefinition: ParameterDefinition + valueRelatedArtifact: RelatedArtifact + valueTriggerDefinition: TriggerDefinition + valueUsageContext: UsageContext + valueDosage: Dosage + valueMeta: Meta +} + +type TaskOutputValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TaskOutput { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: CodeableConcept + valueBase64Binary: Base64Binary + valueBoolean: Boolean + valueCanonical: Canonical + valueCode: Code + valueDate: Date + valueDateTime: DateTime + valueDecimal: Float + valueId: ID + valueInstant: Instant + valueInteger: Int + valueMarkdown: Markdown + valueOid: OID + valuePositiveInt: Int + valueString: String + valueTime: Time + valueUnsignedInt: Int + valueUri: URI + valueUrl: URL + valueUuid: UUID + valueAddress: Address + valueAge: Quantity + valueAnnotation: Annotation + valueAttachment: Attachment + valueCodeableConcept: CodeableConcept + valueCoding: Coding + valueContactPoint: ContactPoint + valueCount: Quantity + valueDistance: Quantity + valueDuration: Quantity + valueHumanName: HumanName + valueIdentifier: Identifier + valueMoney: Money + valuePeriod: Period + valueQuantity: Quantity + valueRange: Range + valueRatio: Ratio + valueReference: TaskOutputValueReferenceReference + valueSampledData: SampledData + valueSignature: Signature + valueTiming: Timing + valueContactDetail: ContactDetail + valueContributor: Contributor + valueDataRequirement: DataRequirement + valueExpression: Expression + valueParameterDefinition: ParameterDefinition + valueRelatedArtifact: RelatedArtifact + valueTriggerDefinition: TriggerDefinition + valueUsageContext: UsageContext + valueDosage: Dosage + valueMeta: Meta +} + +union TaskRestrictionRecipient = Patient | Practitioner | PractitionerRole | RelatedPerson | Group | Organization + +type TaskRestrictionRecipientReference { + id: String + extension: [Extension] + reference: String + resource: TaskRestrictionRecipient + type: URI + identifier: Identifier + display: String +} + +type TaskRestriction { + id: String + extension: [Extension] + modifierExtension: [Extension] + repetitions: Int + period: Period + recipient: [TaskRestrictionRecipientReference] +} + +type TerminologyCapabilitiesClosure { + id: String + extension: [Extension] + modifierExtension: [Extension] + translation: Boolean +} + +type TerminologyCapabilitiesCodeSystem { + id: String + extension: [Extension] + modifierExtension: [Extension] + uri: Canonical + version: [TerminologyCapabilitiesVersion] + subsumption: Boolean +} + +type TerminologyCapabilitiesExpansion { + id: String + extension: [Extension] + modifierExtension: [Extension] + hierarchical: Boolean + paging: Boolean + incomplete: Boolean + parameter: [TerminologyCapabilitiesParameter] + textFilter: Markdown +} + +type TerminologyCapabilitiesFilter { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + op: [Code] +} + +type TerminologyCapabilitiesImplementation { + id: String + extension: [Extension] + modifierExtension: [Extension] + description: String + url: URL +} + +type TerminologyCapabilitiesParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: Code + documentation: String +} + +type TerminologyCapabilitiesSoftware { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + version: String +} + +type TerminologyCapabilitiesTranslation { + id: String + extension: [Extension] + modifierExtension: [Extension] + needsMap: Boolean +} + +type TerminologyCapabilitiesValidateCode { + id: String + extension: [Extension] + modifierExtension: [Extension] + translations: Boolean +} + +type TerminologyCapabilitiesVersion { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: String + isDefault: Boolean + compositional: Boolean + language: [Code] + filter: [TerminologyCapabilitiesFilter] + property: [Code] +} + +type TestReportAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestReportOperation + assert: TestReportAssert +} + +type TestReportAction1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestReportOperation + assert: TestReportAssert +} + +type TestReportAction2 { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestReportOperation +} + +type TestReportAssert { + id: String + extension: [Extension] + modifierExtension: [Extension] + result: Code + message: Markdown + detail: String +} + +type TestReportOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + result: Code + message: Markdown + detail: URI +} + +type TestReportParticipant { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Code + uri: URI + display: String +} + +type TestReportSetup { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: [TestReportAction] +} + +type TestReportTeardown { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: [TestReportAction2] +} + +type TestReportTest { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + description: String + action: [TestReportAction1] +} + +type TestScriptAction { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestScriptOperation + assert: TestScriptAssert +} + +type TestScriptAction1 { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestScriptOperation + assert: TestScriptAssert +} + +type TestScriptAction2 { + id: String + extension: [Extension] + modifierExtension: [Extension] + operation: TestScriptOperation +} + +type TestScriptAssert { + id: String + extension: [Extension] + modifierExtension: [Extension] + label: String + description: String + direction: Code + compareToSourceId: String + compareToSourceExpression: String + compareToSourcePath: String + contentType: Code + expression: String + headerField: String + minimumId: String + navigationLinks: Boolean + operator: Code + path: String + requestMethod: Code + requestURL: String + resource: Code + response: Code + responseCode: String + sourceId: ID + validateProfileId: ID + value: String + warningOnly: Boolean +} + +type TestScriptCapability { + id: String + extension: [Extension] + modifierExtension: [Extension] + required: Boolean + validated: Boolean + description: String + origin: [Int] + destination: Int + link: [URI] + capabilities: Canonical +} + +type TestScriptDestination { + id: String + extension: [Extension] + modifierExtension: [Extension] + index: Int + profile: Coding +} + +type TestScriptFixtureResourceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TestScriptFixture { + id: String + extension: [Extension] + modifierExtension: [Extension] + autocreate: Boolean + autodelete: Boolean + resource: TestScriptFixtureResourceReference +} + +type TestScriptLink { + id: String + extension: [Extension] + modifierExtension: [Extension] + url: URI + description: String +} + +type TestScriptMetadata { + id: String + extension: [Extension] + modifierExtension: [Extension] + link: [TestScriptLink] + capability: [TestScriptCapability] +} + +type TestScriptOperation { + id: String + extension: [Extension] + modifierExtension: [Extension] + type: Coding + resource: Code + label: String + description: String + accept: Code + contentType: Code + destination: Int + encodeRequestUrl: Boolean + method: Code + origin: Int + params: String + requestHeader: [TestScriptRequestHeader] + requestId: ID + responseId: ID + sourceId: ID + targetId: ID + url: String +} + +type TestScriptOrigin { + id: String + extension: [Extension] + modifierExtension: [Extension] + index: Int + profile: Coding +} + +type TestScriptRequestHeader { + id: String + extension: [Extension] + modifierExtension: [Extension] + field: String + value: String +} + +type TestScriptSetup { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: [TestScriptAction] +} + +type TestScriptTeardown { + id: String + extension: [Extension] + modifierExtension: [Extension] + action: [TestScriptAction2] +} + +type TestScriptTest { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + description: String + action: [TestScriptAction1] +} + +type TestScriptVariable { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + defaultValue: String + description: String + expression: String + headerField: String + hint: String + path: String + sourceId: ID +} + +type Timing { + id: String + extension: [Extension] + modifierExtension: [Extension] + event: [DateTime] + repeat: TimingRepeat + code: CodeableConcept +} + +type TimingRepeat { + id: String + extension: [Extension] + modifierExtension: [Extension] + boundsDuration: Quantity + boundsRange: Range + boundsPeriod: Period + count: Int + countMax: Int + duration: Float + durationMax: Float + durationUnit: Code + frequency: Int + frequencyMax: Int + period: Float + periodMax: Float + periodUnit: Code + dayOfWeek: [Code] + timeOfDay: [Time] + when: [Code] + offset: Int +} + +type ValueSetCompose { + id: String + extension: [Extension] + modifierExtension: [Extension] + lockedDate: Date + inactive: Boolean + include: [ValueSetInclude] + exclude: [ValueSetInclude] +} + +type ValueSetConcept { + id: String + extension: [Extension] + modifierExtension: [Extension] + code: Code + display: String + designation: [ValueSetDesignation] +} + +type ValueSetContains { + id: String + extension: [Extension] + modifierExtension: [Extension] + system: URI + abstract: Boolean + inactive: Boolean + version: String + code: Code + display: String + designation: [ValueSetDesignation] + contains: [ValueSetContains] +} + +type ValueSetDesignation { + id: String + extension: [Extension] + modifierExtension: [Extension] + language: Code + use: Coding + value: String +} + +type ValueSetExpansion { + id: String + extension: [Extension] + modifierExtension: [Extension] + identifier: URI + timestamp: DateTime + total: Int + offset: Int + parameter: [ValueSetParameter] + contains: [ValueSetContains] +} + +type ValueSetFilter { + id: String + extension: [Extension] + modifierExtension: [Extension] + property: Code + op: Code + value: String +} + +type ValueSetInclude { + id: String + extension: [Extension] + modifierExtension: [Extension] + system: URI + version: String + concept: [ValueSetConcept] + filter: [ValueSetFilter] + valueSet: [Canonical] +} + +type ValueSetParameter { + id: String + extension: [Extension] + modifierExtension: [Extension] + name: String + valueString: String + valueBoolean: Boolean + valueInteger: Int + valueDecimal: Float + valueUri: URI + valueCode: Code + valueDateTime: DateTime +} + +union VerificationResultAttestationWho = Practitioner | PractitionerRole | Organization + +type VerificationResultAttestationWhoReference { + id: String + extension: [Extension] + reference: String + resource: VerificationResultAttestationWho + type: URI + identifier: Identifier + display: String +} + +union VerificationResultAttestationOnBehalfOf = Organization | Practitioner | PractitionerRole + +type VerificationResultAttestationOnBehalfOfReference { + id: String + extension: [Extension] + reference: String + resource: VerificationResultAttestationOnBehalfOf + type: URI + identifier: Identifier + display: String +} + +type VerificationResultAttestation { + id: String + extension: [Extension] + modifierExtension: [Extension] + who: VerificationResultAttestationWhoReference + onBehalfOf: VerificationResultAttestationOnBehalfOfReference + communicationMethod: CodeableConcept + date: Date + sourceIdentityCertificate: String + proxyIdentityCertificate: String + proxySignature: Signature + sourceSignature: Signature +} + +union VerificationResultPrimarySourceWho = Organization | Practitioner | PractitionerRole + +type VerificationResultPrimarySourceWhoReference { + id: String + extension: [Extension] + reference: String + resource: VerificationResultPrimarySourceWho + type: URI + identifier: Identifier + display: String +} + +type VerificationResultPrimarySource { + id: String + extension: [Extension] + modifierExtension: [Extension] + who: VerificationResultPrimarySourceWhoReference + type: [CodeableConcept] + communicationMethod: [CodeableConcept] + validationStatus: CodeableConcept + validationDate: DateTime + canPushUpdates: CodeableConcept + pushTypeAvailable: [CodeableConcept] +} + +type VerificationResultValidatorOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type VerificationResultValidator { + id: String + extension: [Extension] + modifierExtension: [Extension] + organization: VerificationResultValidatorOrganizationReference + identityCertificate: String + attestationSignature: Signature +} + +type VisionPrescriptionLensSpecification { + id: String + extension: [Extension] + modifierExtension: [Extension] + product: CodeableConcept + eye: Code + sphere: Float + cylinder: Float + axis: Int + prism: [VisionPrescriptionPrism] + add: Float + power: Float + backCurve: Float + diameter: Float + duration: Quantity + color: String + brand: String + note: [Annotation] +} + +type VisionPrescriptionPrism { + id: String + extension: [Extension] + modifierExtension: [Extension] + amount: Float + base: Code +} + +type Address { + id: String + extension: [Extension] + use: Code + type: Code + text: String + line: [String] + city: String + district: String + state: String + postalCode: String + country: String + period: Period +} + +type Age { + value: Float + comparator: Code + unit: String + system: URI + code: Code +} + +union AnnotationAuthorReference = Practitioner | Patient | RelatedPerson | Organization + +type AnnotationAuthorReferenceReference { + id: String + extension: [Extension] + reference: String + resource: AnnotationAuthorReference + type: URI + identifier: Identifier + display: String +} + +type Annotation { + id: String + extension: [Extension] + authorReference: AnnotationAuthorReferenceReference + authorString: String + time: DateTime + text: Markdown +} + +type Attachment { + id: String + extension: [Extension] + contentType: Code + language: Code + data: Base64Binary + url: URL + size: Int + hash: Base64Binary + title: String + creation: DateTime +} + +type BackboneElement { + id: String + extension: [Extension] + modifierExtension: [Extension] +} + +type CodeableConcept { + id: String + extension: [Extension] + coding: [Coding] + text: String +} + +type CodeableReferenceReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CodeableReference { + id: String + extension: [Extension] + concept: CodeableConcept + reference: CodeableReferenceReferenceReference +} + +type Coding { + id: String + extension: [Extension] + system: URI + version: String + code: Code + display: String + userSelected: Boolean +} + +type ContactDetail { + id: String + extension: [Extension] + name: String + telecom: [ContactPoint] +} + +type ContactPoint { + id: String + extension: [Extension] + system: Code + value: String + use: Code + rank: Int + period: Period +} + +type Contributor { + id: String + extension: [Extension] + type: Code + name: String + contact: [ContactDetail] +} + +type Count { + value: Float + comparator: Code + unit: String + system: URI + code: Code +} + +type DataRequirementSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type DataRequirement { + id: String + extension: [Extension] + type: Code + profile: [Canonical] + subjectCodeableConcept: CodeableConcept + subjectReference: DataRequirementSubjectReferenceReference + mustSupport: [String] + codeFilter: [DataRequirementCodeFilter] + dateFilter: [DataRequirementDateFilter] + limit: Int + sort: [DataRequirementSort] +} + +type DataRequirementCodeFilter { + id: String + extension: [Extension] + path: String + searchParam: String + valueSet: Canonical + code: [Coding] +} + +type DataRequirementDateFilter { + id: String + extension: [Extension] + path: String + searchParam: String + valueDateTime: DateTime + valuePeriod: Period + valueDuration: Quantity +} + +type DataRequirementSort { + id: String + extension: [Extension] + path: String + direction: Code +} + +type Distance { + value: Float + comparator: Code + unit: String + system: URI + code: Code +} + +type Duration { + id: String + extension: [Extension] + value: Float + comparator: Code + unit: String + system: URI + code: Code +} + +type Element { + id: String + extension: [Extension] +} + +type Expression { + id: String + extension: [Extension] + description: String + name: ID + language: Code + expression: String + reference: URI +} + +type HumanName { + id: String + extension: [Extension] + use: Code + text: String + family: String + given: [String] + prefix: [String] + suffix: [String] + period: Period +} + +type IdentifierAssignerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type Identifier { + id: String + extension: [Extension] + use: Code + type: CodeableConcept + system: URI + value: String + period: Period + assigner: IdentifierAssignerReference +} + +type Meta { + id: String + extension: [Extension] + versionId: ID + lastUpdated: Instant + source: URI + profile: [Canonical] + security: [Coding] + tag: [Coding] +} + +type Money { + id: String + extension: [Extension] + value: Float + currency: Code +} + +type Narrative { + id: String + extension: [Extension] + status: Code + div: XHTML +} + +type ParameterDefinition { + id: String + extension: [Extension] + name: Code + use: Code + min: Int + max: String + documentation: String + type: Code + profile: Canonical +} + +type Period { + id: String + extension: [Extension] + start: DateTime + end: DateTime +} + +type Quantity { + id: String + extension: [Extension] + value: Float + comparator: Code + unit: String + system: URI + code: Code +} + +type Range { + id: String + extension: [Extension] + low: Quantity + high: Quantity +} + +type Ratio { + id: String + extension: [Extension] + numerator: Quantity + denominator: Quantity +} + +type RatioRange { + id: String + extension: [Extension] + lowNumerator: Quantity + highNumerator: Quantity + denominator: Quantity +} + +type Reference { + id: String + extension: [Extension] + reference: String + type: URI + identifier: Identifier + display: String +} + +type RelatedArtifact { + id: String + extension: [Extension] + type: Code + label: String + display: String + citation: Markdown + url: URL + document: Attachment + resource: Canonical +} + +type SampledData { + id: String + extension: [Extension] + origin: Quantity + period: Float + factor: Float + lowerLimit: Float + upperLimit: Float + dimensions: Int + data: String +} + +union SignatureWho = Practitioner | PractitionerRole | RelatedPerson | Patient | Device | Organization + +type SignatureWhoReference { + id: String + extension: [Extension] + reference: String + resource: SignatureWho + type: URI + identifier: Identifier + display: String +} + +union SignatureOnBehalfOf = Practitioner | PractitionerRole | RelatedPerson | Patient | Device | Organization + +type SignatureOnBehalfOfReference { + id: String + extension: [Extension] + reference: String + resource: SignatureOnBehalfOf + type: URI + identifier: Identifier + display: String +} + +type Signature { + id: String + extension: [Extension] + type: [Coding] + when: Instant + who: SignatureWhoReference + onBehalfOf: SignatureOnBehalfOfReference + targetFormat: Code + sigFormat: Code + data: Base64Binary +} + +type TriggerDefinitionTimingReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Schedule + type: URI + identifier: Identifier + display: String +} + +type TriggerDefinition { + id: String + extension: [Extension] + type: Code + name: String + timingTiming: Timing + timingReference: TriggerDefinitionTimingReferenceReference + timingDate: Date + timingDateTime: DateTime + data: [DataRequirement] + condition: Expression +} + +union UsageContextValueReference = PlanDefinition | ResearchStudy | InsurancePlan | HealthcareService | Group | Location | Organization + +type UsageContextValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: UsageContextValueReference + type: URI + identifier: Identifier + display: String +} + +type UsageContext { + id: String + extension: [Extension] + code: Coding + valueCodeableConcept: CodeableConcept + valueQuantity: Quantity + valueRange: Range + valueReference: UsageContextValueReferenceReference +} + +""" +DocumentReferenceAttachment + For referring to data content defined in other formats. + If the element is present, it must have a value for at least one of the + defined elements, an @id referenced from the Narrative, or extensions +""" +type DocumentReferenceAttachment { + """None""" + id: String + + """ + May be used to represent additional information that is not part of the basic + definition of the element. To make the use of extensions safe and manageable, + there is a strict set of governance applied to the definition and use of + extensions. Though any implementer can define an extension, there is a set of + requirements that SHALL be met as part of the definition of the extension. + """ + extension: [Extension] + + """ + Identifies the type of the data in the attachment and allows a method to be + chosen to interpret or render the data. Includes mime type parameters such as + charset where appropriate. + """ + contentType: Code + + """ + The human language of the content. The value can be any valid value according + to BCP 47. + """ + language: Code + + """ + The actual data of the attachment - a sequence of bytes, base64 encoded. + """ + data: Base64Binary + + """A location where the data can be accessed.""" + url: URL + + """For accessing binary resource saved in 'url' field.""" + resource: Binary + + """ + The number of bytes of data that make up this attachment (before base64 + encoding, if that is done). + """ + size: Int + + """The calculated hash of the data using SHA-1. Represented using base64.""" + hash: Base64Binary + + """A label or set of text to display in place of the data.""" + title: String + + """The date that the attachment was first created.""" + creation: DateTime +} + +type MedicationRequest implements DomainResource & Resource { + dispense: [MedicationDispense] + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + statusReason: CodeableConcept + intent: Code + category: [CodeableConcept] + priority: Code + doNotPerform: Boolean + reportedBoolean: Boolean + reportedReference: MedicationRequestReportedReferenceReference + medicationCodeableConcept: CodeableConcept + medicationReference: MedicationRequestMedicationReferenceReference + subject: MedicationRequestSubjectReference + encounter: MedicationRequestEncounterReference + supportingInformation: [MedicationRequestSupportingInformationReference] + authoredOn: DateTime + requester: MedicationRequestRequesterReference + performer: MedicationRequestPerformerReference + performerType: CodeableConcept + recorder: MedicationRequestRecorderReference + reasonCode: [CodeableConcept] + reasonReference: [MedicationRequestReasonReferenceReference] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [MedicationRequestBasedOnReference] + groupIdentifier: Identifier + courseOfTherapyType: CodeableConcept + insurance: [MedicationRequestInsuranceReference] + note: [Annotation] + dosageInstruction: [Dosage] + dispenseRequest: MedicationRequestDispenseRequest + substitution: MedicationRequestSubstitution + priorPrescription: MedicationRequestPriorPrescriptionReference + detectedIssue: [MedicationRequestDetectedIssueReference] + eventHistory: [MedicationRequestEventHistoryReference] +} + +type Patient implements DomainResource & Resource { + accounts: [Account] + adverseEvents: [AdverseEvent] + allergyIntolerances: [AllergyIntolerance] + appointments: [Appointment] + appointmentResponses: [AppointmentResponse] + basics: [Basic] + bodyStructures: [BodyStructure] + carePlans: [CarePlan] + careTeams: [CareTeam] + chargeItems: [ChargeItem] + claims: [Claim] + claimResponses: [ClaimResponse] + clinicalImpressions: [ClinicalImpression] + communications: [Communication] + communicationRequests: [CommunicationRequest] + compositions: [Composition] + conditions: [Condition] + consents: [Consent] + contracts: [Contract] + coverages: [Coverage] + coverageEligibilityRequests: [CoverageEligibilityRequest] + coverageEligibilityResponses: [CoverageEligibilityResponse] + detectedIssues: [DetectedIssue] + devices: [Device] + deviceRequests: [DeviceRequest] + deviceUseStatements: [DeviceUseStatement] + diagnosticReports: [DiagnosticReport] + documentManifests: [DocumentManifest] + documentReferences: [DocumentReference] + encounters: [Encounter] + enrollmentRequests: [EnrollmentRequest] + episodesOfCare: [EpisodeOfCare] + explanationOfBenefits: [ExplanationOfBenefit] + familyMemberHistories: [FamilyMemberHistory] + flags: [Flag] + goals: [Goal] + groups: [Group] + guidanceResponses: [GuidanceResponse] + imagingStudies: [ImagingStudy] + immunizations: [Immunization] + immunizationEvaluations: [ImmunizationEvaluation] + immunizationRecommendations: [ImmunizationRecommendation] + invoices: [Invoice] + linkages: [Linkage] + lists: [List] + measureReports: [MeasureReport] + media: [Media] + medicationAdministrations: [MedicationAdministration] + medicationDispenses: [MedicationDispense] + medicationRequests: [MedicationRequest] + medicationStatements: [MedicationStatement] + molecularSequences: [MolecularSequence] + nutritionOrders: [NutritionOrder] + observations: [Observation] + paymentNotices: [PaymentNotice] + persons: [Person] + procedures: [Procedure] + provenances: [Provenance] + questionnaireResponses: [QuestionnaireResponse] + relatedPersons: [RelatedPerson] + requestGroups: [RequestGroup] + researchSubjects: [ResearchSubject] + riskAssessments: [RiskAssessment] + schedules: [Schedule] + serviceRequests: [ServiceRequest] + specimens: [Specimen] + subscriptions: [Subscription] + subscriptionStatuses: [SubscriptionStatus] + subscriptionTopics: [SubscriptionTopic] + supplyDeliveries: [SupplyDelivery] + supplyRequests: [SupplyRequest] + tasks: [Task] + visionPrescriptions: [VisionPrescription] + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + name: [HumanName] + telecom: [ContactPoint] + gender: Code + birthDate: Date + deceasedBoolean: Boolean + deceasedDateTime: DateTime + address: [Address] + maritalStatus: CodeableConcept + multipleBirthBoolean: Boolean + multipleBirthInteger: Int + photo: [Attachment] + contact: [PatientContact] + communication: [PatientCommunication] + generalPractitioner: [PatientGeneralPractitionerReference] + managingOrganization: PatientManagingOrganizationReference + link: [PatientLink] +} + +type Practitioner implements DomainResource & Resource { + practitionerRole: [PractitionerRole] + group: [Group] + measureReport: [MeasureReport] + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + name: [HumanName] + telecom: [ContactPoint] + address: [Address] + gender: Code + birthDate: Date + photo: [Attachment] + qualification: [PractitionerQualification] + communication: [CodeableConcept] +} + +type Subscription implements DomainResource & Resource { + subscriptionStatus: [SubscriptionStatus] + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + status: Code + contact: [ContactPoint] + end: Instant + reason: String + criteria: String + error: String + channel: SubscriptionChannel +} + +type SubscriptionStatus implements DomainResource & Resource { + subscriptionTopic: SubscriptionTopic + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + status: Code + type: Code + eventsSinceSubscriptionStart: String + notificationEvent: [SubscriptionStatusNotificationEvent] + subscription: SubscriptionStatusSubscriptionReference + topic: Canonical + error: [CodeableConcept] +} + +type ExtensionValueReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type Extension { + id: String + extension: [Extension] + url: URI + valueBase64Binary: Base64Binary + valueBoolean: Boolean + valueCanonical: Canonical + valueCode: Code + valueDate: Date + valueDateTime: DateTime + valueDecimal: Float + valueId: ID + valueInstant: Instant + valueInteger: Int + valueMarkdown: Markdown + valueOid: OID + valuePositiveInt: Int + valueString: String + valueTime: Time + valueUnsignedInt: Int + valueUri: URI + valueUrl: URL + valueUuid: UUID + valueAddress: Address + valueAge: Quantity + valueAnnotation: Annotation + valueAttachment: Attachment + valueCodeableConcept: CodeableConcept + valueCodeableReference: CodeableReference + valueCoding: Coding + valueContactPoint: ContactPoint + valueCount: Quantity + valueDistance: Quantity + valueDuration: Quantity + valueHumanName: HumanName + valueIdentifier: Identifier + valueMoney: Money + valuePeriod: Period + valueQuantity: Quantity + valueRange: Range + valueRatio: Ratio + valueRatioRange: RatioRange + valueReference: ExtensionValueReferenceReference + valueSampledData: SampledData + valueSignature: Signature + valueTiming: Timing + valueContactDetail: ContactDetail + valueContributor: Contributor + valueDataRequirement: DataRequirement + valueExpression: Expression + valueParameterDefinition: ParameterDefinition + valueRelatedArtifact: RelatedArtifact + valueTriggerDefinition: TriggerDefinition + valueUsageContext: UsageContext + valueDosage: Dosage +} + +input SearchDateValue { + """ + the value for the parameter in the resource is equal to the provided value + """ + equals: Date + + """ + the value for the parameter in the resource is not equal to the provided value + """ + notEquals: Date + + """ + the value for the parameter in the resource is greater than the provided value + """ + greaterThan: Date + + """ + the value for the parameter in the resource is greater or equal to the provided value + """ + greaterThanOrEqualTo: Date + + """ + the value for the parameter in the resource is less than the provided value + """ + lessThan: Date + + """ + the value for the parameter in the resource is less or equal to the provided value + """ + lessThanOrEqualTo: Date + + """ + the value for the parameter in the resource starts after the provided value + """ + startsAfter: Date + + """ + the value for the parameter in the resource ends before the provided value + """ + endsBefore: Date + + """ + the value for the parameter in the resource is approximately the same to the provided value. + Note that the recommended value for the approximation is 10% of the stated value (or for a date, 10% of the gap between now and the date), but systems may choose other values where appropriate + """ + approximately: Date +} + +input SearchDate { + searchType: String = "date" + value: SearchDateValue + values: [SearchDateValue] + missing: Boolean +} + +input SearchExtensionValue { + url: String + valueString: String + notEquals: NotSearchExtensionValue +} + +input NotSearchExtensionValue { + url: String + valueString: String + values: [SearchExtensionValue] +} + +input SearchExtension { + searchType: String = "token" + value: SearchExtensionValue + values: [SearchExtensionValue] + missing: Boolean + notEquals: NotSearchExtensionValue +} + +input SearchNumberValue { + """ + the value for the parameter in the resource is equal to the provided value + """ + equals: Decimal + + """ + the value for the parameter in the resource is not equal to the provided value + """ + notEquals: Decimal + + """ + the value for the parameter in the resource is greater than the provided value + """ + greaterThan: Decimal + + """ + the value for the parameter in the resource is greater or equal to the provided value + """ + greaterThanOrEqualTo: Decimal + + """ + the value for the parameter in the resource is less than the provided value + """ + lessThan: Decimal + + """ + the value for the parameter in the resource is less or equal to the provided value + """ + lessThanOrEqualTo: Decimal + + """ + the value for the parameter in the resource starts after the provided value + """ + startsAfter: Decimal + + """ + the value for the parameter in the resource ends before the provided value + """ + endsBefore: Decimal + + """ + the value for the parameter in the resource is approximately the same to the provided value. + Note that the recommended value for the approximation is 10% of the stated value (or for a date, 10% of the gap between now and the date), but systems may choose other values where appropriate + """ + approximately: Decimal +} + +input SearchNumber { + searchType: String = "number" + value: SearchNumberValue + values: [SearchNumberValue] + missing: Boolean +} + +input SearchQuantityValue { + prefix: String + value: Decimal + system: String + code: String +} + +input SearchQuantity { + searchType: String = "quantity" + prefix: String + value: Decimal + system: String + code: String + missing: Boolean + notEquals: SearchQuantityValue +} + +input SearchReferenceValue { + value: String + target: String +} + +input SearchReference { + searchType: String = "reference" + value: String + target: String + missing: Boolean + notEquals: SearchReferenceValue +} + +input SearchStringValue { + value: String + values: [String] +} + +input SearchString { + searchType: String = "string" + value: String + values: [String] + missing: Boolean + above: Boolean + below: Boolean + notEquals: SearchStringValue + contains: String + exact: String +} + +input SearchTokenValue { + code: String + value: String + system: String + notEquals: NotSearchTokenValue +} + +input NotSearchTokenValue { + code: String + value: String + system: String + values: [SearchTokenValue] +} + +input SearchToken { + searchType: String = "token" + value: SearchTokenValue + values: [SearchTokenValue] + missing: Boolean + notEquals: NotSearchTokenValue + text: String + ofType: SearchTokenValue +} + +interface DomainResource implements Resource { + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] +} + +interface Resource { + id: ID! + meta: Meta + implicitRules: URI + language: Code +} + +union AccountSubject = Patient | Device | Practitioner | PractitionerRole | Location | HealthcareService | Organization + +type AccountSubjectReference { + id: String + extension: [Extension] + reference: String + resource: AccountSubject + type: URI + identifier: Identifier + display: String +} + +type AccountOwnerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type AccountPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Account + type: URI + identifier: Identifier + display: String +} + +type Account implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: CodeableConcept + name: String + subject: [AccountSubjectReference] + servicePeriod: Period + coverage: [AccountCoverage] + owner: AccountOwnerReference + description: String + guarantor: [AccountGuarantor] + partOf: AccountPartOfReference +} + +type AccountBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Account + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AccountBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AccountBundleEntry] +} + +type ActivityDefinitionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type ActivityDefinitionLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union ActivityDefinitionProductReference = Medication | Substance | Ingredient + +type ActivityDefinitionProductReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ActivityDefinitionProductReference + type: URI + identifier: Identifier + display: String +} + +type ActivityDefinitionSpecimenRequirementReference { + id: String + extension: [Extension] + reference: String + resource: SpecimenDefinition + type: URI + identifier: Identifier + display: String +} + +type ActivityDefinitionObservationRequirementReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ActivityDefinitionObservationResultRequirementReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDefinition + type: URI + identifier: Identifier + display: String +} + +type ActivityDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + subtitle: String + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: ActivityDefinitionSubjectReferenceReference + subjectCanonical: Canonical + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + library: [Canonical] + kind: Code + profile: Canonical + code: CodeableConcept + intent: Code + priority: Code + doNotPerform: Boolean + timingTiming: Timing + timingDateTime: DateTime + timingAge: Quantity + timingPeriod: Period + timingRange: Range + timingDuration: Quantity + location: ActivityDefinitionLocationReference + participant: [ActivityDefinitionParticipant] + productReference: ActivityDefinitionProductReferenceReference + productCodeableConcept: CodeableConcept + quantity: Quantity + dosage: [Dosage] + bodySite: [CodeableConcept] + specimenRequirement: [ActivityDefinitionSpecimenRequirementReference] + observationRequirement: [ActivityDefinitionObservationRequirementReference] + observationResultRequirement: [ActivityDefinitionObservationResultRequirementReference] + transform: Canonical + dynamicValue: [ActivityDefinitionDynamicValue] +} + +type ActivityDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ActivityDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ActivityDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ActivityDefinitionBundleEntry] +} + +type AdministrableProductDefinitionFormOfReference { + id: String + extension: [Extension] + reference: String + resource: MedicinalProductDefinition + type: URI + identifier: Identifier + display: String +} + +type AdministrableProductDefinitionProducedFromReference { + id: String + extension: [Extension] + reference: String + resource: ManufacturedItemDefinition + type: URI + identifier: Identifier + display: String +} + +type AdministrableProductDefinitionDeviceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceDefinition + type: URI + identifier: Identifier + display: String +} + +type AdministrableProductDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + formOf: [AdministrableProductDefinitionFormOfReference] + administrableDoseForm: CodeableConcept + unitOfPresentation: CodeableConcept + producedFrom: [AdministrableProductDefinitionProducedFromReference] + ingredient: [CodeableConcept] + device: AdministrableProductDefinitionDeviceReference + property: [AdministrableProductDefinitionProperty] + routeOfAdministration: [AdministrableProductDefinitionRouteOfAdministration] +} + +type AdministrableProductDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: AdministrableProductDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AdministrableProductDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AdministrableProductDefinitionBundleEntry] +} + +union AdverseEventSubject = Patient | Group | Practitioner | RelatedPerson + +type AdverseEventSubjectReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventSubject + type: URI + identifier: Identifier + display: String +} + +type AdverseEventEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type AdverseEventResultingConditionReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type AdverseEventLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union AdverseEventRecorder = Patient | Practitioner | PractitionerRole | RelatedPerson + +type AdverseEventRecorderReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventRecorder + type: URI + identifier: Identifier + display: String +} + +union AdverseEventContributor = Practitioner | PractitionerRole | Device + +type AdverseEventContributorReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventContributor + type: URI + identifier: Identifier + display: String +} + +union AdverseEventSubjectMedicalHistory = Condition | Observation | AllergyIntolerance | FamilyMemberHistory | Immunization | Procedure | Media | DocumentReference + +type AdverseEventSubjectMedicalHistoryReference { + id: String + extension: [Extension] + reference: String + resource: AdverseEventSubjectMedicalHistory + type: URI + identifier: Identifier + display: String +} + +type AdverseEventReferenceDocumentReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type AdverseEventStudyReference { + id: String + extension: [Extension] + reference: String + resource: ResearchStudy + type: URI + identifier: Identifier + display: String +} + +type AdverseEvent implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + actuality: Code + category: [CodeableConcept] + event: CodeableConcept + subject: AdverseEventSubjectReference + encounter: AdverseEventEncounterReference + date: DateTime + detected: DateTime + recordedDate: DateTime + resultingCondition: [AdverseEventResultingConditionReference] + location: AdverseEventLocationReference + seriousness: CodeableConcept + severity: CodeableConcept + outcome: CodeableConcept + recorder: AdverseEventRecorderReference + contributor: [AdverseEventContributorReference] + suspectEntity: [AdverseEventSuspectEntity] + subjectMedicalHistory: [AdverseEventSubjectMedicalHistoryReference] + referenceDocument: [AdverseEventReferenceDocumentReference] + study: [AdverseEventStudyReference] +} + +type AdverseEventBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: AdverseEvent + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AdverseEventBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AdverseEventBundleEntry] +} + +type AllergyIntolerancePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type AllergyIntoleranceEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union AllergyIntoleranceRecorder = Practitioner | PractitionerRole | Patient | RelatedPerson + +type AllergyIntoleranceRecorderReference { + id: String + extension: [Extension] + reference: String + resource: AllergyIntoleranceRecorder + type: URI + identifier: Identifier + display: String +} + +union AllergyIntoleranceAsserter = Patient | RelatedPerson | Practitioner | PractitionerRole + +type AllergyIntoleranceAsserterReference { + id: String + extension: [Extension] + reference: String + resource: AllergyIntoleranceAsserter + type: URI + identifier: Identifier + display: String +} + +type AllergyIntolerance implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + clinicalStatus: CodeableConcept + verificationStatus: CodeableConcept + type: Code + category: [Code] + criticality: Code + code: CodeableConcept + patient: AllergyIntolerancePatientReference + encounter: AllergyIntoleranceEncounterReference + onsetDateTime: DateTime + onsetAge: Quantity + onsetPeriod: Period + onsetRange: Range + onsetString: String + recordedDate: DateTime + recorder: AllergyIntoleranceRecorderReference + asserter: AllergyIntoleranceAsserterReference + lastOccurrence: DateTime + note: [Annotation] + reaction: [AllergyIntoleranceReaction] +} + +type AllergyIntoleranceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: AllergyIntolerance + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AllergyIntoleranceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AllergyIntoleranceBundleEntry] +} + +union AppointmentReasonReference = Condition | Procedure | Observation | ImmunizationRecommendation + +type AppointmentReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: AppointmentReasonReference + type: URI + identifier: Identifier + display: String +} + +type AppointmentSupportingInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type AppointmentSlotReference { + id: String + extension: [Extension] + reference: String + resource: Slot + type: URI + identifier: Identifier + display: String +} + +type AppointmentBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type Appointment implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + cancelationReason: CodeableConcept + serviceCategory: [CodeableConcept] + serviceType: [CodeableConcept] + specialty: [CodeableConcept] + appointmentType: CodeableConcept + reasonCode: [CodeableConcept] + reasonReference: [AppointmentReasonReferenceReference] + priority: Int + description: String + supportingInformation: [AppointmentSupportingInformationReference] + start: Instant + end: Instant + minutesDuration: Int + slot: [AppointmentSlotReference] + created: DateTime + comment: String + patientInstruction: String + basedOn: [AppointmentBasedOnReference] + participant: [AppointmentParticipant] + requestedPeriod: [Period] +} + +type AppointmentBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Appointment + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AppointmentBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AppointmentBundleEntry] +} + +type AppointmentResponseAppointmentReference { + id: String + extension: [Extension] + reference: String + resource: Appointment + type: URI + identifier: Identifier + display: String +} + +union AppointmentResponseActor = Patient | Practitioner | PractitionerRole | RelatedPerson | Device | HealthcareService | Location + +type AppointmentResponseActorReference { + id: String + extension: [Extension] + reference: String + resource: AppointmentResponseActor + type: URI + identifier: Identifier + display: String +} + +type AppointmentResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + appointment: AppointmentResponseAppointmentReference + start: Instant + end: Instant + participantType: [CodeableConcept] + actor: AppointmentResponseActorReference + participantStatus: Code + comment: String +} + +type AppointmentResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: AppointmentResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AppointmentResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AppointmentResponseBundleEntry] +} + +type AuditEvent implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + type: Coding + subtype: [Coding] + action: Code + period: Period + recorded: Instant + outcome: Code + outcomeDesc: String + purposeOfEvent: [CodeableConcept] + agent: [AuditEventAgent] + source: AuditEventSource + entity: [AuditEventEntity] +} + +type AuditEventBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: AuditEvent + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type AuditEventBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [AuditEventBundleEntry] +} + +type BasicSubjectReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union BasicAuthor = Practitioner | PractitionerRole | Patient | RelatedPerson | Organization + +type BasicAuthorReference { + id: String + extension: [Extension] + reference: String + resource: BasicAuthor + type: URI + identifier: Identifier + display: String +} + +type Basic implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + code: CodeableConcept + subject: BasicSubjectReference + created: Date + author: BasicAuthorReference +} + +type BasicBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Basic + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BasicBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [BasicBundleEntry] +} + +type BinarySecurityContextReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type Binary implements Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + contentType: Code + securityContext: BinarySecurityContextReference + data: Base64Binary +} + +type BinaryBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Binary + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BinaryBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [BinaryBundleEntry] +} + +type BiologicallyDerivedProductRequestReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type BiologicallyDerivedProductParentReference { + id: String + extension: [Extension] + reference: String + resource: BiologicallyDerivedProduct + type: URI + identifier: Identifier + display: String +} + +type BiologicallyDerivedProduct implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + productCategory: Code + productCode: CodeableConcept + status: Code + request: [BiologicallyDerivedProductRequestReference] + quantity: Int + parent: [BiologicallyDerivedProductParentReference] + collection: BiologicallyDerivedProductCollection + processing: [BiologicallyDerivedProductProcessing] + manipulation: BiologicallyDerivedProductManipulation + storage: [BiologicallyDerivedProductStorage] +} + +type BiologicallyDerivedProductBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: BiologicallyDerivedProduct + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BiologicallyDerivedProductBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [BiologicallyDerivedProductBundleEntry] +} + +type BodyStructurePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type BodyStructure implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + morphology: CodeableConcept + location: CodeableConcept + locationQualifier: [CodeableConcept] + description: String + image: [Attachment] + patient: BodyStructurePatientReference +} + +type BodyStructureBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: BodyStructure + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BodyStructureBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [BodyStructureBundleEntry] +} + +type Bundle implements Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + identifier: Identifier + type: Code + timestamp: Instant + total: Int + link: [BundleLink] + entry: [BundleEntry] + signature: Signature +} + +type BundleBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Bundle + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type BundleBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [BundleBundleEntry] +} + +type CapabilityStatement implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + kind: Code + instantiates: [Canonical] + imports: [Canonical] + software: CapabilityStatementSoftware + implementation: CapabilityStatementImplementation + fhirVersion: Code + format: [Code] + patchFormat: [Code] + implementationGuide: [Canonical] + rest: [CapabilityStatementRest] + messaging: [CapabilityStatementMessaging] + document: [CapabilityStatementDocument] +} + +type CapabilityStatementBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CapabilityStatement + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CapabilityStatementBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CapabilityStatementBundleEntry] +} + +type CarePlanBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: CarePlan + type: URI + identifier: Identifier + display: String +} + +type CarePlanReplacesReference { + id: String + extension: [Extension] + reference: String + resource: CarePlan + type: URI + identifier: Identifier + display: String +} + +type CarePlanPartOfReference { + id: String + extension: [Extension] + reference: String + resource: CarePlan + type: URI + identifier: Identifier + display: String +} + +union CarePlanSubject = Patient | Group + +type CarePlanSubjectReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanSubject + type: URI + identifier: Identifier + display: String +} + +type CarePlanEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union CarePlanAuthor = Patient | Practitioner | PractitionerRole | Device | RelatedPerson | Organization | CareTeam + +type CarePlanAuthorReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanAuthor + type: URI + identifier: Identifier + display: String +} + +union CarePlanContributor = Patient | Practitioner | PractitionerRole | Device | RelatedPerson | Organization | CareTeam + +type CarePlanContributorReference { + id: String + extension: [Extension] + reference: String + resource: CarePlanContributor + type: URI + identifier: Identifier + display: String +} + +type CarePlanCareTeamReference { + id: String + extension: [Extension] + reference: String + resource: CareTeam + type: URI + identifier: Identifier + display: String +} + +type CarePlanAddressesReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type CarePlanSupportingInfoReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CarePlanGoalReference { + id: String + extension: [Extension] + reference: String + resource: Goal + type: URI + identifier: Identifier + display: String +} + +type CarePlan implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [CarePlanBasedOnReference] + replaces: [CarePlanReplacesReference] + partOf: [CarePlanPartOfReference] + status: Code + intent: Code + category: [CodeableConcept] + title: String + description: String + subject: CarePlanSubjectReference + encounter: CarePlanEncounterReference + period: Period + created: DateTime + author: CarePlanAuthorReference + contributor: [CarePlanContributorReference] + careTeam: [CarePlanCareTeamReference] + addresses: [CarePlanAddressesReference] + supportingInfo: [CarePlanSupportingInfoReference] + goal: [CarePlanGoalReference] + activity: [CarePlanActivity] + note: [Annotation] +} + +type CarePlanBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CarePlan + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CarePlanBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CarePlanBundleEntry] +} + +union CareTeamSubject = Patient | Group + +type CareTeamSubjectReference { + id: String + extension: [Extension] + reference: String + resource: CareTeamSubject + type: URI + identifier: Identifier + display: String +} + +type CareTeamEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type CareTeamReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +type CareTeamManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CareTeam implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + category: [CodeableConcept] + name: String + subject: CareTeamSubjectReference + encounter: CareTeamEncounterReference + period: Period + participant: [CareTeamParticipant] + reasonCode: [CodeableConcept] + reasonReference: [CareTeamReasonReferenceReference] + managingOrganization: [CareTeamManagingOrganizationReference] + telecom: [ContactPoint] + note: [Annotation] +} + +type CareTeamBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CareTeam + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CareTeamBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CareTeamBundleEntry] +} + +union CatalogEntryReferencedItem = Medication | Device | Organization | Practitioner | PractitionerRole | HealthcareService | ActivityDefinition | PlanDefinition | SpecimenDefinition | ObservationDefinition | Binary + +type CatalogEntryReferencedItemReference { + id: String + extension: [Extension] + reference: String + resource: CatalogEntryReferencedItem + type: URI + identifier: Identifier + display: String +} + +type CatalogEntry implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: CodeableConcept + orderable: Boolean + referencedItem: CatalogEntryReferencedItemReference + additionalIdentifier: [Identifier] + classification: [CodeableConcept] + status: Code + validityPeriod: Period + validTo: DateTime + lastUpdated: DateTime + additionalCharacteristic: [CodeableConcept] + additionalClassification: [CodeableConcept] + relatedEntry: [CatalogEntryRelatedEntry] +} + +type CatalogEntryBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CatalogEntry + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CatalogEntryBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CatalogEntryBundleEntry] +} + +type ChargeItemPartOfReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItem + type: URI + identifier: Identifier + display: String +} + +union ChargeItemSubject = Patient | Group + +type ChargeItemSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemSubject + type: URI + identifier: Identifier + display: String +} + +union ChargeItemContext = Encounter | EpisodeOfCare + +type ChargeItemContextReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemContext + type: URI + identifier: Identifier + display: String +} + +type ChargeItemPerformingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ChargeItemRequestingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ChargeItemCostCenterReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ChargeItemEnterer = Practitioner | PractitionerRole | Organization | Patient | Device | RelatedPerson + +type ChargeItemEntererReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemEnterer + type: URI + identifier: Identifier + display: String +} + +union ChargeItemService = DiagnosticReport | ImagingStudy | Immunization | MedicationAdministration | MedicationDispense | Observation | Procedure | SupplyDelivery + +type ChargeItemServiceReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemService + type: URI + identifier: Identifier + display: String +} + +union ChargeItemProductReference = Device | Medication | Substance + +type ChargeItemProductReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemProductReference + type: URI + identifier: Identifier + display: String +} + +type ChargeItemAccountReference { + id: String + extension: [Extension] + reference: String + resource: Account + type: URI + identifier: Identifier + display: String +} + +type ChargeItemSupportingInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ChargeItem implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + definitionUri: [URI] + definitionCanonical: [Canonical] + status: Code + partOf: [ChargeItemPartOfReference] + code: CodeableConcept + subject: ChargeItemSubjectReference + context: ChargeItemContextReference + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + performer: [ChargeItemPerformer] + performingOrganization: ChargeItemPerformingOrganizationReference + requestingOrganization: ChargeItemRequestingOrganizationReference + costCenter: ChargeItemCostCenterReference + quantity: Quantity + bodysite: [CodeableConcept] + factorOverride: Float + priceOverride: Money + overrideReason: String + enterer: ChargeItemEntererReference + enteredDate: DateTime + reason: [CodeableConcept] + service: [ChargeItemServiceReference] + productReference: ChargeItemProductReferenceReference + productCodeableConcept: CodeableConcept + account: [ChargeItemAccountReference] + note: [Annotation] + supportingInformation: [ChargeItemSupportingInformationReference] +} + +type ChargeItemBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ChargeItem + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ChargeItemBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ChargeItemBundleEntry] +} + +union ChargeItemDefinitionInstance = Medication | Substance | Device + +type ChargeItemDefinitionInstanceReference { + id: String + extension: [Extension] + reference: String + resource: ChargeItemDefinitionInstance + type: URI + identifier: Identifier + display: String +} + +type ChargeItemDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + title: String + derivedFromUri: [URI] + partOf: [Canonical] + replaces: [Canonical] + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + code: CodeableConcept + instance: [ChargeItemDefinitionInstanceReference] + applicability: [ChargeItemDefinitionApplicability] + propertyGroup: [ChargeItemDefinitionPropertyGroup] +} + +type ChargeItemDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ChargeItemDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ChargeItemDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ChargeItemDefinitionBundleEntry] +} + +type Citation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + summary: [CitationSummary] + classification: [CitationClassification] + note: [Annotation] + currentState: [CodeableConcept] + statusDate: [CitationStatusDate] + relatesTo: [CitationRelatesTo] + citedArtifact: CitationCitedArtifact +} + +type CitationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Citation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CitationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CitationBundleEntry] +} + +type ClaimPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union ClaimEnterer = Practitioner | PractitionerRole + +type ClaimEntererReference { + id: String + extension: [Extension] + reference: String + resource: ClaimEnterer + type: URI + identifier: Identifier + display: String +} + +type ClaimInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ClaimProvider = Practitioner | PractitionerRole | Organization + +type ClaimProviderReference { + id: String + extension: [Extension] + reference: String + resource: ClaimProvider + type: URI + identifier: Identifier + display: String +} + +union ClaimPrescription = DeviceRequest | MedicationRequest | VisionPrescription + +type ClaimPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: ClaimPrescription + type: URI + identifier: Identifier + display: String +} + +union ClaimOriginalPrescription = DeviceRequest | MedicationRequest | VisionPrescription + +type ClaimOriginalPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: ClaimOriginalPrescription + type: URI + identifier: Identifier + display: String +} + +type ClaimReferralReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type ClaimFacilityReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type Claim implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: CodeableConcept + subType: CodeableConcept + use: Code + patient: ClaimPatientReference + billablePeriod: Period + created: DateTime + enterer: ClaimEntererReference + insurer: ClaimInsurerReference + provider: ClaimProviderReference + priority: CodeableConcept + fundsReserve: CodeableConcept + related: [ClaimRelated] + prescription: ClaimPrescriptionReference + originalPrescription: ClaimOriginalPrescriptionReference + payee: ClaimPayee + referral: ClaimReferralReference + facility: ClaimFacilityReference + careTeam: [ClaimCareTeam] + supportingInfo: [ClaimSupportingInfo] + diagnosis: [ClaimDiagnosis] + procedure: [ClaimProcedure] + insurance: [ClaimInsurance] + accident: ClaimAccident + item: [ClaimItem] + total: Money +} + +type ClaimBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Claim + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ClaimBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ClaimBundleEntry] +} + +type ClaimResponsePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ClaimResponseRequestor = Practitioner | PractitionerRole | Organization + +type ClaimResponseRequestorReference { + id: String + extension: [Extension] + reference: String + resource: ClaimResponseRequestor + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseRequestReference { + id: String + extension: [Extension] + reference: String + resource: Claim + type: URI + identifier: Identifier + display: String +} + +type ClaimResponseCommunicationRequestReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequest + type: URI + identifier: Identifier + display: String +} + +type ClaimResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: CodeableConcept + subType: CodeableConcept + use: Code + patient: ClaimResponsePatientReference + created: DateTime + insurer: ClaimResponseInsurerReference + requestor: ClaimResponseRequestorReference + request: ClaimResponseRequestReference + outcome: Code + disposition: String + preAuthRef: String + preAuthPeriod: Period + payeeType: CodeableConcept + item: [ClaimResponseItem] + addItem: [ClaimResponseAddItem] + adjudication: [ClaimResponseAdjudication] + total: [ClaimResponseTotal] + payment: ClaimResponsePayment + fundsReserve: CodeableConcept + formCode: CodeableConcept + form: Attachment + processNote: [ClaimResponseProcessNote] + communicationRequest: [ClaimResponseCommunicationRequestReference] + insurance: [ClaimResponseInsurance] + error: [ClaimResponseError] +} + +type ClaimResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ClaimResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ClaimResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ClaimResponseBundleEntry] +} + +union ClinicalImpressionSubject = Patient | Group + +type ClinicalImpressionSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpressionSubject + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ClinicalImpressionAssessor = Practitioner | PractitionerRole + +type ClinicalImpressionAssessorReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpressionAssessor + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionPreviousReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpression + type: URI + identifier: Identifier + display: String +} + +union ClinicalImpressionProblem = Condition | AllergyIntolerance + +type ClinicalImpressionProblemReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalImpressionProblem + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionPrognosisReferenceReference { + id: String + extension: [Extension] + reference: String + resource: RiskAssessment + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpressionSupportingInfoReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ClinicalImpression implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + statusReason: CodeableConcept + code: CodeableConcept + description: String + subject: ClinicalImpressionSubjectReference + encounter: ClinicalImpressionEncounterReference + effectiveDateTime: DateTime + effectivePeriod: Period + date: DateTime + assessor: ClinicalImpressionAssessorReference + previous: ClinicalImpressionPreviousReference + problem: [ClinicalImpressionProblemReference] + investigation: [ClinicalImpressionInvestigation] + protocol: [URI] + summary: String + finding: [ClinicalImpressionFinding] + prognosisCodeableConcept: [CodeableConcept] + prognosisReference: [ClinicalImpressionPrognosisReferenceReference] + supportingInfo: [ClinicalImpressionSupportingInfoReference] + note: [Annotation] +} + +type ClinicalImpressionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ClinicalImpression + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ClinicalImpressionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ClinicalImpressionBundleEntry] +} + +union ClinicalUseDefinitionSubject = MedicinalProductDefinition | Medication | ActivityDefinition | PlanDefinition | Device | DeviceDefinition | Substance + +type ClinicalUseDefinitionSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinitionSubject + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinitionPopulationReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type ClinicalUseDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: Code + category: [CodeableConcept] + subject: [ClinicalUseDefinitionSubjectReference] + status: CodeableConcept + contraindication: ClinicalUseDefinitionContraindication + indication: ClinicalUseDefinitionIndication + interaction: ClinicalUseDefinitionInteraction + population: [ClinicalUseDefinitionPopulationReference] + undesirableEffect: ClinicalUseDefinitionUndesirableEffect + warning: ClinicalUseDefinitionWarning +} + +type ClinicalUseDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ClinicalUseDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ClinicalUseDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ClinicalUseDefinitionBundleEntry] +} + +type CodeSystem implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + caseSensitive: Boolean + valueSet: Canonical + hierarchyMeaning: Code + compositional: Boolean + versionNeeded: Boolean + content: Code + supplements: Canonical + count: Int + filter: [CodeSystemFilter] + property: [CodeSystemProperty] + concept: [CodeSystemConcept] +} + +type CodeSystemBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CodeSystem + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CodeSystemBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CodeSystemBundleEntry] +} + +type CommunicationBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationInResponseToReference { + id: String + extension: [Extension] + reference: String + resource: Communication + type: URI + identifier: Identifier + display: String +} + +union CommunicationSubject = Patient | Group + +type CommunicationSubjectReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationSubject + type: URI + identifier: Identifier + display: String +} + +type CommunicationAboutReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union CommunicationRecipient = Device | Organization | Patient | Practitioner | PractitionerRole | RelatedPerson | Group | CareTeam | HealthcareService + +type CommunicationRecipientReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRecipient + type: URI + identifier: Identifier + display: String +} + +union CommunicationSender = Device | Organization | Patient | Practitioner | PractitionerRole | RelatedPerson | HealthcareService + +type CommunicationSenderReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationSender + type: URI + identifier: Identifier + display: String +} + +union CommunicationReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type CommunicationReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationReasonReference + type: URI + identifier: Identifier + display: String +} + +type Communication implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [CommunicationBasedOnReference] + partOf: [CommunicationPartOfReference] + inResponseTo: [CommunicationInResponseToReference] + status: Code + statusReason: CodeableConcept + category: [CodeableConcept] + priority: Code + medium: [CodeableConcept] + subject: CommunicationSubjectReference + topic: CodeableConcept + about: [CommunicationAboutReference] + encounter: CommunicationEncounterReference + sent: DateTime + received: DateTime + recipient: [CommunicationRecipientReference] + sender: CommunicationSenderReference + reasonCode: [CodeableConcept] + reasonReference: [CommunicationReasonReferenceReference] + payload: [CommunicationPayload] + note: [Annotation] +} + +type CommunicationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Communication + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CommunicationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CommunicationBundleEntry] +} + +type CommunicationRequestBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationRequestReplacesReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequest + type: URI + identifier: Identifier + display: String +} + +union CommunicationRequestSubject = Patient | Group + +type CommunicationRequestSubjectReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequestSubject + type: URI + identifier: Identifier + display: String +} + +type CommunicationRequestAboutReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CommunicationRequestEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union CommunicationRequestRequester = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device + +type CommunicationRequestRequesterReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequestRequester + type: URI + identifier: Identifier + display: String +} + +union CommunicationRequestRecipient = Device | Organization | Patient | Practitioner | PractitionerRole | RelatedPerson | Group | CareTeam | HealthcareService + +type CommunicationRequestRecipientReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequestRecipient + type: URI + identifier: Identifier + display: String +} + +union CommunicationRequestSender = Device | Organization | Patient | Practitioner | PractitionerRole | RelatedPerson | HealthcareService + +type CommunicationRequestSenderReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequestSender + type: URI + identifier: Identifier + display: String +} + +union CommunicationRequestReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type CommunicationRequestReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: CommunicationRequestReasonReference + type: URI + identifier: Identifier + display: String +} + +type CommunicationRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [CommunicationRequestBasedOnReference] + replaces: [CommunicationRequestReplacesReference] + groupIdentifier: Identifier + status: Code + statusReason: CodeableConcept + category: [CodeableConcept] + priority: Code + doNotPerform: Boolean + medium: [CodeableConcept] + subject: CommunicationRequestSubjectReference + about: [CommunicationRequestAboutReference] + encounter: CommunicationRequestEncounterReference + payload: [CommunicationRequestPayload] + occurrenceDateTime: DateTime + occurrencePeriod: Period + authoredOn: DateTime + requester: CommunicationRequestRequesterReference + recipient: [CommunicationRequestRecipientReference] + sender: CommunicationRequestSenderReference + reasonCode: [CodeableConcept] + reasonReference: [CommunicationRequestReasonReferenceReference] + note: [Annotation] +} + +type CommunicationRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CommunicationRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CommunicationRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CommunicationRequestBundleEntry] +} + +type CompartmentDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + purpose: Markdown + code: Code + search: Boolean + resource: [CompartmentDefinitionResource] +} + +type CompartmentDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CompartmentDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CompartmentDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CompartmentDefinitionBundleEntry] +} + +type CompositionSubjectReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type CompositionEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union CompositionAuthor = Practitioner | PractitionerRole | Device | Patient | RelatedPerson | Organization + +type CompositionAuthorReference { + id: String + extension: [Extension] + reference: String + resource: CompositionAuthor + type: URI + identifier: Identifier + display: String +} + +type CompositionCustodianReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type Composition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + status: Code + type: CodeableConcept + category: [CodeableConcept] + subject: CompositionSubjectReference + encounter: CompositionEncounterReference + date: DateTime + author: [CompositionAuthorReference] + title: String + confidentiality: Code + attester: [CompositionAttester] + custodian: CompositionCustodianReference + relatesTo: [CompositionRelatesTo] + event: [CompositionEvent] + section: [CompositionSection] +} + +type CompositionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Composition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CompositionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CompositionBundleEntry] +} + +type ConceptMap implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: Identifier + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + sourceUri: URI + sourceCanonical: Canonical + targetUri: URI + targetCanonical: Canonical + group: [ConceptMapGroup] +} + +type ConceptMapBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ConceptMap + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ConceptMapBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ConceptMapBundleEntry] +} + +union ConditionSubject = Patient | Group + +type ConditionSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ConditionSubject + type: URI + identifier: Identifier + display: String +} + +type ConditionEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ConditionRecorder = Practitioner | PractitionerRole | Patient | RelatedPerson + +type ConditionRecorderReference { + id: String + extension: [Extension] + reference: String + resource: ConditionRecorder + type: URI + identifier: Identifier + display: String +} + +union ConditionAsserter = Practitioner | PractitionerRole | Patient | RelatedPerson + +type ConditionAsserterReference { + id: String + extension: [Extension] + reference: String + resource: ConditionAsserter + type: URI + identifier: Identifier + display: String +} + +type Condition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + clinicalStatus: CodeableConcept + verificationStatus: CodeableConcept + category: [CodeableConcept] + severity: CodeableConcept + code: CodeableConcept + bodySite: [CodeableConcept] + subject: ConditionSubjectReference + encounter: ConditionEncounterReference + onsetDateTime: DateTime + onsetAge: Quantity + onsetPeriod: Period + onsetRange: Range + onsetString: String + abatementDateTime: DateTime + abatementAge: Quantity + abatementPeriod: Period + abatementRange: Range + abatementString: String + recordedDate: DateTime + recorder: ConditionRecorderReference + asserter: ConditionAsserterReference + stage: [ConditionStage] + evidence: [ConditionEvidence] + note: [Annotation] +} + +type ConditionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Condition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ConditionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ConditionBundleEntry] +} + +type ConsentPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union ConsentPerformer = Organization | Patient | Practitioner | RelatedPerson | PractitionerRole + +type ConsentPerformerReference { + id: String + extension: [Extension] + reference: String + resource: ConsentPerformer + type: URI + identifier: Identifier + display: String +} + +type ConsentOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ConsentSourceReference = Consent | DocumentReference | Contract | QuestionnaireResponse + +type ConsentSourceReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ConsentSourceReference + type: URI + identifier: Identifier + display: String +} + +type Consent implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + scope: CodeableConcept + category: [CodeableConcept] + patient: ConsentPatientReference + dateTime: DateTime + performer: [ConsentPerformerReference] + organization: [ConsentOrganizationReference] + sourceAttachment: Attachment + sourceReference: ConsentSourceReferenceReference + policy: [ConsentPolicy] + policyRule: CodeableConcept + verification: [ConsentVerification] + provision: ConsentProvision +} + +type ConsentBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Consent + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ConsentBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ConsentBundleEntry] +} + +type ContractInstantiatesCanonicalReference { + id: String + extension: [Extension] + reference: String + resource: Contract + type: URI + identifier: Identifier + display: String +} + +type ContractSubjectTypeReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractAuthorityReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ContractDomainReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ContractSiteReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union ContractAuthor = Patient | Practitioner | PractitionerRole | Organization + +type ContractAuthorReference { + id: String + extension: [Extension] + reference: String + resource: ContractAuthor + type: URI + identifier: Identifier + display: String +} + +type ContractTopicReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractSupportingInfoReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ContractRelevantHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +union ContractLegallyBindingReference = Composition | DocumentReference | QuestionnaireResponse | Contract + +type ContractLegallyBindingReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ContractLegallyBindingReference + type: URI + identifier: Identifier + display: String +} + +type Contract implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + url: URI + version: String + status: Code + legalState: CodeableConcept + instantiatesCanonical: ContractInstantiatesCanonicalReference + instantiatesUri: URI + contentDerivative: CodeableConcept + issued: DateTime + applies: Period + expirationType: CodeableConcept + subject: [ContractSubjectTypeReference] + authority: [ContractAuthorityReference] + domain: [ContractDomainReference] + site: [ContractSiteReference] + name: String + title: String + subtitle: String + alias: [String] + author: ContractAuthorReference + scope: CodeableConcept + topicCodeableConcept: CodeableConcept + topicReference: ContractTopicReferenceReference + type: CodeableConcept + subType: [CodeableConcept] + contentDefinition: ContractContentDefinition + term: [ContractTerm] + supportingInfo: [ContractSupportingInfoReference] + relevantHistory: [ContractRelevantHistoryReference] + signer: [ContractSigner] + friendly: [ContractFriendly] + legal: [ContractLegal] + rule: [ContractRule] + legallyBindingAttachment: Attachment + legallyBindingReference: ContractLegallyBindingReferenceReference +} + +type ContractBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Contract + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ContractBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ContractBundleEntry] +} + +union CoveragePolicyHolder = Patient | RelatedPerson | Organization + +type CoveragePolicyHolderReference { + id: String + extension: [Extension] + reference: String + resource: CoveragePolicyHolder + type: URI + identifier: Identifier + display: String +} + +union CoverageSubscriber = Patient | RelatedPerson + +type CoverageSubscriberReference { + id: String + extension: [Extension] + reference: String + resource: CoverageSubscriber + type: URI + identifier: Identifier + display: String +} + +type CoverageBeneficiaryReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union CoveragePayor = Organization | Patient | RelatedPerson + +type CoveragePayorReference { + id: String + extension: [Extension] + reference: String + resource: CoveragePayor + type: URI + identifier: Identifier + display: String +} + +type CoverageContractReference { + id: String + extension: [Extension] + reference: String + resource: Contract + type: URI + identifier: Identifier + display: String +} + +type Coverage implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: CodeableConcept + policyHolder: CoveragePolicyHolderReference + subscriber: CoverageSubscriberReference + subscriberId: String + beneficiary: CoverageBeneficiaryReference + dependent: String + relationship: CodeableConcept + period: Period + payor: [CoveragePayorReference] + class: [CoverageClass] + order: Int + network: String + costToBeneficiary: [CoverageCostToBeneficiary] + subrogation: Boolean + contract: [CoverageContractReference] +} + +type CoverageBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Coverage + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CoverageBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CoverageBundleEntry] +} + +type CoverageEligibilityRequestPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union CoverageEligibilityRequestEnterer = Practitioner | PractitionerRole + +type CoverageEligibilityRequestEntererReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityRequestEnterer + type: URI + identifier: Identifier + display: String +} + +union CoverageEligibilityRequestProvider = Practitioner | PractitionerRole | Organization + +type CoverageEligibilityRequestProviderReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityRequestProvider + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequestFacilityReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + priority: CodeableConcept + purpose: [Code] + patient: CoverageEligibilityRequestPatientReference + servicedDate: Date + servicedPeriod: Period + created: DateTime + enterer: CoverageEligibilityRequestEntererReference + provider: CoverageEligibilityRequestProviderReference + insurer: CoverageEligibilityRequestInsurerReference + facility: CoverageEligibilityRequestFacilityReference + supportingInfo: [CoverageEligibilityRequestSupportingInfo] + insurance: [CoverageEligibilityRequestInsurance] + item: [CoverageEligibilityRequestItem] +} + +type CoverageEligibilityRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CoverageEligibilityRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CoverageEligibilityRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CoverageEligibilityRequestBundleEntry] +} + +type CoverageEligibilityResponsePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union CoverageEligibilityResponseRequestor = Practitioner | PractitionerRole | Organization + +type CoverageEligibilityResponseRequestorReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityResponseRequestor + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityResponseRequestReference { + id: String + extension: [Extension] + reference: String + resource: CoverageEligibilityRequest + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityResponseInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type CoverageEligibilityResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + purpose: [Code] + patient: CoverageEligibilityResponsePatientReference + servicedDate: Date + servicedPeriod: Period + created: DateTime + requestor: CoverageEligibilityResponseRequestorReference + request: CoverageEligibilityResponseRequestReference + outcome: Code + disposition: String + insurer: CoverageEligibilityResponseInsurerReference + insurance: [CoverageEligibilityResponseInsurance] + preAuthRef: String + form: CodeableConcept + error: [CoverageEligibilityResponseError] +} + +type CoverageEligibilityResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: CoverageEligibilityResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type CoverageEligibilityResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [CoverageEligibilityResponseBundleEntry] +} + +type DetectedIssuePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union DetectedIssueAuthor = Practitioner | PractitionerRole | Device + +type DetectedIssueAuthorReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssueAuthor + type: URI + identifier: Identifier + display: String +} + +type DetectedIssueImplicatedReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DetectedIssue implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + code: CodeableConcept + severity: Code + patient: DetectedIssuePatientReference + identifiedDateTime: DateTime + identifiedPeriod: Period + author: DetectedIssueAuthorReference + implicated: [DetectedIssueImplicatedReference] + evidence: [DetectedIssueEvidence] + detail: String + reference: URI + mitigation: [DetectedIssueMitigation] +} + +type DetectedIssueBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DetectedIssue + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DetectedIssueBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DetectedIssueBundleEntry] +} + +type DeviceDefinitionReference { + id: String + extension: [Extension] + reference: String + resource: DeviceDefinition + type: URI + identifier: Identifier + display: String +} + +type DevicePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type DeviceOwnerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type DeviceLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type DeviceParentReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type Device implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + definition: DeviceDefinitionReference + udiCarrier: [DeviceUdiCarrier] + status: Code + statusReason: [CodeableConcept] + distinctIdentifier: String + manufacturer: String + manufactureDate: DateTime + expirationDate: DateTime + lotNumber: String + serialNumber: String + deviceName: [DeviceDeviceName] + modelNumber: String + partNumber: String + type: CodeableConcept + specialization: [DeviceSpecialization] + version: [DeviceVersion] + property: [DeviceProperty] + patient: DevicePatientReference + owner: DeviceOwnerReference + contact: [ContactPoint] + location: DeviceLocationReference + url: URI + note: [Annotation] + safety: [CodeableConcept] + parent: DeviceParentReference +} + +type DeviceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Device + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DeviceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DeviceBundleEntry] +} + +type DeviceDefinitionManufacturerReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type DeviceDefinitionOwnerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type DeviceDefinitionParentDeviceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceDefinition + type: URI + identifier: Identifier + display: String +} + +type DeviceDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + udiDeviceIdentifier: [DeviceDefinitionUdiDeviceIdentifier] + manufacturerString: String + manufacturerReference: DeviceDefinitionManufacturerReferenceReference + deviceName: [DeviceDefinitionDeviceName] + modelNumber: String + type: CodeableConcept + specialization: [DeviceDefinitionSpecialization] + version: [String] + safety: [CodeableConcept] + shelfLifeStorage: [ProductShelfLife] + physicalCharacteristics: ProdCharacteristic + languageCode: [CodeableConcept] + capability: [DeviceDefinitionCapability] + property: [DeviceDefinitionProperty] + owner: DeviceDefinitionOwnerReference + contact: [ContactPoint] + url: URI + onlineInformation: URI + note: [Annotation] + quantity: Quantity + parentDevice: DeviceDefinitionParentDeviceReference + material: [DeviceDefinitionMaterial] +} + +type DeviceDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DeviceDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DeviceDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DeviceDefinitionBundleEntry] +} + +type DeviceMetricSourceReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type DeviceMetricParentReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type DeviceMetric implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: CodeableConcept + unit: CodeableConcept + source: DeviceMetricSourceReference + parent: DeviceMetricParentReference + operationalStatus: Code + color: Code + category: Code + measurementPeriod: Timing + calibration: [DeviceMetricCalibration] +} + +type DeviceMetricBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DeviceMetric + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DeviceMetricBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DeviceMetricBundleEntry] +} + +type DeviceRequestBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DeviceRequestPriorRequestReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DeviceRequestCodeReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +union DeviceRequestSubject = Patient | Group | Location | Device + +type DeviceRequestSubjectReference { + id: String + extension: [Extension] + reference: String + resource: DeviceRequestSubject + type: URI + identifier: Identifier + display: String +} + +type DeviceRequestEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union DeviceRequestRequester = Device | Practitioner | PractitionerRole | Organization + +type DeviceRequestRequesterReference { + id: String + extension: [Extension] + reference: String + resource: DeviceRequestRequester + type: URI + identifier: Identifier + display: String +} + +union DeviceRequestPerformer = Practitioner | PractitionerRole | Organization | CareTeam | HealthcareService | Patient | Device | RelatedPerson + +type DeviceRequestPerformerReference { + id: String + extension: [Extension] + reference: String + resource: DeviceRequestPerformer + type: URI + identifier: Identifier + display: String +} + +union DeviceRequestReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type DeviceRequestReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceRequestReasonReference + type: URI + identifier: Identifier + display: String +} + +union DeviceRequestInsurance = Coverage | ClaimResponse + +type DeviceRequestInsuranceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceRequestInsurance + type: URI + identifier: Identifier + display: String +} + +type DeviceRequestSupportingInfoReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DeviceRequestRelevantHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type DeviceRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [DeviceRequestBasedOnReference] + priorRequest: [DeviceRequestPriorRequestReference] + groupIdentifier: Identifier + status: Code + intent: Code + priority: Code + codeReference: DeviceRequestCodeReferenceReference + codeCodeableConcept: CodeableConcept + parameter: [DeviceRequestParameter] + subject: DeviceRequestSubjectReference + encounter: DeviceRequestEncounterReference + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + authoredOn: DateTime + requester: DeviceRequestRequesterReference + performerType: CodeableConcept + performer: DeviceRequestPerformerReference + reasonCode: [CodeableConcept] + reasonReference: [DeviceRequestReasonReferenceReference] + insurance: [DeviceRequestInsuranceReference] + supportingInfo: [DeviceRequestSupportingInfoReference] + note: [Annotation] + relevantHistory: [DeviceRequestRelevantHistoryReference] +} + +type DeviceRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DeviceRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DeviceRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DeviceRequestBundleEntry] +} + +type DeviceUseStatementBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +union DeviceUseStatementSubject = Patient | Group + +type DeviceUseStatementSubjectReference { + id: String + extension: [Extension] + reference: String + resource: DeviceUseStatementSubject + type: URI + identifier: Identifier + display: String +} + +union DeviceUseStatementDerivedFrom = ServiceRequest | Procedure | Claim | Observation | QuestionnaireResponse | DocumentReference + +type DeviceUseStatementDerivedFromReference { + id: String + extension: [Extension] + reference: String + resource: DeviceUseStatementDerivedFrom + type: URI + identifier: Identifier + display: String +} + +union DeviceUseStatementSource = Patient | Practitioner | PractitionerRole | RelatedPerson + +type DeviceUseStatementSourceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceUseStatementSource + type: URI + identifier: Identifier + display: String +} + +type DeviceUseStatementDeviceReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +union DeviceUseStatementReasonReference = Condition | Observation | DiagnosticReport | DocumentReference | Media + +type DeviceUseStatementReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: DeviceUseStatementReasonReference + type: URI + identifier: Identifier + display: String +} + +type DeviceUseStatement implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [DeviceUseStatementBasedOnReference] + status: Code + subject: DeviceUseStatementSubjectReference + derivedFrom: [DeviceUseStatementDerivedFromReference] + timingTiming: Timing + timingPeriod: Period + timingDateTime: DateTime + recordedOn: DateTime + source: DeviceUseStatementSourceReference + device: DeviceUseStatementDeviceReference + reasonCode: [CodeableConcept] + reasonReference: [DeviceUseStatementReasonReferenceReference] + bodySite: CodeableConcept + note: [Annotation] +} + +type DeviceUseStatementBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DeviceUseStatement + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DeviceUseStatementBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DeviceUseStatementBundleEntry] +} + +union DiagnosticReportBasedOn = CarePlan | ImmunizationRecommendation | MedicationRequest | NutritionOrder | ServiceRequest + +type DiagnosticReportBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: DiagnosticReportBasedOn + type: URI + identifier: Identifier + display: String +} + +union DiagnosticReportSubject = Patient | Group | Device | Location | Organization | Procedure | Practitioner | Medication | Substance + +type DiagnosticReportSubjectReference { + id: String + extension: [Extension] + reference: String + resource: DiagnosticReportSubject + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReportEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union DiagnosticReportPerformer = Practitioner | PractitionerRole | Organization | CareTeam + +type DiagnosticReportPerformerReference { + id: String + extension: [Extension] + reference: String + resource: DiagnosticReportPerformer + type: URI + identifier: Identifier + display: String +} + +union DiagnosticReportResultsInterpreter = Practitioner | PractitionerRole | Organization | CareTeam + +type DiagnosticReportResultsInterpreterReference { + id: String + extension: [Extension] + reference: String + resource: DiagnosticReportResultsInterpreter + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReportSpecimenReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReportResultReference { + id: String + extension: [Extension] + reference: String + resource: Observation + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReportImagingStudyReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudy + type: URI + identifier: Identifier + display: String +} + +type DiagnosticReport implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [DiagnosticReportBasedOnReference] + status: Code + category: [CodeableConcept] + code: CodeableConcept + subject: DiagnosticReportSubjectReference + encounter: DiagnosticReportEncounterReference + effectiveDateTime: DateTime + effectivePeriod: Period + issued: Instant + performer: [DiagnosticReportPerformerReference] + resultsInterpreter: [DiagnosticReportResultsInterpreterReference] + specimen: [DiagnosticReportSpecimenReference] + result: [DiagnosticReportResultReference] + imagingStudy: [DiagnosticReportImagingStudyReference] + media: [DiagnosticReportMedia] + conclusion: String + conclusionCode: [CodeableConcept] + presentedForm: [Attachment] +} + +type DiagnosticReportBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DiagnosticReport + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DiagnosticReportBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DiagnosticReportBundleEntry] +} + +union DocumentManifestSubject = Patient | Practitioner | Group | Device + +type DocumentManifestSubjectReference { + id: String + extension: [Extension] + reference: String + resource: DocumentManifestSubject + type: URI + identifier: Identifier + display: String +} + +union DocumentManifestAuthor = Practitioner | PractitionerRole | Organization | Device | Patient | RelatedPerson + +type DocumentManifestAuthorReference { + id: String + extension: [Extension] + reference: String + resource: DocumentManifestAuthor + type: URI + identifier: Identifier + display: String +} + +union DocumentManifestRecipient = Patient | Practitioner | PractitionerRole | RelatedPerson | Organization + +type DocumentManifestRecipientReference { + id: String + extension: [Extension] + reference: String + resource: DocumentManifestRecipient + type: URI + identifier: Identifier + display: String +} + +type DocumentManifestContentReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type DocumentManifest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + masterIdentifier: Identifier + identifier: [Identifier] + status: Code + type: CodeableConcept + subject: DocumentManifestSubjectReference + created: DateTime + author: [DocumentManifestAuthorReference] + recipient: [DocumentManifestRecipientReference] + source: URI + description: String + content: [DocumentManifestContentReference] + related: [DocumentManifestRelated] +} + +type DocumentManifestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DocumentManifest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DocumentManifestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DocumentManifestBundleEntry] +} + +union DocumentReferenceSubject = Patient | Practitioner | Group | Device + +type DocumentReferenceSubjectReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReferenceSubject + type: URI + identifier: Identifier + display: String +} + +union DocumentReferenceAuthor = Practitioner | PractitionerRole | Organization | Device | Patient | RelatedPerson + +type DocumentReferenceAuthorReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReferenceAuthor + type: URI + identifier: Identifier + display: String +} + +union DocumentReferenceAuthenticator = Practitioner | PractitionerRole | Organization + +type DocumentReferenceAuthenticatorReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReferenceAuthenticator + type: URI + identifier: Identifier + display: String +} + +type DocumentReferenceCustodianReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type DocumentReference implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + masterIdentifier: Identifier + identifier: [Identifier] + status: Code + docStatus: Code + type: CodeableConcept + category: [CodeableConcept] + subject: DocumentReferenceSubjectReference + date: Instant + author: [DocumentReferenceAuthorReference] + authenticator: DocumentReferenceAuthenticatorReference + custodian: DocumentReferenceCustodianReference + relatesTo: [DocumentReferenceRelatesTo] + description: String + securityLabel: [CodeableConcept] + content: [DocumentReferenceContent] + context: DocumentReferenceContext +} + +type DocumentReferenceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: DocumentReference + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type DocumentReferenceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [DocumentReferenceBundleEntry] +} + +union EncounterSubject = Patient | Group + +type EncounterSubjectReference { + id: String + extension: [Extension] + reference: String + resource: EncounterSubject + type: URI + identifier: Identifier + display: String +} + +type EncounterEpisodeOfCareReference { + id: String + extension: [Extension] + reference: String + resource: EpisodeOfCare + type: URI + identifier: Identifier + display: String +} + +type EncounterBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type EncounterAppointmentReference { + id: String + extension: [Extension] + reference: String + resource: Appointment + type: URI + identifier: Identifier + display: String +} + +union EncounterReasonReference = Condition | Procedure | Observation | ImmunizationRecommendation + +type EncounterReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: EncounterReasonReference + type: URI + identifier: Identifier + display: String +} + +type EncounterAccountReference { + id: String + extension: [Extension] + reference: String + resource: Account + type: URI + identifier: Identifier + display: String +} + +type EncounterServiceProviderReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type EncounterPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type Encounter implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + statusHistory: [EncounterStatusHistory] + class: Coding + classHistory: [EncounterClassHistory] + type: [CodeableConcept] + serviceType: CodeableConcept + priority: CodeableConcept + subject: EncounterSubjectReference + episodeOfCare: [EncounterEpisodeOfCareReference] + basedOn: [EncounterBasedOnReference] + participant: [EncounterParticipant] + appointment: [EncounterAppointmentReference] + period: Period + length: Quantity + reasonCode: [CodeableConcept] + reasonReference: [EncounterReasonReferenceReference] + diagnosis: [EncounterDiagnosis] + account: [EncounterAccountReference] + hospitalization: EncounterHospitalization + location: [EncounterLocation] + serviceProvider: EncounterServiceProviderReference + partOf: EncounterPartOfReference +} + +type EncounterBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Encounter + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EncounterBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EncounterBundleEntry] +} + +type EndpointManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type Endpoint implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + connectionType: Coding + name: String + managingOrganization: EndpointManagingOrganizationReference + contact: [ContactPoint] + period: Period + payloadType: [CodeableConcept] + payloadMimeType: [Code] + address: URL + header: [String] +} + +type EndpointBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Endpoint + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EndpointBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EndpointBundleEntry] +} + +type EnrollmentRequestInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union EnrollmentRequestProvider = Practitioner | PractitionerRole | Organization + +type EnrollmentRequestProviderReference { + id: String + extension: [Extension] + reference: String + resource: EnrollmentRequestProvider + type: URI + identifier: Identifier + display: String +} + +type EnrollmentRequestCandidateReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type EnrollmentRequestCoverageReference { + id: String + extension: [Extension] + reference: String + resource: Coverage + type: URI + identifier: Identifier + display: String +} + +type EnrollmentRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + created: DateTime + insurer: EnrollmentRequestInsurerReference + provider: EnrollmentRequestProviderReference + candidate: EnrollmentRequestCandidateReference + coverage: EnrollmentRequestCoverageReference +} + +type EnrollmentRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EnrollmentRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EnrollmentRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EnrollmentRequestBundleEntry] +} + +type EnrollmentResponseRequestReference { + id: String + extension: [Extension] + reference: String + resource: EnrollmentRequest + type: URI + identifier: Identifier + display: String +} + +type EnrollmentResponseOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union EnrollmentResponseRequestProvider = Practitioner | PractitionerRole | Organization + +type EnrollmentResponseRequestProviderReference { + id: String + extension: [Extension] + reference: String + resource: EnrollmentResponseRequestProvider + type: URI + identifier: Identifier + display: String +} + +type EnrollmentResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + request: EnrollmentResponseRequestReference + outcome: Code + disposition: String + created: DateTime + organization: EnrollmentResponseOrganizationReference + requestProvider: EnrollmentResponseRequestProviderReference +} + +type EnrollmentResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EnrollmentResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EnrollmentResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EnrollmentResponseBundleEntry] +} + +type EpisodeOfCarePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCareManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCareReferralRequestReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +union EpisodeOfCareCareManager = Practitioner | PractitionerRole + +type EpisodeOfCareCareManagerReference { + id: String + extension: [Extension] + reference: String + resource: EpisodeOfCareCareManager + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCareTeamReference { + id: String + extension: [Extension] + reference: String + resource: CareTeam + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCareAccountReference { + id: String + extension: [Extension] + reference: String + resource: Account + type: URI + identifier: Identifier + display: String +} + +type EpisodeOfCare implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + statusHistory: [EpisodeOfCareStatusHistory] + type: [CodeableConcept] + diagnosis: [EpisodeOfCareDiagnosis] + patient: EpisodeOfCarePatientReference + managingOrganization: EpisodeOfCareManagingOrganizationReference + period: Period + referralRequest: [EpisodeOfCareReferralRequestReference] + careManager: EpisodeOfCareCareManagerReference + team: [EpisodeOfCareTeamReference] + account: [EpisodeOfCareAccountReference] +} + +type EpisodeOfCareBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EpisodeOfCare + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EpisodeOfCareBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EpisodeOfCareBundleEntry] +} + +type EventDefinitionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type EventDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + subtitle: String + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: EventDefinitionSubjectReferenceReference + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + trigger: [TriggerDefinition] +} + +type EventDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EventDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EventDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EventDefinitionBundleEntry] +} + +type EvidenceCiteAsReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Citation + type: URI + identifier: Identifier + display: String +} + +type Evidence implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + title: String + citeAsReference: EvidenceCiteAsReferenceReference + citeAsMarkdown: Markdown + status: Code + date: DateTime + useContext: [UsageContext] + approvalDate: Date + lastReviewDate: Date + publisher: String + contact: [ContactDetail] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + description: Markdown + assertion: Markdown + note: [Annotation] + variableDefinition: [EvidenceVariableDefinition] + synthesisType: CodeableConcept + studyType: CodeableConcept + statistic: [EvidenceStatistic] + certainty: [EvidenceCertainty] +} + +type EvidenceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Evidence + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EvidenceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EvidenceBundleEntry] +} + +type EvidenceReportCiteAsReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Citation + type: URI + identifier: Identifier + display: String +} + +type EvidenceReport implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + status: Code + useContext: [UsageContext] + identifier: [Identifier] + relatedIdentifier: [Identifier] + citeAsReference: EvidenceReportCiteAsReferenceReference + citeAsMarkdown: Markdown + type: CodeableConcept + note: [Annotation] + relatedArtifact: [RelatedArtifact] + subject: EvidenceReportSubject + publisher: String + contact: [ContactDetail] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatesTo: [EvidenceReportRelatesTo] + section: [EvidenceReportSection] +} + +type EvidenceReportBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EvidenceReport + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EvidenceReportBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EvidenceReportBundleEntry] +} + +type EvidenceVariable implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + shortTitle: String + subtitle: String + status: Code + date: DateTime + description: Markdown + note: [Annotation] + useContext: [UsageContext] + publisher: String + contact: [ContactDetail] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + actual: Boolean + characteristicCombination: Code + characteristic: [EvidenceVariableCharacteristic] + handling: Code + category: [EvidenceVariableCategory] +} + +type EvidenceVariableBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: EvidenceVariable + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type EvidenceVariableBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [EvidenceVariableBundleEntry] +} + +type ExampleScenario implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + copyright: Markdown + purpose: Markdown + actor: [ExampleScenarioActor] + instance: [ExampleScenarioInstance] + process: [ExampleScenarioProcess] + workflow: [Canonical] +} + +type ExampleScenarioBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ExampleScenario + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ExampleScenarioBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ExampleScenarioBundleEntry] +} + +type ExplanationOfBenefitPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union ExplanationOfBenefitEnterer = Practitioner | PractitionerRole + +type ExplanationOfBenefitEntererReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitEnterer + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitInsurerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ExplanationOfBenefitProvider = Practitioner | PractitionerRole | Organization + +type ExplanationOfBenefitProviderReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitProvider + type: URI + identifier: Identifier + display: String +} + +union ExplanationOfBenefitPrescription = MedicationRequest | VisionPrescription + +type ExplanationOfBenefitPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: ExplanationOfBenefitPrescription + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitOriginalPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequest + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitReferralReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitFacilityReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitClaimReference { + id: String + extension: [Extension] + reference: String + resource: Claim + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefitClaimResponseReference { + id: String + extension: [Extension] + reference: String + resource: ClaimResponse + type: URI + identifier: Identifier + display: String +} + +type ExplanationOfBenefit implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: CodeableConcept + subType: CodeableConcept + use: Code + patient: ExplanationOfBenefitPatientReference + billablePeriod: Period + created: DateTime + enterer: ExplanationOfBenefitEntererReference + insurer: ExplanationOfBenefitInsurerReference + provider: ExplanationOfBenefitProviderReference + priority: CodeableConcept + fundsReserveRequested: CodeableConcept + fundsReserve: CodeableConcept + related: [ExplanationOfBenefitRelated] + prescription: ExplanationOfBenefitPrescriptionReference + originalPrescription: ExplanationOfBenefitOriginalPrescriptionReference + payee: ExplanationOfBenefitPayee + referral: ExplanationOfBenefitReferralReference + facility: ExplanationOfBenefitFacilityReference + claim: ExplanationOfBenefitClaimReference + claimResponse: ExplanationOfBenefitClaimResponseReference + outcome: Code + disposition: String + preAuthRef: [String] + preAuthRefPeriod: [Period] + careTeam: [ExplanationOfBenefitCareTeam] + supportingInfo: [ExplanationOfBenefitSupportingInfo] + diagnosis: [ExplanationOfBenefitDiagnosis] + procedure: [ExplanationOfBenefitProcedure] + precedence: Int + insurance: [ExplanationOfBenefitInsurance] + accident: ExplanationOfBenefitAccident + item: [ExplanationOfBenefitItem] + addItem: [ExplanationOfBenefitAddItem] + adjudication: [ExplanationOfBenefitAdjudication] + total: [ExplanationOfBenefitTotal] + payment: ExplanationOfBenefitPayment + formCode: CodeableConcept + form: Attachment + processNote: [ExplanationOfBenefitProcessNote] + benefitPeriod: Period + benefitBalance: [ExplanationOfBenefitBenefitBalance] +} + +type ExplanationOfBenefitBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ExplanationOfBenefit + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ExplanationOfBenefitBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ExplanationOfBenefitBundleEntry] +} + +type FamilyMemberHistoryPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union FamilyMemberHistoryReasonReference = Condition | Observation | AllergyIntolerance | QuestionnaireResponse | DiagnosticReport | DocumentReference + +type FamilyMemberHistoryReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: FamilyMemberHistoryReasonReference + type: URI + identifier: Identifier + display: String +} + +type FamilyMemberHistory implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + status: Code + dataAbsentReason: CodeableConcept + patient: FamilyMemberHistoryPatientReference + date: DateTime + name: String + relationship: CodeableConcept + sex: CodeableConcept + bornPeriod: Period + bornDate: Date + bornString: String + ageAge: Quantity + ageRange: Range + ageString: String + estimatedAge: Boolean + deceasedBoolean: Boolean + deceasedAge: Quantity + deceasedRange: Range + deceasedDate: Date + deceasedString: String + reasonCode: [CodeableConcept] + reasonReference: [FamilyMemberHistoryReasonReferenceReference] + note: [Annotation] + condition: [FamilyMemberHistoryCondition] +} + +type FamilyMemberHistoryBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: FamilyMemberHistory + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type FamilyMemberHistoryBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [FamilyMemberHistoryBundleEntry] +} + +union FlagSubject = Patient | Location | Group | Organization | Practitioner | PlanDefinition | Medication | Procedure + +type FlagSubjectReference { + id: String + extension: [Extension] + reference: String + resource: FlagSubject + type: URI + identifier: Identifier + display: String +} + +type FlagEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union FlagAuthor = Device | Organization | Patient | Practitioner | PractitionerRole + +type FlagAuthorReference { + id: String + extension: [Extension] + reference: String + resource: FlagAuthor + type: URI + identifier: Identifier + display: String +} + +type Flag implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + category: [CodeableConcept] + code: CodeableConcept + subject: FlagSubjectReference + period: Period + encounter: FlagEncounterReference + author: FlagAuthorReference +} + +type FlagBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Flag + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type FlagBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [FlagBundleEntry] +} + +union GoalSubject = Patient | Group | Organization + +type GoalSubjectReference { + id: String + extension: [Extension] + reference: String + resource: GoalSubject + type: URI + identifier: Identifier + display: String +} + +union GoalExpressedBy = Patient | Practitioner | PractitionerRole | RelatedPerson + +type GoalExpressedByReference { + id: String + extension: [Extension] + reference: String + resource: GoalExpressedBy + type: URI + identifier: Identifier + display: String +} + +union GoalAddresses = Condition | Observation | MedicationStatement | NutritionOrder | ServiceRequest | RiskAssessment + +type GoalAddressesReference { + id: String + extension: [Extension] + reference: String + resource: GoalAddresses + type: URI + identifier: Identifier + display: String +} + +type GoalOutcomeReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Observation + type: URI + identifier: Identifier + display: String +} + +type Goal implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + lifecycleStatus: Code + achievementStatus: CodeableConcept + category: [CodeableConcept] + priority: CodeableConcept + description: CodeableConcept + subject: GoalSubjectReference + startDate: Date + startCodeableConcept: CodeableConcept + target: [GoalTarget] + statusDate: Date + statusReason: String + expressedBy: GoalExpressedByReference + addresses: [GoalAddressesReference] + note: [Annotation] + outcomeCode: [CodeableConcept] + outcomeReference: [GoalOutcomeReferenceReference] +} + +type GoalBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Goal + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type GoalBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [GoalBundleEntry] +} + +type GraphDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + start: Code + profile: Canonical + link: [GraphDefinitionLink] +} + +type GraphDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: GraphDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type GraphDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [GraphDefinitionBundleEntry] +} + +union GroupManagingEntity = Organization | RelatedPerson | Practitioner | PractitionerRole + +type GroupManagingEntityReference { + id: String + extension: [Extension] + reference: String + resource: GroupManagingEntity + type: URI + identifier: Identifier + display: String +} + +type Group implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + type: Code + actual: Boolean + code: CodeableConcept + name: String + quantity: Int + managingEntity: GroupManagingEntityReference + characteristic: [GroupCharacteristic] + member: [GroupMember] +} + +type GroupBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Group + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type GroupBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [GroupBundleEntry] +} + +union GuidanceResponseSubject = Patient | Group + +type GuidanceResponseSubjectReference { + id: String + extension: [Extension] + reference: String + resource: GuidanceResponseSubject + type: URI + identifier: Identifier + display: String +} + +type GuidanceResponseEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type GuidanceResponsePerformerReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +union GuidanceResponseReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type GuidanceResponseReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: GuidanceResponseReasonReference + type: URI + identifier: Identifier + display: String +} + +type GuidanceResponseEvaluationMessageReference { + id: String + extension: [Extension] + reference: String + resource: OperationOutcome + type: URI + identifier: Identifier + display: String +} + +type GuidanceResponseOutputParametersReference { + id: String + extension: [Extension] + reference: String + resource: Parameters + type: URI + identifier: Identifier + display: String +} + +union GuidanceResponseResult = CarePlan | RequestGroup + +type GuidanceResponseResultReference { + id: String + extension: [Extension] + reference: String + resource: GuidanceResponseResult + type: URI + identifier: Identifier + display: String +} + +type GuidanceResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + requestIdentifier: Identifier + identifier: [Identifier] + moduleUri: URI + moduleCanonical: Canonical + moduleCodeableConcept: CodeableConcept + status: Code + subject: GuidanceResponseSubjectReference + encounter: GuidanceResponseEncounterReference + occurrenceDateTime: DateTime + performer: GuidanceResponsePerformerReference + reasonCode: [CodeableConcept] + reasonReference: [GuidanceResponseReasonReferenceReference] + note: [Annotation] + evaluationMessage: [GuidanceResponseEvaluationMessageReference] + outputParameters: GuidanceResponseOutputParametersReference + result: GuidanceResponseResultReference + dataRequirement: [DataRequirement] +} + +type GuidanceResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: GuidanceResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type GuidanceResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [GuidanceResponseBundleEntry] +} + +type HealthcareServiceProvidedByReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type HealthcareServiceLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type HealthcareServiceCoverageAreaReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type HealthcareServiceEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type HealthcareService implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + providedBy: HealthcareServiceProvidedByReference + category: [CodeableConcept] + type: [CodeableConcept] + specialty: [CodeableConcept] + location: [HealthcareServiceLocationReference] + name: String + comment: String + extraDetails: Markdown + photo: Attachment + telecom: [ContactPoint] + coverageArea: [HealthcareServiceCoverageAreaReference] + serviceProvisionCode: [CodeableConcept] + eligibility: [HealthcareServiceEligibility] + program: [CodeableConcept] + characteristic: [CodeableConcept] + communication: [CodeableConcept] + referralMethod: [CodeableConcept] + appointmentRequired: Boolean + availableTime: [HealthcareServiceAvailableTime] + notAvailable: [HealthcareServiceNotAvailable] + availabilityExceptions: String + endpoint: [HealthcareServiceEndpointReference] +} + +type HealthcareServiceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: HealthcareService + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type HealthcareServiceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [HealthcareServiceBundleEntry] +} + +union ImagingStudySubject = Patient | Device | Group + +type ImagingStudySubjectReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudySubject + type: URI + identifier: Identifier + display: String +} + +type ImagingStudyEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ImagingStudyBasedOn = CarePlan | ServiceRequest | Appointment | AppointmentResponse | Task + +type ImagingStudyBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudyBasedOn + type: URI + identifier: Identifier + display: String +} + +union ImagingStudyReferrer = Practitioner | PractitionerRole + +type ImagingStudyReferrerReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudyReferrer + type: URI + identifier: Identifier + display: String +} + +union ImagingStudyInterpreter = Practitioner | PractitionerRole + +type ImagingStudyInterpreterReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudyInterpreter + type: URI + identifier: Identifier + display: String +} + +type ImagingStudyEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type ImagingStudyProcedureReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Procedure + type: URI + identifier: Identifier + display: String +} + +type ImagingStudyLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union ImagingStudyReasonReference = Condition | Observation | Media | DiagnosticReport | DocumentReference + +type ImagingStudyReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ImagingStudyReasonReference + type: URI + identifier: Identifier + display: String +} + +type ImagingStudy implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + modality: [Coding] + subject: ImagingStudySubjectReference + encounter: ImagingStudyEncounterReference + started: DateTime + basedOn: [ImagingStudyBasedOnReference] + referrer: ImagingStudyReferrerReference + interpreter: [ImagingStudyInterpreterReference] + endpoint: [ImagingStudyEndpointReference] + numberOfSeries: Int + numberOfInstances: Int + procedureReference: ImagingStudyProcedureReferenceReference + procedureCode: [CodeableConcept] + location: ImagingStudyLocationReference + reasonCode: [CodeableConcept] + reasonReference: [ImagingStudyReasonReferenceReference] + note: [Annotation] + description: String + series: [ImagingStudySeries] +} + +type ImagingStudyBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ImagingStudy + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ImagingStudyBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ImagingStudyBundleEntry] +} + +type ImmunizationPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type ImmunizationEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type ImmunizationLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ImmunizationManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ImmunizationReasonReference = Condition | Observation | DiagnosticReport + +type ImmunizationReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ImmunizationReasonReference + type: URI + identifier: Identifier + display: String +} + +type Immunization implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + statusReason: CodeableConcept + vaccineCode: CodeableConcept + patient: ImmunizationPatientReference + encounter: ImmunizationEncounterReference + occurrenceDateTime: DateTime + occurrenceString: String + recorded: DateTime + primarySource: Boolean + reportOrigin: CodeableConcept + location: ImmunizationLocationReference + manufacturer: ImmunizationManufacturerReference + lotNumber: String + expirationDate: Date + site: CodeableConcept + route: CodeableConcept + doseQuantity: Quantity + performer: [ImmunizationPerformer] + note: [Annotation] + reasonCode: [CodeableConcept] + reasonReference: [ImmunizationReasonReferenceReference] + isSubpotent: Boolean + subpotentReason: [CodeableConcept] + education: [ImmunizationEducation] + programEligibility: [CodeableConcept] + fundingSource: CodeableConcept + reaction: [ImmunizationReaction] + protocolApplied: [ImmunizationProtocolApplied] +} + +type ImmunizationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Immunization + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ImmunizationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ImmunizationBundleEntry] +} + +type ImmunizationEvaluationPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type ImmunizationEvaluationAuthorityReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ImmunizationEvaluationImmunizationEventReference { + id: String + extension: [Extension] + reference: String + resource: Immunization + type: URI + identifier: Identifier + display: String +} + +type ImmunizationEvaluation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + patient: ImmunizationEvaluationPatientReference + date: DateTime + authority: ImmunizationEvaluationAuthorityReference + targetDisease: CodeableConcept + immunizationEvent: ImmunizationEvaluationImmunizationEventReference + doseStatus: CodeableConcept + doseStatusReason: [CodeableConcept] + description: String + series: String + doseNumberPositiveInt: Int + doseNumberString: String + seriesDosesPositiveInt: Int + seriesDosesString: String +} + +type ImmunizationEvaluationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ImmunizationEvaluation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ImmunizationEvaluationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ImmunizationEvaluationBundleEntry] +} + +type ImmunizationRecommendationPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type ImmunizationRecommendationAuthorityReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ImmunizationRecommendation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + patient: ImmunizationRecommendationPatientReference + date: DateTime + authority: ImmunizationRecommendationAuthorityReference + recommendation: [ImmunizationRecommendationRecommendation] +} + +type ImmunizationRecommendationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ImmunizationRecommendation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ImmunizationRecommendationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ImmunizationRecommendationBundleEntry] +} + +type ImplementationGuide implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + copyright: Markdown + packageId: ID + license: Code + fhirVersion: [Code] + dependsOn: [ImplementationGuideDependsOn] + global: [ImplementationGuideGlobal] + definition: ImplementationGuideDefinition + manifest: ImplementationGuideManifest +} + +type ImplementationGuideBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ImplementationGuide + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ImplementationGuideBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ImplementationGuideBundleEntry] +} + +union IngredientFor = MedicinalProductDefinition | AdministrableProductDefinition | ManufacturedItemDefinition + +type IngredientForReference { + id: String + extension: [Extension] + reference: String + resource: IngredientFor + type: URI + identifier: Identifier + display: String +} + +type Ingredient implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + status: Code + for: [IngredientForReference] + role: CodeableConcept + function: [CodeableConcept] + allergenicIndicator: Boolean + manufacturer: [IngredientManufacturer] + substance: IngredientSubstance +} + +type IngredientBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Ingredient + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type IngredientBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [IngredientBundleEntry] +} + +type InsurancePlanOwnedByReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanAdministeredByReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanCoverageAreaReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type InsurancePlanNetworkReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InsurancePlan implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: [CodeableConcept] + name: String + alias: [String] + period: Period + ownedBy: InsurancePlanOwnedByReference + administeredBy: InsurancePlanAdministeredByReference + coverageArea: [InsurancePlanCoverageAreaReference] + contact: [InsurancePlanContact] + endpoint: [InsurancePlanEndpointReference] + network: [InsurancePlanNetworkReference] + coverage: [InsurancePlanCoverage] + plan: [InsurancePlanPlan] +} + +type InsurancePlanBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: InsurancePlan + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type InsurancePlanBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [InsurancePlanBundleEntry] +} + +union InvoiceSubject = Patient | Group + +type InvoiceSubjectReference { + id: String + extension: [Extension] + reference: String + resource: InvoiceSubject + type: URI + identifier: Identifier + display: String +} + +union InvoiceRecipient = Organization | Patient | RelatedPerson + +type InvoiceRecipientReference { + id: String + extension: [Extension] + reference: String + resource: InvoiceRecipient + type: URI + identifier: Identifier + display: String +} + +type InvoiceIssuerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type InvoiceAccountReference { + id: String + extension: [Extension] + reference: String + resource: Account + type: URI + identifier: Identifier + display: String +} + +type Invoice implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + cancelledReason: String + type: CodeableConcept + subject: InvoiceSubjectReference + recipient: InvoiceRecipientReference + date: DateTime + participant: [InvoiceParticipant] + issuer: InvoiceIssuerReference + account: InvoiceAccountReference + lineItem: [InvoiceLineItem] + totalPriceComponent: [InvoicePriceComponent] + totalNet: Money + totalGross: Money + paymentTerms: Markdown + note: [Annotation] +} + +type InvoiceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Invoice + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type InvoiceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [InvoiceBundleEntry] +} + +type LibrarySubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type Library implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + subtitle: String + status: Code + experimental: Boolean + type: CodeableConcept + subjectCodeableConcept: CodeableConcept + subjectReference: LibrarySubjectReferenceReference + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + parameter: [ParameterDefinition] + dataRequirement: [DataRequirement] + content: [Attachment] +} + +type LibraryBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Library + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type LibraryBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [LibraryBundleEntry] +} + +union LinkageAuthor = Practitioner | PractitionerRole | Organization + +type LinkageAuthorReference { + id: String + extension: [Extension] + reference: String + resource: LinkageAuthor + type: URI + identifier: Identifier + display: String +} + +type Linkage implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + active: Boolean + author: LinkageAuthorReference + item: [LinkageItem] +} + +type LinkageBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Linkage + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type LinkageBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [LinkageBundleEntry] +} + +union ListSubject = Patient | Group | Device | Location + +type ListSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ListSubject + type: URI + identifier: Identifier + display: String +} + +type ListEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ListSource = Practitioner | PractitionerRole | Patient | Device + +type ListSourceReference { + id: String + extension: [Extension] + reference: String + resource: ListSource + type: URI + identifier: Identifier + display: String +} + +type List implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + mode: Code + title: String + code: CodeableConcept + subject: ListSubjectReference + encounter: ListEncounterReference + date: DateTime + source: ListSourceReference + orderedBy: CodeableConcept + note: [Annotation] + entry: [ListEntry] + emptyReason: CodeableConcept +} + +type ListBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: List + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ListBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ListBundleEntry] +} + +type LocationManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type LocationPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type LocationEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type Location implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + operationalStatus: Coding + name: String + alias: [String] + description: String + mode: Code + type: [CodeableConcept] + telecom: [ContactPoint] + address: Address + physicalType: CodeableConcept + position: LocationPosition + managingOrganization: LocationManagingOrganizationReference + partOf: LocationPartOfReference + hoursOfOperation: [LocationHoursOfOperation] + availabilityExceptions: String + endpoint: [LocationEndpointReference] +} + +type LocationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Location + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type LocationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [LocationBundleEntry] +} + +type ManufacturedItemDefinitionManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type ManufacturedItemDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + manufacturedDoseForm: CodeableConcept + unitOfPresentation: CodeableConcept + manufacturer: [ManufacturedItemDefinitionManufacturerReference] + ingredient: [CodeableConcept] + property: [ManufacturedItemDefinitionProperty] +} + +type ManufacturedItemDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ManufacturedItemDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ManufacturedItemDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ManufacturedItemDefinitionBundleEntry] +} + +type MeasureSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type Measure implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + subtitle: String + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: MeasureSubjectReferenceReference + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + library: [Canonical] + disclaimer: Markdown + scoring: CodeableConcept + compositeScoring: CodeableConcept + type: [CodeableConcept] + riskAdjustment: String + rateAggregation: String + rationale: Markdown + clinicalRecommendationStatement: Markdown + improvementNotation: CodeableConcept + definition: [Markdown] + guidance: Markdown + group: [MeasureGroup] + supplementalData: [MeasureSupplementalData] +} + +type MeasureBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Measure + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MeasureBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MeasureBundleEntry] +} + +union MeasureReportSubject = Patient | Practitioner | PractitionerRole | Location | Device | RelatedPerson | Group + +type MeasureReportSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MeasureReportSubject + type: URI + identifier: Identifier + display: String +} + +union MeasureReportReporter = Practitioner | PractitionerRole | Location | Organization + +type MeasureReportReporterReference { + id: String + extension: [Extension] + reference: String + resource: MeasureReportReporter + type: URI + identifier: Identifier + display: String +} + +type MeasureReportEvaluatedResourceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type MeasureReport implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + type: Code + measure: Canonical + subject: MeasureReportSubjectReference + date: DateTime + reporter: MeasureReportReporterReference + period: Period + improvementNotation: CodeableConcept + group: [MeasureReportGroup] + evaluatedResource: [MeasureReportEvaluatedResourceReference] +} + +type MeasureReportBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MeasureReport + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MeasureReportBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MeasureReportBundleEntry] +} + +union MediaBasedOn = ServiceRequest | CarePlan + +type MediaBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: MediaBasedOn + type: URI + identifier: Identifier + display: String +} + +type MediaPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union MediaSubject = Patient | Practitioner | PractitionerRole | Group | Device | Specimen | Location + +type MediaSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MediaSubject + type: URI + identifier: Identifier + display: String +} + +type MediaEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union MediaOperator = Practitioner | PractitionerRole | Organization | CareTeam | Patient | Device | RelatedPerson + +type MediaOperatorReference { + id: String + extension: [Extension] + reference: String + resource: MediaOperator + type: URI + identifier: Identifier + display: String +} + +union MediaDevice = Device | DeviceMetric + +type MediaDeviceReference { + id: String + extension: [Extension] + reference: String + resource: MediaDevice + type: URI + identifier: Identifier + display: String +} + +type Media implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [MediaBasedOnReference] + partOf: [MediaPartOfReference] + status: Code + type: CodeableConcept + modality: CodeableConcept + view: CodeableConcept + subject: MediaSubjectReference + encounter: MediaEncounterReference + createdDateTime: DateTime + createdPeriod: Period + issued: Instant + operator: MediaOperatorReference + reasonCode: [CodeableConcept] + bodySite: CodeableConcept + deviceName: String + device: MediaDeviceReference + height: Int + width: Int + frames: Int + duration: Float + content: Attachment + note: [Annotation] +} + +type MediaBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Media + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MediaBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MediaBundleEntry] +} + +type MedicationManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type Medication implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + code: CodeableConcept + status: Code + manufacturer: MedicationManufacturerReference + form: CodeableConcept + amount: Ratio + ingredient: [MedicationIngredient] + batch: MedicationBatch +} + +type MedicationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Medication + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationBundleEntry] +} + +union MedicationAdministrationPartOf = MedicationAdministration | Procedure + +type MedicationAdministrationPartOfReference { + id: String + extension: [Extension] + reference: String + resource: MedicationAdministrationPartOf + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationMedicationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Medication + type: URI + identifier: Identifier + display: String +} + +union MedicationAdministrationSubject = Patient | Group + +type MedicationAdministrationSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MedicationAdministrationSubject + type: URI + identifier: Identifier + display: String +} + +union MedicationAdministrationContext = Encounter | EpisodeOfCare + +type MedicationAdministrationContextReference { + id: String + extension: [Extension] + reference: String + resource: MedicationAdministrationContext + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationSupportingInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union MedicationAdministrationReasonReference = Condition | Observation | DiagnosticReport + +type MedicationAdministrationReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationAdministrationReasonReference + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationRequestReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequest + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationDeviceReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministrationEventHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type MedicationAdministration implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiates: [URI] + partOf: [MedicationAdministrationPartOfReference] + status: Code + statusReason: [CodeableConcept] + category: CodeableConcept + medicationCodeableConcept: CodeableConcept + medicationReference: MedicationAdministrationMedicationReferenceReference + subject: MedicationAdministrationSubjectReference + context: MedicationAdministrationContextReference + supportingInformation: [MedicationAdministrationSupportingInformationReference] + effectiveDateTime: DateTime + effectivePeriod: Period + performer: [MedicationAdministrationPerformer] + reasonCode: [CodeableConcept] + reasonReference: [MedicationAdministrationReasonReferenceReference] + request: MedicationAdministrationRequestReference + device: [MedicationAdministrationDeviceReference] + note: [Annotation] + dosage: MedicationAdministrationDosage + eventHistory: [MedicationAdministrationEventHistoryReference] +} + +type MedicationAdministrationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicationAdministration + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationAdministrationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationAdministrationBundleEntry] +} + +type MedicationDispensePartOfReference { + id: String + extension: [Extension] + reference: String + resource: Procedure + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseStatusReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssue + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseMedicationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Medication + type: URI + identifier: Identifier + display: String +} + +union MedicationDispenseSubject = Patient | Group + +type MedicationDispenseSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MedicationDispenseSubject + type: URI + identifier: Identifier + display: String +} + +union MedicationDispenseContext = Encounter | EpisodeOfCare + +type MedicationDispenseContextReference { + id: String + extension: [Extension] + reference: String + resource: MedicationDispenseContext + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseSupportingInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseAuthorizingPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequest + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseDestinationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union MedicationDispenseReceiver = Patient | Practitioner + +type MedicationDispenseReceiverReference { + id: String + extension: [Extension] + reference: String + resource: MedicationDispenseReceiver + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseDetectedIssueReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssue + type: URI + identifier: Identifier + display: String +} + +type MedicationDispenseEventHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type MedicationDispense implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + partOf: [MedicationDispensePartOfReference] + status: Code + statusReasonCodeableConcept: CodeableConcept + statusReasonReference: MedicationDispenseStatusReasonReferenceReference + category: CodeableConcept + medicationCodeableConcept: CodeableConcept + medicationReference: MedicationDispenseMedicationReferenceReference + subject: MedicationDispenseSubjectReference + context: MedicationDispenseContextReference + supportingInformation: [MedicationDispenseSupportingInformationReference] + performer: [MedicationDispensePerformer] + location: MedicationDispenseLocationReference + authorizingPrescription: [MedicationDispenseAuthorizingPrescriptionReference] + type: CodeableConcept + quantity: Quantity + daysSupply: Quantity + whenPrepared: DateTime + whenHandedOver: DateTime + destination: MedicationDispenseDestinationReference + receiver: [MedicationDispenseReceiverReference] + note: [Annotation] + dosageInstruction: [Dosage] + substitution: MedicationDispenseSubstitution + detectedIssue: [MedicationDispenseDetectedIssueReference] + eventHistory: [MedicationDispenseEventHistoryReference] +} + +type MedicationDispenseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicationDispense + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationDispenseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationDispenseBundleEntry] +} + +type MedicationKnowledgeManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeAssociatedMedicationReference { + id: String + extension: [Extension] + reference: String + resource: Medication + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledgeContraindicationReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssue + type: URI + identifier: Identifier + display: String +} + +type MedicationKnowledge implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + code: CodeableConcept + status: Code + manufacturer: MedicationKnowledgeManufacturerReference + doseForm: CodeableConcept + amount: Quantity + synonym: [String] + relatedMedicationKnowledge: [MedicationKnowledgeRelatedMedicationKnowledge] + associatedMedication: [MedicationKnowledgeAssociatedMedicationReference] + productType: [CodeableConcept] + monograph: [MedicationKnowledgeMonograph] + ingredient: [MedicationKnowledgeIngredient] + preparationInstruction: Markdown + intendedRoute: [CodeableConcept] + cost: [MedicationKnowledgeCost] + monitoringProgram: [MedicationKnowledgeMonitoringProgram] + administrationGuidelines: [MedicationKnowledgeAdministrationGuidelines] + medicineClassification: [MedicationKnowledgeMedicineClassification] + packaging: MedicationKnowledgePackaging + drugCharacteristic: [MedicationKnowledgeDrugCharacteristic] + contraindication: [MedicationKnowledgeContraindicationReference] + regulatory: [MedicationKnowledgeRegulatory] + kinetics: [MedicationKnowledgeKinetics] +} + +type MedicationKnowledgeBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicationKnowledge + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationKnowledgeBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationKnowledgeBundleEntry] +} + +union MedicationRequestReportedReference = Patient | Practitioner | PractitionerRole | RelatedPerson | Organization + +type MedicationRequestReportedReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestReportedReference + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestMedicationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Medication + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestSubject = Patient | Group + +type MedicationRequestSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestSubject + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestSupportingInformationReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestRequester = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device + +type MedicationRequestRequesterReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestRequester + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestPerformer = Practitioner | PractitionerRole | Organization | Patient | Device | RelatedPerson | CareTeam + +type MedicationRequestPerformerReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestPerformer + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestRecorder = Practitioner | PractitionerRole + +type MedicationRequestRecorderReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestRecorder + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestReasonReference = Condition | Observation + +type MedicationRequestReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestReasonReference + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestBasedOn = CarePlan | MedicationRequest | ServiceRequest | ImmunizationRecommendation + +type MedicationRequestBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestBasedOn + type: URI + identifier: Identifier + display: String +} + +union MedicationRequestInsurance = Coverage | ClaimResponse + +type MedicationRequestInsuranceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequestInsurance + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestPriorPrescriptionReference { + id: String + extension: [Extension] + reference: String + resource: MedicationRequest + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestDetectedIssueReference { + id: String + extension: [Extension] + reference: String + resource: DetectedIssue + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestEventHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type MedicationRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicationRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationRequestBundleEntry] +} + +union MedicationStatementBasedOn = MedicationRequest | CarePlan | ServiceRequest + +type MedicationStatementBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementBasedOn + type: URI + identifier: Identifier + display: String +} + +union MedicationStatementPartOf = MedicationAdministration | MedicationDispense | MedicationStatement | Procedure | Observation + +type MedicationStatementPartOfReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementPartOf + type: URI + identifier: Identifier + display: String +} + +type MedicationStatementMedicationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Medication + type: URI + identifier: Identifier + display: String +} + +union MedicationStatementSubject = Patient | Group + +type MedicationStatementSubjectReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementSubject + type: URI + identifier: Identifier + display: String +} + +union MedicationStatementContext = Encounter | EpisodeOfCare + +type MedicationStatementContextReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementContext + type: URI + identifier: Identifier + display: String +} + +union MedicationStatementInformationSource = Patient | Practitioner | PractitionerRole | RelatedPerson | Organization + +type MedicationStatementInformationSourceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementInformationSource + type: URI + identifier: Identifier + display: String +} + +type MedicationStatementDerivedFromReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union MedicationStatementReasonReference = Condition | Observation | DiagnosticReport + +type MedicationStatementReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: MedicationStatementReasonReference + type: URI + identifier: Identifier + display: String +} + +type MedicationStatement implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [MedicationStatementBasedOnReference] + partOf: [MedicationStatementPartOfReference] + status: Code + statusReason: [CodeableConcept] + category: CodeableConcept + medicationCodeableConcept: CodeableConcept + medicationReference: MedicationStatementMedicationReferenceReference + subject: MedicationStatementSubjectReference + context: MedicationStatementContextReference + effectiveDateTime: DateTime + effectivePeriod: Period + dateAsserted: DateTime + informationSource: MedicationStatementInformationSourceReference + derivedFrom: [MedicationStatementDerivedFromReference] + reasonCode: [CodeableConcept] + reasonReference: [MedicationStatementReasonReferenceReference] + note: [Annotation] + dosage: [Dosage] +} + +type MedicationStatementBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicationStatement + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicationStatementBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicationStatementBundleEntry] +} + +type MedicinalProductDefinitionImpurityReference { + id: String + extension: [Extension] + reference: String + resource: SubstanceDefinition + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionAttachedDocumentReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionMasterFileReference { + id: String + extension: [Extension] + reference: String + resource: DocumentReference + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinitionClinicalTrialReference { + id: String + extension: [Extension] + reference: String + resource: ResearchStudy + type: URI + identifier: Identifier + display: String +} + +type MedicinalProductDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: CodeableConcept + domain: CodeableConcept + version: String + status: CodeableConcept + statusDate: DateTime + description: Markdown + combinedPharmaceuticalDoseForm: CodeableConcept + route: [CodeableConcept] + indication: Markdown + legalStatusOfSupply: CodeableConcept + additionalMonitoringIndicator: CodeableConcept + specialMeasures: [CodeableConcept] + pediatricUseIndicator: CodeableConcept + classification: [CodeableConcept] + marketingStatus: [MarketingStatus] + packagedMedicinalProduct: [CodeableConcept] + ingredient: [CodeableConcept] + impurity: [MedicinalProductDefinitionImpurityReference] + attachedDocument: [MedicinalProductDefinitionAttachedDocumentReference] + masterFile: [MedicinalProductDefinitionMasterFileReference] + contact: [MedicinalProductDefinitionContact] + clinicalTrial: [MedicinalProductDefinitionClinicalTrialReference] + code: [Coding] + name: [MedicinalProductDefinitionName] + crossReference: [MedicinalProductDefinitionCrossReference] + operation: [MedicinalProductDefinitionOperation] + characteristic: [MedicinalProductDefinitionCharacteristic] +} + +type MedicinalProductDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MedicinalProductDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MedicinalProductDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MedicinalProductDefinitionBundleEntry] +} + +type MessageDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + replaces: [Canonical] + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + base: Canonical + parent: [Canonical] + eventCoding: Coding + eventUri: URI + category: Code + focus: [MessageDefinitionFocus] + responseRequired: Code + allowedResponse: [MessageDefinitionAllowedResponse] + graph: [Canonical] +} + +type MessageDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MessageDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MessageDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MessageDefinitionBundleEntry] +} + +union MessageHeaderSender = Practitioner | PractitionerRole | Organization + +type MessageHeaderSenderReference { + id: String + extension: [Extension] + reference: String + resource: MessageHeaderSender + type: URI + identifier: Identifier + display: String +} + +union MessageHeaderEnterer = Practitioner | PractitionerRole + +type MessageHeaderEntererReference { + id: String + extension: [Extension] + reference: String + resource: MessageHeaderEnterer + type: URI + identifier: Identifier + display: String +} + +union MessageHeaderAuthor = Practitioner | PractitionerRole + +type MessageHeaderAuthorReference { + id: String + extension: [Extension] + reference: String + resource: MessageHeaderAuthor + type: URI + identifier: Identifier + display: String +} + +union MessageHeaderResponsible = Practitioner | PractitionerRole | Organization + +type MessageHeaderResponsibleReference { + id: String + extension: [Extension] + reference: String + resource: MessageHeaderResponsible + type: URI + identifier: Identifier + display: String +} + +type MessageHeaderFocusReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type MessageHeader implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + eventCoding: Coding + eventUri: URI + destination: [MessageHeaderDestination] + sender: MessageHeaderSenderReference + enterer: MessageHeaderEntererReference + author: MessageHeaderAuthorReference + source: MessageHeaderSource + responsible: MessageHeaderResponsibleReference + reason: CodeableConcept + response: MessageHeaderResponse + focus: [MessageHeaderFocusReference] + definition: Canonical +} + +type MessageHeaderBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MessageHeader + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MessageHeaderBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MessageHeaderBundleEntry] +} + +type MolecularSequencePatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type MolecularSequenceSpecimenReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +type MolecularSequenceDeviceReference { + id: String + extension: [Extension] + reference: String + resource: Device + type: URI + identifier: Identifier + display: String +} + +type MolecularSequencePerformerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type MolecularSequencePointerReference { + id: String + extension: [Extension] + reference: String + resource: MolecularSequence + type: URI + identifier: Identifier + display: String +} + +type MolecularSequence implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + type: Code + coordinateSystem: Int + patient: MolecularSequencePatientReference + specimen: MolecularSequenceSpecimenReference + device: MolecularSequenceDeviceReference + performer: MolecularSequencePerformerReference + quantity: Quantity + referenceSeq: MolecularSequenceReferenceSeq + variant: [MolecularSequenceVariant] + observedSeq: String + quality: [MolecularSequenceQuality] + readCoverage: Int + repository: [MolecularSequenceRepository] + pointer: [MolecularSequencePointerReference] + structureVariant: [MolecularSequenceStructureVariant] +} + +type MolecularSequenceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: MolecularSequence + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type MolecularSequenceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [MolecularSequenceBundleEntry] +} + +type NamingSystem implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + name: String + status: Code + kind: Code + date: DateTime + publisher: String + contact: [ContactDetail] + responsible: String + type: CodeableConcept + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + usage: String + uniqueId: [NamingSystemUniqueId] +} + +type NamingSystemBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: NamingSystem + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type NamingSystemBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [NamingSystemBundleEntry] +} + +type NutritionOrderPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type NutritionOrderEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union NutritionOrderOrderer = Practitioner | PractitionerRole + +type NutritionOrderOrdererReference { + id: String + extension: [Extension] + reference: String + resource: NutritionOrderOrderer + type: URI + identifier: Identifier + display: String +} + +type NutritionOrderAllergyIntoleranceReference { + id: String + extension: [Extension] + reference: String + resource: AllergyIntolerance + type: URI + identifier: Identifier + display: String +} + +type NutritionOrder implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + instantiates: [URI] + status: Code + intent: Code + patient: NutritionOrderPatientReference + encounter: NutritionOrderEncounterReference + dateTime: DateTime + orderer: NutritionOrderOrdererReference + allergyIntolerance: [NutritionOrderAllergyIntoleranceReference] + foodPreferenceModifier: [CodeableConcept] + excludeFoodModifier: [CodeableConcept] + oralDiet: NutritionOrderOralDiet + supplement: [NutritionOrderSupplement] + enteralFormula: NutritionOrderEnteralFormula + note: [Annotation] +} + +type NutritionOrderBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: NutritionOrder + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type NutritionOrderBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [NutritionOrderBundleEntry] +} + +type NutritionProductManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type NutritionProductKnownAllergenReference { + id: String + extension: [Extension] + reference: String + resource: Substance + type: URI + identifier: Identifier + display: String +} + +type NutritionProduct implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + status: Code + category: [CodeableConcept] + code: CodeableConcept + manufacturer: [NutritionProductManufacturerReference] + nutrient: [NutritionProductNutrient] + ingredient: [NutritionProductIngredient] + knownAllergen: [NutritionProductKnownAllergenReference] + productCharacteristic: [NutritionProductProductCharacteristic] + instance: NutritionProductInstance + note: [Annotation] +} + +type NutritionProductBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: NutritionProduct + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type NutritionProductBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [NutritionProductBundleEntry] +} + +union ObservationBasedOn = CarePlan | DeviceRequest | ImmunizationRecommendation | MedicationRequest | NutritionOrder | ServiceRequest + +type ObservationBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ObservationBasedOn + type: URI + identifier: Identifier + display: String +} + +union ObservationPartOf = MedicationAdministration | MedicationDispense | MedicationStatement | Procedure | Immunization | ImagingStudy + +type ObservationPartOfReference { + id: String + extension: [Extension] + reference: String + resource: ObservationPartOf + type: URI + identifier: Identifier + display: String +} + +union ObservationSubject = Patient | Group | Device | Location | Organization | Procedure | Practitioner | Medication | Substance + +type ObservationSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ObservationSubject + type: URI + identifier: Identifier + display: String +} + +type ObservationFocusReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ObservationEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ObservationPerformer = Practitioner | PractitionerRole | Organization | CareTeam | Patient | RelatedPerson + +type ObservationPerformerReference { + id: String + extension: [Extension] + reference: String + resource: ObservationPerformer + type: URI + identifier: Identifier + display: String +} + +type ObservationSpecimenReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +union ObservationDevice = Device | DeviceMetric + +type ObservationDeviceReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDevice + type: URI + identifier: Identifier + display: String +} + +union ObservationHasMember = Observation | QuestionnaireResponse | MolecularSequence + +type ObservationHasMemberReference { + id: String + extension: [Extension] + reference: String + resource: ObservationHasMember + type: URI + identifier: Identifier + display: String +} + +union ObservationDerivedFrom = DocumentReference | ImagingStudy | Media | QuestionnaireResponse | Observation | MolecularSequence + +type ObservationDerivedFromReference { + id: String + extension: [Extension] + reference: String + resource: ObservationDerivedFrom + type: URI + identifier: Identifier + display: String +} + +type Observation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [ObservationBasedOnReference] + partOf: [ObservationPartOfReference] + status: Code + category: [CodeableConcept] + code: CodeableConcept + subject: ObservationSubjectReference + focus: [ObservationFocusReference] + encounter: ObservationEncounterReference + effectiveDateTime: DateTime + effectivePeriod: Period + effectiveTiming: Timing + effectiveInstant: Instant + issued: Instant + performer: [ObservationPerformerReference] + valueQuantity: Quantity + valueCodeableConcept: CodeableConcept + valueString: String + valueBoolean: Boolean + valueInteger: Int + valueRange: Range + valueRatio: Ratio + valueSampledData: SampledData + valueTime: Time + valueDateTime: DateTime + valuePeriod: Period + dataAbsentReason: CodeableConcept + interpretation: [CodeableConcept] + note: [Annotation] + bodySite: CodeableConcept + method: CodeableConcept + specimen: ObservationSpecimenReference + device: ObservationDeviceReference + referenceRange: [ObservationReferenceRange] + hasMember: [ObservationHasMemberReference] + derivedFrom: [ObservationDerivedFromReference] + component: [ObservationComponent] +} + +type ObservationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Observation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ObservationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ObservationBundleEntry] +} + +type ObservationDefinitionValidCodedValueSetReference { + id: String + extension: [Extension] + reference: String + resource: ValueSet + type: URI + identifier: Identifier + display: String +} + +type ObservationDefinitionNormalCodedValueSetReference { + id: String + extension: [Extension] + reference: String + resource: ValueSet + type: URI + identifier: Identifier + display: String +} + +type ObservationDefinitionAbnormalCodedValueSetReference { + id: String + extension: [Extension] + reference: String + resource: ValueSet + type: URI + identifier: Identifier + display: String +} + +type ObservationDefinitionCriticalCodedValueSetReference { + id: String + extension: [Extension] + reference: String + resource: ValueSet + type: URI + identifier: Identifier + display: String +} + +type ObservationDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + category: [CodeableConcept] + code: CodeableConcept + identifier: [Identifier] + permittedDataType: [Code] + multipleResultsAllowed: Boolean + method: CodeableConcept + preferredReportName: String + quantitativeDetails: ObservationDefinitionQuantitativeDetails + qualifiedInterval: [ObservationDefinitionQualifiedInterval] + validCodedValueSet: ObservationDefinitionValidCodedValueSetReference + normalCodedValueSet: ObservationDefinitionNormalCodedValueSetReference + abnormalCodedValueSet: ObservationDefinitionAbnormalCodedValueSetReference + criticalCodedValueSet: ObservationDefinitionCriticalCodedValueSetReference +} + +type ObservationDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ObservationDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ObservationDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ObservationDefinitionBundleEntry] +} + +type OperationDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + title: String + status: Code + kind: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + affectsState: Boolean + code: Code + comment: Markdown + base: Canonical + resource: [Code] + system: Boolean + type: Boolean + instance: Boolean + inputProfile: Canonical + outputProfile: Canonical + parameter: [OperationDefinitionParameter] + overload: [OperationDefinitionOverload] +} + +type OperationDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: OperationDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type OperationDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [OperationDefinitionBundleEntry] +} + +type OperationOutcome implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + issue: [OperationOutcomeIssue] +} + +type OperationOutcomeBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: OperationOutcome + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type OperationOutcomeBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [OperationOutcomeBundleEntry] +} + +type OrganizationPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type OrganizationEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type Organization implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + type: [CodeableConcept] + name: String + alias: [String] + telecom: [ContactPoint] + address: [Address] + partOf: OrganizationPartOfReference + contact: [OrganizationContact] + endpoint: [OrganizationEndpointReference] +} + +type OrganizationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Organization + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type OrganizationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [OrganizationBundleEntry] +} + +type OrganizationAffiliationOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliationParticipatingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliationNetworkReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliationLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliationHealthcareServiceReference { + id: String + extension: [Extension] + reference: String + resource: HealthcareService + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliationEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type OrganizationAffiliation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + period: Period + organization: OrganizationAffiliationOrganizationReference + participatingOrganization: OrganizationAffiliationParticipatingOrganizationReference + network: [OrganizationAffiliationNetworkReference] + code: [CodeableConcept] + specialty: [CodeableConcept] + location: [OrganizationAffiliationLocationReference] + healthcareService: [OrganizationAffiliationHealthcareServiceReference] + telecom: [ContactPoint] + endpoint: [OrganizationAffiliationEndpointReference] +} + +type OrganizationAffiliationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: OrganizationAffiliation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type OrganizationAffiliationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [OrganizationAffiliationBundleEntry] +} + +type PackagedProductDefinitionPackageForReference { + id: String + extension: [Extension] + reference: String + resource: MedicinalProductDefinition + type: URI + identifier: Identifier + display: String +} + +type PackagedProductDefinitionManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PackagedProductDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + name: String + type: CodeableConcept + packageFor: [PackagedProductDefinitionPackageForReference] + status: CodeableConcept + statusDate: DateTime + containedItemQuantity: [Quantity] + description: Markdown + legalStatusOfSupply: [PackagedProductDefinitionLegalStatusOfSupply] + marketingStatus: [MarketingStatus] + characteristic: [CodeableConcept] + copackagedIndicator: Boolean + manufacturer: [PackagedProductDefinitionManufacturerReference] + package: PackagedProductDefinitionPackage +} + +type PackagedProductDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: PackagedProductDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PackagedProductDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PackagedProductDefinitionBundleEntry] +} + +type Parameters implements Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + parameter: [ParametersParameter] +} + +type ParametersBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Parameters + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ParametersBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ParametersBundleEntry] +} + +union PatientGeneralPractitioner = Organization | Practitioner | PractitionerRole + +type PatientGeneralPractitionerReference { + id: String + extension: [Extension] + reference: String + resource: PatientGeneralPractitioner + type: URI + identifier: Identifier + display: String +} + +type PatientManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PatientBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Patient + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PatientBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PatientBundleEntry] +} + +type PaymentNoticeRequestReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type PaymentNoticeResponseReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union PaymentNoticeProvider = Practitioner | PractitionerRole | Organization + +type PaymentNoticeProviderReference { + id: String + extension: [Extension] + reference: String + resource: PaymentNoticeProvider + type: URI + identifier: Identifier + display: String +} + +type PaymentNoticePaymentReference { + id: String + extension: [Extension] + reference: String + resource: PaymentReconciliation + type: URI + identifier: Identifier + display: String +} + +union PaymentNoticePayee = Practitioner | PractitionerRole | Organization + +type PaymentNoticePayeeReference { + id: String + extension: [Extension] + reference: String + resource: PaymentNoticePayee + type: URI + identifier: Identifier + display: String +} + +type PaymentNoticeRecipientReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PaymentNotice implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + request: PaymentNoticeRequestReference + response: PaymentNoticeResponseReference + created: DateTime + provider: PaymentNoticeProviderReference + payment: PaymentNoticePaymentReference + paymentDate: Date + payee: PaymentNoticePayeeReference + recipient: PaymentNoticeRecipientReference + amount: Money + paymentStatus: CodeableConcept +} + +type PaymentNoticeBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: PaymentNotice + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PaymentNoticeBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PaymentNoticeBundleEntry] +} + +type PaymentReconciliationPaymentIssuerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PaymentReconciliationRequestReference { + id: String + extension: [Extension] + reference: String + resource: Task + type: URI + identifier: Identifier + display: String +} + +union PaymentReconciliationRequestor = Practitioner | PractitionerRole | Organization + +type PaymentReconciliationRequestorReference { + id: String + extension: [Extension] + reference: String + resource: PaymentReconciliationRequestor + type: URI + identifier: Identifier + display: String +} + +type PaymentReconciliation implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + period: Period + created: DateTime + paymentIssuer: PaymentReconciliationPaymentIssuerReference + request: PaymentReconciliationRequestReference + requestor: PaymentReconciliationRequestorReference + outcome: Code + disposition: String + paymentDate: Date + paymentAmount: Money + paymentIdentifier: Identifier + detail: [PaymentReconciliationDetail] + formCode: CodeableConcept + processNote: [PaymentReconciliationProcessNote] +} + +type PaymentReconciliationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: PaymentReconciliation + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PaymentReconciliationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PaymentReconciliationBundleEntry] +} + +type PersonManagingOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type Person implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + name: [HumanName] + telecom: [ContactPoint] + gender: Code + birthDate: Date + address: [Address] + photo: Attachment + managingOrganization: PersonManagingOrganizationReference + active: Boolean + link: [PersonLink] +} + +type PersonBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Person + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PersonBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PersonBundleEntry] +} + +type PlanDefinitionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type PlanDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + subtitle: String + type: CodeableConcept + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: PlanDefinitionSubjectReferenceReference + subjectCanonical: Canonical + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + library: [Canonical] + goal: [PlanDefinitionGoal] + action: [PlanDefinitionAction] +} + +type PlanDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: PlanDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PlanDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PlanDefinitionBundleEntry] +} + +type PractitionerBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Practitioner + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PractitionerBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PractitionerBundleEntry] +} + +type PractitionerRolePractitionerReference { + id: String + extension: [Extension] + reference: String + resource: Practitioner + type: URI + identifier: Identifier + display: String +} + +type PractitionerRoleOrganizationReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type PractitionerRoleLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type PractitionerRoleHealthcareServiceReference { + id: String + extension: [Extension] + reference: String + resource: HealthcareService + type: URI + identifier: Identifier + display: String +} + +type PractitionerRoleEndpointReference { + id: String + extension: [Extension] + reference: String + resource: Endpoint + type: URI + identifier: Identifier + display: String +} + +type PractitionerRole implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + period: Period + practitioner: PractitionerRolePractitionerReference + organization: PractitionerRoleOrganizationReference + code: [CodeableConcept] + specialty: [CodeableConcept] + location: [PractitionerRoleLocationReference] + healthcareService: [PractitionerRoleHealthcareServiceReference] + telecom: [ContactPoint] + availableTime: [PractitionerRoleAvailableTime] + notAvailable: [PractitionerRoleNotAvailable] + availabilityExceptions: String + endpoint: [PractitionerRoleEndpointReference] +} + +type PractitionerRoleBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: PractitionerRole + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type PractitionerRoleBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [PractitionerRoleBundleEntry] +} + +union ProcedureBasedOn = CarePlan | ServiceRequest + +type ProcedureBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureBasedOn + type: URI + identifier: Identifier + display: String +} + +union ProcedurePartOf = Procedure | Observation | MedicationAdministration + +type ProcedurePartOfReference { + id: String + extension: [Extension] + reference: String + resource: ProcedurePartOf + type: URI + identifier: Identifier + display: String +} + +union ProcedureSubject = Patient | Group + +type ProcedureSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureSubject + type: URI + identifier: Identifier + display: String +} + +type ProcedureEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ProcedureRecorder = Patient | RelatedPerson | Practitioner | PractitionerRole + +type ProcedureRecorderReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureRecorder + type: URI + identifier: Identifier + display: String +} + +union ProcedureAsserter = Patient | RelatedPerson | Practitioner | PractitionerRole + +type ProcedureAsserterReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureAsserter + type: URI + identifier: Identifier + display: String +} + +type ProcedureLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union ProcedureReasonReference = Condition | Observation | Procedure | DiagnosticReport | DocumentReference + +type ProcedureReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureReasonReference + type: URI + identifier: Identifier + display: String +} + +union ProcedureReport = DiagnosticReport | DocumentReference | Composition + +type ProcedureReportReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureReport + type: URI + identifier: Identifier + display: String +} + +type ProcedureComplicationDetailReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +union ProcedureUsedReference = Device | Medication | Substance + +type ProcedureUsedReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ProcedureUsedReference + type: URI + identifier: Identifier + display: String +} + +type Procedure implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [ProcedureBasedOnReference] + partOf: [ProcedurePartOfReference] + status: Code + statusReason: CodeableConcept + category: CodeableConcept + code: CodeableConcept + subject: ProcedureSubjectReference + encounter: ProcedureEncounterReference + performedDateTime: DateTime + performedPeriod: Period + performedString: String + performedAge: Quantity + performedRange: Range + recorder: ProcedureRecorderReference + asserter: ProcedureAsserterReference + performer: [ProcedurePerformer] + location: ProcedureLocationReference + reasonCode: [CodeableConcept] + reasonReference: [ProcedureReasonReferenceReference] + bodySite: [CodeableConcept] + outcome: CodeableConcept + report: [ProcedureReportReference] + complication: [CodeableConcept] + complicationDetail: [ProcedureComplicationDetailReference] + followUp: [CodeableConcept] + note: [Annotation] + focalDevice: [ProcedureFocalDevice] + usedReference: [ProcedureUsedReferenceReference] + usedCode: [CodeableConcept] +} + +type ProcedureBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Procedure + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ProcedureBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ProcedureBundleEntry] +} + +type ProvenanceTargetReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ProvenanceLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type Provenance implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + target: [ProvenanceTargetReference] + occurredPeriod: Period + occurredDateTime: DateTime + recorded: Instant + policy: [URI] + location: ProvenanceLocationReference + reason: [CodeableConcept] + activity: CodeableConcept + agent: [ProvenanceAgent] + entity: [ProvenanceEntity] + signature: [Signature] +} + +type ProvenanceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Provenance + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ProvenanceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ProvenanceBundleEntry] +} + +type Questionnaire implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + derivedFrom: [Canonical] + status: Code + experimental: Boolean + subjectType: [Code] + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + code: [Coding] + item: [QuestionnaireItem] +} + +type QuestionnaireBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Questionnaire + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type QuestionnaireBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [QuestionnaireBundleEntry] +} + +union QuestionnaireResponseBasedOn = CarePlan | ServiceRequest + +type QuestionnaireResponseBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: QuestionnaireResponseBasedOn + type: URI + identifier: Identifier + display: String +} + +union QuestionnaireResponsePartOf = Observation | Procedure + +type QuestionnaireResponsePartOfReference { + id: String + extension: [Extension] + reference: String + resource: QuestionnaireResponsePartOf + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireResponseSubjectReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireResponseEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union QuestionnaireResponseAuthor = Device | Practitioner | PractitionerRole | Patient | RelatedPerson | Organization + +type QuestionnaireResponseAuthorReference { + id: String + extension: [Extension] + reference: String + resource: QuestionnaireResponseAuthor + type: URI + identifier: Identifier + display: String +} + +union QuestionnaireResponseSource = Patient | Practitioner | PractitionerRole | RelatedPerson + +type QuestionnaireResponseSourceReference { + id: String + extension: [Extension] + reference: String + resource: QuestionnaireResponseSource + type: URI + identifier: Identifier + display: String +} + +type QuestionnaireResponse implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + basedOn: [QuestionnaireResponseBasedOnReference] + partOf: [QuestionnaireResponsePartOfReference] + questionnaire: Canonical + status: Code + subject: QuestionnaireResponseSubjectReference + encounter: QuestionnaireResponseEncounterReference + authored: DateTime + author: QuestionnaireResponseAuthorReference + source: QuestionnaireResponseSourceReference + item: [QuestionnaireResponseItem] +} + +type QuestionnaireResponseBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: QuestionnaireResponse + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type QuestionnaireResponseBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [QuestionnaireResponseBundleEntry] +} + +union RegulatedAuthorizationSubject = MedicinalProductDefinition | BiologicallyDerivedProduct | NutritionProduct | PackagedProductDefinition | SubstanceDefinition | DeviceDefinition | ResearchStudy | ActivityDefinition | PlanDefinition | ObservationDefinition | Practitioner | Organization | Location + +type RegulatedAuthorizationSubjectReference { + id: String + extension: [Extension] + reference: String + resource: RegulatedAuthorizationSubject + type: URI + identifier: Identifier + display: String +} + +type RegulatedAuthorizationIndicationReference { + id: String + extension: [Extension] + reference: String + resource: ClinicalUseDefinition + type: URI + identifier: Identifier + display: String +} + +type RegulatedAuthorizationHolderReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type RegulatedAuthorizationRegulatorReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type RegulatedAuthorization implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + subject: [RegulatedAuthorizationSubjectReference] + type: CodeableConcept + description: Markdown + region: [CodeableConcept] + status: CodeableConcept + statusDate: DateTime + validityPeriod: Period + indication: RegulatedAuthorizationIndicationReference + intendedUse: CodeableConcept + basis: [CodeableConcept] + holder: RegulatedAuthorizationHolderReference + regulator: RegulatedAuthorizationRegulatorReference + case: RegulatedAuthorizationCase +} + +type RegulatedAuthorizationBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: RegulatedAuthorization + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type RegulatedAuthorizationBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [RegulatedAuthorizationBundleEntry] +} + +type RelatedPersonPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type RelatedPerson implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + patient: RelatedPersonPatientReference + relationship: [CodeableConcept] + name: [HumanName] + telecom: [ContactPoint] + gender: Code + birthDate: Date + address: [Address] + photo: [Attachment] + period: Period + communication: [RelatedPersonCommunication] +} + +type RelatedPersonBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: RelatedPerson + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type RelatedPersonBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [RelatedPersonBundleEntry] +} + +type RequestGroupBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type RequestGroupReplacesReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union RequestGroupSubject = Patient | Group + +type RequestGroupSubjectReference { + id: String + extension: [Extension] + reference: String + resource: RequestGroupSubject + type: URI + identifier: Identifier + display: String +} + +type RequestGroupEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union RequestGroupAuthor = Device | Practitioner | PractitionerRole + +type RequestGroupAuthorReference { + id: String + extension: [Extension] + reference: String + resource: RequestGroupAuthor + type: URI + identifier: Identifier + display: String +} + +union RequestGroupReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type RequestGroupReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: RequestGroupReasonReference + type: URI + identifier: Identifier + display: String +} + +type RequestGroup implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [RequestGroupBasedOnReference] + replaces: [RequestGroupReplacesReference] + groupIdentifier: Identifier + status: Code + intent: Code + priority: Code + code: CodeableConcept + subject: RequestGroupSubjectReference + encounter: RequestGroupEncounterReference + authoredOn: DateTime + author: RequestGroupAuthorReference + reasonCode: [CodeableConcept] + reasonReference: [RequestGroupReasonReferenceReference] + note: [Annotation] + action: [RequestGroupAction] +} + +type RequestGroupBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: RequestGroup + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type RequestGroupBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [RequestGroupBundleEntry] +} + +type ResearchDefinitionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type ResearchDefinitionPopulationReference { + id: String + extension: [Extension] + reference: String + resource: ResearchElementDefinition + type: URI + identifier: Identifier + display: String +} + +type ResearchDefinitionExposureReference { + id: String + extension: [Extension] + reference: String + resource: ResearchElementDefinition + type: URI + identifier: Identifier + display: String +} + +type ResearchDefinitionExposureAlternativeReference { + id: String + extension: [Extension] + reference: String + resource: ResearchElementDefinition + type: URI + identifier: Identifier + display: String +} + +type ResearchDefinitionOutcomeReference { + id: String + extension: [Extension] + reference: String + resource: ResearchElementDefinition + type: URI + identifier: Identifier + display: String +} + +type ResearchDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + shortTitle: String + subtitle: String + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: ResearchDefinitionSubjectReferenceReference + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + comment: [String] + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + library: [Canonical] + population: ResearchDefinitionPopulationReference + exposure: ResearchDefinitionExposureReference + exposureAlternative: ResearchDefinitionExposureAlternativeReference + outcome: ResearchDefinitionOutcomeReference +} + +type ResearchDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ResearchDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ResearchDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ResearchDefinitionBundleEntry] +} + +type ResearchElementDefinitionSubjectReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type ResearchElementDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + shortTitle: String + subtitle: String + status: Code + experimental: Boolean + subjectCodeableConcept: CodeableConcept + subjectReference: ResearchElementDefinitionSubjectReferenceReference + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + comment: [String] + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + usage: String + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + topic: [CodeableConcept] + author: [ContactDetail] + editor: [ContactDetail] + reviewer: [ContactDetail] + endorser: [ContactDetail] + relatedArtifact: [RelatedArtifact] + library: [Canonical] + type: Code + variableType: Code + characteristic: [ResearchElementDefinitionCharacteristic] +} + +type ResearchElementDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ResearchElementDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ResearchElementDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ResearchElementDefinitionBundleEntry] +} + +type ResearchStudyProtocolReference { + id: String + extension: [Extension] + reference: String + resource: PlanDefinition + type: URI + identifier: Identifier + display: String +} + +type ResearchStudyPartOfReference { + id: String + extension: [Extension] + reference: String + resource: ResearchStudy + type: URI + identifier: Identifier + display: String +} + +type ResearchStudyEnrollmentReference { + id: String + extension: [Extension] + reference: String + resource: Group + type: URI + identifier: Identifier + display: String +} + +type ResearchStudySponsorReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +union ResearchStudyPrincipalInvestigator = Practitioner | PractitionerRole + +type ResearchStudyPrincipalInvestigatorReference { + id: String + extension: [Extension] + reference: String + resource: ResearchStudyPrincipalInvestigator + type: URI + identifier: Identifier + display: String +} + +type ResearchStudySiteReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type ResearchStudy implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + title: String + protocol: [ResearchStudyProtocolReference] + partOf: [ResearchStudyPartOfReference] + status: Code + primaryPurposeType: CodeableConcept + phase: CodeableConcept + category: [CodeableConcept] + focus: [CodeableConcept] + condition: [CodeableConcept] + contact: [ContactDetail] + relatedArtifact: [RelatedArtifact] + keyword: [CodeableConcept] + location: [CodeableConcept] + description: Markdown + enrollment: [ResearchStudyEnrollmentReference] + period: Period + sponsor: ResearchStudySponsorReference + principalInvestigator: ResearchStudyPrincipalInvestigatorReference + site: [ResearchStudySiteReference] + reasonStopped: CodeableConcept + note: [Annotation] + arm: [ResearchStudyArm] + objective: [ResearchStudyObjective] +} + +type ResearchStudyBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ResearchStudy + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ResearchStudyBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ResearchStudyBundleEntry] +} + +type ResearchSubjectStudyReference { + id: String + extension: [Extension] + reference: String + resource: ResearchStudy + type: URI + identifier: Identifier + display: String +} + +type ResearchSubjectIndividualReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type ResearchSubjectConsentReference { + id: String + extension: [Extension] + reference: String + resource: Consent + type: URI + identifier: Identifier + display: String +} + +type ResearchSubject implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + period: Period + study: ResearchSubjectStudyReference + individual: ResearchSubjectIndividualReference + assignedArm: String + actualArm: String + consent: ResearchSubjectConsentReference +} + +type ResearchSubjectBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ResearchSubject + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ResearchSubjectBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ResearchSubjectBundleEntry] +} + +type RiskAssessmentBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type RiskAssessmentParentReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union RiskAssessmentSubject = Patient | Group + +type RiskAssessmentSubjectReference { + id: String + extension: [Extension] + reference: String + resource: RiskAssessmentSubject + type: URI + identifier: Identifier + display: String +} + +type RiskAssessmentEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +type RiskAssessmentConditionReference { + id: String + extension: [Extension] + reference: String + resource: Condition + type: URI + identifier: Identifier + display: String +} + +union RiskAssessmentPerformer = Practitioner | PractitionerRole | Device + +type RiskAssessmentPerformerReference { + id: String + extension: [Extension] + reference: String + resource: RiskAssessmentPerformer + type: URI + identifier: Identifier + display: String +} + +union RiskAssessmentReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type RiskAssessmentReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: RiskAssessmentReasonReference + type: URI + identifier: Identifier + display: String +} + +type RiskAssessmentBasisReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type RiskAssessment implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: RiskAssessmentBasedOnReference + parent: RiskAssessmentParentReference + status: Code + method: CodeableConcept + code: CodeableConcept + subject: RiskAssessmentSubjectReference + encounter: RiskAssessmentEncounterReference + occurrenceDateTime: DateTime + occurrencePeriod: Period + condition: RiskAssessmentConditionReference + performer: RiskAssessmentPerformerReference + reasonCode: [CodeableConcept] + reasonReference: [RiskAssessmentReasonReferenceReference] + basis: [RiskAssessmentBasisReference] + prediction: [RiskAssessmentPrediction] + mitigation: String + note: [Annotation] +} + +type RiskAssessmentBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: RiskAssessment + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type RiskAssessmentBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [RiskAssessmentBundleEntry] +} + +union ScheduleActor = Patient | Practitioner | PractitionerRole | RelatedPerson | Device | HealthcareService | Location + +type ScheduleActorReference { + id: String + extension: [Extension] + reference: String + resource: ScheduleActor + type: URI + identifier: Identifier + display: String +} + +type Schedule implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + active: Boolean + serviceCategory: [CodeableConcept] + serviceType: [CodeableConcept] + specialty: [CodeableConcept] + actor: [ScheduleActorReference] + planningHorizon: Period + comment: String +} + +type ScheduleBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Schedule + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ScheduleBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ScheduleBundleEntry] +} + +type SearchParameter implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + derivedFrom: Canonical + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + code: Code + base: [Code] + type: Code + expression: String + xpath: String + xpathUsage: Code + target: [Code] + multipleOr: Boolean + multipleAnd: Boolean + comparator: [Code] + modifier: [Code] + chain: [String] + component: [SearchParameterComponent] +} + +type SearchParameterBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SearchParameter + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SearchParameterBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SearchParameterBundleEntry] +} + +union ServiceRequestBasedOn = CarePlan | ServiceRequest | MedicationRequest + +type ServiceRequestBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestBasedOn + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestReplacesReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +union ServiceRequestSubject = Patient | Group | Location | Device + +type ServiceRequestSubjectReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestSubject + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union ServiceRequestRequester = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device + +type ServiceRequestRequesterReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestRequester + type: URI + identifier: Identifier + display: String +} + +union ServiceRequestPerformer = Practitioner | PractitionerRole | Organization | CareTeam | HealthcareService | Patient | Device | RelatedPerson + +type ServiceRequestPerformerReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestPerformer + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestLocationReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union ServiceRequestReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type ServiceRequestReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestReasonReference + type: URI + identifier: Identifier + display: String +} + +union ServiceRequestInsurance = Coverage | ClaimResponse + +type ServiceRequestInsuranceReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequestInsurance + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestSupportingInfoReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestSpecimenReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +type ServiceRequestRelevantHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type ServiceRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: [Canonical] + instantiatesUri: [URI] + basedOn: [ServiceRequestBasedOnReference] + replaces: [ServiceRequestReplacesReference] + requisition: Identifier + status: Code + intent: Code + category: [CodeableConcept] + priority: Code + doNotPerform: Boolean + code: CodeableConcept + orderDetail: [CodeableConcept] + quantityQuantity: Quantity + quantityRatio: Ratio + quantityRange: Range + subject: ServiceRequestSubjectReference + encounter: ServiceRequestEncounterReference + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + asNeededBoolean: Boolean + asNeededCodeableConcept: CodeableConcept + authoredOn: DateTime + requester: ServiceRequestRequesterReference + performerType: CodeableConcept + performer: [ServiceRequestPerformerReference] + locationCode: [CodeableConcept] + locationReference: [ServiceRequestLocationReferenceReference] + reasonCode: [CodeableConcept] + reasonReference: [ServiceRequestReasonReferenceReference] + insurance: [ServiceRequestInsuranceReference] + supportingInfo: [ServiceRequestSupportingInfoReference] + specimen: [ServiceRequestSpecimenReference] + bodySite: [CodeableConcept] + note: [Annotation] + patientInstruction: String + relevantHistory: [ServiceRequestRelevantHistoryReference] +} + +type ServiceRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ServiceRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ServiceRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ServiceRequestBundleEntry] +} + +type SlotScheduleReference { + id: String + extension: [Extension] + reference: String + resource: Schedule + type: URI + identifier: Identifier + display: String +} + +type Slot implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + serviceCategory: [CodeableConcept] + serviceType: [CodeableConcept] + specialty: [CodeableConcept] + appointmentType: CodeableConcept + schedule: SlotScheduleReference + status: Code + start: Instant + end: Instant + overbooked: Boolean + comment: String +} + +type SlotBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Slot + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SlotBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SlotBundleEntry] +} + +union SpecimenSubject = Patient | Group | Device | Substance | Location + +type SpecimenSubjectReference { + id: String + extension: [Extension] + reference: String + resource: SpecimenSubject + type: URI + identifier: Identifier + display: String +} + +type SpecimenParentReference { + id: String + extension: [Extension] + reference: String + resource: Specimen + type: URI + identifier: Identifier + display: String +} + +type SpecimenRequestReference { + id: String + extension: [Extension] + reference: String + resource: ServiceRequest + type: URI + identifier: Identifier + display: String +} + +type Specimen implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + accessionIdentifier: Identifier + status: Code + type: CodeableConcept + subject: SpecimenSubjectReference + receivedTime: DateTime + parent: [SpecimenParentReference] + request: [SpecimenRequestReference] + collection: SpecimenCollection + processing: [SpecimenProcessing] + container: [SpecimenContainer] + condition: [CodeableConcept] + note: [Annotation] +} + +type SpecimenBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Specimen + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SpecimenBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SpecimenBundleEntry] +} + +type SpecimenDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + typeCollected: CodeableConcept + patientPreparation: [CodeableConcept] + timeAspect: String + collection: [CodeableConcept] + typeTested: [SpecimenDefinitionTypeTested] +} + +type SpecimenDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SpecimenDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SpecimenDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SpecimenDefinitionBundleEntry] +} + +type StructureDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + keyword: [Coding] + fhirVersion: Code + mapping: [StructureDefinitionMapping] + kind: Code + abstract: Boolean + context: [StructureDefinitionContext] + contextInvariant: [String] + type: URI + baseDefinition: Canonical + derivation: Code + snapshot: StructureDefinitionSnapshot + differential: StructureDefinitionDifferential +} + +type StructureDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: StructureDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type StructureDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [StructureDefinitionBundleEntry] +} + +type StructureMap implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + structure: [StructureMapStructure] + import: [Canonical] + group: [StructureMapGroup] +} + +type StructureMapBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: StructureMap + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type StructureMapBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [StructureMapBundleEntry] +} + +type SubscriptionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Subscription + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SubscriptionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SubscriptionBundleEntry] +} + +type SubscriptionStatusSubscriptionReference { + id: String + extension: [Extension] + reference: String + resource: Subscription + type: URI + identifier: Identifier + display: String +} + +type SubscriptionStatusBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SubscriptionStatus + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SubscriptionStatusBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SubscriptionStatusBundleEntry] +} + +type SubscriptionTopic implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + title: String + derivedFrom: [Canonical] + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + approvalDate: Date + lastReviewDate: Date + effectivePeriod: Period + resourceTrigger: [SubscriptionTopicResourceTrigger] + eventTrigger: [SubscriptionTopicEventTrigger] + canFilterBy: [SubscriptionTopicCanFilterBy] + notificationShape: [SubscriptionTopicNotificationShape] +} + +type SubscriptionTopicBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SubscriptionTopic + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SubscriptionTopicBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SubscriptionTopicBundleEntry] +} + +type Substance implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + category: [CodeableConcept] + code: CodeableConcept + description: String + instance: [SubstanceInstance] + ingredient: [SubstanceIngredient] +} + +type SubstanceBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Substance + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SubstanceBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SubstanceBundleEntry] +} + +type SubstanceDefinitionInformationSourceReference { + id: String + extension: [Extension] + reference: String + resource: Citation + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionManufacturerReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinitionSupplierReference { + id: String + extension: [Extension] + reference: String + resource: Organization + type: URI + identifier: Identifier + display: String +} + +type SubstanceDefinition implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + version: String + status: CodeableConcept + classification: [CodeableConcept] + domain: CodeableConcept + grade: [CodeableConcept] + description: Markdown + informationSource: [SubstanceDefinitionInformationSourceReference] + note: [Annotation] + manufacturer: [SubstanceDefinitionManufacturerReference] + supplier: [SubstanceDefinitionSupplierReference] + moiety: [SubstanceDefinitionMoiety] + property: [SubstanceDefinitionProperty] + molecularWeight: [SubstanceDefinitionMolecularWeight] + structure: SubstanceDefinitionStructure + code: [SubstanceDefinitionCode] + name: [SubstanceDefinitionName] + relationship: [SubstanceDefinitionRelationship] + sourceMaterial: SubstanceDefinitionSourceMaterial +} + +type SubstanceDefinitionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SubstanceDefinition + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SubstanceDefinitionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SubstanceDefinitionBundleEntry] +} + +type SupplyDeliveryBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequest + type: URI + identifier: Identifier + display: String +} + +union SupplyDeliveryPartOf = SupplyDelivery | Contract + +type SupplyDeliveryPartOfReference { + id: String + extension: [Extension] + reference: String + resource: SupplyDeliveryPartOf + type: URI + identifier: Identifier + display: String +} + +type SupplyDeliveryPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +union SupplyDeliverySupplier = Practitioner | PractitionerRole | Organization + +type SupplyDeliverySupplierReference { + id: String + extension: [Extension] + reference: String + resource: SupplyDeliverySupplier + type: URI + identifier: Identifier + display: String +} + +type SupplyDeliveryDestinationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +union SupplyDeliveryReceiver = Practitioner | PractitionerRole + +type SupplyDeliveryReceiverReference { + id: String + extension: [Extension] + reference: String + resource: SupplyDeliveryReceiver + type: URI + identifier: Identifier + display: String +} + +type SupplyDelivery implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + basedOn: [SupplyDeliveryBasedOnReference] + partOf: [SupplyDeliveryPartOfReference] + status: Code + patient: SupplyDeliveryPatientReference + type: CodeableConcept + suppliedItem: SupplyDeliverySuppliedItem + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + supplier: SupplyDeliverySupplierReference + destination: SupplyDeliveryDestinationReference + receiver: [SupplyDeliveryReceiverReference] +} + +type SupplyDeliveryBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SupplyDelivery + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SupplyDeliveryBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SupplyDeliveryBundleEntry] +} + +union SupplyRequestItemReference = Medication | Substance | Device + +type SupplyRequestItemReferenceReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestItemReference + type: URI + identifier: Identifier + display: String +} + +union SupplyRequestRequester = Practitioner | PractitionerRole | Organization | Patient | RelatedPerson | Device + +type SupplyRequestRequesterReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestRequester + type: URI + identifier: Identifier + display: String +} + +union SupplyRequestSupplier = Organization | HealthcareService + +type SupplyRequestSupplierReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestSupplier + type: URI + identifier: Identifier + display: String +} + +union SupplyRequestReasonReference = Condition | Observation | DiagnosticReport | DocumentReference + +type SupplyRequestReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestReasonReference + type: URI + identifier: Identifier + display: String +} + +union SupplyRequestDeliverFrom = Organization | Location + +type SupplyRequestDeliverFromReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestDeliverFrom + type: URI + identifier: Identifier + display: String +} + +union SupplyRequestDeliverTo = Organization | Location | Patient + +type SupplyRequestDeliverToReference { + id: String + extension: [Extension] + reference: String + resource: SupplyRequestDeliverTo + type: URI + identifier: Identifier + display: String +} + +type SupplyRequest implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + category: CodeableConcept + priority: Code + itemCodeableConcept: CodeableConcept + itemReference: SupplyRequestItemReferenceReference + quantity: Quantity + parameter: [SupplyRequestParameter] + occurrenceDateTime: DateTime + occurrencePeriod: Period + occurrenceTiming: Timing + authoredOn: DateTime + requester: SupplyRequestRequesterReference + supplier: [SupplyRequestSupplierReference] + reasonCode: [CodeableConcept] + reasonReference: [SupplyRequestReasonReferenceReference] + deliverFrom: SupplyRequestDeliverFromReference + deliverTo: SupplyRequestDeliverToReference +} + +type SupplyRequestBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: SupplyRequest + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type SupplyRequestBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [SupplyRequestBundleEntry] +} + +type TaskBasedOnReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TaskPartOfReference { + id: String + extension: [Extension] + reference: String + resource: Task + type: URI + identifier: Identifier + display: String +} + +type TaskFocusReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TaskForReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TaskEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union TaskRequester = Device | Organization | Patient | Practitioner | PractitionerRole | RelatedPerson + +type TaskRequesterReference { + id: String + extension: [Extension] + reference: String + resource: TaskRequester + type: URI + identifier: Identifier + display: String +} + +union TaskOwner = Practitioner | PractitionerRole | Organization | CareTeam | HealthcareService | Patient | Device | RelatedPerson + +type TaskOwnerReference { + id: String + extension: [Extension] + reference: String + resource: TaskOwner + type: URI + identifier: Identifier + display: String +} + +type TaskLocationReference { + id: String + extension: [Extension] + reference: String + resource: Location + type: URI + identifier: Identifier + display: String +} + +type TaskReasonReferenceReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +union TaskInsurance = Coverage | ClaimResponse + +type TaskInsuranceReference { + id: String + extension: [Extension] + reference: String + resource: TaskInsurance + type: URI + identifier: Identifier + display: String +} + +type TaskRelevantHistoryReference { + id: String + extension: [Extension] + reference: String + resource: Provenance + type: URI + identifier: Identifier + display: String +} + +type Task implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + instantiatesCanonical: Canonical + instantiatesUri: URI + basedOn: [TaskBasedOnReference] + groupIdentifier: Identifier + partOf: [TaskPartOfReference] + status: Code + statusReason: CodeableConcept + businessStatus: CodeableConcept + intent: Code + priority: Code + code: CodeableConcept + description: String + focus: TaskFocusReference + for: TaskForReference + encounter: TaskEncounterReference + executionPeriod: Period + authoredOn: DateTime + lastModified: DateTime + requester: TaskRequesterReference + performerType: [CodeableConcept] + owner: TaskOwnerReference + location: TaskLocationReference + reasonCode: CodeableConcept + reasonReference: TaskReasonReferenceReference + insurance: [TaskInsuranceReference] + note: [Annotation] + relevantHistory: [TaskRelevantHistoryReference] + restriction: TaskRestriction + input: [TaskInput] + output: [TaskOutput] +} + +type TaskBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: Task + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type TaskBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [TaskBundleEntry] +} + +type TerminologyCapabilities implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + kind: Code + software: TerminologyCapabilitiesSoftware + implementation: TerminologyCapabilitiesImplementation + lockedDate: Boolean + codeSystem: [TerminologyCapabilitiesCodeSystem] + expansion: TerminologyCapabilitiesExpansion + codeSearch: Code + validateCode: TerminologyCapabilitiesValidateCode + translation: TerminologyCapabilitiesTranslation + closure: TerminologyCapabilitiesClosure +} + +type TerminologyCapabilitiesBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: TerminologyCapabilities + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type TerminologyCapabilitiesBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [TerminologyCapabilitiesBundleEntry] +} + +type TestReportTestScriptReference { + id: String + extension: [Extension] + reference: String + resource: TestScript + type: URI + identifier: Identifier + display: String +} + +type TestReport implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: Identifier + name: String + status: Code + testScript: TestReportTestScriptReference + result: Code + score: Float + tester: String + issued: DateTime + participant: [TestReportParticipant] + setup: TestReportSetup + test: [TestReportTest] + teardown: TestReportTeardown +} + +type TestReportBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: TestReport + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type TestReportBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [TestReportBundleEntry] +} + +type TestScriptProfileReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type TestScript implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: Identifier + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + purpose: Markdown + copyright: Markdown + origin: [TestScriptOrigin] + destination: [TestScriptDestination] + metadata: TestScriptMetadata + fixture: [TestScriptFixture] + profile: [TestScriptProfileReference] + variable: [TestScriptVariable] + setup: TestScriptSetup + test: [TestScriptTest] + teardown: TestScriptTeardown +} + +type TestScriptBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: TestScript + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type TestScriptBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [TestScriptBundleEntry] +} + +type ValueSet implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + url: URI + identifier: [Identifier] + version: String + name: String + title: String + status: Code + experimental: Boolean + date: DateTime + publisher: String + contact: [ContactDetail] + description: Markdown + useContext: [UsageContext] + jurisdiction: [CodeableConcept] + immutable: Boolean + purpose: Markdown + copyright: Markdown + compose: ValueSetCompose + expansion: ValueSetExpansion +} + +type ValueSetBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: ValueSet + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type ValueSetBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [ValueSetBundleEntry] +} + +type VerificationResultTargetReference { + id: String + extension: [Extension] + reference: String + resource: Resource + type: URI + identifier: Identifier + display: String +} + +type VerificationResult implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + target: [VerificationResultTargetReference] + targetLocation: [String] + need: CodeableConcept + status: Code + statusDate: DateTime + validationType: CodeableConcept + validationProcess: [CodeableConcept] + frequency: Timing + lastPerformed: DateTime + nextScheduled: Date + failureAction: CodeableConcept + primarySource: [VerificationResultPrimarySource] + attestation: VerificationResultAttestation + validator: [VerificationResultValidator] +} + +type VerificationResultBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: VerificationResult + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type VerificationResultBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [VerificationResultBundleEntry] +} + +type VisionPrescriptionPatientReference { + id: String + extension: [Extension] + reference: String + resource: Patient + type: URI + identifier: Identifier + display: String +} + +type VisionPrescriptionEncounterReference { + id: String + extension: [Extension] + reference: String + resource: Encounter + type: URI + identifier: Identifier + display: String +} + +union VisionPrescriptionPrescriber = Practitioner | PractitionerRole + +type VisionPrescriptionPrescriberReference { + id: String + extension: [Extension] + reference: String + resource: VisionPrescriptionPrescriber + type: URI + identifier: Identifier + display: String +} + +type VisionPrescription implements DomainResource & Resource { + resourceType: String + id: ID! + meta: Meta + implicitRules: URI + language: Code + text: Narrative + contained: [Resource] + extension: [Extension] + modifierExtension: [Extension] + identifier: [Identifier] + status: Code + created: DateTime + patient: VisionPrescriptionPatientReference + encounter: VisionPrescriptionEncounterReference + dateWritten: DateTime + prescriber: VisionPrescriptionPrescriberReference + lensSpecification: [VisionPrescriptionLensSpecification] +} + +type VisionPrescriptionBundleEntry { + id: String + link: [BundleLink] + fullUrl: URI + resource: VisionPrescription + search: BundleSearch + request: BundleRequest + response: BundleResponse +} + +type VisionPrescriptionBundle { + id: String + meta: Meta + identifier: [Identifier] + type: Code + timestamp: Instant + total: Int + entry: [VisionPrescriptionBundleEntry] +} + +scalar Base64Binary + +scalar Canonical + +scalar Code + +""" +Custom scalar type for date search parameter. Format can be one of YYYY, YYYY-MM, YYYY-MM-DD, YYYY-MM-DDThh:mm:ss+zz:zz or YYYY-MM-DDThh:mm:ssZ +""" +scalar Date + +scalar DateTime + +"""Decimal custom scalar type""" +scalar Decimal + +scalar Instant + +scalar Markdown + +scalar OID + +scalar Time + +scalar URI + +scalar URL + +scalar UUID + +scalar XHTML + +scalar _FieldSet + +scalar _Any + +type _Service { + sdl: String +} + +union _Entity = Account | ActivityDefinition | AdministrableProductDefinition | AdverseEvent | AllergyIntolerance | Appointment | AppointmentResponse | AuditEvent | Basic | Binary | BiologicallyDerivedProduct | BodyStructure | Bundle | CapabilityStatement | CarePlan | CareTeam | CatalogEntry | ChargeItem | ChargeItemDefinition | Citation | Claim | ClaimResponse | ClinicalImpression | ClinicalUseDefinition | CodeSystem | Communication | CommunicationRequest | CompartmentDefinition | Composition | ConceptMap | Condition | Consent | Contract | Coverage | CoverageEligibilityRequest | CoverageEligibilityResponse | DetectedIssue | Device | DeviceDefinition | DeviceMetric | DeviceRequest | DeviceUseStatement | DiagnosticReport | DocumentManifest | DocumentReference | Encounter | Endpoint | EnrollmentRequest | EnrollmentResponse | EpisodeOfCare | EventDefinition | Evidence | EvidenceReport | EvidenceVariable | ExampleScenario | ExplanationOfBenefit | FamilyMemberHistory | Flag | Goal | GraphDefinition | Group | GuidanceResponse | HealthcareService | ImagingStudy | Immunization | ImmunizationEvaluation | ImmunizationRecommendation | ImplementationGuide | Ingredient | InsurancePlan | Invoice | Library | Linkage | List | Location | ManufacturedItemDefinition | Measure | MeasureReport | Media | Medication | MedicationAdministration | MedicationDispense | MedicationKnowledge | MedicationRequest | MedicationStatement | MedicinalProductDefinition | MessageDefinition | MessageHeader | MolecularSequence | NamingSystem | NutritionOrder | NutritionProduct | Observation | ObservationDefinition | OperationDefinition | OperationOutcome | Organization | OrganizationAffiliation | PackagedProductDefinition | Parameters | Patient | PaymentNotice | PaymentReconciliation | Person | PlanDefinition | Practitioner | PractitionerRole | Procedure | Provenance | Questionnaire | QuestionnaireResponse | RegulatedAuthorization | RelatedPerson | RequestGroup | ResearchDefinition | ResearchElementDefinition | ResearchStudy | ResearchSubject | RiskAssessment | Schedule | SearchParameter | ServiceRequest | Slot | Specimen | SpecimenDefinition | StructureDefinition | StructureMap | Subscription | SubscriptionStatus | SubscriptionTopic | Substance | SubstanceDefinition | SupplyDelivery | SupplyRequest | Task | TerminologyCapabilities | TestReport | TestScript | ValueSet | VerificationResult | VisionPrescription + +''' + + return graphql_schema, "FHIR server graphql schema" + + def _run(self) -> Tuple[str, str]: + """ + Synchronous version of the tool (falls back to async implementation). + + Raises: + NotImplementedError: Always raises to enforce async usage + """ + raise NotImplementedError("Use async version of this tool") diff --git a/language_model_gateway/gateway/tools/flow_chart_generator_tool.py b/language_model_gateway/gateway/tools/flow_chart_generator_tool.py index 4ef020152..4dbeb20bc 100644 --- a/language_model_gateway/gateway/tools/flow_chart_generator_tool.py +++ b/language_model_gateway/gateway/tools/flow_chart_generator_tool.py @@ -1,5 +1,6 @@ import logging import os +import tempfile from typing import Type, Literal, Tuple, Optional, List, Dict, Union, Set from uuid import uuid4 @@ -161,7 +162,9 @@ async def _arun( image_file_name: str = f"{uuid4()}.png" # Use file manager to save the file (if needed) - image_generation_path_ = os.environ.get("IMAGE_GENERATION_PATH", "/tmp") + image_generation_path_ = os.environ.get( + "IMAGE_GENERATION_PATH", tempfile.gettempdir() + ) file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ ) diff --git a/language_model_gateway/gateway/tools/github_pull_request_analyzer_tool.py b/language_model_gateway/gateway/tools/github_pull_request_analyzer_tool.py index 841a339a3..03aebf136 100644 --- a/language_model_gateway/gateway/tools/github_pull_request_analyzer_tool.py +++ b/language_model_gateway/gateway/tools/github_pull_request_analyzer_tool.py @@ -1,17 +1,28 @@ import logging import os from datetime import datetime -from typing import Type, Optional, List, Tuple, Literal +from typing import Type, Optional, List, Tuple, Literal, Dict, Annotated +from langchain_core.runnables import RunnableConfig +from langgraph.prebuilt import InjectedState from pydantic import BaseModel, Field from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.csv_to_markdown_converter import ( + CsvToMarkdownConverter, +) from language_model_gateway.gateway.utilities.github.github_pull_request import ( GithubPullRequest, ) from language_model_gateway.gateway.utilities.github.github_pull_request_helper import ( GithubPullRequestHelper, ) +from language_model_gateway.gateway.utilities.github.github_pull_request_per_contributor_info import ( + GithubPullRequestPerContributorInfo, +) +from language_model_gateway.gateway.utilities.github.github_pull_request_result import ( + GithubPullRequestResult, +) logger = logging.getLogger(__name__) @@ -49,9 +60,6 @@ class GitHubPullRequestAnalyzerAgentInput(BaseModel): # ... (rest of the attributes remain the same) """ - # IMPORTANT: Claude 3.5 Haiku 2024-10-22 has a bug where, when streaming, it changes parameter names to be camelCase - # Hence use camelCase names for all parameters instead of snake_case - repository_name: Optional[str] = Field( default=None, description=( @@ -74,9 +82,35 @@ class GitHubPullRequestAnalyzerAgentInput(BaseModel): default=None, description="Latest date for pull request creation (inclusive)", ) - include_details: Optional[bool] = Field( + counts_only: Optional[bool] = Field( + default=False, + description="Whether to return just count of issues or each issue details", + ) + sort_by: Optional[Literal["created", "updated", "popularity", "long-running"]] = ( + Field( + default="created", + description="Sort pull requests by created, updated, popularity, or long-running. Default is 'created'.", + ) + ) + sort_by_direction: Optional[Literal["asc", "desc"]] = Field( + default="desc", + description="Sort direction for pull requests. Choices: 'asc', 'desc'. Default is 'desc'.", + ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) + limit: Optional[int] = Field( + default=100, + description="Maximum number of pull requests to retrieve", + ) + include_description: Optional[bool] = Field( default=False, - description="Include detailed pull request information or return contributor summary", + description="Whether to include pull request description", + ) + auth_token: Annotated[Optional[str], InjectedState("auth_token")] = Field( + default=None, + description="Injected state", ) @@ -115,29 +149,44 @@ class GitHubPullRequestAnalyzerTool(ResilientBaseTool): description: str = ( "Advanced GitHub pull request analysis tool. " "USAGE TIPS: " - "- Specify repository with 'in [repo]' " - "- Specify contributor with username " + "- Specify repository with 'in [repo]'. repository can be null for all repos " + "- Specify contributor with username. contributor can be null for all contributors " "- If querying for a specific date range, include 'from [date] to [date]' " - "- Include 'details' for detailed pull request information " + "- Set 'counts_only' if you want to get counts only" + "- Set 'sort_by' to sort by 'created', 'updated', 'popularity', or 'long-running' " + "- Set 'sort_by_direction' to 'asc' or 'desc' " + "- Set 'use_verbose_logging' to get verbose logs" + "- Set 'limit' to limit the number of pull requests to retrieve" + "- Set 'include_description' to include description" "- Example queries: " "'Pull requests in kubernetes/kubernetes', " "'PRs from johndoe in myorg/myrepo', " + "'PRs including description from johndoe in myorg/myrepo', " "'What pull requests from imranq2 in helix.pipelines repo'" ) args_schema: Type[BaseModel] = GitHubPullRequestAnalyzerAgentInput response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" - github_pull_request_helper: GithubPullRequestHelper # noinspection PyPep8Naming def _run( self, + *, repository_name: Optional[str] = None, minimum_created_date: Optional[datetime] = None, maximum_created_date: Optional[datetime] = None, contributor_name: Optional[str] = None, - include_details: Optional[bool] = None, + counts_only: Optional[bool] = None, + sort_by: Optional[ + Literal["created", "updated", "popularity", "long-running"] + ] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + use_verbose_logging: Optional[bool] = None, + limit: Optional[int] = None, + include_description: Optional[bool] = None, + config: RunnableConfig, + auth_token: Optional[str] = None, ) -> Tuple[str, str]: """ Synchronous version of the tool (falls back to async implementation). @@ -150,11 +199,21 @@ def _run( # noinspection PyPep8Naming async def _arun( self, + *, repository_name: Optional[str] = None, minimum_created_date: Optional[datetime] = None, maximum_created_date: Optional[datetime] = None, contributor_name: Optional[str] = None, - include_details: Optional[bool] = None, + counts_only: Optional[bool] = None, + sort_by: Optional[ + Literal["created", "updated", "popularity", "long-running"] + ] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + use_verbose_logging: Optional[bool] = None, + limit: Optional[int] = None, + include_description: Optional[bool] = None, + config: RunnableConfig, + auth_token: Optional[str] = None, ) -> Tuple[str, str]: """ Asynchronous version of the GitHub Pull Request extraction tool. @@ -163,26 +222,42 @@ async def _arun( Tuple of pull request analysis text and artifact description """ - logger.info( - "GitHubPullRequestAnalyzerAgent:" - + f" {repository_name=}, {minimum_created_date=}, {maximum_created_date=}" - + f", {contributor_name=}, {include_details=}" - ) - - log_prefix: str = ( - "GitHubPullRequestAnalyzerAgent:" - + f" {repository_name=}, {minimum_created_date=}, {maximum_created_date=}" - + f", {contributor_name=}, {include_details=}" - ) + log_prefix: str = "GitHubPullRequestAnalyzerAgent: " + log_prefix_items: List[str] = [] + if repository_name: + log_prefix_items.append(f"{repository_name=}") + if minimum_created_date: + log_prefix_items.append( + f"minimum_created_date={minimum_created_date.isoformat()}" + ) + if maximum_created_date: + log_prefix_items.append(f"maximum_created_date={maximum_created_date}") + if contributor_name: + log_prefix_items.append(f"{contributor_name=}") + if counts_only: + log_prefix_items.append(f"{counts_only=}") + if sort_by: + log_prefix_items.append(f"{sort_by=}") + if sort_by_direction: + log_prefix_items.append(f"{sort_by_direction=}") + if auth_token: + log_prefix_items.append("auth_token=***") + + log_prefix = log_prefix + ", ".join(log_prefix_items) try: # Initialize GitHub Pull Request Helper # Retrieve closed pull requests max_repos: int = int(os.environ.get("GITHUB_MAXIMUM_REPOS", 100)) - max_pull_requests: int = int( - os.environ.get("GITHUB_MAXIMUM_PULL_REQUESTS_PER_REPO", 100) + max_pull_requests: Optional[int] = ( + int(os.environ.get("GITHUB_MAXIMUM_PULL_REQUESTS_PER_REPO", 100)) + if not counts_only + else None ) - closed_prs: List[GithubPullRequest] = ( + if limit: + max_pull_requests = limit + + pull_request_result: GithubPullRequestResult = ( await self.github_pull_request_helper.retrieve_closed_prs( max_repos=max_repos, max_pull_requests=max_pull_requests, @@ -190,37 +265,54 @@ async def _arun( max_created_at=maximum_created_date, include_merged=True, repo_name=repository_name, + sort_by=sort_by, + sort_by_direction=sort_by_direction, ) ) + pull_requests: List[GithubPullRequest] = pull_request_result.pull_requests full_text: str - if include_details: - full_text = "" - for pr in closed_prs: - full_text += f"PR: {pr.title} by {pr.user} closed on {pr.closed_at} - {pr.html_url}\n" + if not counts_only: + full_text = "Number,Title,User,Created,Closed,Url,State,Description\n" + for pr in pull_requests: + clean_title: str = pr.title.replace('"', "'") + clean_body: str = ( + pr.body.replace('"', "'") + if pr.body and include_description + else "" + ) + full_text += f'{pr.pull_request_number},"{clean_title}",{pr.user},{pr.created_at},{pr.closed_at},{pr.html_url},{pr.state},"{clean_body}"\n' else: # Summarize pull requests by engineer - pr_summary = self.github_pull_request_helper.summarize_prs_by_engineer( - pull_requests=closed_prs + pr_counts: Dict[str, GithubPullRequestPerContributorInfo] = ( + self.github_pull_request_helper.summarize_prs_by_engineer( + pull_requests=pull_requests + ) ) - # Generate detailed text report - report_lines = [ - "Pull Requests by Contributor:", - ] + full_text = self.github_pull_request_helper.export_results_as_csv( + pr_counts=pr_counts + ) - for engineer, info in pr_summary.items(): - report_lines.append(f"{engineer}: {info.pull_request_count}") + # Create artifact description + artifact = log_prefix + f", Analyzed {len(pull_requests)} PRs" + if pull_request_result.error: + artifact += f"\nError: {pull_request_result.error}" - full_text = "\n".join(report_lines) + if len(pull_requests) == 0: + artifact += f"\nQueries:\n{pull_request_result.query}" + elif use_verbose_logging: + artifact += f"\nQueries:\n{pull_request_result.query}" + # artifact += "\n\nRaw:" + # artifact += f"\n```{full_text}```" - # Create artifact description - artifact = log_prefix + f", Analyzed {len(closed_prs)} closed PRs" + artifact += "\n\nResults:" + artifact += f"\n{CsvToMarkdownConverter.csv_to_markdown_table(full_text)}" return full_text, artifact except Exception as e: error_msg = f"Error analyzing GitHub pull requests: {str(e)}" - error_artifact = log_prefix + " Analysis Failed" + error_artifact = log_prefix + " Analysis Failed" + str(e) logger.error(error_msg) return error_msg, error_artifact diff --git a/language_model_gateway/gateway/tools/github_pull_request_diff_tool.py b/language_model_gateway/gateway/tools/github_pull_request_diff_tool.py index ea7f560db..77a10b201 100644 --- a/language_model_gateway/gateway/tools/github_pull_request_diff_tool.py +++ b/language_model_gateway/gateway/tools/github_pull_request_diff_tool.py @@ -19,6 +19,10 @@ class GitHubPullRequestDiffAgentDiffInput(BaseModel): title="Pull Request URL", description="URL of the GitHub pull request to analyze", ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class GitHubPullRequestDiffTool(ResilientBaseTool): @@ -37,6 +41,7 @@ class GitHubPullRequestDiffTool(ResilientBaseTool): def _run( self, url: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, ) -> Tuple[str, str]: """ Synchronous version of the tool (falls back to async implementation). @@ -49,6 +54,7 @@ def _run( async def _arun( self, url: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, ) -> Tuple[str, str]: """ Asynchronous version of the GitHub Pull Request extraction tool. @@ -65,7 +71,8 @@ async def _arun( ) # Create artifact description artifact = f"GitHubPullRequestDiffAgent: Downloaded diff for {url}" - + if use_verbose_logging: + artifact += f"\n===== Content =====\n```{diff_content}```\n===== End of Content =====" return diff_content, artifact except Exception as e: diff --git a/language_model_gateway/gateway/tools/github_pull_request_retriever_tool.py b/language_model_gateway/gateway/tools/github_pull_request_retriever_tool.py new file mode 100644 index 000000000..c0df30f83 --- /dev/null +++ b/language_model_gateway/gateway/tools/github_pull_request_retriever_tool.py @@ -0,0 +1,83 @@ +import logging + +from pydantic import BaseModel, Field + +from typing import Type, Optional, Tuple, Literal +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.github.github_pull_request import ( + GithubPullRequest, +) +from language_model_gateway.gateway.utilities.github.github_pull_request_helper import ( + GithubPullRequestHelper, +) + +logger = logging.getLogger(__name__) + + +class GitHubPullRequestRetrieverInput(BaseModel): + """Input model for GitHub Pull Request retriever tool.""" + + url: str = Field( + ..., + title="Pull Request URL", + description="URL of the GitHub pull request to retrieve information from", + ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) + + +class GitHubPullRequestRetriever(ResilientBaseTool): + """ + LangChain-compatible tool for retrieving information about a GitHub pull request. + """ + + name: str = "github_pull_request_retriever" + description: str = "Retrieves information about a GitHub pull request given its URL, such as title, description, etc." + + args_schema: Type[BaseModel] = GitHubPullRequestRetrieverInput + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + github_pull_request_helper: GithubPullRequestHelper + + def _run( + self, + url: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, + ) -> Tuple[str, str]: + """ + Synchronous version of the tool (falls back to async implementation). + + Raises: + NotImplementedError: Always raises to enforce async usage + """ + raise NotImplementedError("Use async version of this tool") + + async def _arun( + self, + url: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, + ) -> Tuple[str, str]: + """ + Asynchronous version of the GitHub Pull Request retriever tool. + + Returns: + Tuple of pull request information and artifact description + """ + assert url, "Pull request URL is required" + + try: + pull_request: GithubPullRequest = ( + await self.github_pull_request_helper.get_pr_info(pr_url=url) + ) + artifact = f"GitHubPullRequestRetriever: Retrieved information for {url}" + if use_verbose_logging: + artifact += f"\n===== Pull Request Info =====\n{pull_request}\n===== End of Info =====" + return str(pull_request), artifact + + except Exception as e: + error_msg = f"Error retrieving GitHub pull request: {str(e)}" + error_artifact = "GitHubPullRequestRetriever: Retrieval failed" + logger.error(error_msg) + return error_msg, error_artifact diff --git a/language_model_gateway/gateway/tools/google_search_tool.py b/language_model_gateway/gateway/tools/google_search_tool.py index 6c7b104b4..5babd84b9 100644 --- a/language_model_gateway/gateway/tools/google_search_tool.py +++ b/language_model_gateway/gateway/tools/google_search_tool.py @@ -15,6 +15,10 @@ class GoogleSearchToolInput(BaseModel): query: str = Field(description="The search query to send to Google Search") + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class GoogleSearchTool(ResilientBaseTool): @@ -117,11 +121,15 @@ async def aclose(self) -> None: """Close the HTTP client.""" await self._client.aclose() - def _run(self, query: str) -> Tuple[str, str]: + def _run( + self, query: str, use_verbose_logging: Optional[bool] = None + ) -> Tuple[str, str]: """Use async version of this tool.""" raise NotImplementedError("Use async version of this tool") - async def _arun(self, query: str) -> Tuple[str, str]: + async def _arun( + self, query: str, use_verbose_logging: Optional[bool] = None + ) -> Tuple[str, str]: """Async implementation of the Google search tool.""" assert self._api_key, "GOOGLE_API_KEY environment variable is required" @@ -148,7 +156,11 @@ async def _arun(self, query: str) -> Tuple[str, str]: response: str = "\n".join(snippets) if os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1": logger.info(f"Google Search results: {response}") - return response, f'GoogleSearchAgent: Searched Google for "{query}"' + + artifact: str = f'GoogleSearchAgent: Searched Google for "{query}"' + if use_verbose_logging: + artifact += f"\n```{response}```" + return response, artifact except Exception as e: logger.exception(e, stack_info=True) return ( diff --git a/language_model_gateway/gateway/tools/graph_viz_diagram_generator_tool.py b/language_model_gateway/gateway/tools/graph_viz_diagram_generator_tool.py index 0dff82dfa..b688689db 100644 --- a/language_model_gateway/gateway/tools/graph_viz_diagram_generator_tool.py +++ b/language_model_gateway/gateway/tools/graph_viz_diagram_generator_tool.py @@ -85,9 +85,9 @@ async def _arun(self, dot_input: str) -> Tuple[str, str]: # Render the diagram image_generation_path_ = os.environ["IMAGE_GENERATION_PATH"] - assert ( - image_generation_path_ - ), "IMAGE_GENERATION_PATH environment variable is not set" + assert image_generation_path_, ( + "IMAGE_GENERATION_PATH environment variable is not set" + ) image_file_name: str = f"{uuid4()}.png" # dot.render(output_file, cleanup=True) diff --git a/language_model_gateway/gateway/tools/health_summary_generator_tool.py b/language_model_gateway/gateway/tools/health_summary_generator_tool.py new file mode 100644 index 000000000..2eb3843b9 --- /dev/null +++ b/language_model_gateway/gateway/tools/health_summary_generator_tool.py @@ -0,0 +1,86 @@ +from language_model_gateway.gateway.file_managers.file_manager import FileManager +from language_model_gateway.gateway.file_managers.file_manager_factory import ( + FileManagerFactory, +) +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from pydantic import BaseModel, Field +from typing import Type, Tuple, Literal +from starlette.responses import Response, StreamingResponse + +from language_model_gateway.gateway.utilities.s3_url import S3Url + + +class HealthSummaryGeneratorModel(BaseModel): + """ + Model to generate the health summary report for each user showing the diagnosis, procedures and medications of the + user + """ + + s3_uri: str = Field( + description="S3 uri for the file for which we will be generating the health summary", + ) + + +class HealthSummaryGeneratorTool(ResilientBaseTool): + """ + The HealthSummaryGeneratorTool is designed to generate comprehensive health summary reports for users + by processing claims data files stored in S3. This tool extracts and deduplicates information about + diagnoses, procedures, and medications for each user, producing a structured JSON report. + """ + + name: str = "health_summary_generator" + + description: str = """ + The HealthSummaryGeneratorTool is designed to generate comprehensive health summary reports for users + by processing claims data files stored in S3. This tool extracts and deduplicates information about + diagnoses, procedures, and medications for each user, producing a structured JSON report. + Features: + - Accepts a file URL pointing to a claims file in S3. + - Extracts data related to diagnoses, procedures, and pharmaceuticals, checking for both names and codes. + - Searches for descriptions of codes if provided, using them for further processing. + - Deduplicates all extracted data to ensure clean output. + - Generates a summary JSON object for each user, outlining consolidated health data. + """ + + args_schema: Type[BaseModel] = ( + HealthSummaryGeneratorModel # Should be the input parameters class you created above + ) + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + file_manager_factory: FileManagerFactory + + async def _arun(self, s3_uri: str) -> Tuple[str, str]: + """ + Asynchronous version of the health summary generator tool. + :param s3_uri: (string) s3 uri of the file which we need to parse. + :return: The content of the file. + """ + # Create a file manager instance from the factory + file_manager: FileManager = self.file_manager_factory.get_file_manager( + folder=s3_uri + ) + + s3_url_object = S3Url(s3_uri) + bucket_name = s3_url_object.bucket + file_name = s3_url_object.key + + # Download the file from the S3 bucket + response: StreamingResponse | Response = await file_manager.read_file_async( + folder=bucket_name, file_path=file_name + ) + + # Check if the response is successful + if not isinstance(response, StreamingResponse): + return "Failed to retrieve the file", f"Error retrieving file: {response}" + + # Extract content from the file + content = await file_manager.extract_content(response) + return content, "File successfully fetched" + + def _run(self, s3_uri: str) -> Tuple[str, str]: + """ + Synchronous version of the tool (falls back to async implementation). + :param s3_uri: (string) s3 uri of the file which we need to parse. + Raises: + NotImplementedError: Always raises to enforce async usage + """ + raise NotImplementedError("Use async version of this tool") diff --git a/language_model_gateway/gateway/tools/image_generator_tool.py b/language_model_gateway/gateway/tools/image_generator_tool.py index 9df646254..5349a5fe5 100644 --- a/language_model_gateway/gateway/tools/image_generator_tool.py +++ b/language_model_gateway/gateway/tools/image_generator_tool.py @@ -74,9 +74,9 @@ async def _arun(self, prompt: str) -> Tuple[str, str]: ) # base64_image: str = base64.b64encode(image_data).decode("utf-8") image_generation_path_ = os.environ["IMAGE_GENERATION_PATH"] - assert ( - image_generation_path_ - ), "IMAGE_GENERATION_PATH environment variable is not set" + assert image_generation_path_, ( + "IMAGE_GENERATION_PATH environment variable is not set" + ) image_file_name: str = f"{uuid4()}.png" file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ @@ -108,10 +108,10 @@ async def _arun(self, prompt: str) -> Tuple[str, str]: f"ImageGeneratorAgent[{self.model_provider}]: Generated image from prompt: {prompt}: {markdown_image} ", ) else: - return ( - url, - f"ImageGeneratorAgent[{self.model_provider}]: Generated image from prompt: {prompt}: <{url}> ", - ) + markdown_image = f"![Generated Image]({url})" + artifact: str = f"ImageGeneratorAgent[{self.model_provider}]: Generated image from prompt: {prompt}: <{url}> " + artifact += f"\n\n{markdown_image}" + return url, artifact except Exception as e: logger.error(f"Failed to generate image: {str(e)}") logger.exception(e, stack_info=True) diff --git a/language_model_gateway/gateway/tools/jira_issue_retriever.py b/language_model_gateway/gateway/tools/jira_issue_retriever.py new file mode 100644 index 000000000..418d57d6a --- /dev/null +++ b/language_model_gateway/gateway/tools/jira_issue_retriever.py @@ -0,0 +1,102 @@ +import logging +from typing import Type, Tuple, Literal +from pydantic import BaseModel, Field +from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.jira.jira_issue_result import ( + JiraIssueResult, +) +from language_model_gateway.gateway.utilities.jira.jira_issues_helper import ( + JiraIssueHelper, +) + +logger = logging.getLogger(__name__) + + +class JiraIssueRetrieverAgentInput(BaseModel): + """ + Input model for retrieving a specific Jira issue by ID. + """ + + issue_id: str = Field( + default="", + description="The ID of the Jira issue to retrieve. It typically follows this format: 2-4 capital letters + hyphen or space + 1-5 digits. Examples: ATC-1234, Atc 6789, EFS-564", + ) + + +class JiraIssueRetriever(ResilientBaseTool): + """ + A LangChain-compatible tool for retrieving a specific Jira issue by ID. + """ + + name: str = "jira_issue_retriever" + description: str = ( + "Tool to retrieve a specific Jira issue by ID. " + "USAGE TIPS: " + "- Provide the Jira issue ID to retrieve the issue details." + "- ID typically follows this format: 2-4 capital letters + hyphen or space + 1-5 digits. Examples: ATC-1234, Atc 6789, EFS-564" + ) + + args_schema: Type[BaseModel] = JiraIssueRetrieverAgentInput + response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" + + jira_issues_helper: JiraIssueHelper + + async def _arun( + self, + issue_id: str, + ) -> Tuple[str, str]: + """ + Asynchronous version of the Jira Issue by ID tool. + + Returns: + Tuple of Jira issue text and artifact description + """ + log_prefix: str = f"JiraIssueRetriever: issue_id={issue_id}" + + try: + jira_issue_result: JiraIssueResult = ( + await self.jira_issues_helper.retrieve_issue_by_id(issue_id=issue_id) + ) + + if jira_issue_result.error: + error_msg = f"Error retrieving Jira issue: {jira_issue_result.error}" + error_artifact = ( + log_prefix + f" Retrieval Failed: {jira_issue_result.error}" + ) + logger.error(error_msg) + return error_msg, error_artifact + + jira_issue = jira_issue_result.issues[0] + + full_text = ( + f"**Id**: {jira_issue.key}\n" + f"**Summary**: {jira_issue.summary}\n" + f"**Status**: {jira_issue.status}\n" + f"**Assignee**: {jira_issue.assignee}\n" + f"**Created**: {jira_issue.created_at}\n" + f"**Closed**: {jira_issue.closed_at}\n" + f"**Description**: {jira_issue.description}\n" + ) + + artifact = log_prefix + f", Retrieved issue {jira_issue.key}.\n\n" + artifact += f"\n{full_text}" + + return full_text, artifact + + except Exception as e: + error_msg = f"Error retrieving Jira issue: {str(e)}" + error_artifact = log_prefix + " Retrieval Failed: " + str(e) + logger.error(error_msg) + return error_msg, error_artifact + + def _run( + self, + issue_id: str, + ) -> Tuple[str, str]: + """ + Synchronous version of the Jira Issue by ID tool. + + Returns: + Tuple of Jira issue text and artifact description + """ + raise NotImplementedError("Use async version of this tool") diff --git a/language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py b/language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py index e374101f1..85bb4f12f 100644 --- a/language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py +++ b/language_model_gateway/gateway/tools/jira_issues_analyzer_tool.py @@ -6,7 +6,13 @@ from pydantic import BaseModel, Field from language_model_gateway.gateway.tools.resilient_base_tool import ResilientBaseTool +from language_model_gateway.gateway.utilities.csv_to_markdown_converter import ( + CsvToMarkdownConverter, +) from language_model_gateway.gateway.utilities.jira.jira_issue import JiraIssue +from language_model_gateway.gateway.utilities.jira.jira_issue_result import ( + JiraIssueResult, +) from language_model_gateway.gateway.utilities.jira.jira_issues_helper import ( JiraIssueHelper, ) @@ -16,20 +22,20 @@ class JiraIssuesAnalyzerAgentInput(BaseModel): """ - Input model for configuring GitHub Pull Request extraction and analysis. + Input model for configuring Jira data extraction and analysis. """ project_name: Optional[str] = Field( default=None, description=( - "Specific project name to analyze. " - "PARSING INSTRUCTION: Extract exact project name from the query. " + "Optional specific project name to analyze. " + "PARSING INSTRUCTION: Extract exact project name from the query if query specifies a project name. " ), ) assignee: Optional[str] = Field( default=None, description=( - "Jira username to filter issues. " + "Optional Jira username to filter issues. " "PARSING INSTRUCTION: Extract Jira username mentioned in the query." ), ) @@ -41,53 +47,65 @@ class JiraIssuesAnalyzerAgentInput(BaseModel): default=None, description="Latest date for issue creation (inclusive)", ) - summary_only: Optional[bool] = Field( + minimum_updated_date: Optional[datetime] = Field( + default=None, + description="Earliest date for issue update (inclusive)", + ) + maximum_updated_date: Optional[datetime] = Field( + default=None, + description="Latest date for issue update (inclusive)", + ) + counts_only: Optional[bool] = Field( + default=False, + description="Whether to return just count of issues or each issue details", + ) + sort_by: Optional[Literal["updated", "created", "resolved"]] = Field( + default="updated", + description="Field to sort by. Choices: 'updated', 'created', 'resolved'. Default is 'updated'.", + ) + sort_by_direction: Optional[Literal["asc", "desc"]] = Field( + default="desc", + description="Sort direction for jira issues. Choices: 'asc', 'desc'. Default is 'desc'.", + ) + include_full_description: Optional[bool] = Field( default=False, - description="Whether to return just the summary or full issue details", + description="Include full issue description or just summary", + ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) + limit: Optional[int] = Field( + default=100, + description="Maximum number of jira issues to retrieve", ) class JiraIssuesAnalyzerTool(ResilientBaseTool): """ - A LangChain-compatible tool for comprehensive GitHub pull request analysis. - - This tool provides advanced capabilities for extracting and analyzing - pull request data from a GitHub organization. It supports: - - Filtering issues by project, date range, and contributor - - Generating summary reports of pull request activity - - Retrieving detailed pull request information - - Key Features: - - Asynchronous pull request retrieval - - Configurable analysis scope - - Detailed or summarized reporting - - Error handling and logging - - Requires: - - GitHub access token - - GITHUB_ORGANIZATION_NAME environment variable - - Example Usage: - ```python - tool = JiraIssuesAnalyzerTool(access_token='your_github_token') - results, artifact = await tool._arun( - project_name='my-project', - minimum_created_date=datetime(2023, 1, 1), - includeDetails=True - ) - ``` + A LangChain-compatible tool for comprehensive Jira issue analysis. + + This tool can be used to extract and analyze Jira issues across projects and assignees. + """ name: str = "jira_issues_analyzer" description: str = ( - "Advanced Jira Issue analysis tool. Set includeDetails if you want detailed issue information. " + "Advanced Jira Issue analysis tool. " "USAGE TIPS: " - "- Specify project with 'in [project]' " "- Specify assignee with username " + "- If querying for a specific date range, include 'from [date] to [date]' " + "- Set 'counts_only' if you want to get counts only" + "- Set include_full_description to get full issue description" + "- Set 'sort_by' to sort by 'created', 'updated', 'popularity', or 'long-running' " + "- Set 'sort_by_direction' to 'asc' or 'desc' " + "- Set 'use_verbose_logging' to get verbose logs" + "- Set 'limit' to get a specific number of issues" "- Example queries: " "'Pull issues in EFS', " "'Issues assigned to johndoe in EFS', " "'What issues assigned to imranq2 in EFS project'" + "'Get last 10 issues'" ) args_schema: Type[BaseModel] = JiraIssuesAnalyzerAgentInput @@ -101,8 +119,15 @@ def _run( project_name: Optional[str] = None, minimum_created_date: Optional[datetime] = None, maximum_created_date: Optional[datetime] = None, + minimum_updated_date: Optional[datetime] = None, + maximum_updated_date: Optional[datetime] = None, assignee: Optional[str] = None, - summary_only: Optional[bool] = None, + counts_only: Optional[bool] = None, + sort_by: Optional[Literal["updated", "created", "resolved"]] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + include_full_description: Optional[bool] = None, + use_verbose_logging: Optional[bool] = None, + limit: Optional[int] = None, ) -> Tuple[str, str]: """ Synchronous version of the tool (falls back to async implementation). @@ -118,8 +143,15 @@ async def _arun( project_name: Optional[str] = None, minimum_created_date: Optional[datetime] = None, maximum_created_date: Optional[datetime] = None, + minimum_updated_date: Optional[datetime] = None, + maximum_updated_date: Optional[datetime] = None, assignee: Optional[str] = None, - summary_only: Optional[bool] = None, + counts_only: Optional[bool] = None, + sort_by: Optional[Literal["updated", "created", "resolved"]] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + include_full_description: Optional[bool] = None, + use_verbose_logging: Optional[bool] = None, + limit: Optional[int] = None, ) -> Tuple[str, str]: """ Asynchronous version of the Jira Issues analyzer tool. @@ -128,64 +160,99 @@ async def _arun( Tuple of Jira issue text and artifact description """ - logger.info( - "JiraIssuesAnalyzerAgent:" - + f" {project_name=}, {minimum_created_date=}, {maximum_created_date=}" - + f", {assignee=}, {summary_only=}" - ) + log_prefix: str = "JiraIssuesAnalyzerAgent: " + log_prefix_items: List[str] = [] + if project_name: + log_prefix_items.append(f"{project_name=}") + if minimum_created_date: + log_prefix_items.append( + f"minimum_created_date={minimum_created_date.isoformat()}" + ) + if maximum_created_date: + log_prefix_items.append( + f"maximum_created_date={maximum_created_date.isoformat()}" + ) + if minimum_updated_date: + log_prefix_items.append( + f"minimum_updated_date={minimum_updated_date.isoformat()}" + ) + if maximum_updated_date: + log_prefix_items.append( + f"maximum_updated_date={maximum_updated_date.isoformat()}" + ) + if assignee: + log_prefix_items.append(f"{assignee=}") + if counts_only: + log_prefix_items.append(f"{counts_only=}") + if sort_by: + log_prefix_items.append(f"{sort_by=}") - log_prefix: str = ( - "JiraIssuesAnalyzerAgent:" - + f" {project_name=}, {minimum_created_date=}, {maximum_created_date=}" - + f", {assignee=}, {summary_only=}" - ) + log_prefix += ", ".join(log_prefix_items) try: max_projects: int = int(os.environ.get("JIRA_MAXIMUM_PROJECTS", 100)) max_issues: int = int( os.environ.get("JIRA_MAXIMUM_ISSUES_PER_PROJECT", 100) ) - jira_issues: List[JiraIssue] = ( + if limit: + max_issues = limit + jira_issues_result: JiraIssueResult = ( await self.jira_issues_helper.retrieve_closed_issues( max_projects=max_projects, max_issues=max_issues, min_created_at=minimum_created_date, max_created_at=maximum_created_date, + min_updated_at=minimum_updated_date, + max_updated_at=maximum_updated_date, project_key=project_name, assignee=assignee, + sort_by=sort_by, + sort_by_direction=sort_by_direction, + include_full_description=include_full_description, ) ) + if jira_issues_result.error: + error_msg = f"Error analyzing Jira issues: {jira_issues_result.error}" + error_artifact = ( + log_prefix + f" Analysis Failed: {jira_issues_result.error}" + ) + logger.error(error_msg) + return error_msg, error_artifact + + jira_issues: List[JiraIssue] = jira_issues_result.issues + full_text: str - if not summary_only: - full_text = "" + if not counts_only: + full_text = "Id,Summary,Status,Assignee,Created,Closed\n" for issue in jira_issues: - full_text += f"Issue: {issue.summary} status: {issue.status} assigned to {issue.assignee}" - f" created on {issue.created_at}\n" - f" closed on {issue.closed_at}\n" + clean_summary: str = issue.summary.replace('"', "'") + full_text += f'{issue.key},"{clean_summary}",{issue.status},{issue.assignee},{issue.created_at.date().isoformat()},{issue.closed_at.date().isoformat() if issue.closed_at else "N/A"}\n' else: # Summarize issues by engineer pr_summary = self.jira_issues_helper.summarize_issues_by_assignee( issues=jira_issues ) - - # Generate detailed text report - report_lines = [ - "Issues by Assignee:", - ] - - for engineer, info in pr_summary.items(): - report_lines.append(f"{engineer}: {info.issue_count}") - - full_text = "\n".join(report_lines) + full_text = self.jira_issues_helper.export_results_to_csv( + issue_counts=pr_summary + ) # Create artifact description - artifact = log_prefix + f", Analyzed {len(jira_issues)} closed issues" + artifact = log_prefix + f", Analyzed {len(jira_issues)} closed issues." + if jira_issues_result.error: + artifact += f"\nError: {jira_issues_result.error}" + if len(jira_issues) == 0: + artifact += f"\nJira Query:\n{jira_issues_result.query}" + elif use_verbose_logging: + artifact += f"\nJira Query: {jira_issues_result.query}" + + artifact += "\n\nResults:" + artifact += f"\n{CsvToMarkdownConverter.csv_to_markdown_table(full_text)}" return full_text, artifact except Exception as e: error_msg = f"Error analyzing Jira issues: {str(e)}" - error_artifact = log_prefix + " Analysis Failed" + error_artifact = log_prefix + " Analysis Failed: " + str(e) logger.error(error_msg) return error_msg, error_artifact diff --git a/language_model_gateway/gateway/tools/mcp_tool_provider.py b/language_model_gateway/gateway/tools/mcp_tool_provider.py new file mode 100644 index 000000000..8631257a4 --- /dev/null +++ b/language_model_gateway/gateway/tools/mcp_tool_provider.py @@ -0,0 +1,121 @@ +import logging +import os +from typing import Dict, List + +from langchain_core.tools import BaseTool +from langchain_mcp_adapters.sessions import StreamableHttpConnection + +from language_model_gateway.configs.config_schema import AgentConfig +from language_model_gateway.gateway.langchain_overrides.multiserver_mcp_client_with_caching import ( + MultiServerMCPClientWithCaching, +) +from language_model_gateway.gateway.utilities.cache.mcp_tools_expiring_cache import ( + McpToolsMetadataExpiringCache, +) + +logger = logging.getLogger(__name__) + + +class MCPToolProvider: + """ + A class to provide tools for the MCP (Model Control Protocol) gateway. + This class is responsible for managing and providing access to various tools + that can be used in conjunction with the MCP. + """ + + def __init__(self, *, cache: McpToolsMetadataExpiringCache) -> None: + """ + Initialize the MCPToolProvider with a cache. + + Args: + cache: An ExpiringCache instance to store tools by their MCP URLs. + """ + self.tools_by_mcp_url: Dict[str, List[BaseTool]] = {} + self._cache: McpToolsMetadataExpiringCache = cache + assert self._cache is not None, "Cache must be provided" + + async def load_async(self) -> None: + pass + + async def get_tools_by_url_async( + self, *, tool: AgentConfig, headers: Dict[str, str] + ) -> List[BaseTool]: + try: + url: str | None = tool.url + assert url is not None, "Tool URL must be provided" + # first see if the url is already loaded + if url in self.tools_by_mcp_url: + return self.tools_by_mcp_url[url] + + # TODO: probably cache the tools and just use the headers by specifying an httpx_client_factory + mcp_tool_config: StreamableHttpConnection = { + "url": url, + "transport": "streamable_http", + # specify the http client factory to use the headers + # httpx_client_factory + # and/or bearer "auth"# auth: NotRequired[httpx.Auth] + } + if tool.headers: + # replace the strings with os.path.expandvars # to allow for environment variable expansion + mcp_tool_config["headers"] = { + key: os.path.expandvars(value) + for key, value in tool.headers.items() + } + + # pass Authorization header if provided + if headers: + auth_header: str | None = next( + ( + headers.get(key) + for key in headers + if key.lower() == "authorization" + ), + None, + ) + if auth_header: + # add the Authorization header to the mcp_tool_config headers + mcp_tool_config["headers"] = { + **mcp_tool_config.get("headers", {}), + "Authorization": auth_header, + } + logger.debug("Loading MCP tools with Authorization header") + + tool_names: List[str] | None = tool.tools.split(",") if tool.tools else None + client: MultiServerMCPClientWithCaching = MultiServerMCPClientWithCaching( + cache=self._cache, + connections={ + f"{tool.name}": mcp_tool_config, + }, + tool_names=tool_names, + ) + tools: List[BaseTool] = await client.get_tools() + if tool_names and tools: + # filter tools by tool_name if provided + tools = [t for t in tools if t.name in tool_names] + self.tools_by_mcp_url[url] = tools + return tools + except* Exception as e: + url = tool.url if tool.url else "unknown" + logger.error( + f"get_tools_by_url_async Failed to load MCP tools from {url}: {type(e)} {e}" + ) + raise e + + async def get_tools_async( + self, *, tools: list[AgentConfig], headers: Dict[str, str] + ) -> list[BaseTool]: + # get list of tools from the tools from each agent and then concatenate them + all_tools: List[BaseTool] = [] + for tool in tools: + if tool.url is not None: + try: + tools_by_url: List[BaseTool] = await self.get_tools_by_url_async( + tool=tool, headers=headers + ) + all_tools.extend(tools_by_url) + except* Exception as e: + logger.error( + f"get_tools_async Failed to get tools for {tool.name} from {tool.url}: {type(e)} {e}" + ) + raise e + return all_tools diff --git a/language_model_gateway/gateway/tools/network_topology_diagram_tool.py b/language_model_gateway/gateway/tools/network_topology_diagram_tool.py index 03e5cbe0d..326e98584 100644 --- a/language_model_gateway/gateway/tools/network_topology_diagram_tool.py +++ b/language_model_gateway/gateway/tools/network_topology_diagram_tool.py @@ -1,5 +1,6 @@ import logging import os +import tempfile from typing import Type, Literal, Tuple, Optional, List, Dict, Any from uuid import uuid4 @@ -180,7 +181,9 @@ async def _arun( image_file_name: str = f"{uuid4()}.png" # Use file manager to save the file - image_generation_path_ = os.environ.get("IMAGE_GENERATION_PATH", "/tmp") + image_generation_path_ = os.environ.get( + "IMAGE_GENERATION_PATH", tempfile.gettempdir() + ) file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ ) @@ -204,9 +207,7 @@ async def _arun( "SequenceDiagramGeneratorTool: Failed to save image to disk", ) - artifact: str = ( - f"NetworkTopologyGeneratorTool: Generated network topology diagram <{url}> " - ) + artifact: str = f"NetworkTopologyGeneratorTool: Generated network topology diagram <{url}> " # Return the image bytes and a description return url, artifact diff --git a/language_model_gateway/gateway/tools/pdf_extraction_tool.py b/language_model_gateway/gateway/tools/pdf_extraction_tool.py index 1f9a2b893..92663348a 100644 --- a/language_model_gateway/gateway/tools/pdf_extraction_tool.py +++ b/language_model_gateway/gateway/tools/pdf_extraction_tool.py @@ -36,6 +36,10 @@ class PDFExtractionToolInput(BaseModel): default=False, description="Use OCR (Optical Character Recognition) if text extraction fails", ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class PDFExtractionTool(ResilientBaseTool): @@ -61,6 +65,7 @@ def _run( start_page: Optional[int] = None, end_page: Optional[int] = None, use_ocr: bool = False, + use_verbose_logging: Optional[bool] = None, ) -> Tuple[str, str]: """ Synchronous version of the tool (falls back to async implementation). @@ -79,6 +84,7 @@ async def _arun( start_page: Optional[int] = None, end_page: Optional[int] = None, use_ocr: bool = False, + use_verbose_logging: Optional[bool] = None, ) -> Tuple[str, str]: """ Asynchronous version of the tool with OCR support. @@ -89,6 +95,7 @@ async def _arun( start_page (Optional[int]): Starting page for extraction end_page (Optional[int]): Ending page for extraction use_ocr (bool): Use AWS Textract for OCR if text extraction fails + use_verbose_logging (Optional[bool]): Whether to enable verbose logging Returns: Tuple of extracted text and artifact description @@ -152,6 +159,8 @@ async def _arun( f"PDFExtractionAgent: Extracted text from pages {start} to {end} " f"(Total pages: {total_pages}, OCR: {'Yes' if use_ocr else 'No'})" ) + if use_verbose_logging: + artifact += f"\n===== Extracted text =====\n```{full_text}```\n====== End of Text ======" return full_text.strip(), artifact diff --git a/language_model_gateway/gateway/tools/provider_search_tool.py b/language_model_gateway/gateway/tools/provider_search_tool.py index 8ef198b05..dbbc84a5f 100644 --- a/language_model_gateway/gateway/tools/provider_search_tool.py +++ b/language_model_gateway/gateway/tools/provider_search_tool.py @@ -22,13 +22,15 @@ class ProviderSearchToolInput(BaseModel): insurance: Optional[List[str]] = Field( description="List of insurance plans to filter by" ) + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class ProviderSearchTool(ResilientBaseTool): name: str = "provider_search" - description: str = ( - "Search for healthcare providers (e.g., doctors, clinics and hospitals) based on various criteria like name, specialty, location, insurance etc." - ) + description: str = "Search for healthcare providers (e.g., doctors, clinics and hospitals) based on various criteria like name, specialty, location, insurance etc." args_schema: Type[BaseModel] = ProviderSearchToolInput response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" api_url: Optional[str] = os.environ.get("PROVIDER_SEARCH_API_URL") @@ -44,7 +46,7 @@ def _build_query(self) -> str: ) { searchProviders( searchProvidersInput: { - client: [{ dataSets: NPPES }] + client: [{ dataSets: [CONNECTHUB, NPPES] }] search: $search searchPosition: $searchPosition specialty: $specialty @@ -99,6 +101,17 @@ def _build_query(self) -> str: } endpoint { name + address + status + identifier { + system + value + } + connectionType { + code + display + system + } } } } @@ -115,7 +128,6 @@ def _prepare_variables( specialty: Optional[List[str]] = None, insurance: Optional[List[str]] = None, ) -> Dict[str, Any]: - variables: Dict[ str, str | float | int | Dict[str, Any] | List[Dict[str, Any]] | None ] = { @@ -165,6 +177,7 @@ def _run( distance: Optional[float] = None, specialty: Optional[List[str]] = None, insurance: Optional[List[str]] = None, + use_verbose_logging: Optional[bool] = None, ) -> Dict[str, Any]: """Synchronous execution""" raise NotImplementedError("Use async version of this tool") @@ -177,6 +190,7 @@ async def _arun( distance: Optional[float] = None, specialty: Optional[List[str]] = None, insurance: Optional[List[str]] = None, + use_verbose_logging: Optional[bool] = None, ) -> Tuple[Dict[str, Any], str]: """Asynchronous execution""" @@ -202,10 +216,11 @@ async def _arun( try: response = await async_client.post(self.api_url, json=payload, timeout=30.0) - return ( - self._handle_response(response), - f"ProviderSearchAgent: Searched for {search} {variables} ", - ) + artifact: str = f"ProviderSearchAgent: Searched for {search} {variables} " + if use_verbose_logging: + artifact += f"\nRequest: {payload}" + artifact += f"===== Response ======\n```{response.text}```\n====== End of Response ======" + return self._handle_response(response), artifact except httpx.TimeoutException: raise Exception("Request timed out") diff --git a/language_model_gateway/gateway/tools/python_repl_tool.py b/language_model_gateway/gateway/tools/python_repl_tool.py index b2159ab3a..9df9e5b64 100644 --- a/language_model_gateway/gateway/tools/python_repl_tool.py +++ b/language_model_gateway/gateway/tools/python_repl_tool.py @@ -16,9 +16,7 @@ class PythonReplToolInput(BaseModel): class PythonReplTool(ResilientBaseTool): name: str = "python_repl" - description: str = ( - "A Python shell. Use this to execute python commands. Input should be a valid python command. If you want to see the output of a value, you should print it out with `print(...)`." - ) + description: str = "A Python shell. Use this to execute python commands. Input should be a valid python command. If you want to see the output of a value, you should print it out with `print(...)`." args_schema: Type[BaseModel] = PythonReplToolInput async def _arun(self, query: str) -> str: diff --git a/language_model_gateway/gateway/tools/resilient_base_tool.py b/language_model_gateway/gateway/tools/resilient_base_tool.py index c19438bcb..7104b30bc 100644 --- a/language_model_gateway/gateway/tools/resilient_base_tool.py +++ b/language_model_gateway/gateway/tools/resilient_base_tool.py @@ -2,6 +2,7 @@ from typing import Optional, Any, Dict, Union, List from langchain_core.tools import BaseTool +from pydantic import BaseModel class ResilientBaseTool(BaseTool, metaclass=ABCMeta): @@ -36,6 +37,8 @@ def camel_to_snake(name: str) -> str: # find keys that are not present in self.args_schema # and convert them to snake_case + assert self.args_schema is not None + assert isinstance(self.args_schema, BaseModel) input_fields: List[str] = [c for c in self.args_schema.model_fields.keys()] tool_input = { (camel_to_snake(key) if key not in input_fields else key): value diff --git a/language_model_gateway/gateway/tools/scraping_bee_web_scraper_tool.py b/language_model_gateway/gateway/tools/scraping_bee_web_scraper_tool.py index 0ba5cbf9e..b85a19220 100644 --- a/language_model_gateway/gateway/tools/scraping_bee_web_scraper_tool.py +++ b/language_model_gateway/gateway/tools/scraping_bee_web_scraper_tool.py @@ -16,6 +16,10 @@ class ScrapingBeeWebScraperToolInput(BaseModel): url: str = Field(description="url of the webpage to scrape") query: Optional[str] = Field(description="Query to search for on the webpage") + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class ScrapingBeeWebScraperTool(ResilientBaseTool): @@ -112,19 +116,29 @@ async def _extract_text_content_async(self, html_content: str) -> str: html_content=html_content ) - def _run(self, url: str, query: Optional[str] = None) -> Tuple[str, str]: + def _run( + self, + url: str, + query: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, + ) -> Tuple[str, str]: """Synchronous run method required by LangChain""" raise NotImplementedError("Use async version of this tool") - async def _arun(self, url: str, query: Optional[str] = None) -> Tuple[str, str]: + async def _arun( + self, + url: str, + query: Optional[str] = None, + use_verbose_logging: Optional[bool] = None, + ) -> Tuple[str, str]: """Async run method""" content: Optional[str] = await self._async_scrape(url=url, query=query) if content: - return ( - await self._extract_text_content_async(content), - f"ScrapingBeeWebScraperAgent: Scraped content using ScrapingBee from <{url}> ", - ) + artifact: str = f"ScrapingBeeWebScraperAgent: Scraped content using ScrapingBee from <{url}> " + if use_verbose_logging: + logger.info(f"\n```\n{content}\n```") + return await self._extract_text_content_async(content), artifact else: return ( "Error: Failed to scrape the webpage.", diff --git a/language_model_gateway/gateway/tools/sequence_diagram_generator_tool.py b/language_model_gateway/gateway/tools/sequence_diagram_generator_tool.py index a7a041dfe..3799b72f4 100644 --- a/language_model_gateway/gateway/tools/sequence_diagram_generator_tool.py +++ b/language_model_gateway/gateway/tools/sequence_diagram_generator_tool.py @@ -1,5 +1,6 @@ import logging import os +import tempfile from typing import Type, Literal, Tuple, Optional, List from uuid import uuid4 @@ -121,7 +122,9 @@ async def _arun( image_file_name: str = f"{uuid4()}.png" # Use file manager to save the file (if needed) - image_generation_path_ = os.environ.get("IMAGE_GENERATION_PATH", "/tmp") + image_generation_path_ = os.environ.get( + "IMAGE_GENERATION_PATH", tempfile.gettempdir() + ) file_manager: FileManager = self.file_manager_factory.get_file_manager( folder=image_generation_path_ ) diff --git a/language_model_gateway/gateway/tools/tool_provider.py b/language_model_gateway/gateway/tools/tool_provider.py index 5141535f2..c74009c0f 100644 --- a/language_model_gateway/gateway/tools/tool_provider.py +++ b/language_model_gateway/gateway/tools/tool_provider.py @@ -15,6 +15,12 @@ ImageGeneratorFactory, ) from language_model_gateway.gateway.ocr.ocr_extractor_factory import OCRExtractorFactory +from language_model_gateway.gateway.tools.confluence_page_retriever import ( + ConfluencePageRetriever, +) +from language_model_gateway.gateway.tools.confluence_search_tool import ( + ConfluenceSearchTool, +) from language_model_gateway.gateway.tools.current_time_tool import CurrentTimeTool from langchain_community.tools.pubmed.tool import PubmedQueryRun @@ -24,20 +30,34 @@ from language_model_gateway.gateway.tools.flow_chart_generator_tool import ( FlowChartGeneratorTool, ) +from language_model_gateway.gateway.tools.health_summary_generator_tool import ( + HealthSummaryGeneratorTool, +) from language_model_gateway.gateway.tools.github_pull_request_analyzer_tool import ( GitHubPullRequestAnalyzerTool, ) from language_model_gateway.gateway.tools.github_pull_request_diff_tool import ( GitHubPullRequestDiffTool, ) +from language_model_gateway.gateway.tools.github_pull_request_retriever_tool import ( + GitHubPullRequestRetriever, +) from language_model_gateway.gateway.tools.google_search_tool import GoogleSearchTool from language_model_gateway.gateway.tools.graph_viz_diagram_generator_tool import ( GraphVizDiagramGeneratorTool, ) +from language_model_gateway.gateway.tools.fhir_graphql_schema_provider import ( + GraphqlSchemaProviderTool, +) from language_model_gateway.gateway.tools.image_generator_tool import ImageGeneratorTool from language_model_gateway.gateway.tools.jira_issues_analyzer_tool import ( JiraIssuesAnalyzerTool, ) +from language_model_gateway.gateway.tools.databricks_sql_tool import DatabricksSQLTool + +from language_model_gateway.gateway.tools.jira_issue_retriever import ( + JiraIssueRetriever, +) from language_model_gateway.gateway.tools.network_topology_diagram_tool import ( NetworkTopologyGeneratorTool, ) @@ -51,6 +71,19 @@ SequenceDiagramGeneratorTool, ) from language_model_gateway.gateway.tools.url_to_markdown_tool import URLToMarkdownTool +from language_model_gateway.gateway.tools.calculator_average_tool import ( + CalculatorAverageTool, +) +from language_model_gateway.gateway.tools.calculator_stddev_tool import ( + CalculatorStddevTool, +) +from language_model_gateway.gateway.tools.calculator_sum_tool import CalculatorSumTool +from language_model_gateway.gateway.tools.calculator_length_tool import ( + CalculatorLengthTool, +) +from language_model_gateway.gateway.utilities.confluence.confluence_helper import ( + ConfluenceHelper, +) from language_model_gateway.gateway.utilities.environment_variables import ( EnvironmentVariables, ) @@ -60,6 +93,9 @@ from language_model_gateway.gateway.utilities.jira.jira_issues_helper import ( JiraIssueHelper, ) +from language_model_gateway.gateway.utilities.databricks.databricks_helper import ( + DatabricksHelper, +) class ToolProvider: @@ -72,6 +108,8 @@ def __init__( environment_variables: EnvironmentVariables, github_pull_request_helper: GithubPullRequestHelper, jira_issues_helper: JiraIssueHelper, + confluence_helper: ConfluenceHelper, + databricks_helper: DatabricksHelper, ) -> None: web_search_tool: BaseTool default_web_search_tool: str = environ.get( @@ -89,6 +127,10 @@ def __init__( self.tools: Dict[str, BaseTool] = { "current_date": CurrentTimeTool(), + "calculator_average": CalculatorAverageTool(), + "calculator_stddev": CalculatorStddevTool(), + "calculator_sum": CalculatorSumTool(), + "calculator_length": CalculatorLengthTool(), "web_search": web_search_tool, "pubmed": PubmedQueryRun(), "google_search": GoogleSearchTool(), @@ -96,6 +138,9 @@ def __init__( "python_repl": PythonReplTool(), "get_web_page": URLToMarkdownTool(), "arxiv_search": ArxivQueryRun(), + "health_summary_generator": HealthSummaryGeneratorTool( + file_manager_factory=file_manager_factory, + ), "image_generator": ImageGeneratorTool( image_generator_factory=image_generator_factory, file_manager_factory=file_manager_factory, @@ -137,6 +182,22 @@ def __init__( "jira_issues_analyzer": JiraIssuesAnalyzerTool( jira_issues_helper=jira_issues_helper ), + "databricks_query_validator": DatabricksSQLTool( + databricks_helper=databricks_helper + ), + "fhir_graphql_schema_provider": GraphqlSchemaProviderTool(), + "jira_issue_retriever": JiraIssueRetriever( + jira_issues_helper=jira_issues_helper + ), + "github_pull_request_retriever": GitHubPullRequestRetriever( + github_pull_request_helper=github_pull_request_helper + ), + "confluence_search_tool": ConfluenceSearchTool( + confluence_helper=confluence_helper + ), + "confluence_page_retriever": ConfluencePageRetriever( + confluence_helper=confluence_helper + ), # "sql_query": QuerySQLDataBaseTool( # db=SQLDatabase( # engine=Engine( @@ -148,10 +209,21 @@ def __init__( # ), } - def get_tool_by_name(self, *, tool: AgentConfig) -> BaseTool: + def get_tool_by_name( + self, *, tool: AgentConfig, headers: Dict[str, str] + ) -> BaseTool: if tool.name in self.tools: return self.tools[tool.name] raise ValueError(f"Tool with name {tool.name} not found") - def get_tools(self, *, tools: list[AgentConfig]) -> list[BaseTool]: - return [self.get_tool_by_name(tool=tool) for tool in tools] + def has_tool(self, *, tool: AgentConfig) -> bool: + return tool.name in self.tools + + def get_tools( + self, *, tools: list[AgentConfig], headers: Dict[str, str] + ) -> list[BaseTool]: + return [ + self.get_tool_by_name(tool=tool, headers=headers) + for tool in tools + if self.has_tool(tool=tool) + ] diff --git a/language_model_gateway/gateway/tools/url_to_markdown_tool.py b/language_model_gateway/gateway/tools/url_to_markdown_tool.py index e51c1255e..37927ceef 100644 --- a/language_model_gateway/gateway/tools/url_to_markdown_tool.py +++ b/language_model_gateway/gateway/tools/url_to_markdown_tool.py @@ -1,6 +1,6 @@ import logging import os -from typing import Type, Literal, Tuple +from typing import Type, Literal, Tuple, Optional import httpx from httpx import Headers @@ -17,6 +17,10 @@ class URLToMarkdownToolInput(BaseModel): url: str = Field(description="url of the webpage to scrape") + use_verbose_logging: Optional[bool] = Field( + default=False, + description="Whether to enable verbose logging", + ) class URLToMarkdownTool(ResilientBaseTool): @@ -32,7 +36,9 @@ class URLToMarkdownTool(ResilientBaseTool): args_schema: Type[BaseModel] = URLToMarkdownToolInput response_format: Literal["content", "content_and_artifact"] = "content_and_artifact" - def _run(self, url: str) -> Tuple[str, str]: + def _run( + self, url: str, use_verbose_logging: Optional[bool] = None + ) -> Tuple[str, str]: """ Synchronous version of the tool (falls back to async implementation). :param url: The URL of the webpage to fetch. @@ -40,7 +46,9 @@ def _run(self, url: str) -> Tuple[str, str]: """ raise NotImplementedError("Use async version of this tool") - async def _arun(self, url: str) -> Tuple[str, str]: + async def _arun( + self, url: str, use_verbose_logging: Optional[bool] = None + ) -> Tuple[str, str]: """ Asynchronous version of the tool. :param url: The URL of the webpage to fetch. @@ -69,7 +77,10 @@ async def _arun(self, url: str) -> Tuple[str, str]: logger.info( f"====== Scraped {url} ======\n{content}\n====== End of Scraped Markdown ======" ) - return content, f"URLToMarkdownAgent: Scraped content from <{url}> " + artifact: str = f"URLToMarkdownAgent: Scraped content from <{url}> " + if use_verbose_logging: + logger.info(f"\n```\n{content}\n```") + return content, artifact except Exception as e: return ( f"Failed to fetch or process the URL {url}: {str(e)}", diff --git a/language_model_gateway/gateway/utilities/auth/__init__.py b/language_model_gateway/gateway/utilities/auth/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/language_model_gateway/gateway/utilities/auth/token_verifier.py b/language_model_gateway/gateway/utilities/auth/token_verifier.py new file mode 100644 index 000000000..92de0e667 --- /dev/null +++ b/language_model_gateway/gateway/utilities/auth/token_verifier.py @@ -0,0 +1,173 @@ +import datetime +import logging +import time +from typing import Optional, Any, Dict, List, cast + +import httpx +from httpx import ConnectError +from joserfc import jwt +from aiocache import cached +from joserfc.errors import ExpiredTokenError +from joserfc.jwk import KeySet + +from zoneinfo import ZoneInfo + +logger = logging.getLogger(__name__) + + +class TokenVerifier: + def __init__( + self, + *, + jwks_uri: Optional[str] = None, + well_known_uri: Optional[str] = None, + issuer: Optional[str] = None, + audience: Optional[str] = None, + algorithms: Optional[list[str]] = None, + ): + assert jwks_uri or well_known_uri, ( + "Either JWKS URI or Well-Known URI must be provided" + ) + self.jwks_uri: Optional[str] = jwks_uri + self.well_known_uri: Optional[str] = well_known_uri + self.algorithms: List[str] = algorithms or ["RS256"] + self.jwks: KeySet | None = None # Will be set by async fetch + self.issuer: Optional[str] = issuer + self.audience: Optional[str] = audience + + @cached(ttl=60 * 60) + async def fetch_jwks_async(self) -> None: + # if we don't have a JWKS URI, try to fetch it from the well-known configuration + if not self.jwks_uri: + if not self.well_known_uri: + raise ValueError("Neither JWKS URI nor Well-Known URI is set") + self.jwks_uri, self.issuer = await self.get_jwks_uri_and_issuer_async() + + async with httpx.AsyncClient() as client: + try: + logger.info(f"Fetching JWKS from {self.jwks_uri}") + response = await client.get(self.jwks_uri) + response.raise_for_status() + jwks_data = response.json() + # Store all keys in a dict for fast lookup by kid + self.jwks = KeySet.import_key_set(jwks_data) + except httpx.HTTPStatusError as e: + raise ValueError( + f"Failed to fetch JWKS from {self.jwks_uri} with status {e.response.status_code} : {e}" + ) + except ConnectError as e: + raise ConnectionError( + f"Failed to connect to JWKS URI: {self.jwks_uri}: {e}" + ) + + @staticmethod + def extract_token(authorization_header: str | None) -> Optional[str]: + if not authorization_header: + return None + parts = authorization_header.split() + if len(parts) == 2 and parts[0].lower() == "bearer": + return parts[1] + return None + + async def verify_token_async(self, *, token: str) -> Dict[str, Any]: + """ + Verify a JWT token asynchronously using the JWKS from the provided URI. + + Args: + token: The JWT token string to validate. + Returns: + The decoded claims if the token is valid. + """ + assert token, "Token must not be empty" + await self.fetch_jwks_async() + assert self.jwks, "JWKS must be fetched before verifying tokens" + + exp_str: str = "None" + now_str: str = "None" + try: + # Validate the token + verified = jwt.decode(token, self.jwks, algorithms=self.algorithms) + + exp = verified.claims.get("exp") + now = time.time() + # convert exp and now to ET (America/New_York) for logging + tz = None + try: + tz = ZoneInfo("America/New_York") + except Exception: + tz = None # fallback to localtime if zoneinfo fails + + def to_eastern_time(ts: Optional[float]) -> str: + """Convert a timestamp to a formatted string in Eastern Time (ET).""" + if not ts: + return "None" + try: + dt = ( + datetime.datetime.fromtimestamp(ts, tz) + if tz + else datetime.datetime.fromtimestamp(ts) + ) + return dt.strftime("%Y-%m-%d %I:%M:%S %p %Z") # AM/PM format + except Exception: + return str(ts) + + exp_str = to_eastern_time(exp) + now_str = to_eastern_time(now) + # Create claims registry + claims_requests = jwt.JWTClaimsRegistry() + claims_requests.validate(verified.claims) + + logger.debug(f"Successfully verified token: {token}") + + return verified.claims + except ExpiredTokenError as e: + logger.warning(f"Token has expired: {token}") + raise ValueError( + f"This OAuth Token has expired. Exp: {exp_str}, Now: {now_str}.\nPlease Sign Out and Sign In to get a fresh OAuth token." + ) from e + except Exception as e: + raise ValueError( + f"Invalid token provided. Exp: {exp_str}, Now: {now_str}. Please check the token." + ) from e + + async def fetch_well_known_config_async(self) -> Dict[str, Any]: + """ + Fetches the OpenID Connect discovery document and returns its contents as a dict. + Returns: + dict: The parsed discovery document. + Raises: + ValueError: If the document cannot be fetched or parsed. + """ + if not self.well_known_uri: + raise ValueError("well_known_uri is not set") + async with httpx.AsyncClient() as client: + try: + logger.info( + f"Fetching OIDC discovery document from {self.well_known_uri}" + ) + response = await client.get(self.well_known_uri) + response.raise_for_status() + return cast(Dict[str, Any], response.json()) + except httpx.HTTPStatusError as e: + raise ValueError( + f"Failed to fetch OIDC discovery document from {self.well_known_uri} with status {e.response.status_code} : {e}" + ) + except ConnectError as e: + raise ConnectionError( + f"Failed to connect to OIDC discovery document: {self.well_known_uri}: {e}" + ) + + async def get_jwks_uri_and_issuer_async(self) -> tuple[str, str]: + """ + Retrieves the JWKS URI and issuer from the well-known OpenID Connect configuration. + Returns: + tuple: (jwks_uri, issuer) + Raises: + ValueError: If required fields are missing. + """ + config = await self.fetch_well_known_config_async() + jwks_uri = config.get("jwks_uri") + issuer = config.get("issuer") + if not jwks_uri or not issuer: + raise ValueError("jwks_uri or issuer not found in well-known configuration") + return jwks_uri, issuer diff --git a/language_model_gateway/gateway/utilities/cache/__init__.py b/language_model_gateway/gateway/utilities/cache/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/language_model_gateway/gateway/utilities/cache/config_expiring_cache.py b/language_model_gateway/gateway/utilities/cache/config_expiring_cache.py new file mode 100644 index 000000000..1c4f7acbf --- /dev/null +++ b/language_model_gateway/gateway/utilities/cache/config_expiring_cache.py @@ -0,0 +1,114 @@ +import asyncio +import logging +import time +from typing import Optional, List, override +from uuid import uuid4, UUID + +from language_model_gateway.configs.config_schema import ChatModelConfig +from language_model_gateway.gateway.utilities.cache.expiring_cache import ExpiringCache + +logger = logging.getLogger(__name__) + + +class ConfigExpiringCache(ExpiringCache[List[ChatModelConfig]]): + """ + Expiring cache for model configurations. + This cache stores a list of ChatModelConfig objects and expires after a specified time-to-live (TTL) period. + It is designed to be used in asynchronous environments and supports thread-safe operations. + The cache can be initialized with an optional initial value and will automatically + expire after the specified TTL in seconds. + """ + + _cache: Optional[List[ChatModelConfig]] = None + """ Cache for model configurations, stored as a list of ChatModelConfig objects. """ + _cache_timestamp: Optional[float] = None + """ Timestamp when the cache was last updated, used to determine cache validity. """ + _lock: asyncio.Lock = asyncio.Lock() + """ Asynchronous lock to ensure thread-safe access to the cache. """ + + def __init__( + self, *, ttl_seconds: float, init_value: Optional[List[ChatModelConfig]] = None + ) -> None: + """ + Initialize the expiring cache for model configurations. + Args: + ttl_seconds (float): Time-to-live for the cache in seconds. After this period, + the cache will be considered invalid. + init_value (Optional[List[ChatModelConfig]]): Optional initial value to populate the cache. + If not provided, the cache starts empty. + """ + self._ttl: float = ttl_seconds + self._identifier: UUID = uuid4() + if init_value is not None: + self._cache = init_value + self._cache_timestamp = time.time() + + @override + def is_valid(self) -> bool: + """ + Check if the cache is still valid based on the TTL. + Returns: + bool: True if the cache is valid (i.e., not expired), False otherwise. + """ + if self._cache is None or self._cache_timestamp is None: + return False + current_time: float = time.time() + cache_is_valid: bool = current_time - self._cache_timestamp < self._ttl + logger.debug( + f"ExpiringCache with id: {self._identifier} cache is valid: {cache_is_valid}. " + f"current time({current_time}) - cache_timestamp({self._cache_timestamp}) < ttl ({self._ttl})" + ) + return cache_is_valid + + @override + async def get(self) -> Optional[List[ChatModelConfig]]: + """ + Retrieve the current cache value if it is valid. + Returns: + Optional[List[ChatModelConfig]]: The cached value if valid, None otherwise. + """ + if self.is_valid(): + return self._cache + return None + + @override + async def set(self, value: List[ChatModelConfig]) -> None: + """ + Set the cache to a new value and update the cache timestamp. + Args: + value (List[ChatModelConfig]): The new value to store in the cache. + """ + async with self._lock: + self._cache = value + self._cache_timestamp = time.time() + logger.info( + f"ExpiringCache with id: {self._identifier} set cache with timestamp: {self._cache_timestamp}" + ) + + @override + async def clear(self) -> None: + """ + Clear the cache, removing any stored value and resetting the timestamp. + """ + async with self._lock: + self._cache = None + self._cache_timestamp = None + logger.info(f"ExpiringCache with id: {self._identifier} cleared cache") + + @override + async def create( + self, *, init_value: Optional[List[ChatModelConfig]] = None + ) -> Optional[List[ChatModelConfig]]: + """ + Create a new cache with an optional initial value. + Args: + init_value (Optional[List[ChatModelConfig]]): An optional initial value to set in the cache. + If not provided, the cache starts empty. + Returns: + Optional[List[ChatModelConfig]]: The initial value if provided, None otherwise. + """ + async with self._lock: + self._cache = init_value if init_value is not None else None + self._cache_timestamp = time.time() + logger.info(f"ExpiringCache with id: {self._identifier} created cache") + return self._cache diff --git a/language_model_gateway/gateway/utilities/cache/expiring_cache.py b/language_model_gateway/gateway/utilities/cache/expiring_cache.py new file mode 100644 index 000000000..2adc9258c --- /dev/null +++ b/language_model_gateway/gateway/utilities/cache/expiring_cache.py @@ -0,0 +1,58 @@ +from abc import ABC, abstractmethod +from typing import Optional + + +class ExpiringCache[T](ABC): + """ + Abstract base class for an expiring cache. + This class defines the interface for an expiring cache that can store and manage + values of type T with an expiration mechanism. + It provides methods to check validity, get, set, clear, and create cache entries. + Attributes: + T (type): The type of value stored in the cache. + """ + + @abstractmethod + def is_valid(self) -> bool: + """ + Check if the cache is valid based on its expiration criteria. + Returns: + bool: True if the cache is valid (i.e., not expired), False otherwise. + """ + pass + + @abstractmethod + async def get(self) -> Optional[T]: + """ + Retrieve the current cache value if it is valid. + Returns: + Optional[T]: The cached value if valid, None otherwise. + """ + pass + + @abstractmethod + async def set(self, value: T) -> None: + """ + Set the cache to a new value and update the cache timestamp. + Args: + value (T): The new value to store in the cache. + """ + pass + + @abstractmethod + async def clear(self) -> None: + """ + Clear the cache, removing any stored value and resetting the timestamp. + """ + pass + + @abstractmethod + async def create(self, *, init_value: Optional[T] = None) -> Optional[T]: + """ + Create a new cache with an optional initial value. + Args: + init_value (Optional[T]): An optional initial value to set in the cache. + Returns: + Optional[T]: The initial value if provided, None otherwise. + """ + pass diff --git a/language_model_gateway/gateway/utilities/cache/mcp_tools_expiring_cache.py b/language_model_gateway/gateway/utilities/cache/mcp_tools_expiring_cache.py new file mode 100644 index 000000000..5cc6b0184 --- /dev/null +++ b/language_model_gateway/gateway/utilities/cache/mcp_tools_expiring_cache.py @@ -0,0 +1,123 @@ +import asyncio +import logging +import time +from typing import Optional, Dict, List, override +from uuid import uuid4, UUID + +from mcp import Tool + +from language_model_gateway.gateway.utilities.cache.expiring_cache import ExpiringCache + +logger = logging.getLogger(__name__) + + +class McpToolsMetadataExpiringCache(ExpiringCache[Dict[str, List[Tool]]]): + """ + Expiring cache for MCP tools metadata. + + This cache stores metadata about tools used in MCP (Model Configuration Protocol) + and expires after a specified time-to-live (TTL) period. + It is designed to be used in asynchronous environments and supports thread-safe operations. + The cache can be initialized with an optional initial value and will automatically + expire after the specified TTL in seconds. + """ + + _cache: Optional[Dict[str, List[Tool]]] = None + """ Cache for MCP tools metadata, stored as a dictionary mapping tool names to lists of Tool objects. """ + _cache_timestamp: Optional[float] = None + """ Timestamp when the cache was last updated, used to determine cache validity. """ + _lock: asyncio.Lock = asyncio.Lock() + """ Asynchronous lock to ensure thread-safe access to the cache. """ + + def __init__( + self, *, ttl_seconds: float, init_value: Optional[Dict[str, List[Tool]]] = None + ) -> None: + """ + Initialize the expiring cache for MCP tools metadata. + Args: + ttl_seconds (float): Time-to-live for the cache in seconds. After this period, + the cache will be considered invalid. + init_value (Optional[Dict[str, List[Tool]]]): Optional initial value to populate the cache. + If not provided, the cache starts empty. + + """ + self._ttl: float = ttl_seconds + self._identifier: UUID = uuid4() + if init_value is not None: + self._cache = init_value + self._cache_timestamp = time.time() + + @override + def is_valid(self) -> bool: + """ + Check if the cache is still valid based on the TTL. + Returns: + bool: True if the cache is valid (i.e., not expired), False otherwise. + """ + if self._cache is None or self._cache_timestamp is None: + return False + current_time: float = time.time() + cache_is_valid: bool = current_time - self._cache_timestamp < self._ttl + logger.debug( + f"ExpiringCache with id: {self._identifier} cache is valid: {cache_is_valid}. " + f"current time({current_time}) - cache_timestamp({self._cache_timestamp}) < ttl ({self._ttl})" + ) + return cache_is_valid + + @override + async def get(self) -> Optional[Dict[str, List[Tool]]]: + """ + Retrieve the current cache value if it is valid. + Returns: + Optional[Dict[str, List[Tool]]]: The cached metadata if valid, None otherwise. + """ + if self.is_valid(): + return self._cache + return None + + @override + async def set(self, value: Dict[str, List[Tool]]) -> None: + """ + Set the cache to a new value and update the cache timestamp. + + Args: + value (Dict[str, List[Tool]]): The new metadata to store in the cache + + """ + async with self._lock: + self._cache = value + self._cache_timestamp = time.time() + logger.info( + f"ExpiringCache with id: {self._identifier} set cache with timestamp: {self._cache_timestamp}" + ) + + @override + async def create( + self, *, init_value: Optional[Dict[str, List[Tool]]] = None + ) -> Dict[str, List[Tool]] | None: + """ + Create a new cache with an optional initial value. + + Args: + init_value (Optional[Dict[str, List[Tool]]]): Optional initial value to populate + the cache. If not provided, the cache starts empty. + Returns: + Optional[Dict[str, List[Tool]]]: The newly created cache, which may be empty if no initial value is provided. + """ + async with self._lock: + self._cache = init_value if init_value is not None else {} + self._cache_timestamp = time.time() + logger.info(f"ExpiringCache with id: {self._identifier} created cache") + return self._cache + + @override + async def clear(self) -> None: + """ + Clear the cache by setting it to None and resetting the timestamp. + This method is thread-safe and ensures that the cache is emptied. + + """ + async with self._lock: + self._cache = None + self._cache_timestamp = None + logger.info(f"ExpiringCache with id: {self._identifier} cleared cache") diff --git a/language_model_gateway/gateway/utilities/chat_message_helpers.py b/language_model_gateway/gateway/utilities/chat_message_helpers.py index fd9eaa64d..0c40c4fa4 100644 --- a/language_model_gateway/gateway/utilities/chat_message_helpers.py +++ b/language_model_gateway/gateway/utilities/chat_message_helpers.py @@ -25,9 +25,9 @@ def convert_message_content_to_string(content: str | list[str | Dict[str, Any]]) if content_item_type == "text": text.append(content_item.get("text") or "") else: - assert ( - False - ), f"Unsupported content item type: {type(content_item)}: {content_item}" + assert False, ( + f"Unsupported content item type: {type(content_item)}: {content_item}" + ) return "".join(text) @@ -35,13 +35,13 @@ def langchain_to_chat_message(message: BaseMessage) -> Optional[ChatCompletionMe """Create a ChatMessage from a LangChain message.""" match message: case SystemMessage(): - assert ( - False - ), "System messages should not be converted to ChatCompletionMessage" + assert False, ( + "System messages should not be converted to ChatCompletionMessage" + ) case HumanMessage(): - assert ( - False - ), "Human messages should not be converted to ChatCompletionMessage" + assert False, ( + "Human messages should not be converted to ChatCompletionMessage" + ) case AIMessage(): ai_message = ChatCompletionMessage( role="assistant", @@ -62,16 +62,16 @@ def langchain_to_chat_message(message: BaseMessage) -> Optional[ChatCompletionMe ) return ai_message case LangchainChatMessage(): - assert ( - False - ), "Chat messages should not be converted to ChatCompletionMessage" + assert False, ( + "Chat messages should not be converted to ChatCompletionMessage" + ) case _: raise ValueError(f"Unsupported message type: {message.__class__.__name__}") return None def remove_tool_calls( - content: str | list[str | dict[str, Any]] + content: str | list[str | dict[str, Any]], ) -> str | list[str | dict[str, Any]]: """Remove tool calls from content.""" if isinstance(content, str): diff --git a/language_model_gateway/gateway/utilities/confluence/__init__.py b/language_model_gateway/gateway/utilities/confluence/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/language_model_gateway/gateway/utilities/confluence/confluence_document.py b/language_model_gateway/gateway/utilities/confluence/confluence_document.py new file mode 100644 index 000000000..a7500ddda --- /dev/null +++ b/language_model_gateway/gateway/utilities/confluence/confluence_document.py @@ -0,0 +1,11 @@ +from dataclasses import dataclass + + +@dataclass +class ConfluenceDocument: + id: str + title: str + url: str + updated_at: str + author_name: str + content: str diff --git a/language_model_gateway/gateway/utilities/confluence/confluence_helper.py b/language_model_gateway/gateway/utilities/confluence/confluence_helper.py new file mode 100644 index 000000000..6f8baa61e --- /dev/null +++ b/language_model_gateway/gateway/utilities/confluence/confluence_helper.py @@ -0,0 +1,207 @@ +import base64 +import csv +import logging +import re +from datetime import datetime +from typing import List, Optional +from urllib.parse import urlencode + +from language_model_gateway.gateway.http.http_client_factory import HttpClientFactory +from language_model_gateway.gateway.utilities.confluence.confluence_document import ( + ConfluenceDocument, +) +from language_model_gateway.gateway.utilities.confluence.confluence_search_result import ( + ConfluenceSearchResult, +) + + +class ConfluenceHelper: + def __init__( + self, + *, + http_client_factory: HttpClientFactory, + confluence_base_url: Optional[str], + access_token: Optional[str], + username: Optional[str], + ): + self.http_client_factory = http_client_factory + self.logger = logging.getLogger(__name__) + self.confluence_base_url = ( + confluence_base_url.rstrip("/") if confluence_base_url else None + ) + self.confluence_access_token = access_token + self.username = username + + credentials = base64.b64encode(f"{username}:{access_token}".encode()).decode() + self.headers = { + "Authorization": f"Basic {credentials}", + "Content-Type": "application/json", + "Accept": "application/json", + "User-Agent": "AsyncConfluenceHelper", + } + + async def search_content( + self, search_string: str, limit: int = 10 + ) -> List[ConfluenceSearchResult]: + if not self.confluence_base_url: + self.logger.error("Confluence base URL is not set.") + return [] + + async with self.http_client_factory.create_http_client( + base_url=self.confluence_base_url, headers=self.headers, timeout=30.0 + ) as client: + try: + cleaned_string = re.sub(r"[^a-zA-Z0-9\s]", "", search_string) + self.logger.info( + f"Searching Confluence for: {search_string}; pre-cleaned search string was: {search_string}" + ) + cql_query = f'siteSearch ~ "{cleaned_string}"' # 'siteSearch' gives much better results than doing 'text' + + base_url = f"{self.confluence_base_url}/wiki/rest/api/search" + params = {"cql": cql_query, "limit": str(limit)} + + # Combine them to create the full URL for logging + full_url = f"{base_url}?{urlencode(params)}" + self.logger.info(f"Making Confluence request to: {full_url}") + + # Make the actual request + response = await client.get(base_url, params=params) + + response.raise_for_status() + + results = response.json().get("results", []) + # self.logger.info(f"Confluence raw response:\n{results}") + search_results = [] + for result in results: + content = result.get("content", {}) + search_results.append( + ConfluenceSearchResult( + id=content.get("id"), + title=content.get("title"), + url=f"{self.confluence_base_url}/wiki/{content.get('_links', {}).get('webui')}", + updated_at=datetime.fromisoformat( + result.get("lastModified").replace("Z", "+00:00") + ) + .date() + .isoformat(), + excerpt=result.get("excerpt"), + ) + ) + return search_results + except Exception as e: + self.logger.error(f"Error searching Confluence content: {str(e)}") + return [] + + def write_results_to_csv( + self, search_results: List[ConfluenceSearchResult], output_file: str + ) -> None: + """ + Export search results to a CSV file. + + Args: + search_results (List[ConfluenceSearchResult]): List of search results + output_file (str): Path to the output CSV file + """ + assert output_file, "Output file path is required" + assert search_results, "Search results are required" + + try: + with open(output_file, mode="w", newline="") as file: + writer = csv.writer(file) + writer.writerow(["Id", "Title", "URL", "Updated", "Excerpt"]) + for result in search_results: + writer.writerow( + [ + result.id, + result.title, + result.url, + result.updated_at, + result.excerpt, + ] + ) + self.logger.info(f"Results exported to {output_file}") + except IOError as e: + self.logger.error(f"Failed to export results: {e}") + + def format_results_as_csv( + self, search_results: List[ConfluenceSearchResult] + ) -> str: + """ + Export search results to a CSV formatted string. + + Args: + search_results (List[ConfluenceSearchResult]): List of search results + + Returns: + str: CSV formatted string of search results + """ + assert search_results, "Search results are required" + + output = "Id,Title,URL,Updated,Excerpt\n" + for result in search_results: + output += f"{result.id},{result.title},{result.url},{result.updated_at},{result.excerpt}\n" + return output + + def format_results_as_csv_for_display( + self, search_results: List[ConfluenceSearchResult] + ) -> str: + """ + Export search results to a CSV formatted string. + + Args: + search_results (List[ConfluenceSearchResult]): List of search results + + Returns: + str: CSV formatted string of search results + """ + assert search_results, "Search results are required" + + output = "Title,URL,Updated\n" + for result in search_results: + output += f"{result.title},{result.url},{result.updated_at}\n" + return output + + async def retrieve_page_by_id(self, page_id: str) -> Optional[ConfluenceDocument]: + if not self.confluence_base_url: + self.logger.error("Confluence base URL is not set.") + return None + + async with self.http_client_factory.create_http_client( + base_url=self.confluence_base_url, headers=self.headers, timeout=30.0 + ) as client: + try: + url = f"{self.confluence_base_url}/wiki/rest/api/content/{page_id}?expand=body.storage,version.by" + self.logger.info( + f"Retrieving Confluence page with ID: {page_id}, full URL: {url}" + ) + + response = await client.get(url) + response.raise_for_status() + + result = response.json() + content = result.get("body", {}).get("storage", {}).get("value", "") + updated_at = ( + datetime.fromisoformat( + result.get("version", {}).get("when").replace("Z", "+00:00") + ) + .date() + .isoformat() + ) + author_name = ( + result.get("version", {}) + .get("by", {}) + .get("displayName", "Unknown") + ) + + page = ConfluenceDocument( + id=result.get("id"), + title=result.get("title"), + url=f"{self.confluence_base_url}/wiki/{result.get('_links', {}).get('webui')}", + updated_at=updated_at, + author_name=author_name, + content=content, + ) + return page + except Exception as e: + self.logger.error(f"Error retrieving Confluence page: {str(e)}") + return None diff --git a/language_model_gateway/gateway/utilities/confluence/confluence_search_result.py b/language_model_gateway/gateway/utilities/confluence/confluence_search_result.py new file mode 100644 index 000000000..94e79a1cd --- /dev/null +++ b/language_model_gateway/gateway/utilities/confluence/confluence_search_result.py @@ -0,0 +1,11 @@ +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class ConfluenceSearchResult: + id: str + title: str + url: str + updated_at: Optional[str] = None + excerpt: Optional[str] = None diff --git a/language_model_gateway/gateway/utilities/csv_to_markdown_converter.py b/language_model_gateway/gateway/utilities/csv_to_markdown_converter.py new file mode 100644 index 000000000..ab170df83 --- /dev/null +++ b/language_model_gateway/gateway/utilities/csv_to_markdown_converter.py @@ -0,0 +1,139 @@ +import csv +from io import StringIO +from typing import Union, Optional + + +class CsvToMarkdownConverter: + @staticmethod + def csv_to_markdown_table( + csv_string: str, + delimiter: str = ",", + quote_char: str = '"', + has_header: bool = True, + max_column_width: Optional[int] = None, + ) -> str: + """ + Convert a CSV string to a Markdown table, handling quoted fields. + + Args: + csv_string (str): The input CSV string + delimiter (str, optional): CSV delimiter. Defaults to ','. + quote_char (str, optional): Quote character. Defaults to '"'. + has_header (bool, optional): Whether the first row is a header. Defaults to True. + max_column_width (Optional[int], optional): Maximum column width before truncation. Defaults to None. + + Returns: + str: Markdown formatted table + """ + # Normalize input string and strip whitespace + csv_string = csv_string.strip() + + # Use StringIO to make the CSV string file-like + csv_file = StringIO(csv_string) + + # Use csv reader with quote handling + csv_reader = csv.reader( + csv_file, + delimiter=delimiter, + quotechar=quote_char, + skipinitialspace=True, # Ignore spaces after delimiter + ) + + # Convert rows to list for processing + try: + rows = list(csv_reader) + except csv.Error as e: + return f"Error parsing CSV: {str(e)}" + + if not rows: + return "| No Data |" + + # Separate headers and data rows + headers = ( + rows[0] if has_header else [f"Column {i + 1}" for i in range(len(rows[0]))] + ) + data_rows = rows[1:] if has_header else rows + + def escape_markdown_chars(text: str) -> str: + """ + Comprehensively escape characters for Markdown table safety. + + Args: + text (str): Input text to escape + + Returns: + str: Escaped text safe for Markdown tables + """ + # Escape Markdown special characters + escape_map = { + "|": "\\|", # Pipe character (table separator) + "_": "\\_", # Italic/underline marker + "*": "\\*", # Bold/italic marker + "[": "\\[", # Link start + "]": "\\]", # Link end + "`": "\\`", # Code marker + } + + # Escape special characters + escaped_text = "".join(escape_map.get(char, char) for char in text) + + # Handle escape sequences + escaped_text = ( + escaped_text.replace("\n", "\\n") # Newline + .replace("\t", "\\t") # Tab + .replace("\r", "\\r") # Carriage return + ) + + return escaped_text + + def sanitize_cell_content(cell: Union[str, object]) -> str: + """ + Sanitize cell content for Markdown table display. + + Args: + cell (Union[str, object]): Cell content to sanitize + + Returns: + str: Sanitized string representation + """ + # Convert to string and handle None/empty values + if cell is None: + return "" + + # Convert to string and escape + cell_str = str(cell).strip() + + # Escape Markdown and special characters + return escape_markdown_chars(cell_str) + + # Truncate content if max_column_width is specified + def truncate_cell(cell: str) -> str: + if max_column_width and len(cell) > max_column_width: + return cell[: max_column_width - 3] + "..." + return cell + + # Create Markdown table + # noinspection PyListCreation + markdown_lines = [] + + # Header row with sanitization and optional truncation + markdown_lines.append( + "| " + + " | ".join( + truncate_cell(sanitize_cell_content(header)) for header in headers + ) + + " |" + ) + + # Separator row with alignment + markdown_lines.append("| " + " | ".join(["---"] * len(headers)) + " |") + + # Data rows with sanitization and optional truncation + for row in data_rows: + markdown_lines.append( + "| " + + " | ".join(truncate_cell(sanitize_cell_content(cell)) for cell in row) + + " |" + ) + + return "\n".join(markdown_lines) diff --git a/language_model_gateway/gateway/utilities/databricks/__init__.py b/language_model_gateway/gateway/utilities/databricks/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/language_model_gateway/gateway/utilities/databricks/databricks_helper.py b/language_model_gateway/gateway/utilities/databricks/databricks_helper.py new file mode 100644 index 000000000..d09caff91 --- /dev/null +++ b/language_model_gateway/gateway/utilities/databricks/databricks_helper.py @@ -0,0 +1,151 @@ +import logging +import os +import time +from logging import Logger +from databricks.sdk import WorkspaceClient +from databricks.sdk.service.sql import StatementState, StatementResponse +import pandas as pd +from pandas.core.frame import DataFrame + + +class DatabricksHelper: + def __init__( + self, + *, + catalog: str = "bronze", + schema: str = "fhir_rpt", + ) -> None: + # Initialize logger as time, error level, and message + self.logger: Logger = logging.getLogger(__name__) + logging.basicConfig( + format="%(asctime)s - %(levelname)s - %(message)s", level=logging.INFO + ) + self.catalog = catalog + self.schema = schema + + def parse_databricks_statement_response( + self, statement_response: StatementResponse + ) -> pd.DataFrame: + """ + Simple parser to create a DataFrame from Databricks StatementResponse + Args: + statement_response: Databricks StatementResponse object + Returns: + Pandas DataFrame with query results + """ + try: + assert statement_response.manifest + assert statement_response.manifest.schema + assert statement_response.manifest.schema.columns + # Extract column names + column_names = [ + column.name for column in statement_response.manifest.schema.columns + ] + assert statement_response.result + # Extract data array + data_array = statement_response.result.data_array + # Create DataFrame + df = pd.DataFrame(data_array, columns=column_names) + + return df + + except Exception as e: + self.logger.error(f"Error parsing Databricks statement response: {e}") + return None + + def dataframe_to_markdown(self, df: DataFrame) -> str: + """ + Convert a pandas DataFrame to a markdown-formatted table + Args: + df (pandas.DataFrame): Input DataFrame + Returns: + str: Markdown-formatted table + """ + # Create header + markdown_table = "| " + " | ".join(df.columns) + " |\n" + # Create separator line + markdown_table += "| " + " | ".join(["---"] * len(df.columns)) + " |\n" + # Add rows + for _, row in df.iterrows(): + markdown_table += "| " + " | ".join(str(val) for val in row) + " |\n" + + return markdown_table + + def execute_query(self, query: str, max_wait_time: int = 300) -> str: + required_vars = [ + "DATABRICKS_HOST", + "DATABRICKS_TOKEN", + "DATABRICKS_SQL_WAREHOUSE_ID", + ] + for var in required_vars: + if not os.environ.get(var): + raise ValueError(f"{var} environment variable not set") + + try: + ws_client = WorkspaceClient( + host=os.environ.get("DATABRICKS_HOST"), + token=os.environ.get("DATABRICKS_TOKEN"), + ) + # Execute initial statement + # Handle warehouse_id as an environment variable + self.logger.debug(f"Executing Databricks query: {query}") + warehouse_id = os.environ.get("DATABRICKS_SQL_WAREHOUSE_ID") + self.logger.debug(f"Warehouse ID: {warehouse_id}") + if not warehouse_id: + raise ValueError( + "DATABRICKS_SQL_WAREHOUSE_ID environment variable not set" + ) + results = ws_client.statement_execution.execute_statement( + query, warehouse_id=warehouse_id + ) + assert results.status is not None + self.logger.debug(f"Initial results status: {results.status.state}") + + # Track start time for timeout + start_time = time.time() + + # Wait while statement is pending + while results.status.state == StatementState.PENDING: + # Check for timeout + self.logger.debug("Waiting for query to complete") + if time.time() - start_time >= max_wait_time: + self.logger.error(f"Query timed out after {max_wait_time} seconds") + raise TimeoutError("Query execution timed out") + + # Wait before checking again + time.sleep(1) # Wait 1 second between checks + + # Refresh the statement status + self.logger.debug("Refreshing statement status") + assert results.statement_id is not None + results = ws_client.statement_execution.get_statement( + results.statement_id + ) + assert results.status is not None + if results.status.state != StatementState.PENDING: + break + + assert results.status is not None + # Check for failed state + if results.status.state == StatementState.FAILED: + error_message = ( + results.status.error.message + if results.status.error + else "Unknown error" + ) + self.logger.error(f"Error executing Databricks query: {error_message}") + return f"Error executing Databricks query: {error_message}" + + # Log successful execution + self.logger.info(f"Query executed successfully: {results}") + + # Parse and return results + df = self.parse_databricks_statement_response(results) + if df is not None: + return self.dataframe_to_markdown(df) + + return "Dataframe was None. Unable to parse results" + + except Exception as e: + self.logger.error(f"Error executing Databricks query: {e}") + return "" diff --git a/language_model_gateway/gateway/utilities/environment_variables.py b/language_model_gateway/gateway/utilities/environment_variables.py index 094f6f858..d137daff6 100644 --- a/language_model_gateway/gateway/utilities/environment_variables.py +++ b/language_model_gateway/gateway/utilities/environment_variables.py @@ -22,3 +22,24 @@ def jira_token(self) -> Optional[str]: @property def jira_username(self) -> Optional[str]: return os.environ.get("JIRA_USERNAME") + + @property + def auth_jwks_uri(self) -> Optional[str]: + return os.environ.get("AUTH_JWKS_URI") + + @property + def auth_audience(self) -> Optional[str]: + return os.environ.get("AUTH_AUDIENCE") + + @property + def auth_issuer(self) -> Optional[str]: + return os.environ.get("AUTH_ISSUER") + + @property + def auth_algorithms(self) -> Optional[list[str]]: + auth_algorithms: str | None = os.environ.get("AUTH_ALGORITHMS") + return auth_algorithms.split(",") if auth_algorithms else None + + @property + def auth_well_known_uri(self) -> Optional[str]: + return os.environ.get("AUTH_WELL_KNOWN_URI") diff --git a/language_model_gateway/gateway/utilities/exception_logger.py b/language_model_gateway/gateway/utilities/exception_logger.py new file mode 100644 index 000000000..e573d7464 --- /dev/null +++ b/language_model_gateway/gateway/utilities/exception_logger.py @@ -0,0 +1,159 @@ +import logging +import os +import traceback +from typing import List, Optional + +import sys + +logger = logging.getLogger(__name__) + + +class ExceptionLogger: + @staticmethod + def extract_error_details(error: Exception | ExceptionGroup) -> str: + """ + Extract comprehensive error details from an Exception or ExceptionGroup. + + Args: + error (Union[Exception, ExceptionGroup]): The exception to extract details from + + Returns: + str: A formatted string containing error details + """ + + def get_short_traceback( + exception: Optional[BaseException] = None, max_depth: int = 3 + ) -> List[str]: + """ + Generate a short, readable stack trace. + + :param exception: Exception to trace (uses current exception if None) + :param max_depth: Maximum number of stack frames to include + :return: List of simplified stack trace entries + """ + # If no exception provided, get the current exception + if exception is None: + exception = sys.exc_info()[1] + + if exception is None: + return [] + + # Get the traceback + tb = exception.__traceback__ + + # Collect stack frames + stack_frames = [] + current_frame = tb + depth = 0 + + while current_frame and depth < max_depth: + # Get filename and line number + filename: str = os.path.basename( + current_frame.tb_frame.f_code.co_filename + ) + lineno: int | None = current_frame.tb_lineno + func_name: str = current_frame.tb_frame.f_code.co_name + + # Create a readable stack frame entry + stack_entry = f"{filename}:{lineno} in {func_name}" + stack_frames.append(stack_entry) + + # Move to next frame + current_frame = current_frame.tb_next + depth += 1 + + # If the exception has a __cause__ or __context__, include their tracebacks as well + cause = getattr(exception, "__cause__", None) + context = getattr(exception, "__context__", None) + if (cause or context) and depth < max_depth: + related = cause or context + stack_frames.append("Caused by:") + stack_frames.extend( + get_short_traceback( + related, max_depth=max_depth - len(stack_frames) + ) + ) + + return stack_frames + + def extract_exception_messages( + exception: Exception | BaseException, + ) -> List[str]: + """ + Extract messages from a nested exception chain. + + :param exception: The root exception + :return: List of exception messages from the exception chain + """ + messages = [] + current_exception: Optional[BaseException] = exception + + while current_exception is not None: + # Extract message or str representation + message = str(current_exception) + messages.append(message) + + # Move to the cause/context of the exception + current_exception = ( + current_exception.__cause__ or current_exception.__context__ + ) + + return messages + + def format_single_exception(exc: Exception) -> str: + """ + Format details for a single exception. + + Args: + exc (Exception): The exception to format + + Returns: + str: Formatted exception details + """ + # Extract full traceback + tb_details = traceback.extract_tb(exc.__traceback__) + + # Construct error message with type, value, and traceback + messages = extract_exception_messages(exc) + # error_lines = [ + # f"Type: {type(exc).__name__}", + # f"Message:", + # ] + error_lines: List[str] = [] + error_lines.extend(messages) + # error_lines.append("Stack trace:") + # short_trace_lines: List[str] = get_short_traceback(exc) + # error_lines.extend(short_trace_lines) + if logger.isEnabledFor(logging.DEBUG): + error_lines.append("Traceback:") + # # Add traceback details + for frame in tb_details: + error_lines.append( + f" File {frame.filename}, line {frame.lineno}, in {frame.name}" + ) + if frame.line: + error_lines.append(f" {frame.line.strip()}") + + return "\n".join(error_lines) + + # Handle single Exception + if isinstance(error, Exception) and not isinstance(error, ExceptionGroup): + return format_single_exception(error) + + # Handle ExceptionGroup + if isinstance(error, ExceptionGroup): + error_details: List[str] = [] + + # Recursively extract details from nested exceptions + def extract_nested_exceptions(exc_group: ExceptionGroup) -> None: + for exc in exc_group.exceptions: + if isinstance(exc, ExceptionGroup): + extract_nested_exceptions(exc) + else: + error_details.append(format_single_exception(exc)) + + # Start extraction + error_details.append(f"Exception Group: {error.message}") + extract_nested_exceptions(error) + + return "\n\n".join(error_details) diff --git a/language_model_gateway/gateway/utilities/expiring_cache.py b/language_model_gateway/gateway/utilities/expiring_cache.py deleted file mode 100644 index 5b401c904..000000000 --- a/language_model_gateway/gateway/utilities/expiring_cache.py +++ /dev/null @@ -1,47 +0,0 @@ -import asyncio -import logging -import time -from typing import Optional -from uuid import uuid4, UUID - - -logger = logging.getLogger(__name__) - - -class ExpiringCache[T]: - def __init__(self, *, ttl_seconds: float) -> None: - self._cache: Optional[T] = None - self._cache_timestamp: Optional[float] = None - self._lock: asyncio.Lock = asyncio.Lock() - self._ttl: float = ttl_seconds - self._identifier: UUID = uuid4() - - def is_valid(self) -> bool: - if self._cache is None or self._cache_timestamp is None: - return False - current_time: float = time.time() - cache_is_valid: bool = current_time - self._cache_timestamp < self._ttl - logger.debug( - f"ExpiringCache with id: {self._identifier} cache is valid: {cache_is_valid}. " - f"current time({current_time}) - cache_timestamp({self._cache_timestamp}) < ttl ({self._ttl})" - ) - return cache_is_valid - - async def get(self) -> Optional[T]: - if self.is_valid(): - return self._cache - return None - - async def set(self, value: T) -> None: - async with self._lock: - self._cache = value - self._cache_timestamp = time.time() - logger.info( - f"ExpiringCache with id: {self._identifier} set cache with timestamp: {self._cache_timestamp}" - ) - - async def clear(self) -> None: - async with self._lock: - self._cache = None - self._cache_timestamp = None - logger.info(f"ExpiringCache with id: {self._identifier} cleared cache") diff --git a/language_model_gateway/gateway/utilities/github/github_pull_request.py b/language_model_gateway/gateway/utilities/github/github_pull_request.py index b5125a6d0..05f5003d7 100644 --- a/language_model_gateway/gateway/utilities/github/github_pull_request.py +++ b/language_model_gateway/gateway/utilities/github/github_pull_request.py @@ -5,9 +5,14 @@ @dataclasses.dataclass class GithubPullRequest: + pull_request_number: str repo: str user: str title: str + created_at: Optional[datetime] closed_at: Optional[datetime] + updated_at: Optional[datetime] html_url: str diff_url: Optional[str] + state: Optional[str] + body: Optional[str] diff --git a/language_model_gateway/gateway/utilities/github/github_pull_request_helper.py b/language_model_gateway/gateway/utilities/github/github_pull_request_helper.py index dbefadc28..26f3ef003 100644 --- a/language_model_gateway/gateway/utilities/github/github_pull_request_helper.py +++ b/language_model_gateway/gateway/utilities/github/github_pull_request_helper.py @@ -1,13 +1,14 @@ import asyncio import logging +import os import re from datetime import datetime from logging import Logger -from typing import Dict, Optional, List, Union, Any +from typing import Dict, Optional, List, Union, Any, Literal from urllib.parse import urlparse import httpx -from httpx import Response +from httpx import Response, URL from language_model_gateway.gateway.http.http_client_factory import HttpClientFactory from language_model_gateway.gateway.utilities.github.github_pull_request import ( @@ -16,6 +17,9 @@ from language_model_gateway.gateway.utilities.github.github_pull_request_per_contributor_info import ( GithubPullRequestPerContributorInfo, ) +from language_model_gateway.gateway.utilities.github.github_pull_request_result import ( + GithubPullRequestResult, +) class GithubPullRequestHelper: @@ -91,7 +95,12 @@ async def retrieve_closed_prs( max_created_at: Optional[datetime] = None, include_merged: bool = True, repo_name: Optional[str] = None, - ) -> List[GithubPullRequest]: + sort_by: Optional[ + Literal["created", "updated", "popularity", "long-running"] + ] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + status: Optional[Literal["closed"]] = None, + ) -> GithubPullRequestResult: """ Async method to retrieve closed pull requests across organization repositories. """ @@ -99,12 +108,25 @@ async def retrieve_closed_prs( assert self.org_name, "Organization name is required" assert self.github_access_token, "GitHub access token is required" + if os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1": + self.logger.info( + f"Retrieving closed PRs for {self.org_name} organization" + f" with max_repos={max_repos}, max_pull_requests={max_pull_requests}," + f" min_created_at={min_created_at}, max_created_at={max_created_at}," + f" include_merged={include_merged}, repo_name={repo_name}," + f" sort_by={sort_by}, sort_by_direction={sort_by_direction}," + f" status={status}" + ) + async with self.http_client_factory.create_http_client( base_url=self.base_url, headers=self.headers, timeout=30.0 ) as client: + query: str = "" try: if repo_name: repos_url = f"{self.base_url}/repos/{self.org_name}/{repo_name}" + if os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1": + self.logger.info(f"Fetching repository: {repos_url}") repo_response = await client.get( repos_url, headers={ @@ -112,6 +134,10 @@ async def retrieve_closed_prs( **self.headers, }, ) + + if not query: + url: URL = repo_response.request.url + query += f"\n{str(url)}" repo_response.raise_for_status() repos = [repo_response.json()] else: @@ -122,26 +148,35 @@ async def retrieve_closed_prs( page_number: int = 1 while pages_remaining: + params: Dict[str, Any] = { + "type": "all", + "sort": "pushed", + "direction": "desc", + "per_page": max_repos or 50, + "page": page_number, + } + if os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1": + self.logger.info( + f"Fetching repositories: {repos_url}: {params}" + ) repos_response = await client.get( repos_url, headers={ "Accept": "application/vnd.github+json", **self.headers, }, - params={ - "type": "all", - "sort": "pushed", - "direction": "desc", - "per_page": max_repos or 50, - "page": page_number, - }, + params=params, ) + url = repos_response.request.url + query += f"\n{str(url)}" + repos_response.raise_for_status() repos.extend(repos_response.json()) if max_repos and len(repos) >= max_repos: pages_remaining = False elif len(repos_response.json()) == 0: pages_remaining = False + page_number += 1 # Limit repositories if max_repos is specified repos = repos[:max_repos] if max_repos else repos @@ -153,18 +188,50 @@ async def retrieve_closed_prs( prs_url = ( f"{self.base_url}/repos/{self.org_name}/{repo['name']}/pulls" ) - prs_response = await client.get( - prs_url, - params={ - "state": "closed", - "sort": "created", - "direction": "desc", - }, - ) - prs_response.raise_for_status() - prs: List[Dict[str, Any]] = prs_response.json() + pages_remaining = True + prs: List[Dict[str, Any]] = [] + page_number = 1 + + while pages_remaining: + params = { + "state": status or "closed", + "sort": sort_by or "created", + "direction": sort_by_direction or "desc", + "per_page": max_pull_requests or 50, + "page": page_number, + } + if os.environ.get("LOG_INPUT_AND_OUTPUT", "0") == "1": + self.logger.info(f"Fetching PRs: {prs_url}: {params}") + + prs_response = await client.get( + prs_url, + params=params, + ) + query += f"\n{str(prs_response.request.url)}" + prs_response.raise_for_status() + prs.extend(prs_response.json()) + if len(prs_response.json()) == 0: + pages_remaining = False + else: + if max_pull_requests and len(prs) >= max_pull_requests: + pages_remaining = False + + if max_created_at: + pr_created_at = datetime.fromisoformat( + prs[-1]["created_at"].replace("Z", "+00:00") + ) + if pr_created_at <= max_created_at: + pages_remaining = False + if min_created_at: + pr_created_at = datetime.fromisoformat( + prs[-1]["created_at"].replace("Z", "+00:00") + ) + if pr_created_at < min_created_at: + pages_remaining = False + page_number += 1 for pr_index, pr in enumerate(prs): + self.logger.info(f"PR DETAILS:\n{pr}") if max_pull_requests and pr_index >= max_pull_requests: break @@ -178,11 +245,19 @@ async def retrieve_closed_prs( if not max_created_at or pr_created_at <= max_created_at: if (include_merged and pr.get("'merge_commit_sha'")) or pr[ "state" - ] == "closed": + ] == (status or "closed"): closed_prs_list.append( GithubPullRequest( + pull_request_number=pr["number"], repo=repo["name"], title=pr.get("title") or "No Title", + created_at=( + datetime.fromisoformat( + pr["created_at"].replace("Z", "+00:00") + ) + if pr.get("created_at") + else None + ), closed_at=( datetime.fromisoformat( pr["closed_at"].replace("Z", "+00:00") @@ -190,18 +265,55 @@ async def retrieve_closed_prs( if pr.get("closed_at") else None ), + updated_at=( + datetime.fromisoformat( + pr["updated_at"].replace("Z", "+00:00") + ) + if pr.get("updated_at") + else None + ), html_url=pr.get("html_url") or "No URL", diff_url=pr.get("diff_url") or "No URL", user=pr.get("user", {}).get("login") or "No User", + state=pr.get("state"), + body=pr.get("body"), ) ) - return closed_prs_list + # sort the result across all repos + def sort_func(pr1: GithubPullRequest) -> Union[datetime, int, None]: + if sort_by == "created": + return pr1.created_at + elif sort_by == "updated": + return pr1.updated_at + else: + return pr1.created_at + + closed_prs_list = sorted( + closed_prs_list, + key=sort_func, # type: ignore[arg-type] + reverse=( + True + if not sort_by_direction or sort_by_direction == "desc" + else False + ), + ) + closed_prs_list = ( + closed_prs_list[:max_pull_requests] + if max_pull_requests + else closed_prs_list + ) + + return GithubPullRequestResult( + pull_requests=closed_prs_list, query=query, error=None + ) except Exception as e: self.logger.error(f"Error retrieving PRs: {e}") - raise + return GithubPullRequestResult( + pull_requests=[], query=query, error=str(e) + ) # noinspection PyMethodMayBeStatic def summarize_prs_by_engineer( @@ -316,6 +428,8 @@ async def get_pr_diff_content(self, *, pr_url: str) -> str: ) pr_response.raise_for_status() + # self.logger.info(f"PR Response:\n{pr_response.text}") + return pr_response.text except Exception as e: @@ -326,7 +440,7 @@ def export_results( self, *, pr_counts: Dict[str, GithubPullRequestPerContributorInfo], - output_file: Optional[str] = None, + output_file: str, ) -> None: """ Export PR count results to console and optional file. @@ -335,22 +449,93 @@ def export_results( pr_counts (Dict[str, GithubPullRequestPerContributorInfo]): PR counts by engineer output_file (Optional[str]): Path to output file """ - # Print results to console - self.logger.info("\n------ Closed PRs by Engineer ------\n") + assert output_file, "Output file path is required" + assert pr_counts, "PR counts are required" + + try: + with open(output_file, "w") as f: + f.write(self.export_results_as_csv(pr_counts=pr_counts)) + self.logger.info(f"Results exported to {output_file}") + except IOError as e: + self.logger.error(f"Failed to export results: {e}") + + # noinspection PyMethodMayBeStatic + def export_results_as_csv( + self, + *, + pr_counts: Dict[str, GithubPullRequestPerContributorInfo], + ) -> str: + """ + Export PR count results to console and optional file. + + Args: + pr_counts (Dict[str, GithubPullRequestPerContributorInfo]): PR counts by engineer + """ + + result: str = "Contributor,PullRequests,Repos\n" for engineer, info in pr_counts.items(): - self.logger.info(f"{engineer} | {info.pull_request_count} | {info.repos}") - self.logger.info("\n------------------------------------\n") + repos_text: str = " | ".join(info.repos) if info.repos else "" + result += f'{engineer},{info.pull_request_count},"{repos_text}"\n' + return result + + async def get_pr_info(self, *, pr_url: str) -> GithubPullRequest: + """ + Async method to fetch information for a given GitHub PR URL. - # Optional file export - if output_file: + Args: + pr_url (str): Full GitHub PR URL + + Returns: + GithubPullRequest: The pull request information + """ + assert self.org_name, "Organization name is required" + assert self.github_access_token, "GitHub access token is required" + + async with self.http_client_factory.create_http_client( + base_url=self.base_url + ) as client: try: - with open(output_file, "w") as f: - f.write("Contributor\tPR Count\tRepos\n") - for engineer, info in pr_counts.items(): - repos_text: str = " | ".join(info.repos) if info.repos else "" - f.write( - f"{engineer}\t{info.pull_request_count}\t{repos_text}\n" + # Parse the PR URL + pr_details: Dict[str, Any] = self.parse_pr_url(pr_url=pr_url) + + # Construct PR URL + pr_url = f"{self.base_url}/repos/{pr_details['owner']}/{pr_details['repo']}/pulls/{pr_details['pr_number']}" + headers: Dict[str, str] = { + "Authorization": f"Bearer {self.github_access_token}", + "Accept": "application/vnd.github.v3+json", + "User-Agent": "AsyncGithubPullRequestHelper", + } + # Fetch PR details + pr_response: Response = await client.get( + url=pr_url, headers=headers, follow_redirects=True + ) + pr_response.raise_for_status() + pr_data = pr_response.json() + + return GithubPullRequest( + pull_request_number=pr_data["number"], + repo=pr_data["base"]["repo"]["name"], + user=pr_data["user"]["login"], + title=pr_data["title"], + created_at=datetime.fromisoformat( + pr_data["created_at"].replace("Z", "+00:00") + ), + closed_at=( + datetime.fromisoformat( + pr_data["closed_at"].replace("Z", "+00:00") ) - self.logger.info(f"Results exported to {output_file}") - except IOError as e: - self.logger.error(f"Failed to export results: {e}") + if pr_data.get("closed_at") + else None + ), + updated_at=datetime.fromisoformat( + pr_data["updated_at"].replace("Z", "+00:00") + ), + html_url=pr_data["html_url"], + diff_url=pr_data.get("diff_url"), + state=pr_data["state"], + body=pr_data.get("body"), + ) + + except Exception as e: + self.logger.error(f"Error fetching PR information: {e}") + raise diff --git a/language_model_gateway/gateway/utilities/github/github_pull_request_result.py b/language_model_gateway/gateway/utilities/github/github_pull_request_result.py new file mode 100644 index 000000000..c871befaa --- /dev/null +++ b/language_model_gateway/gateway/utilities/github/github_pull_request_result.py @@ -0,0 +1,13 @@ +import dataclasses +from typing import List, Optional + +from language_model_gateway.gateway.utilities.github.github_pull_request import ( + GithubPullRequest, +) + + +@dataclasses.dataclass +class GithubPullRequestResult: + pull_requests: List[GithubPullRequest] + query: str + error: Optional[str] diff --git a/language_model_gateway/gateway/utilities/jira/jira_issue.py b/language_model_gateway/gateway/utilities/jira/jira_issue.py index 6eba38dc4..c456870bf 100644 --- a/language_model_gateway/gateway/utilities/jira/jira_issue.py +++ b/language_model_gateway/gateway/utilities/jira/jira_issue.py @@ -7,8 +7,18 @@ class JiraIssue: key: str summary: str + url: str status: str created_at: datetime closed_at: Optional[datetime] = None assignee: Optional[str] = None + assignee_email: Optional[str] = None + reporter: Optional[str] = None + reporter_email: Optional[str] = None + creator: Optional[str] = None + creator_email: Optional[str] = None + issue_type: Optional[str] = None + project_name: Optional[str] = None project: Optional[str] = None + description: Optional[str] = None + priority: Optional[str] = None diff --git a/language_model_gateway/gateway/utilities/jira/jira_issue_result.py b/language_model_gateway/gateway/utilities/jira/jira_issue_result.py new file mode 100644 index 000000000..d8417fe8e --- /dev/null +++ b/language_model_gateway/gateway/utilities/jira/jira_issue_result.py @@ -0,0 +1,11 @@ +import dataclasses +from typing import List, Optional + +from language_model_gateway.gateway.utilities.jira.jira_issue import JiraIssue + + +@dataclasses.dataclass +class JiraIssueResult: + issues: List[JiraIssue] + query: str + error: Optional[str] diff --git a/language_model_gateway/gateway/utilities/jira/jira_issues_helper.py b/language_model_gateway/gateway/utilities/jira/jira_issues_helper.py index d4ee19e22..c5ccdf2de 100644 --- a/language_model_gateway/gateway/utilities/jira/jira_issues_helper.py +++ b/language_model_gateway/gateway/utilities/jira/jira_issues_helper.py @@ -2,13 +2,18 @@ import logging from datetime import datetime from logging import Logger -from typing import Dict, Optional, List, Any +from typing import Dict, Optional, List, Any, Literal + +from httpx import URL from language_model_gateway.gateway.http.http_client_factory import HttpClientFactory from language_model_gateway.gateway.utilities.jira.JiraIssuesPerAssigneeInfo import ( JiraIssuesPerAssigneeInfo, ) from language_model_gateway.gateway.utilities.jira.jira_issue import JiraIssue +from language_model_gateway.gateway.utilities.jira.jira_issue_result import ( + JiraIssueResult, +) class JiraIssueHelper: @@ -51,9 +56,15 @@ async def retrieve_closed_issues( max_issues: Optional[int] = None, min_created_at: Optional[datetime] = None, max_created_at: Optional[datetime] = None, + min_updated_at: Optional[datetime] = None, + max_updated_at: Optional[datetime] = None, project_key: Optional[str] = None, assignee: Optional[str] = None, - ) -> List[JiraIssue]: + sort_by: Optional[Literal["updated", "created", "resolved"]] = None, + sort_by_direction: Optional[Literal["asc", "desc"]] = None, + include_full_description: Optional[bool] = False, + status: Optional[str] = "Closed", + ) -> JiraIssueResult: """ Async method to retrieve closed issues across Jira projects. @@ -62,8 +73,14 @@ async def retrieve_closed_issues( max_issues (int, optional): Maximum number of issues to retrieve min_created_at (datetime, optional): Minimum creation date max_created_at (datetime, optional): Maximum creation date + min_updated_at (datetime, optional): Minimum updated date + max_updated_at (datetime, optional): Maximum updated date project_key (str, optional): Specific project to fetch issues from assignee (str, optional): Specific assignee to filter issues + sort_by (str, optional): Field to sort by + sort_by_direction (str, optional): Sort direction + include_full_description (bool, optional): Include full description + status: (str, Optional): match status Returns: List[JiraIssue]: List of closed Jira issues @@ -74,12 +91,13 @@ async def retrieve_closed_issues( async with self.http_client_factory.create_http_client( base_url=self.jira_base_url, headers=self.headers, timeout=30.0 ) as client: + query: str = "" try: # Construct JQL (Jira Query Language) based on parameters - jql_conditions = ["status = Closed"] + jql_conditions = [f"status = '{status}'"] if project_key: - jql_conditions.append(f"project = {project_key}") + jql_conditions.append(f"project = '{project_key}'") if min_created_at: jql_conditions.append( @@ -91,41 +109,74 @@ async def retrieve_closed_issues( f"created <= '{max_created_at.strftime('%Y-%m-%d')}'" ) + if min_updated_at: + jql_conditions.append( + f"updated >= '{min_updated_at.strftime('%Y-%m-%d')}'" + ) + + if max_updated_at: + jql_conditions.append( + f"updated <= '{max_updated_at.strftime('%Y-%m-%d')}'" + ) + if assignee: - jql_conditions.append(f"assignee = {assignee}") + jql_conditions.append(f"assignee = '{assignee}'") jql = " AND ".join(jql_conditions) + # order the list descending by updated date + if sort_by: + if not sort_by_direction: + sort_by_direction = "desc" + jql += f" ORDER BY {sort_by} {sort_by_direction}" + else: + jql += " ORDER BY updated desc" + # Pagination parameters - start_at = 0 - max_results = max_issues or 100 + max_results = max_issues or 100 # * (max_projects or 10) closed_issues_list: List[JiraIssue] = [] pages_remaining = True + next_page_token: Optional[str] = None while pages_remaining: - response = await client.get( - f"{self.jira_base_url}/rest/api/3/search", - params={ - "jql": jql, - "startAt": start_at, - "maxResults": max_results, - "fields": [ - "summary", - "status", - "created", - "resolutiondate", - "assignee", - "project", - ], - }, + # https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-search/#api-rest-api-3-search-jql-post + params = { + "jql": jql, + # "startAt": start_at, + "nextPageToken": next_page_token, + "maxResults": max_results, + "fields": [ + # "*all", + "id", + "summary", + "status", + "created", + "resolutiondate", + "assignee", + "assignee", + "reporter", + "creator", + "project", + "issuetype", + "priority", + "description", + ], + } + response = await client.post( + f"{self.jira_base_url}/rest/api/3/search/jql", + json=params, ) response.raise_for_status() + url: URL = response.request.url + query += f"{url}: {response.request.content.decode()}\n" + issues_data = response.json() for issue in issues_data.get("issues", []): - assignee_object: Optional[Dict[str, Any]] = issue["fields"].get( + fields_ = issue["fields"] + assignee_object: Optional[Dict[str, Any]] = fields_.get( "assignee", {} ) assignee_name: str = ( @@ -133,25 +184,95 @@ async def retrieve_closed_issues( if assignee_object else "Unassigned" ) + assignee_email: str = ( + assignee_object.get("emailAddress", "Unassigned") + if assignee_object + else "Unassigned" + ) + reporter_object: Optional[Dict[str, Any]] = fields_.get( + "reporter", {} + ) + reporter_name: str = ( + reporter_object.get("displayName", "Unassigned") + if reporter_object + else "Unassigned" + ) + reporter_email: str = ( + reporter_object.get("emailAddress", "Unassigned") + if reporter_object + else "Unassigned" + ) + creator_object: Optional[Dict[str, Any]] = fields_.get( + "creator", {} + ) + creator_name: str = ( + creator_object.get("displayName", "Unassigned") + if creator_object + else "Unassigned" + ) + creator_email: str = ( + creator_object.get("emailAddress", "Unassigned") + if creator_object + else "Unassigned" + ) + issue_type: str = fields_.get("issuetype", {}).get("name") + project_name: str = fields_.get("project", {}).get("name") + + def read_description(description: Dict[str, Any] | None) -> str: + if not include_full_description: + return "" + if not description: + return "" + try: + description1 = "" + content: List[Dict[str, Any]] = description.get( + "content", [] + ) + for item in content: + if item.get("type") == "paragraph": + for element in item.get("content", []): + if element.get("type") == "text": + description1 += element.get("text", "") + return description1 + except Exception as e: + self.logger.error( + f"Error reading description: {e}: {description}" + ) + return "" + + item_description: str = read_description( + fields_.get("description", {}) + ) + issue_priority: str = fields_.get("priority", {}).get("name") closed_issues_list.append( JiraIssue( - key=issue["key"], - summary=issue["fields"].get("summary", "No Summary"), - status=issue["fields"]["status"]["name"], + key=issue.get("key"), + url=issue.get("self"), + summary=fields_.get("summary", "No Summary"), + status=fields_.get("status", {}).get("name"), created_at=datetime.fromisoformat( - issue["fields"]["created"].replace("Z", "+00:00") + fields_["created"].replace("Z", "+00:00") ), closed_at=( datetime.fromisoformat( - issue["fields"] - .get("resolutiondate", "") - .replace("Z", "+00:00") + fields_.get("resolutiondate", "").replace( + "Z", "+00:00" + ) ) - if issue["fields"].get("resolutiondate") + if fields_.get("resolutiondate") else None ), assignee=assignee_name, - project=issue["fields"].get("project", {}).get("key"), + assignee_email=assignee_email, + reporter=reporter_name, + reporter_email=reporter_email, + creator=creator_name, + creator_email=creator_email, + issue_type=issue_type, + project_name=project_name, + description=item_description, + priority=issue_priority, + project=fields_.get("project", {}).get("key"), ) ) @@ -164,13 +285,20 @@ async def retrieve_closed_issues( ): pages_remaining = False - start_at += max_results + next_page_token = issues_data.get("nextPageToken") + if next_page_token is None: + pages_remaining = False - return closed_issues_list + return JiraIssueResult( + issues=closed_issues_list, query=query, error=None + ) except Exception as e: - self.logger.error(f"Error retrieving Jira issues: {e}") - raise + return JiraIssueResult( + issues=[], + query=query, + error=str(e), + ) # noinspection PyMethodMayBeStatic def summarize_issues_by_assignee( @@ -216,7 +344,7 @@ def export_results( self, *, issue_counts: Dict[str, JiraIssuesPerAssigneeInfo], - output_file: Optional[str] = None, + output_file: str, ) -> None: """ Export issue count results to console and optional file. @@ -225,22 +353,153 @@ def export_results( issue_counts (Dict[str, Dict[str, Any]]): Issue counts by assignee output_file (Optional[str]): Path to output file """ - # Print results to console - self.logger.info("\n------ Closed Issues by Assignee ------\n") + assert issue_counts, "Issue counts are required" + assert output_file or output_file is None, "Output file path is invalid" + + try: + with open(output_file, "w") as f: + f.write(self.export_results_to_csv(issue_counts=issue_counts)) + self.logger.info(f"Results exported to {output_file}") + except IOError as e: + self.logger.error(f"Failed to export results: {e}") + + # noinspection PyMethodMayBeStatic + def export_results_to_csv( + self, + *, + issue_counts: Dict[str, JiraIssuesPerAssigneeInfo], + ) -> str: + """ + Export issue count results to console and optional file. + + Args: + issue_counts (Dict[str, Dict[str, Any]]): Issue counts by assignee + """ + + result: str = "Assignee,IssueCount,Projects\n" for assignee, info in issue_counts.items(): - self.logger.info(f"{assignee} | {info.issue_count} | {info.projects}") - self.logger.info("\n------------------------------------\n") + projects_text: str = " | ".join(info.projects) if info.projects else "" + result += f'{assignee},{info.issue_count},"{projects_text}"\n' + return result + + async def retrieve_issue_by_id( + self, + issue_id: str, + ) -> JiraIssueResult: + """ + Async method to retrieve a specific Jira issue by ID. - # Optional file export - if output_file: + Args: + issue_id (str): The ID of the Jira issue to retrieve + + Returns: + JiraIssueResult: The result containing the Jira issue + """ + assert self.jira_base_url, "Jira base URL is required" + assert self.jira_access_token, "Jira access token is required" + + async with self.http_client_factory.create_http_client( + base_url=self.jira_base_url, headers=self.headers, timeout=30.0 + ) as client: + query: str = "" try: - with open(output_file, "w") as f: - f.write("Assignee\tIssue Count\tProjects\n") - for assignee, info in issue_counts.items(): - projects_text: str = ( - " | ".join(info.projects) if info.projects else "" + response = await client.get( + f"{self.jira_base_url}/rest/api/3/issue/{issue_id}" + ) + response.raise_for_status() + + url: URL = response.request.url + query += f"{url}: {response.request.content.decode()}\n" + + issue_data = response.json() + fields_ = issue_data["fields"] + + assignee_object: Optional[Dict[str, Any]] = fields_.get("assignee", {}) + assignee_name: str = ( + assignee_object.get("displayName", "Unassigned") + if assignee_object + else "Unassigned" + ) + assignee_email: str = ( + assignee_object.get("emailAddress", "Unassigned") + if assignee_object + else "Unassigned" + ) + reporter_object: Optional[Dict[str, Any]] = fields_.get("reporter", {}) + reporter_name: str = ( + reporter_object.get("displayName", "Unassigned") + if reporter_object + else "Unassigned" + ) + reporter_email: str = ( + reporter_object.get("emailAddress", "Unassigned") + if reporter_object + else "Unassigned" + ) + creator_object: Optional[Dict[str, Any]] = fields_.get("creator", {}) + creator_name: str = ( + creator_object.get("displayName", "Unassigned") + if creator_object + else "Unassigned" + ) + creator_email: str = ( + creator_object.get("emailAddress", "Unassigned") + if creator_object + else "Unassigned" + ) + issue_type: str = fields_.get("issuetype", {}).get("name") + project_name: str = fields_.get("project", {}).get("name") + + def read_description(description: Dict[str, Any] | None) -> str: + if not description: + return "" + try: + description1 = "" + content: List[Dict[str, Any]] = description.get("content", []) + for item in content: + if item.get("type") == "paragraph": + for element in item.get("content", []): + if element.get("type") == "text": + description1 += element.get("text", "") + return description1 + except Exception as e: + self.logger.error( + f"Error reading description: {e}: {description}" + ) + return "" + + item_description: str = read_description(fields_.get("description", {})) + issue_priority: str = fields_.get("priority", {}).get("name") + + jira_issue = JiraIssue( + key=issue_data.get("key"), + url=issue_data.get("self"), + summary=fields_.get("summary", "No Summary"), + status=fields_.get("status", {}).get("name"), + created_at=datetime.fromisoformat( + fields_["created"].replace("Z", "+00:00") + ), + closed_at=( + datetime.fromisoformat( + fields_.get("resolutiondate", "").replace("Z", "+00:00") ) - f.write(f"{assignee}\t{info.issue_count}\t{projects_text}\n") - self.logger.info(f"Results exported to {output_file}") - except IOError as e: - self.logger.error(f"Failed to export results: {e}") + if fields_.get("resolutiondate") + else None + ), + assignee=assignee_name, + assignee_email=assignee_email, + reporter=reporter_name, + reporter_email=reporter_email, + creator=creator_name, + creator_email=creator_email, + issue_type=issue_type, + project_name=project_name, + description=item_description, + priority=issue_priority, + project=fields_.get("project", {}).get("key"), + ) + + return JiraIssueResult(issues=[jira_issue], query=query, error=None) + + except Exception as e: + return JiraIssueResult(issues=[], query=query, error=str(e)) diff --git a/openwebui_functions/__init__.py b/openwebui_functions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openwebui_functions/language_model_gateway_pipe.json b/openwebui_functions/language_model_gateway_pipe.json new file mode 100644 index 000000000..5b3ea0f7f --- /dev/null +++ b/openwebui_functions/language_model_gateway_pipe.json @@ -0,0 +1,22 @@ +[ + { + "id": "language_model_gateway", + "user_id": "6c03bf27-dbbf-44c1-b980-2c6a4608f712", + "name": "language_model_gateway", + "type": "pipe", + "content": "\"\"\"title: LangChain Pipe Function (Streaming Version)\nauthor: Imran Qureshi @ b.well Connected Health (mailto:imran.qureshi@bwell.com)\nauthor_url: https://github.com/imranq2\nversion: 0.2.0\nThis module defines a Pipe class that reads the oauth_id_token from the request cookies and uses it in Authorization header\nto make requests to the OpenAI API. It supports both streaming and non-streaming responses.\n\"\"\"\n\nimport asyncio\nimport datetime\nimport json\nimport logging\nimport os\nimport time\nfrom pathlib import PurePosixPath\nfrom typing import AsyncGenerator, List\nfrom typing import Optional, Callable, Awaitable, Any, Dict\nfrom urllib.parse import urlparse, urlunparse\n\nimport httpx\nfrom pydantic import BaseModel\nfrom pydantic import Field\nfrom starlette.requests import Request\n\nlogger = logging.getLogger(__name__)\n\n\nclass Pipe:\n class Valves(BaseModel):\n emit_interval: float = Field(\n default=2.0, description=\"Interval in seconds between status emissions\"\n )\n enable_status_indicator: bool = Field(\n default=True, description=\"Enable or disable status indicator emissions\"\n )\n OPENAI_API_BASE_URL: str | None = Field(\n default=None,\n description=\"Base URL for OpenAI API, e.g., https://api.openai.com/v1\",\n )\n model_name_prefix: str = Field(\n default=\"MCP: \",\n description=\"Prefix for model names in the dropdown\",\n )\n restrict_to_admins: bool = Field(\n default=False,\n description=\"Restrict access to this pipe to admin users only\",\n )\n restrict_to_model_ids: list[str] = Field(\n default_factory=list,\n description=\"List of model IDs to restrict access to. If empty, no restriction is applied.\",\n )\n debug_mode: bool = Field(\n default=False,\n description=\"Enable debug mode for additional logging and debugging information\",\n )\n\n def __init__(self) -> None:\n self.type: str = \"pipe\"\n self.id: str = \"language_model_gateway\"\n openai_api_base_url_ = self.read_base_url()\n self.valves = self.Valves(OPENAI_API_BASE_URL=openai_api_base_url_)\n self.name: str = self.valves.model_name_prefix\n self.last_emit_time: float = 0\n self.pipelines: List[Dict[str, Any]] | None = None\n\n # noinspection PyMethodMayBeStatic\n def read_base_url(self) -> Optional[str]:\n \"\"\"\n Reads the OpenAI API base URL from environment variables.\n Returns:\n The OpenAI API base URL if set, otherwise None.\n \"\"\"\n return os.getenv(\"LANGUAGE_MODEL_GATEWAY_API_BASE_URL\") or os.getenv(\n \"OPENAI_API_BASE_URL\"\n )\n\n # noinspection PyMethodMayBeStatic\n async def on_startup(self) -> None:\n # This function is called when the server is started.\n logger.debug(f\"on_startup:{__name__}\")\n self.pipelines = await self.get_models()\n pass\n\n # noinspection PyMethodMayBeStatic\n async def on_shutdown(self) -> None:\n # This function is called when the server is stopped.\n logger.debug(f\"on_shutdown:{__name__}\")\n pass\n\n async def on_valves_updated(self) -> None:\n # This function is called when the valves are updated.\n logger.debug(f\"on_valves_updated:{__name__}\")\n self.pipelines = await self.get_models()\n pass\n\n async def emit_status(\n self,\n __event_emitter__: Optional[Callable[[Dict[str, Any]], Awaitable[None]]],\n level: str,\n message: str,\n done: bool,\n ) -> None:\n current_time = time.time()\n if (\n __event_emitter__\n and self.valves.enable_status_indicator\n and (\n current_time - self.last_emit_time >= self.valves.emit_interval or done\n )\n ):\n await __event_emitter__(\n {\n \"type\": \"status\",\n \"data\": {\n \"status\": \"complete\" if done else \"in_progress\",\n \"level\": level,\n \"description\": message,\n \"done\": done,\n },\n }\n )\n self.last_emit_time = current_time\n\n async def stream_hardcoded_response(\n self,\n *,\n body: Dict[str, Any],\n __request__: Optional[Request] = None,\n __user__: Optional[Dict[str, Any]] = None,\n __event_emitter__: Callable[[Dict[str, Any]], Awaitable[None]] | None = None,\n __event_call__: Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]]\n | None = None,\n ) -> AsyncGenerator[str, None]:\n \"\"\"\n Async generator to stream response chunks\n \"\"\"\n try:\n await self.emit_status(\n __event_emitter__,\n \"info\",\n f\"/initiating Chain: headers={__request__.headers if __request__ else None}\"\n f\", cookies={__request__.cookies if __request__ else None}\"\n f\" {__user__=} {body=}\",\n False,\n )\n\n if __request__ is None or __user__ is None:\n raise ValueError(\"Request and user information must be provided.\")\n\n # Simulate streaming response\n # Generate chunks in OpenAI streaming format\n chunks = [\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\"role\": \"assistant\"},\n \"finish_reason\": None,\n }\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\"content\": \"Here\"},\n \"finish_reason\": None,\n }\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\"index\": 0, \"delta\": {\"content\": \" is\"}, \"finish_reason\": None}\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\"index\": 0, \"delta\": {\"content\": \" a\"}, \"finish_reason\": None}\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\"content\": \" streamed\"},\n \"finish_reason\": None,\n }\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\n \"content\": f\"\\nheaders=\\n{__request__.headers}\\ncookies=\\n{__request__.cookies}\\n{__user__=}\\n{body=}\",\n },\n \"finish_reason\": None,\n }\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\n \"content\": f\"\\nOAuth_id_token:\\n{__request__.cookies.get('oauth_id_token')}\\n\",\n },\n \"finish_reason\": None,\n }\n ],\n },\n {\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [{\"index\": 0, \"delta\": {}, \"finish_reason\": \"stop\"}],\n },\n ]\n\n for chunk in chunks:\n # Yield each chunk as a JSON-encoded string with a data: prefix\n yield f\"data: {json.dumps(chunk)}\\n\\n\"\n await self.emit_status(__event_emitter__, \"info\", \"Streaming...\", False)\n await asyncio.sleep(0.5) # Simulate streaming delay\n\n await self.emit_status(__event_emitter__, \"info\", \"Stream Complete\", True)\n\n except Exception as e:\n error_chunk = {\n \"id\": \"chatcmpl-error\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"error\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\"content\": f\"Error: {str(e)}\"},\n \"finish_reason\": \"stop\",\n }\n ],\n }\n yield f\"data: {json.dumps(error_chunk)}\\n\\n\"\n await self.emit_status(__event_emitter__, \"error\", str(e), True)\n\n @classmethod\n def pathlib_url_join(cls, base_url: str, path: str) -> str:\n \"\"\"\n Join URLs using pathlib for path manipulation.\n\n Args:\n base_url: The base URL\n path: Path to append\n\n Returns:\n Fully constructed URL\n \"\"\"\n # Parse the base URL\n parsed_base = urlparse(base_url)\n\n # Use PurePosixPath to handle path joining\n full_path = str(PurePosixPath(parsed_base.path) / path.lstrip(\"/\"))\n\n # Reconstruct the URL\n reconstructed_url = urlunparse(\n (\n parsed_base.scheme,\n parsed_base.netloc,\n full_path,\n parsed_base.params,\n parsed_base.query,\n parsed_base.fragment,\n )\n )\n\n return reconstructed_url\n\n @staticmethod\n def log_httpx_request(request: httpx.Request) -> str:\n \"\"\"\n Convert an HTTPX request to a detailed string representation.\n\n Args:\n request (httpx.Request): The HTTPX request to log\n\n Returns:\n str: Formatted string representation of the request\n \"\"\"\n # Construct request details\n request_log = f\"\"\"\n HTTPX Request:\n - Method: {request.method}\n - URL: {request.url}\n - Headers: {dict(request.headers)}\n - Body: {request.content.decode(\"utf-8\", errors=\"replace\") if request.content else \"No body\"}\n \"\"\".strip()\n\n return request_log\n\n @staticmethod\n def log_response_as_string(response1: httpx.Response) -> str:\n \"\"\"\n Convert an HTTPX response to a detailed, formatted string.\n\n Args:\n response1 (httpx.Response): The HTTP response to log\n\n Returns:\n str: Comprehensive response log string\n \"\"\"\n try:\n # Attempt to parse JSON response\n try:\n response_body = json.dumps(response1.json(), indent=2)\n except (ValueError, json.JSONDecodeError):\n # Fallback to text if not JSON\n response_body = response1.text[:1000] # Limit body size\n except Exception:\n response_body = \"(Unable to decode response body)\"\n\n response_log = f\"\"\"\n HTTPX Response Log:\n - Timestamp: {datetime.datetime.now().isoformat()}\n - Status Code: {response1.status_code}\n - URL: {response1.request.url}\n - Method: {response1.request.method}\n - Response Headers:\n {json.dumps(dict(response1.headers), indent=2)}\n - Response Body:\n {response_body}\n - Response Encoding: {response1.encoding}\n - Response Elapsed Time: {response1.elapsed}\n \"\"\".strip()\n\n return response_log\n\n # noinspection PyMethodMayBeStatic\n async def pipe(\n self,\n body: Dict[str, Any],\n __request__: Optional[Request] = None,\n __user__: Optional[Dict[str, Any]] = None,\n __event_emitter__: Optional[Callable[[Dict[str, Any]], Awaitable[None]]] = None,\n __event_call__: Optional[\n Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]]\n ] = None,\n ) -> AsyncGenerator[str, None]:\n \"\"\"\n Main pipe method supporting both streaming and non-streaming responses\n \"\"\"\n await self.emit_status(\n __event_emitter__,\n \"info\",\n \"Working...\",\n False,\n )\n logger.debug(f\"pipe:{__name__}\")\n\n logger.debug(\"=== body ===\")\n logger.debug(body)\n logger.debug(\"==== End of body ===\")\n logger.debug(f\"__request__: {__request__}\")\n logger.debug(f\"__user__: {__user__}\")\n logger.debug(\"==== Request Url ====\")\n logger.debug(__request__.url if __request__ else \"No request URL provided\")\n logger.debug(\"==== End of Request Url ====\")\n\n assert __request__ is not None, \"Request object must be provided.\"\n\n # logger.debug the Authorization header if available\n auth_header = __request__.headers.get(\"Authorization\")\n if auth_header:\n logger.debug(f\"Authorization header: {auth_header}\")\n else:\n logger.debug(\"No Authorization header found.\")\n\n if self.valves.debug_mode:\n yield f\"User:\\n{__user__}\" + \"\\n\"\n yield f\"Original Headers:\\n{dict(__request__.headers)}\" + \"\\n\"\n\n auth_token: str | None = __request__.cookies.get(\"oauth_id_token\")\n logger.debug(f\"auth_token: {auth_token}\")\n\n if auth_token is None:\n yield (\n \"No oauth_id_token found in cookies or it may have expired. \"\n \"Please sign out and sign back in.\"\n )\n await self.emit_status(__event_emitter__, \"error\", \"Error\", True)\n return\n\n open_api_base_url: str | None = self.valves.OPENAI_API_BASE_URL\n if open_api_base_url is None:\n logger.debug(\n \"LanguageModelGateway::pipe OPENAI_API_BASE_URL is not set in valves, trying environment variable.\"\n )\n open_api_base_url = self.read_base_url()\n logger.debug(\n f\"LanguageModelGateway::pipe after trying environment variable OpenAI API_BASE_URL: {open_api_base_url}\"\n )\n assert open_api_base_url is not None, (\n \"LanguageModelGateway::pipe OpenAI_API_BASE_URL must be set as an environment variable.\"\n )\n assert open_api_base_url is not None, (\n \"LanguageModelGateway::pipe OpenAI_API_BASE_URL must be set as an environment variable.\"\n )\n logger.debug(f\"open_api_base_url: {open_api_base_url}\")\n\n # Extract model id from the model name\n model_id = body[\"model\"][body[\"model\"].find(\".\") + 1 :]\n\n # Update the model id in the body\n payload = {**body, \"model\": model_id}\n if self.valves.debug_mode:\n yield json.dumps(payload) + \"\\n\"\n\n url = self.pathlib_url_join(base_url=open_api_base_url, path=\"chat/completions\")\n response_text: str = \"\"\n\n v = 11\n\n is_streaming: bool = body.get(\"stream\", False)\n\n try:\n logger.debug(\n f\"LanguageModelGateway::pipe Calling chat completion url: {url} with payload: {payload} and headers: {__request__.headers}\"\n )\n\n # now run the __request__ with the OpenAI API\n # Headers\n headers = {\n \"Content-Type\": \"application/json\",\n \"Authorization\": f\"Bearer {auth_token}\",\n }\n # set User-Agent to the one from the request, if available\n if \"User-Agent\" in __request__.headers:\n headers[\"User-Agent\"] = __request__.headers[\"User-Agent\"]\n # set Referrer to the one from the request, if available\n if \"Referrer\" in __request__.headers:\n headers[\"Referrer\"] = __request__.headers[\"Referrer\"]\n # set Cookie to the one from the request, if available\n if \"Cookie\" in __request__.headers:\n headers[\"Cookie\"] = __request__.headers[\"Cookie\"]\n # set traceparent to the one from the request, if available\n if \"traceparent\" in __request__.headers:\n headers[\"traceparent\"] = __request__.headers[\"traceparent\"]\n if \"origin\" in __request__.headers:\n headers[\"Origin\"] = __request__.headers[\"origin\"]\n if \"Accept-Encoding\" in __request__.headers:\n headers[\"Accept-Encoding\"] = __request__.headers[\"Accept-Encoding\"]\n\n # Add custom headers for OpenWebUI user information\n if __user__ is not None:\n user = __user__\n # check that each value is not None before adding to headers\n if user.get(\"name\") is not None:\n headers[\"X-OpenWebUI-User-Name\"] = user[\"name\"]\n if user.get(\"id\") is not None:\n headers[\"X-OpenWebUI-User-Id\"] = user[\"id\"]\n if user.get(\"email\") is not None:\n headers[\"X-OpenWebUI-User-Email\"] = user[\"email\"]\n if user.get(\"role\") is not None:\n headers[\"X-OpenWebUI-User-Role\"] = user[\"role\"]\n if (\n user.get(\"info\") is not None\n and isinstance(user[\"info\"], dict)\n and user[\"info\"].get(\"location\") is not None\n and isinstance(user[\"info\"][\"location\"], str)\n ):\n location = user[\"info\"][\"location\"]\n if self.valves.debug_mode:\n yield \"Location: \" + type(location).__name__ + f\"{location}\\n\"\n headers[\"X-OpenWebUI-User-Location\"] = user[\"info\"][\"location\"]\n\n # copy any headers that start with \"x-\"\n for key, value in __request__.headers.items():\n if key.lower().startswith(\"x-\"):\n headers[key] = value\n\n if self.valves.debug_mode:\n yield url + \"\\n\"\n yield f\"New Headers: {dict(headers)}\" + \"\\n\"\n yield json.dumps(payload) + \"\\n\"\n\n # Use httpx.post for a plain POST request\n async with httpx.AsyncClient() as client:\n response = await client.post(\n url=url,\n json=payload,\n headers=headers,\n timeout=30.0,\n follow_redirects=True,\n )\n # Raise an exception for HTTP errors\n response.raise_for_status()\n\n # # Handle streaming or regular response\n content_type = response.headers.get(\"content-type\", \"\")\n if content_type.startswith(\"text/event-stream\"):\n # Stream mode: yield lines as they arrive\n async for line in response.aiter_lines():\n if line:\n yield line + \"\\n\"\n else:\n # Non-streaming mode: collect and return full JSON response\n yield response.json()\n\n await self.emit_status(__event_emitter__, \"info\", \"Done\", True)\n except httpx.HTTPStatusError as e:\n yield (\n f\"LanguageModelGateway::pipe HTTP Status Error [{v}]:\"\n + f\" {type(e)} {e}\\n\"\n + f\"{self.log_httpx_request(e.request)}\\n\"\n + f\"{self.log_response_as_string(e.response)}\"\n )\n except Exception as e:\n # logger.error(f\"Error in pipe: {e}\")\n # logger.debug(f\"Error details: {e.__traceback__}\")\n httpx_version = httpx.__version__\n if is_streaming:\n error_chunk = {\n \"id\": \"chatcmpl-error\",\n \"object\": \"chat.completion.chunk\",\n \"created\": int(time.time()),\n \"model\": \"error\",\n \"choices\": [\n {\n \"index\": 0,\n \"delta\": {\"content\": f\"Error: {str(e)}\"},\n \"finish_reason\": \"stop\",\n }\n ],\n }\n yield f\"data: {json.dumps(error_chunk)}\\n\\n\"\n else:\n yield f\"LanguageModelGateway::pipe Error [{v}]: {type(e)} {e} {httpx_version=} [{url=}] original=[{__request__.url}] {response_text=} {payload=}\\n\"\n\n await self.emit_status(__event_emitter__, \"error\", str(e), True)\n\n async def get_models(self) -> list[dict[str, str]]:\n \"\"\"\n Fetches the list of available models from the OpenAI API.\n Returns:\n A list of dictionaries containing model IDs and names.\n\n \"\"\"\n open_api_base_url: str | None = self.valves.OPENAI_API_BASE_URL\n if open_api_base_url is None:\n logger.debug(\n \"LanguageModelGateway:Pipes OPENAI_API_BASE_URL is not set in valves, trying environment variable.\"\n )\n open_api_base_url = self.read_base_url()\n logger.debug(\n f\"LanguageModelGateway:Pipes after trying environment variable OpenAI API_BASE_URL: {open_api_base_url}\"\n )\n if open_api_base_url is None:\n return []\n assert open_api_base_url is not None, (\n \"LanguageModelGateway:Pipes OpenAI_API_BASE_URL must be set as an environment variable.\"\n )\n model_url = self.pathlib_url_join(base_url=open_api_base_url, path=\"models\")\n # call the models endpoint to get the list of available models\n logger.debug(f\"Calling models endpoint: {model_url}\")\n models: list[dict[str, str]] = []\n async with httpx.AsyncClient() as client:\n # Perform the GET request with a timeout\n response = await client.get(\n url=model_url,\n timeout=30.0, # 30 seconds timeout\n )\n\n # Raise an exception for HTTP errors\n response.raise_for_status()\n\n # Parse JSON and extract 'data' key, defaulting to empty list\n models = response.json().get(\"data\", [])\n logger.debug(f\"Received models from {model_url}: {models}\")\n if self.valves.restrict_to_model_ids:\n # Filter models based on the restricted model IDs\n models = [\n model\n for model in models\n if model[\"id\"] in self.valves.restrict_to_model_ids\n ]\n logger.debug(f\"Filtered models: {models}\")\n return [\n {\n \"id\": model[\"id\"],\n \"name\": model[\"id\"],\n }\n for model in models\n ]\n\n async def pipes(self) -> list[dict[str, str]]:\n if self.pipelines is None:\n logger.debug(\"Fetching models for the first time.\")\n self.pipelines = await self.get_models()\n return self.pipelines or []\n", + "meta": { + "description": "Talks to Language Model Gateway and passes the OAuth ID token in the request cookies as Bearer Authorization header.", + "manifest": { + "title": "Language Model Gateway Pipe", + "author": "Imran Qureshi @ b.well Connected Health (mailto:imran.qureshi@bwell.com)", + "author_url": "https://github.com/imranq2", + "version": "0.1.0" + } + }, + "is_active": true, + "is_global": true, + "updated_at": 1745989387, + "created_at": 1745989309 + } +] \ No newline at end of file diff --git a/openwebui_functions/language_model_gateway_pipe.py b/openwebui_functions/language_model_gateway_pipe.py new file mode 100644 index 000000000..fd1af6a36 --- /dev/null +++ b/openwebui_functions/language_model_gateway_pipe.py @@ -0,0 +1,626 @@ +"""title: LangChain Pipe Function (Streaming Version) +author: Imran Qureshi @ b.well Connected Health (mailto:imran.qureshi@bwell.com) +author_url: https://github.com/imranq2 +version: 0.2.0 +This module defines a Pipe class that reads the oauth_id_token from the request cookies and uses it in Authorization header +to make requests to the OpenAI API. It supports both streaming and non-streaming responses. +""" + +import asyncio +import datetime +import json +import logging +import os +import time +from pathlib import PurePosixPath +from typing import AsyncGenerator, List +from typing import Optional, Callable, Awaitable, Any, Dict +from urllib.parse import urlparse, urlunparse + +import httpx +from pydantic import BaseModel +from pydantic import Field +from starlette.requests import Request + +logger = logging.getLogger(__name__) + + +class Pipe: + class Valves(BaseModel): + emit_interval: float = Field( + default=2.0, description="Interval in seconds between status emissions" + ) + enable_status_indicator: bool = Field( + default=True, description="Enable or disable status indicator emissions" + ) + OPENAI_API_BASE_URL: str | None = Field( + default=None, + description="Base URL for OpenAI API, e.g., https://api.openai.com/v1", + ) + model_name_prefix: str = Field( + default="MCP: ", + description="Prefix for model names in the dropdown", + ) + restrict_to_admins: bool = Field( + default=False, + description="Restrict access to this pipe to admin users only", + ) + restrict_to_model_ids: list[str] = Field( + default_factory=list, + description="List of model IDs to restrict access to. If empty, no restriction is applied.", + ) + debug_mode: bool = Field( + default=False, + description="Enable debug mode for additional logging and debugging information", + ) + + def __init__(self) -> None: + self.type: str = "pipe" + self.id: str = "language_model_gateway" + openai_api_base_url_ = self.read_base_url() + self.valves = self.Valves(OPENAI_API_BASE_URL=openai_api_base_url_) + self.name: str = self.valves.model_name_prefix + self.last_emit_time: float = 0 + self.pipelines: List[Dict[str, Any]] | None = None + + # noinspection PyMethodMayBeStatic + def read_base_url(self) -> Optional[str]: + """ + Reads the OpenAI API base URL from environment variables. + Returns: + The OpenAI API base URL if set, otherwise None. + """ + return os.getenv("LANGUAGE_MODEL_GATEWAY_API_BASE_URL") or os.getenv( + "OPENAI_API_BASE_URL" + ) + + # noinspection PyMethodMayBeStatic + async def on_startup(self) -> None: + # This function is called when the server is started. + logger.debug(f"on_startup:{__name__}") + self.pipelines = await self.get_models() + pass + + # noinspection PyMethodMayBeStatic + async def on_shutdown(self) -> None: + # This function is called when the server is stopped. + logger.debug(f"on_shutdown:{__name__}") + pass + + async def on_valves_updated(self) -> None: + # This function is called when the valves are updated. + logger.debug(f"on_valves_updated:{__name__}") + self.pipelines = await self.get_models() + pass + + async def emit_status( + self, + __event_emitter__: Optional[Callable[[Dict[str, Any]], Awaitable[None]]], + level: str, + message: str, + done: bool, + ) -> None: + current_time = time.time() + if ( + __event_emitter__ + and self.valves.enable_status_indicator + and ( + current_time - self.last_emit_time >= self.valves.emit_interval or done + ) + ): + await __event_emitter__( + { + "type": "status", + "data": { + "status": "complete" if done else "in_progress", + "level": level, + "description": message, + "done": done, + }, + } + ) + self.last_emit_time = current_time + + async def stream_hardcoded_response( + self, + *, + body: Dict[str, Any], + __request__: Optional[Request] = None, + __user__: Optional[Dict[str, Any]] = None, + __event_emitter__: Callable[[Dict[str, Any]], Awaitable[None]] | None = None, + __event_call__: Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]] + | None = None, + ) -> AsyncGenerator[str, None]: + """ + Async generator to stream response chunks + """ + try: + await self.emit_status( + __event_emitter__, + "info", + f"/initiating Chain: headers={__request__.headers if __request__ else None}" + f", cookies={__request__.cookies if __request__ else None}" + f" {__user__=} {body=}", + False, + ) + + if __request__ is None or __user__ is None: + raise ValueError("Request and user information must be provided.") + + # Simulate streaming response + # Generate chunks in OpenAI streaming format + chunks = [ + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "delta": {"role": "assistant"}, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "delta": {"content": "Here"}, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + {"index": 0, "delta": {"content": " is"}, "finish_reason": None} + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + {"index": 0, "delta": {"content": " a"}, "finish_reason": None} + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "delta": {"content": " streamed"}, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "delta": { + "content": f"\nheaders=\n{__request__.headers}\ncookies=\n{__request__.cookies}\n{__user__=}\n{body=}", + }, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [ + { + "index": 0, + "delta": { + "content": f"\nOAuth_id_token:\n{__request__.cookies.get('oauth_id_token')}\n", + }, + "finish_reason": None, + } + ], + }, + { + "id": "chatcmpl-123", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "gpt-3.5-turbo", + "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}], + }, + ] + + for chunk in chunks: + # Yield each chunk as a JSON-encoded string with a data: prefix + yield f"data: {json.dumps(chunk)}\n\n" + await self.emit_status(__event_emitter__, "info", "Streaming...", False) + await asyncio.sleep(0.5) # Simulate streaming delay + + await self.emit_status(__event_emitter__, "info", "Stream Complete", True) + + except Exception as e: + error_chunk = { + "id": "chatcmpl-error", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "error", + "choices": [ + { + "index": 0, + "delta": {"content": f"Error: {str(e)}"}, + "finish_reason": "stop", + } + ], + } + yield f"data: {json.dumps(error_chunk)}\n\n" + await self.emit_status(__event_emitter__, "error", str(e), True) + + @classmethod + def pathlib_url_join(cls, base_url: str, path: str) -> str: + """ + Join URLs using pathlib for path manipulation. + + Args: + base_url: The base URL + path: Path to append + + Returns: + Fully constructed URL + """ + # Parse the base URL + parsed_base = urlparse(base_url) + + # Use PurePosixPath to handle path joining + full_path = str(PurePosixPath(parsed_base.path) / path.lstrip("/")) + + # Reconstruct the URL + reconstructed_url = urlunparse( + ( + parsed_base.scheme, + parsed_base.netloc, + full_path, + parsed_base.params, + parsed_base.query, + parsed_base.fragment, + ) + ) + + return reconstructed_url + + @staticmethod + def log_httpx_request(request: httpx.Request) -> str: + """ + Convert an HTTPX request to a detailed string representation. + + Args: + request (httpx.Request): The HTTPX request to log + + Returns: + str: Formatted string representation of the request + """ + # Construct request details + request_log = f""" + HTTPX Request: + - Method: {request.method} + - URL: {request.url} + - Headers: {dict(request.headers)} + - Body: {request.content.decode("utf-8", errors="replace") if request.content else "No body"} + """.strip() + + return request_log + + @staticmethod + def log_response_as_string(response1: httpx.Response) -> str: + """ + Convert an HTTPX response to a detailed, formatted string. + + Args: + response1 (httpx.Response): The HTTP response to log + + Returns: + str: Comprehensive response log string + """ + try: + # Attempt to parse JSON response + try: + response_body = json.dumps(response1.json(), indent=2) + except (ValueError, json.JSONDecodeError): + # Fallback to text if not JSON + response_body = response1.text[:1000] # Limit body size + except Exception: + response_body = "(Unable to decode response body)" + + response_log = f""" + HTTPX Response Log: + - Timestamp: {datetime.datetime.now().isoformat()} + - Status Code: {response1.status_code} + - URL: {response1.request.url} + - Method: {response1.request.method} + - Response Headers: + {json.dumps(dict(response1.headers), indent=2)} + - Response Body: + {response_body} + - Response Encoding: {response1.encoding} + - Response Elapsed Time: {response1.elapsed} + """.strip() + + return response_log + + # noinspection PyMethodMayBeStatic + async def pipe( + self, + body: Dict[str, Any], + __request__: Optional[Request] = None, + __user__: Optional[Dict[str, Any]] = None, + __event_emitter__: Optional[Callable[[Dict[str, Any]], Awaitable[None]]] = None, + __event_call__: Optional[ + Callable[[Dict[str, Any]], Awaitable[Dict[str, Any]]] + ] = None, + ) -> AsyncGenerator[str, None]: + """ + Main pipe method supporting both streaming and non-streaming responses + """ + await self.emit_status( + __event_emitter__, + "info", + "Working...", + False, + ) + logger.debug(f"pipe:{__name__}") + + logger.debug("=== body ===") + logger.debug(body) + logger.debug("==== End of body ===") + logger.debug(f"__request__: {__request__}") + logger.debug(f"__user__: {__user__}") + logger.debug("==== Request Url ====") + logger.debug(__request__.url if __request__ else "No request URL provided") + logger.debug("==== End of Request Url ====") + + assert __request__ is not None, "Request object must be provided." + + # logger.debug the Authorization header if available + auth_header = __request__.headers.get("Authorization") + if auth_header: + logger.debug(f"Authorization header: {auth_header}") + else: + logger.debug("No Authorization header found.") + + if self.valves.debug_mode: + yield f"User:\n{__user__}" + "\n" + yield f"Original Headers:\n{dict(__request__.headers)}" + "\n" + + auth_token: str | None = __request__.cookies.get("oauth_id_token") + logger.debug(f"auth_token: {auth_token}") + + if auth_token is None: + yield ( + "No oauth_id_token found in cookies or it may have expired. " + "Please sign out and sign back in." + ) + await self.emit_status(__event_emitter__, "error", "Error", True) + return + + open_api_base_url: str | None = self.valves.OPENAI_API_BASE_URL + if open_api_base_url is None: + logger.debug( + "LanguageModelGateway::pipe OPENAI_API_BASE_URL is not set in valves, trying environment variable." + ) + open_api_base_url = self.read_base_url() + logger.debug( + f"LanguageModelGateway::pipe after trying environment variable OpenAI API_BASE_URL: {open_api_base_url}" + ) + assert open_api_base_url is not None, ( + "LanguageModelGateway::pipe OpenAI_API_BASE_URL must be set as an environment variable." + ) + assert open_api_base_url is not None, ( + "LanguageModelGateway::pipe OpenAI_API_BASE_URL must be set as an environment variable." + ) + logger.debug(f"open_api_base_url: {open_api_base_url}") + + # Extract model id from the model name + model_id = body["model"][body["model"].find(".") + 1 :] + + # Update the model id in the body + payload = {**body, "model": model_id} + if self.valves.debug_mode: + yield json.dumps(payload) + "\n" + + url = self.pathlib_url_join(base_url=open_api_base_url, path="chat/completions") + response_text: str = "" + + v = 11 + + is_streaming: bool = body.get("stream", False) + + try: + logger.debug( + f"LanguageModelGateway::pipe Calling chat completion url: {url} with payload: {payload} and headers: {__request__.headers}" + ) + + # now run the __request__ with the OpenAI API + # Headers + headers = { + "Content-Type": "application/json", + "Authorization": f"Bearer {auth_token}", + } + # set User-Agent to the one from the request, if available + if "User-Agent" in __request__.headers: + headers["User-Agent"] = __request__.headers["User-Agent"] + # set Referrer to the one from the request, if available + if "Referrer" in __request__.headers: + headers["Referrer"] = __request__.headers["Referrer"] + # set Cookie to the one from the request, if available + if "Cookie" in __request__.headers: + headers["Cookie"] = __request__.headers["Cookie"] + # set traceparent to the one from the request, if available + if "traceparent" in __request__.headers: + headers["traceparent"] = __request__.headers["traceparent"] + if "origin" in __request__.headers: + headers["Origin"] = __request__.headers["origin"] + if "Accept-Encoding" in __request__.headers: + headers["Accept-Encoding"] = __request__.headers["Accept-Encoding"] + + # Add custom headers for OpenWebUI user information + if __user__ is not None: + user = __user__ + # check that each value is not None before adding to headers + if user.get("name") is not None: + headers["X-OpenWebUI-User-Name"] = user["name"] + if user.get("id") is not None: + headers["X-OpenWebUI-User-Id"] = user["id"] + if user.get("email") is not None: + headers["X-OpenWebUI-User-Email"] = user["email"] + if user.get("role") is not None: + headers["X-OpenWebUI-User-Role"] = user["role"] + if ( + user.get("info") is not None + and isinstance(user["info"], dict) + and user["info"].get("location") is not None + and isinstance(user["info"]["location"], str) + ): + location = user["info"]["location"] + if self.valves.debug_mode: + yield "Location: " + type(location).__name__ + f"{location}\n" + headers["X-OpenWebUI-User-Location"] = user["info"]["location"] + + # copy any headers that start with "x-" + for key, value in __request__.headers.items(): + if key.lower().startswith("x-"): + headers[key] = value + + if self.valves.debug_mode: + yield url + "\n" + yield f"New Headers: {dict(headers)}" + "\n" + yield json.dumps(payload) + "\n" + + # Use httpx.post for a plain POST request + async with httpx.AsyncClient() as client: + response = await client.post( + url=url, + json=payload, + headers=headers, + timeout=30.0, + follow_redirects=True, + ) + # Raise an exception for HTTP errors + response.raise_for_status() + + # # Handle streaming or regular response + content_type = response.headers.get("content-type", "") + if content_type.startswith("text/event-stream"): + # Stream mode: yield lines as they arrive + async for line in response.aiter_lines(): + if line: + yield line + "\n" + else: + # Non-streaming mode: collect and return full JSON response + yield response.json() + + await self.emit_status(__event_emitter__, "info", "Done", True) + except httpx.HTTPStatusError as e: + yield ( + f"LanguageModelGateway::pipe HTTP Status Error [{v}]:" + + f" {type(e)} {e}\n" + + f"{self.log_httpx_request(e.request)}\n" + + f"{self.log_response_as_string(e.response)}" + ) + except Exception as e: + # logger.error(f"Error in pipe: {e}") + # logger.debug(f"Error details: {e.__traceback__}") + httpx_version = httpx.__version__ + if is_streaming: + error_chunk = { + "id": "chatcmpl-error", + "object": "chat.completion.chunk", + "created": int(time.time()), + "model": "error", + "choices": [ + { + "index": 0, + "delta": {"content": f"Error: {str(e)}"}, + "finish_reason": "stop", + } + ], + } + yield f"data: {json.dumps(error_chunk)}\n\n" + else: + yield f"LanguageModelGateway::pipe Error [{v}]: {type(e)} {e} {httpx_version=} [{url=}] original=[{__request__.url}] {response_text=} {payload=}\n" + + await self.emit_status(__event_emitter__, "error", str(e), True) + + async def get_models(self) -> list[dict[str, str]]: + """ + Fetches the list of available models from the OpenAI API. + Returns: + A list of dictionaries containing model IDs and names. + + """ + open_api_base_url: str | None = self.valves.OPENAI_API_BASE_URL + if open_api_base_url is None: + logger.debug( + "LanguageModelGateway:Pipes OPENAI_API_BASE_URL is not set in valves, trying environment variable." + ) + open_api_base_url = self.read_base_url() + logger.debug( + f"LanguageModelGateway:Pipes after trying environment variable OpenAI API_BASE_URL: {open_api_base_url}" + ) + if open_api_base_url is None: + return [] + assert open_api_base_url is not None, ( + "LanguageModelGateway:Pipes OpenAI_API_BASE_URL must be set as an environment variable." + ) + model_url = self.pathlib_url_join(base_url=open_api_base_url, path="models") + # call the models endpoint to get the list of available models + logger.debug(f"Calling models endpoint: {model_url}") + models: list[dict[str, str]] = [] + async with httpx.AsyncClient() as client: + # Perform the GET request with a timeout + response = await client.get( + url=model_url, + timeout=30.0, # 30 seconds timeout + ) + + # Raise an exception for HTTP errors + response.raise_for_status() + + # Parse JSON and extract 'data' key, defaulting to empty list + models = response.json().get("data", []) + logger.debug(f"Received models from {model_url}: {models}") + if self.valves.restrict_to_model_ids: + # Filter models based on the restricted model IDs + models = [ + model + for model in models + if model["id"] in self.valves.restrict_to_model_ids + ] + logger.debug(f"Filtered models: {models}") + return [ + { + "id": model["id"], + "name": model["id"], + } + for model in models + ] + + async def pipes(self) -> list[dict[str, str]]: + if self.pipelines is None: + logger.debug("Fetching models for the first time.") + self.pipelines = await self.get_models() + return self.pipelines or [] diff --git a/openwebui_functions/readme.md b/openwebui_functions/readme.md new file mode 100644 index 000000000..f41eb0582 --- /dev/null +++ b/openwebui_functions/readme.md @@ -0,0 +1,19 @@ +# Pipes for installing and running in OpenWebUI + +## OpenWebUI Pipes +https://docs.openwebui.com/features/plugin/functions/pipe/ + +## Instructions to add pipe to OpenWebUI on local machine +- Run `make down; make up-open-webui-auth` to start OpenWebUI with authentication + - Refer to base level README.md for instructions on setting up OAuth if you haven't already. Specifically, the keycloak host mapping in /etc/hosts. +- Login with admin/password to openwebui +- Now run `make set-admin-user-role` to set the admin role for this new user +- Reload the OpenWebUI page in your browser +- Click top right icon and select Admin Panel +- Click Functions tab +- Click Import Functions (don’t click + to add a new function) +- Select the language_model_gateway_pipe.json file in the openwebui_functions folder in language_model_gateway +- This contains the content of openai.py in a json string so update that if you change openai.py +- After the function has been loaded, make sure to click the toggle next to it to turn it on +- Now go back to the main UI +- There should be new models in the model dropdown \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 07dcaebf8..6da038080 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,16 +9,16 @@ warn_return_any = True warn_unused_configs = True [mypy-deepdiff.*] ignore_missing_imports = True -[mypy-boto3.*] -ignore_missing_imports = True -[mypy-botocore.*] -ignore_missing_imports = True [mypy-langchain_google_community.*] ignore_missing_imports = True [mypy-graphviz.*] ignore_missing_imports = True [mypy-markdownify.*] ignore_missing_imports = True +[mypy-databricks.sdk.*] +ignore_missing_imports = True +[mypy-pandas.*] +ignore_missing_imports = True [flake8] ignore = E501, W503, W504, E126, E251, E203 max-line-length = 88 diff --git a/tests/end_to_end/test_google_drive_agent.py b/tests/end_to_end/test_google_drive_agent.py new file mode 100644 index 000000000..cf01e304e --- /dev/null +++ b/tests/end_to_end/test_google_drive_agent.py @@ -0,0 +1,358 @@ +import os +from typing import Dict, Any, List + +import mcp +from authlib.oauth2.rfc6749 import OAuth2Token +from fastmcp.client import StreamableHttpTransport +from langchain_aws import ChatBedrockConverse +from langchain_core.language_models import BaseChatModel +from langchain_core.messages import BaseMessage +from langchain_mcp_adapters.client import MultiServerMCPClient +from langchain_mcp_adapters.sessions import StreamableHttpConnection +from langgraph.graph import StateGraph, MessagesState, START +from langgraph.prebuilt import tools_condition +from mcp.types import ( + Prompt, + Resource, + Tool, + TextContent, + ImageContent, + AudioContent, + ResourceLink, + EmbeddedResource, +) + +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.gateway.converters.streaming_tool_node import ( + StreamingToolNode, +) +from fastmcp import Client +from fastmcp.client.logging import LogMessage +import requests +from authlib.integrations.requests_client import OAuth2Session +import boto3 +from botocore.exceptions import NoCredentialsError, ClientError +from typing import Optional + +import httpx +import pytest +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async +from language_model_gateway.gateway.models.model_factory import ModelFactory +from language_model_gateway.gateway.utilities.environment_reader import ( + EnvironmentReader, +) +from tests.gateway.mocks.mock_chat_model import MockChatModel +from tests.gateway.mocks.mock_model_factory import MockModelFactory + + +def get_access_token(username: str, password: str) -> Dict[str, Any]: + """ + Fetch an OAuth2 access token using Resource Owner Password Credentials grant. + Args: + username (str): The user's username. + password (str): The user's password. + Returns: + dict: The token response. + """ + oauth_client_id = "bwell-client-id" + # oauth_client_secret = os.getenv("oauth_client_secret", "bwell-secret") + oauth_client_secret = "bwell-secret" + openid_provider_url = os.getenv( + "openid_provider_url", + "http://keycloak:8080/realms/bwell-realm/.well-known/openid-configuration", + ) + + resp = requests.get(openid_provider_url, timeout=5) + resp.raise_for_status() + openid_config = resp.json() + token_endpoint = openid_config["token_endpoint"] + + # https://docs.authlib.org/en/latest/client/oauth2.html + client = OAuth2Session( + client_id=oauth_client_id, + client_secret=oauth_client_secret, + # scope="openid email offline_access", + ) + + try: + # Acquire token using client_credentials grant + client_credentials_token = client.fetch_token( + url=token_endpoint, + grant_type="client_credentials", + ) + print( + f"Client credentials token fetched successfully: {client_credentials_token}" + ) + except Exception as e: + print(f"Error fetching client_credentials token: {e}") + raise + try: + token: dict[str, str] | OAuth2Token = client.fetch_token( + url=token_endpoint, + username=username, + password=password, + grant_type="password", + ) + except Exception as e: + print(f"Error fetching access token: {e}") + raise + return token if isinstance(token, dict) else token["access_token"] + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_google_drive_mcp_agent_directly() -> None: + # HTTP server + access_token_result: Dict[str, str] = get_access_token( + username="tester", password="password" + ) + url: str = "http://mcp_server_gateway:5000/google_drive/" + access_token = access_token_result["access_token"] + transport: StreamableHttpTransport = StreamableHttpTransport( + url=url, auth=access_token + ) + + async def log_handler(message: LogMessage) -> None: + if message.level == "error": + print(f"ERROR: {message.data}") + elif message.level == "warning": + print(f"WARNING: {message.data}") + else: + print(f"{message.level.upper()}: {message.data}") + + async def progress_handler( + progress: float, total: float | None, message: str | None + ) -> None: + if total is not None: + percentage = (progress / total) * 100 + print(f"Progress: {percentage:.1f}% - {message or ''}") + else: + print(f"Progress: {progress} - {message or ''}") + + client: Client[Any] = Client( + transport=transport, + log_handler=log_handler, + progress_handler=progress_handler, + ) + async with client: + # Basic server interaction + await client.ping() + + # List available operations + tools: List[Tool] = await client.list_tools() + assert tools is not None + resources: List[Resource] = await client.list_resources() + assert resources is not None + prompts: List[Prompt] = await client.list_prompts() + assert prompts is not None + + # Execute operations + result: mcp.types.CallToolResult = await client.call_tool_mcp( + "download_file_from_url", + { + "url": "https://docs.google.com/document/d/15uw9_mdTON6SQpQHCEgCffVtYBg9woVjvcMErXQSaa0/edit?usp=sharing" + }, + ) + print(result) + content: ( + TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource + ) = result.content[0] + assert content is not None + assert isinstance(content, TextContent) + assert "Hello, this is a test file shared with all of b.well" in content.text + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_google_drive_via_llm() -> None: + verify_aws_boto3_authentication() + # model: BaseChatModel = init_chat_model("openai:gpt-4.1") + model_parameters_dict: Dict[str, Any] = {} + access_token_result: Dict[str, str] = get_access_token( + username="tester", password="password" + ) + url: str = "http://mcp_server_gateway:5000/google_drive" + access_token = access_token_result["access_token"] + + model: BaseChatModel = ChatBedrockConverse( + client=None, + # model="us.anthropic.claude-sonnet-4-20250514-v1:0", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + provider="anthropic", + credentials_profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE"), + region_name=os.environ.get("AWS_REGION", "us-east-1"), + # Setting temperature to 0 for deterministic results + **model_parameters_dict, + ) + mcp_tool_config: StreamableHttpConnection = { + "url": url, + "transport": "streamable_http", + # specify the http client factory to use the headers + # httpx_client_factory + # and/or bearer "auth"# auth: NotRequired[httpx.Auth] + "headers": { + "Authorization": f"Bearer {access_token}", + "Content-Type": "application/json", + }, + } + + client = MultiServerMCPClient( + { + "download_file_from_url": mcp_tool_config, + } + ) + tools = await client.get_tools() + + def call_model(state: MessagesState) -> Dict[str, BaseMessage]: + response = model.bind_tools(tools).invoke(state["messages"]) + return {"messages": response} + + builder = StateGraph(MessagesState) + builder.add_node(call_model) + builder.add_node(StreamingToolNode(tools)) + builder.add_edge(START, "call_model") + builder.add_conditional_edges( + "call_model", + tools_condition, + ) + builder.add_edge("tools", "call_model") + graph = builder.compile() + prompt = { + "messages": "show me contents of this file: https://docs.google.com/document/d/15uw9_mdTON6SQpQHCEgCffVtYBg9woVjvcMErXQSaa0/edit?usp=sharing" + } + # noinspection PyTypeChecker + math_response = await graph.ainvoke(prompt) # type: ignore[arg-type] + print(math_response) + print("=== Google Drive Response ===") + print(math_response["messages"][-1].content) + print("===== End of Math Response =====") + assert ( + "Hello, this is a test file shared with all of b.well" + in math_response["messages"][-1].content + ) + # weather_response = await graph.ainvoke({"messages": "what is the weather in nyc?"}) + # print(weather_response) + + +def verify_aws_boto3_authentication() -> None: + """ + Test if AWS credentials are configured and boto3 can authenticate. + Uses profile and region from environment variables if set. + """ + credentials_profile_name = os.environ.get("AWS_CREDENTIALS_PROFILE") + region_name = os.environ.get("AWS_REGION", "us-east-1") + session_kwargs = {} + if credentials_profile_name: + session_kwargs["profile_name"] = credentials_profile_name + if region_name: + session_kwargs["region_name"] = region_name + try: + session = boto3.Session(**session_kwargs) # type: ignore[arg-type] + sts = session.client("sts") + identity = sts.get_caller_identity() + print(f"AWS authentication successful: {identity}") + assert "Account" in identity + except NoCredentialsError: + print("AWS credentials not found.") + assert False, "AWS credentials not found." + except ClientError as e: + print(f"AWS client error: {e}") + assert False, f"AWS client error: {e}" + except Exception as e: + print(f"Unexpected error: {e}") + assert False, f"Unexpected error: {e}" + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_chat_completions_with_google_drive( + async_client: httpx.AsyncClient, +) -> None: + print("") + access_token_result: Dict[str, str] = get_access_token( + username="tester", password="password" + ) + url: str = "http://mcp_server_gateway:5000/google_drive" + access_token = access_token_result["access_token"] + + test_container: SimpleContainer = await get_container_async() + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "Hello, this is a test file shared with all of b.well" + ) + ), + ) + else: + verify_aws_boto3_authentication() + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="google_drive", + name="Google Drive", + description="Google Drive", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig( + name="google_drive", tools="download_file_from_url", url=url + ), + ], + ) + ] + ) + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "show me contents of this file: https://docs.google.com/document/d/15uw9_mdTON6SQpQHCEgCffVtYBg9woVjvcMErXQSaa0/edit?usp=sharing", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="Google Drive", + extra_headers={ + "Authorization": f"Bearer {access_token}", + }, + ) + + # print the top "choice" + content: Optional[str] = "\n".join( + choice.message.content or "" for choice in chat_completion.choices + ) + assert content is not None + print(content) + assert "Hello, this is a test file shared with all of b.well" in content diff --git a/tests/end_to_end/test_mcp_agent.py b/tests/end_to_end/test_mcp_agent.py new file mode 100644 index 000000000..0879e96ff --- /dev/null +++ b/tests/end_to_end/test_mcp_agent.py @@ -0,0 +1,151 @@ +import os +from typing import Dict, Any, List, Optional + +import pytest +from langchain_aws import ChatBedrockConverse +from langchain_core.language_models import BaseChatModel +from langchain_core.messages import BaseMessage +from langchain_mcp_adapters.client import MultiServerMCPClient +from langgraph.graph import StateGraph, MessagesState, START +from langgraph.prebuilt import tools_condition +from mcp.types import ( + Prompt, + Resource, + Tool, + TextContent, + ImageContent, + AudioContent, + ResourceLink, + EmbeddedResource, +) +from openai import AsyncOpenAI +from openai.types.responses import Response +from openai.types.responses.tool_param import Mcp + +from language_model_gateway.gateway.converters.streaming_tool_node import ( + StreamingToolNode, +) +from fastmcp import Client +from fastmcp.client.client import CallToolResult + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_mcp_agent_directly() -> None: + # HTTP server + client: Client[Any] = Client("http://mcp_server_gateway:5000/math_server") + async with client: + # Basic server interaction + await client.ping() + + # List available operations + tools: List[Tool] = await client.list_tools() + assert tools is not None + resources: List[Resource] = await client.list_resources() + assert resources is not None + prompts: List[Prompt] = await client.list_prompts() + assert prompts is not None + + # Execute operations + result: CallToolResult = await client.call_tool("add", {"a": 12, "b": 8}) + print(result) + content: ( + TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource + ) = result.content[0] + assert content is not None + assert isinstance(content, TextContent) + assert content.text == "20" + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_mcp_agent() -> None: + # model: BaseChatModel = init_chat_model("openai:gpt-4.1") + model_parameters_dict: Dict[str, Any] = {} + + model: BaseChatModel = ChatBedrockConverse( + client=None, + # model="us.anthropic.claude-sonnet-4-20250514-v1:0", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + provider="anthropic", + credentials_profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE"), + region_name=os.environ.get("AWS_REGION", "us-east-1"), + # Setting temperature to 0 for deterministic results + **model_parameters_dict, + ) + + client = MultiServerMCPClient( + { + # "math": { + # "command": "python", + # # Make sure to update to the full absolute path to your math_server.py file + # "args": ["./examples/math_server.py"], + # "transport": "stdio", + # }, + "math": { + # make sure you start your weather server on port 8000 + "url": "http://mcp_server_gateway:5000/math_server", + "transport": "streamable_http", + }, + "providersearch": { + # make sure you start your weather server on port 8000 + "url": "http://mcp_server_gateway:5000/provider_search", + "transport": "streamable_http", + }, + } + ) + tools = await client.get_tools() + + def call_model(state: MessagesState) -> Dict[str, BaseMessage]: + response = model.bind_tools(tools).invoke(state["messages"]) + return {"messages": response} + + builder = StateGraph(MessagesState) + builder.add_node(call_model) + builder.add_node(StreamingToolNode(tools)) + builder.add_edge(START, "call_model") + builder.add_conditional_edges( + "call_model", + tools_condition, + ) + builder.add_edge("tools", "call_model") + graph = builder.compile() + prompt = {"messages": "what's address for Dr. Alice Smith?"} + # noinspection PyTypeChecker + math_response = await graph.ainvoke(prompt) # type: ignore[arg-type] + print(math_response) + print("=== Math Response ===") + print(math_response["messages"][-1].content) + print("===== End of Math Response =====") + assert "123 Main St, Springfield" in math_response["messages"][-1].content + # weather_response = await graph.ainvoke({"messages": "what is the weather in nyc?"}) + # print(weather_response) + + +@pytest.mark.skip( + reason="This test requires opening a public MCP server per https://gofastmcp.com/integrations/openai" +) +async def test_mcp_agent_via_openai() -> None: + # uses the OpenAI API to call the MCP server + openai_api_key: Optional[str] = os.environ.get("OPENAI_API_KEY") + assert openai_api_key is not None, "OPENAI_API_KEY environment variable is not set" + + client = AsyncOpenAI(api_key=openai_api_key) + + tool: Mcp = { + "type": "mcp", + "server_label": "math_server", + "server_url": "http://mcp_server_gateway:5000/math_server", + "require_approval": "never", + } + resp: Response = await client.responses.create( + model="gpt-4.1", + tools=[tool], + input="multiple 2 and 3 using math server", + ) + + print(resp.output_text) diff --git a/tests/gateway/configs/__init__.py b/tests/gateway/configs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/gateway/configs/config_reader/__init__.py b/tests/gateway/configs/config_reader/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/gateway/configs/config_reader/test_github_config_zip_downloader.py b/tests/gateway/configs/config_reader/test_github_config_zip_downloader.py new file mode 100644 index 000000000..10b8cbadb --- /dev/null +++ b/tests/gateway/configs/config_reader/test_github_config_zip_downloader.py @@ -0,0 +1,46 @@ +import os +import pytest +from language_model_gateway.configs.config_reader.github_config_zip_reader import ( + GitHubConfigZipDownloader, +) + + +@pytest.mark.skipif( + os.getenv("GITHUB_TOKEN") is None, + reason="Requires GITHUB_TOKEN", +) +async def test_download_zip_from_github() -> None: + # Public repo zip URL + # zip_url = "https://github.com/icanbwell/language-model-gateway-configuration/zipball/main/" + zip_url = "https://api.github.com/repos/icanbwell/language-model-gateway-configuration/zipball/main" + downloader = GitHubConfigZipDownloader() + extracted_path = await downloader.download_zip(zip_url) + + # Check that the extracted path exists and contains expected files + assert os.path.exists(extracted_path) + # Check that at least one file exists in the extracted directory + files = [ + f + for f in os.listdir(extracted_path) + if os.path.isfile(os.path.join(extracted_path, f)) + ] + dirs = [ + d + for d in os.listdir(extracted_path) + if os.path.isdir(os.path.join(extracted_path, d)) + ] + assert files or dirs + # print the files and directories recursively + for root, dirs, files in os.walk(extracted_path): + for name in files: + print(os.path.join(root, name)) + for name in dirs: + print(os.path.join(root, name)) + + # Clean up + for root, dirs, files in os.walk(extracted_path, topdown=False): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + os.rmdir(extracted_path) diff --git a/tests/gateway/file_managers/test_aws_file_manager.py b/tests/gateway/file_managers/test_aws_file_manager.py index ed9634598..d9ed330e0 100644 --- a/tests/gateway/file_managers/test_aws_file_manager.py +++ b/tests/gateway/file_managers/test_aws_file_manager.py @@ -1,9 +1,12 @@ -from typing import Dict, List, Any +import os +from typing import Dict, List, Any, Generator import boto3 import pytest +from botocore.client import BaseClient from moto import mock_aws from starlette.responses import Response, StreamingResponse +from boto3 import Session from language_model_gateway.gateway.aws.aws_client_factory import AwsClientFactory from language_model_gateway.gateway.file_managers.aws_s3_file_manager import ( @@ -11,17 +14,25 @@ ) from language_model_gateway.gateway.utilities.s3_url import S3Url from tests.gateway.mocks.mock_aws_client_factory import MockAwsClientFactory +from types_boto3_s3.client import S3Client @pytest.fixture -def mock_s3() -> boto3.client: +def mock_s3() -> Generator[S3Client, Any, None]: """Create a mock S3 client using moto.""" with mock_aws(): - yield boto3.client("s3", region_name="us-east-1") + session: Session = boto3.Session( + profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE") + ) + s3_client: S3Client = session.client( + service_name="s3", + region_name="us-east-1", + ) + yield s3_client @pytest.fixture -def aws_client_factory(mock_s3: boto3.client) -> AwsClientFactory: +def aws_client_factory(mock_s3: BaseClient) -> AwsClientFactory: """Create a mock AWS client factory.""" return MockAwsClientFactory(aws_client=mock_s3) @@ -94,7 +105,7 @@ def test_get_bucket(aws_s3_file_manager: AwsS3FileManager) -> None: @pytest.mark.asyncio async def test_save_file_async_success( - aws_s3_file_manager: AwsS3FileManager, mock_s3: boto3.client + aws_s3_file_manager: AwsS3FileManager, mock_s3: S3Client ) -> None: """ Comprehensive test for save_file_async method. @@ -182,7 +193,7 @@ async def test_save_file_async_edge_cases( @pytest.mark.asyncio async def test_read_file_async_success( - aws_s3_file_manager: AwsS3FileManager, mock_s3: boto3.client + aws_s3_file_manager: AwsS3FileManager, mock_s3: S3Client ) -> None: """ Comprehensive test for read_file_async method. @@ -240,7 +251,7 @@ async def test_read_file_async_success( @pytest.mark.asyncio async def test_read_file_async_error_cases( - aws_s3_file_manager: AwsS3FileManager, mock_s3: boto3.client + aws_s3_file_manager: AwsS3FileManager, mock_s3: S3Client ) -> None: """ Test error cases for read_file_async. diff --git a/tests/gateway/mcp_tools/__init__.py b/tests/gateway/mcp_tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_confluence.py b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_confluence.py new file mode 100644 index 000000000..004ae5a1e --- /dev/null +++ b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_confluence.py @@ -0,0 +1,95 @@ +import os +from typing import Optional + +import httpx +import pytest +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async +from language_model_gateway.gateway.models.model_factory import ModelFactory +from language_model_gateway.gateway.utilities.environment_reader import ( + EnvironmentReader, +) +from tests.gateway.mocks.mock_chat_model import MockChatModel +from tests.gateway.mocks.mock_model_factory import MockModelFactory + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_chat_completions_with_mcp_confluence( + async_client: httpx.AsyncClient, +) -> None: + print("") + test_container: SimpleContainer = await get_container_async() + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "Donald Trump won the last US election" + ) + ), + ) + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig( + name="mcp_github_search", + url="https://mcp.atlassian.com/v1/sse", + # headers={"Authorization": "Bearer $GITHUB_TOKEN"}, + ), + ], + ) + ] + ) + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "list last 2 changed Confluence pages in icanbwell organization", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="General Purpose", + ) + + # print the top "choice" + content: Optional[str] = "\n".join( + choice.message.content or "" for choice in chat_completion.choices + ) + assert content is not None + print(content) + assert "fhir" in content diff --git a/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_github.py b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_github.py new file mode 100644 index 000000000..5e8708a45 --- /dev/null +++ b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_github.py @@ -0,0 +1,95 @@ +import os +from typing import Optional + +import httpx +import pytest +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async +from language_model_gateway.gateway.models.model_factory import ModelFactory +from language_model_gateway.gateway.utilities.environment_reader import ( + EnvironmentReader, +) +from tests.gateway.mocks.mock_chat_model import MockChatModel +from tests.gateway.mocks.mock_model_factory import MockModelFactory + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_chat_completions_with_mcp_github( + async_client: httpx.AsyncClient, +) -> None: + print("") + test_container: SimpleContainer = await get_container_async() + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "Donald Trump won the last US election" + ) + ), + ) + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig( + name="mcp_github_search", + url="https://api.githubcopilot.com/mcp/", + headers={"Authorization": "Bearer $GITHUB_TOKEN"}, + ), + ], + ) + ] + ) + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "list first 2 repositories in icanbwell organization that include the word 'fhir' in the name", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="General Purpose", + ) + + # print the top "choice" + content: Optional[str] = "\n".join( + choice.message.content or "" for choice in chat_completion.choices + ) + assert content is not None + print(content) + assert "fhir" in content diff --git a/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_provider_search.py b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_provider_search.py new file mode 100644 index 000000000..0982f1bb5 --- /dev/null +++ b/tests/gateway/mcp_tools/test_chat_anthropic_with_mcp_provider_search.py @@ -0,0 +1,94 @@ +import os +from typing import Optional + +import httpx +import pytest +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async +from language_model_gateway.gateway.models.model_factory import ModelFactory +from language_model_gateway.gateway.utilities.environment_reader import ( + EnvironmentReader, +) +from tests.gateway.mocks.mock_chat_model import MockChatModel +from tests.gateway.mocks.mock_model_factory import MockModelFactory + + +@pytest.mark.skipif( + os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1", + reason="Environment Variable RUN_TESTS_WITH_REAL_LLM not set", +) +async def test_chat_completions_with_mcp_provider_search( + async_client: httpx.AsyncClient, +) -> None: + print("") + test_container: SimpleContainer = await get_container_async() + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "Donald Trump won the last US election" + ) + ), + ) + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig( + name="mcp_provider_search", + url="http://provider_search:8001/mcp/", + ), + ], + ) + ] + ) + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "what's address for Dr. Alice Smith?", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="General Purpose", + ) + + # print the top "choice" + content: Optional[str] = "\n".join( + choice.message.content or "" for choice in chat_completion.choices + ) + assert content is not None + print(content) + assert "123 Main St, Springfield" in content diff --git a/tests/gateway/mcp_tools/test_google_drive_mcp_server.py b/tests/gateway/mcp_tools/test_google_drive_mcp_server.py new file mode 100644 index 000000000..5b43d6da3 --- /dev/null +++ b/tests/gateway/mcp_tools/test_google_drive_mcp_server.py @@ -0,0 +1,79 @@ +import pytest +import httpx +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async +from language_model_gateway.gateway.models.model_factory import ModelFactory +from language_model_gateway.gateway.utilities.environment_reader import ( + EnvironmentReader, +) +from tests.gateway.mocks.mock_chat_model import MockChatModel +from tests.gateway.mocks.mock_model_factory import MockModelFactory + + +@pytest.mark.asyncio +async def test_chat_completions_with_mcp_google_drive( + async_client: httpx.AsyncClient, +) -> None: + test_container: SimpleContainer = await get_container_async() + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "This is a mock response from the LLM." + ) + ), + ) + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="test_google_drive", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="openai", + model="gpt-3.5-turbo", + ), + tools=[ + AgentConfig( + name="download_file_from_url", + url="http://mcp_server_gateway:5051/google_drive/", # Assumes MCP server is running locally + ), + ], + ) + ] + ) + + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # Change if your API runs on a different port + http_client=async_client, + ) + + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "Download https://docs.google.com/document/d/15uw9_mdTON6SQpQHCEgCffVtYBg9woVjvcMErXQSaa0/edit?usp=sharing", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="General Purpose", + ) + assert chat_completion.choices[0].message.content is not None + + await model_configuration_cache.clear() diff --git a/tests/gateway/mocks/mock_aws_client_factory.py b/tests/gateway/mocks/mock_aws_client_factory.py index 3f6b435d5..5aff7767e 100644 --- a/tests/gateway/mocks/mock_aws_client_factory.py +++ b/tests/gateway/mocks/mock_aws_client_factory.py @@ -1,15 +1,21 @@ -from typing import override +from typing import override, cast -import boto3 +from botocore.client import BaseClient from language_model_gateway.gateway.aws.aws_client_factory import AwsClientFactory +from types_boto3_bedrock_runtime.client import BedrockRuntimeClient +from types_boto3_s3.client import S3Client class MockAwsClientFactory(AwsClientFactory): - def __init__(self, *, aws_client: boto3.client) -> None: + def __init__(self, *, aws_client: BaseClient) -> None: self.aws_client = aws_client assert self.aws_client is not None @override - def create_client(self, *, service_name: str) -> boto3.client: - return self.aws_client + def create_bedrock_client(self) -> BedrockRuntimeClient: + return cast(BedrockRuntimeClient, self.aws_client) + + @override + def create_s3_client(self) -> S3Client: + return cast(S3Client, self.aws_client) diff --git a/tests/gateway/mocks/mock_chat_model.py b/tests/gateway/mocks/mock_chat_model.py index 671525826..b5bf52905 100644 --- a/tests/gateway/mocks/mock_chat_model.py +++ b/tests/gateway/mocks/mock_chat_model.py @@ -96,9 +96,7 @@ async def _astream( def bind_tools( self, tools: Sequence[ - Union[ - typing.Dict[str, Any], type, Callable[[], Any], BaseTool - ] # noqa: UP006 + Union[typing.Dict[str, Any], type, Callable[[], Any], BaseTool] # noqa: UP006 ], **kwargs: Any, ) -> Runnable[LanguageModelInput, BaseMessage]: diff --git a/tests/gateway/mocks/mock_chat_response.py b/tests/gateway/mocks/mock_chat_response.py index e699e712d..3fb2eaed4 100644 --- a/tests/gateway/mocks/mock_chat_response.py +++ b/tests/gateway/mocks/mock_chat_response.py @@ -10,5 +10,5 @@ def __call__( *, model_config: ChatModelConfig, headers: Dict[str, str], - chat_request: ChatRequest + chat_request: ChatRequest, ) -> Dict[str, Any]: ... diff --git a/tests/gateway/mocks/mock_http_client_factory.py b/tests/gateway/mocks/mock_http_client_factory.py index df023d546..a5f004569 100644 --- a/tests/gateway/mocks/mock_http_client_factory.py +++ b/tests/gateway/mocks/mock_http_client_factory.py @@ -18,6 +18,6 @@ async def create_http_client( *, base_url: str, headers: Optional[Dict[str, str]] = None, - timeout: Optional[float] = 5.0 + timeout: Optional[float] = 5.0, ) -> AsyncGenerator[httpx.AsyncClient, None]: yield self.fn_http_client() diff --git a/tests/gateway/mocks/mock_image_generator.py b/tests/gateway/mocks/mock_image_generator.py index 8d23d1e35..3783ade3f 100644 --- a/tests/gateway/mocks/mock_image_generator.py +++ b/tests/gateway/mocks/mock_image_generator.py @@ -14,6 +14,6 @@ async def generate_image_async( style: Literal["natural", "cinematic", "digital-art", "pop-art"] = "natural", image_size: Literal[ "256x256", "512x512", "1024x1024", "1792x1024", "1024x1792" - ] = "1024x1024" + ] = "1024x1024", ) -> bytes: return b"mock_image_data" diff --git a/tests/gateway/mocks/mock_langchain_completions_provider.py b/tests/gateway/mocks/mock_langchain_completions_provider.py index 23aec2c5a..6d084359b 100644 --- a/tests/gateway/mocks/mock_langchain_completions_provider.py +++ b/tests/gateway/mocks/mock_langchain_completions_provider.py @@ -11,7 +11,9 @@ LangChainCompletionsProvider, ) from language_model_gateway.gateway.schema.openai.completions import ChatRequest +from language_model_gateway.gateway.tools.mcp_tool_provider import MCPToolProvider from language_model_gateway.gateway.tools.tool_provider import ToolProvider +from language_model_gateway.gateway.utilities.auth.token_verifier import TokenVerifier from tests.gateway.mocks.mock_chat_response import MockChatResponseProtocol @@ -22,12 +24,16 @@ def __init__( model_factory: ModelFactory, lang_graph_to_open_ai_converter: LangGraphToOpenAIConverter, tool_provider: ToolProvider, + mcp_tool_provider: MCPToolProvider, + token_verifier: TokenVerifier, fn_get_response: MockChatResponseProtocol, ) -> None: super().__init__( model_factory=model_factory, lang_graph_to_open_ai_converter=lang_graph_to_open_ai_converter, tool_provider=tool_provider, + mcp_tool_provider=mcp_tool_provider, + token_verifier=token_verifier, ) self.fn_get_response: MockChatResponseProtocol = fn_get_response diff --git a/tests/gateway/test_chat_anthropic_image_generation.py b/tests/gateway/test_chat_anthropic_image_generation.py index b3e96a698..aacecd9c2 100644 --- a/tests/gateway/test_chat_anthropic_image_generation.py +++ b/tests/gateway/test_chat_anthropic_image_generation.py @@ -1,7 +1,7 @@ import httpx import pytest from openai import AsyncOpenAI -from openai.types import ImagesResponse +from openai.types import ImagesResponse, Image @pytest.mark.asyncio @@ -39,7 +39,9 @@ async def test_chat_anthropic_image_generation(async_client: httpx.AsyncClient) n=1, ) - image_url = response.data[0].url + image: Image | None = response.data[0] if response.data else None + assert image is not None + image_url: str | None = image.url print(f"Image URL: {image_url}") assert image_url is not None assert "http" in image_url diff --git a/tests/gateway/test_chat_anthropic_streaming.py b/tests/gateway/test_chat_anthropic_streaming.py index 953f82174..7083d7e30 100644 --- a/tests/gateway/test_chat_anthropic_streaming.py +++ b/tests/gateway/test_chat_anthropic_streaming.py @@ -1,7 +1,7 @@ import httpx import pytest from openai import AsyncOpenAI, AsyncStream -from openai.types.chat import ChatCompletionChunk +from openai.types.chat import ChatCompletionChunk, ChatCompletionUserMessageParam from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async @@ -37,13 +37,12 @@ async def test_chat_completions_streaming(async_client: httpx.AsyncClient) -> No ) # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "what is the first name of Obama?", + } stream: AsyncStream[ChatCompletionChunk] = await client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "what is the first name of Obama?", - } - ], + messages=[message], model="General Purpose", stream=True, ) diff --git a/tests/gateway/test_chat_anthropic_with_google_search.py b/tests/gateway/test_chat_anthropic_with_google_search.py index ae1824311..156145587 100644 --- a/tests/gateway/test_chat_anthropic_with_google_search.py +++ b/tests/gateway/test_chat_anthropic_with_google_search.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx import pytest @@ -10,13 +10,15 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -38,8 +40,8 @@ async def test_chat_completions_with_web_search( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_anthropic_with_pdf_scraping.py b/tests/gateway/test_chat_anthropic_with_pdf_scraping.py index 4fe13d77d..6474dfcf2 100644 --- a/tests/gateway/test_chat_anthropic_with_pdf_scraping.py +++ b/tests/gateway/test_chat_anthropic_with_pdf_scraping.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx from openai import AsyncOpenAI @@ -10,13 +10,15 @@ AgentConfig, PromptConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -36,8 +38,8 @@ async def test_chat_anthropic_with_pdf_scraping( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -108,8 +110,8 @@ async def test_chat_anthropic_with_pdf_ocr_scraping( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_anthropic_with_web_scraping.py b/tests/gateway/test_chat_anthropic_with_web_scraping.py index 4b0c0d9a9..719e47404 100644 --- a/tests/gateway/test_chat_anthropic_with_web_scraping.py +++ b/tests/gateway/test_chat_anthropic_with_web_scraping.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx from openai import AsyncOpenAI @@ -10,13 +10,15 @@ AgentConfig, PromptConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -36,8 +38,8 @@ async def test_chat_anthropic_with_web_scraping( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_anthropic_with_web_search.py b/tests/gateway/test_chat_anthropic_with_web_search.py index 61cd18c99..4c11b4197 100644 --- a/tests/gateway/test_chat_anthropic_with_web_search.py +++ b/tests/gateway/test_chat_anthropic_with_web_search.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx import pytest @@ -10,13 +10,15 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -38,8 +40,8 @@ async def test_chat_completions_with_web_search( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_b_well.py b/tests/gateway/test_chat_b_well.py index 7a24bbd40..27a0be30c 100644 --- a/tests/gateway/test_chat_b_well.py +++ b/tests/gateway/test_chat_b_well.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx from httpx import Response @@ -13,12 +13,14 @@ PromptConfig, ModelParameterConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache async def test_chat_completions_b_well( @@ -54,8 +56,8 @@ async def test_chat_completions_b_well( return # this test only works with AI Agent # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_openai.py b/tests/gateway/test_chat_openai.py index 5393feb8e..b605965c5 100644 --- a/tests/gateway/test_chat_openai.py +++ b/tests/gateway/test_chat_openai.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx from openai import AsyncOpenAI @@ -9,13 +9,15 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -35,8 +37,8 @@ async def test_chat_open_ai(async_client: httpx.AsyncClient) -> None: ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -104,8 +106,8 @@ async def test_chat_completions_with_chat_history( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_openai_streaming.py b/tests/gateway/test_chat_openai_streaming.py index 783a6f11d..e3edbfbbc 100644 --- a/tests/gateway/test_chat_openai_streaming.py +++ b/tests/gateway/test_chat_openai_streaming.py @@ -14,6 +14,9 @@ ModelParameterConfig, PromptConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.utilities.environment_reader import ( @@ -21,8 +24,6 @@ ) from openai.types.chat.chat_completion_chunk import ChoiceDelta, Choice as ChunkChoice -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache - async def test_chat_completions_streaming( async_client: httpx.AsyncClient, httpx_mock: HTTPXMock @@ -94,8 +95,8 @@ async def test_chat_completions_streaming( else: return # this test only works with AI Agent - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_prompt_helper.py b/tests/gateway/test_chat_prompt_helper.py index 4624f950f..633bedf94 100644 --- a/tests/gateway/test_chat_prompt_helper.py +++ b/tests/gateway/test_chat_prompt_helper.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import Optional import httpx from openai import AsyncOpenAI, AsyncStream @@ -10,13 +10,15 @@ PromptConfig, ModelParameterConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_model_factory import MockModelFactory @@ -36,8 +38,8 @@ async def test_chat_prompt_helper(async_client: httpx.AsyncClient) -> None: ), ) - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -113,8 +115,8 @@ async def test_chat_prompt_helper_streaming(async_client: httpx.AsyncClient) -> ), ) - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_chat_streaming.py b/tests/gateway/test_chat_streaming.py index b9ece09a9..11205cef3 100644 --- a/tests/gateway/test_chat_streaming.py +++ b/tests/gateway/test_chat_streaming.py @@ -14,6 +14,9 @@ ModelParameterConfig, PromptConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.utilities.environment_reader import ( @@ -21,8 +24,6 @@ ) from openai.types.chat.chat_completion_chunk import ChoiceDelta, Choice as ChunkChoice -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache - async def test_chat_completions_streaming( async_client: httpx.AsyncClient, httpx_mock: HTTPXMock @@ -94,8 +95,8 @@ async def test_chat_completions_streaming( else: return # this test only works with AI Agent - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/test_token_verifier.py b/tests/gateway/test_token_verifier.py new file mode 100644 index 000000000..7a6fd04b7 --- /dev/null +++ b/tests/gateway/test_token_verifier.py @@ -0,0 +1,61 @@ +from typing import Any, Generator + +import pytest +import base64 + +from joserfc import jwk + +from language_model_gateway.gateway.utilities.auth.token_verifier import TokenVerifier +from joserfc import jwt +import time + +# Sample JWKS and token generation for testing +SECRET = base64.urlsafe_b64encode(b"secret").rstrip(b"=").decode("utf-8") +JWKS: dict[str, list[dict[str, str | list[str]]]] = { + "keys": [{"kty": "oct", "kid": "testkey", "k": SECRET}] +} + +KID = "testkey" +ALGORITHM = "HS256" + + +@pytest.fixture +def mock_jwks(httpx_mock: Any) -> Generator[None, Any, None]: + httpx_mock.add_response(json=JWKS) + yield + + +def create_jwt_token(exp_offset: int = 60) -> str: + header = {"kid": KID, "alg": ALGORITHM} + payload = { + "sub": "1234567890", + "name": "John Doe", + "exp": int(time.time()) + exp_offset, + } + # joserfc requires key as dict for oct (symmetric) keys + key = jwk.import_key(JWKS["keys"][0]) + return jwt.encode(header=header, claims=payload, key=key) + + +def test_extract_token() -> None: + verifier = TokenVerifier(jwks_uri="https://fake-jwks-uri") + header = "Bearer sometoken" + assert verifier.extract_token(header) == "sometoken" + assert verifier.extract_token(None) is None + assert verifier.extract_token("") is None + assert verifier.extract_token("Basic sometoken") is None + + +async def test_verify_token_valid(mock_jwks: Any) -> None: + verifier = TokenVerifier(jwks_uri="https://fake-jwks-uri", algorithms=[ALGORITHM]) + token = create_jwt_token() + claims = await verifier.verify_token_async(token=token) + assert claims["sub"] == "1234567890" + assert claims["name"] == "John Doe" + + +async def test_verify_token_expired(mock_jwks: Any) -> None: + verifier = TokenVerifier(jwks_uri="https://fake-jwks-uri", algorithms=[ALGORITHM]) + token = create_jwt_token(exp_offset=-60) + with pytest.raises(ValueError, match="This OAuth Token has expired"): + await verifier.verify_token_async(token=token) diff --git a/tests/gateway/tools/test_chat_anthropic_image_generator.py b/tests/gateway/tools/test_chat_anthropic_image_generator.py index 65000e34a..37d49fb12 100644 --- a/tests/gateway/tools/test_chat_anthropic_image_generator.py +++ b/tests/gateway/tools/test_chat_anthropic_image_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_anthropic_image_generator(async_client: httpx.AsyncClient) - ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -123,8 +125,8 @@ async def test_chat_anthropic_image_generator_streaming( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_aws_image_model.py b/tests/gateway/tools/test_chat_aws_image_model.py index 9718b3a8a..4ed3d05f9 100644 --- a/tests/gateway/tools/test_chat_aws_image_model.py +++ b/tests/gateway/tools/test_chat_aws_image_model.py @@ -7,12 +7,13 @@ import boto3 import pytest +from types_boto3_bedrock_runtime.client import BedrockRuntimeClient -def create_bedrock_client() -> boto3.client: +def create_bedrock_client() -> BedrockRuntimeClient: """Create and return a Bedrock client""" session1 = boto3.Session(profile_name=os.environ.get("AWS_CREDENTIALS_PROFILE")) - bedrock_client = session1.client( + bedrock_client: BedrockRuntimeClient = session1.client( service_name="bedrock-runtime", region_name="us-east-1", # Replace with your preferred region # Add credentials if not using default AWS configuration: @@ -28,7 +29,7 @@ def generate_image( """Generate an image using Titan Image Generator""" # Create Bedrock client - client = create_bedrock_client() + client: BedrockRuntimeClient = create_bedrock_client() # Prepare the request parameters request_body = { diff --git a/tests/gateway/tools/test_chat_calculator_average.py b/tests/gateway/tools/test_chat_calculator_average.py new file mode 100644 index 000000000..c96412fee --- /dev/null +++ b/tests/gateway/tools/test_chat_calculator_average.py @@ -0,0 +1,99 @@ +import logging + +import httpx +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion, ChatCompletionUserMessageParam +from typing import List, Dict, Any + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__file__) + + +def build_prompt(numbers: List[float]) -> str: + if not numbers: + return "Calculate the average of: " + return f"Calculate the average of: {', '.join(map(str, numbers))}" + + +async def test_chat_calculator_average_tool_bedrock( + async_client: httpx.AsyncClient, +) -> None: + print("") + print("") + test_container: SimpleContainer = await get_container_async() + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig(name="calculator_average"), + ], + ) + ] + ) + + test_cases: List[Dict[str, Any]] = [ + {"numbers": [10, 20, 30], "expected": "20.0"}, + {"numbers": [42], "expected": "42.0"}, + {"numbers": [], "expected": "No numbers provided"}, + {"numbers": [1.5, 2.5, 3.0], "expected": "2.333"}, + {"numbers": [-10, 0, 10], "expected": "0.0"}, + ] + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "what is the current date and time?", + } + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[message], + model="General Purpose", + ) + print(chat_completion) + + for idx, case in enumerate(test_cases): + prompt: str = build_prompt(case["numbers"]) + print(f"\nSending prompt to Bedrock: {prompt}") + + # call API + content_prompt_: ChatCompletionUserMessageParam = { + "role": "user", + "content": prompt, + } + chat_completion = await client.chat.completions.create( + messages=[content_prompt_], + model="General Purpose", + ) + + print(chat_completion) diff --git a/tests/gateway/tools/test_chat_calculator_length.py b/tests/gateway/tools/test_chat_calculator_length.py new file mode 100644 index 000000000..4ce2bbad9 --- /dev/null +++ b/tests/gateway/tools/test_chat_calculator_length.py @@ -0,0 +1,101 @@ +import logging + +import httpx +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion +from typing import List, Dict, Any + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__file__) + + +def build_prompt(items: List[Any]) -> str: + if not items: + return "Calculate the length of: " + return f"Calculate the length of: {', '.join(map(str, items))}" + + +async def test_chat_calculator_length_tool_bedrock( + async_client: httpx.AsyncClient, +) -> None: + print("") + print("") + test_container: SimpleContainer = await get_container_async() + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig(name="calculator_length"), + ], + ) + ] + ) + + test_cases: List[Dict[str, Any]] = [ + {"items": ["apple", "banana", "cherry"], "expected": "3"}, + {"items": ["one"], "expected": "1"}, + {"items": [], "expected": "No list provided"}, + {"items": [1, 2, 3, 4], "expected": "4"}, + {"items": [None, None], "expected": "2"}, + ] + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", + http_client=async_client, + ) + + # call API + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": "what is the current date and time?", + } + ], + model="General Purpose", + ) + print(chat_completion) + + for idx, case in enumerate(test_cases): + prompt: str = build_prompt(case["items"]) + print(f"\nSending prompt to Bedrock: {prompt}") + + # call API + chat_completion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": prompt, + } + ], + model="General Purpose", + ) + + print(chat_completion) diff --git a/tests/gateway/tools/test_chat_calculator_stddev.py b/tests/gateway/tools/test_chat_calculator_stddev.py new file mode 100644 index 000000000..622f72b90 --- /dev/null +++ b/tests/gateway/tools/test_chat_calculator_stddev.py @@ -0,0 +1,101 @@ +import logging + +import httpx +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion +from typing import List, Dict, Any + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__file__) + + +def build_prompt(numbers: List[float]) -> str: + if not numbers: + return "Calculate the standard deviation of: " + return f"Calculate the standard deviation of: {', '.join(map(str, numbers))}" + + +async def test_chat_calculator_stddev_tool_bedrock( + async_client: httpx.AsyncClient, +) -> None: + print("") + print("") + test_container: SimpleContainer = await get_container_async() + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig(name="calculator_stddev"), + ], + ) + ] + ) + + test_cases: List[Dict[str, Any]] = [ + {"numbers": [10, 20, 30], "expected": "8.16"}, + {"numbers": [42], "expected": "Standard deviation of a single number is: 0.0"}, + {"numbers": [], "expected": "No numbers provided"}, + {"numbers": [1.5, 2.5, 3.0], "expected": "0.62"}, + {"numbers": [-10, 0, 10], "expected": "8.16"}, + ] + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", + http_client=async_client, + ) + + # call API + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": "what is the current date and time?", + } + ], + model="General Purpose", + ) + print(chat_completion) + + for idx, case in enumerate(test_cases): + prompt: str = build_prompt(case["numbers"]) + print(f"\nSending prompt to Bedrock: {prompt}") + + # call API + chat_completion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": prompt, + } + ], + model="General Purpose", + ) + + print(chat_completion) diff --git a/tests/gateway/tools/test_chat_calculator_sum.py b/tests/gateway/tools/test_chat_calculator_sum.py new file mode 100644 index 000000000..f5296f70f --- /dev/null +++ b/tests/gateway/tools/test_chat_calculator_sum.py @@ -0,0 +1,101 @@ +import logging + +import httpx +from openai import AsyncOpenAI +from openai.types.chat import ChatCompletion +from typing import List, Dict, Any + +from language_model_gateway.configs.config_schema import ( + ChatModelConfig, + ModelConfig, + AgentConfig, +) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) +from language_model_gateway.container.simple_container import SimpleContainer +from language_model_gateway.gateway.api_container import get_container_async + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__file__) + + +def build_prompt(numbers: List[float]) -> str: + if not numbers: + return "Calculate the sum of: " + return f"Calculate the sum of: {', '.join(map(str, numbers))}" + + +async def test_chat_calculator_sum_tool_bedrock( + async_client: httpx.AsyncClient, +) -> None: + print("") + print("") + test_container: SimpleContainer = await get_container_async() + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig(name="calculator_sum"), + ], + ) + ] + ) + + test_cases: List[Dict[str, Any]] = [ + {"numbers": [10, 20, 30], "expected": "60.0"}, + {"numbers": [42], "expected": "42.0"}, + {"numbers": [], "expected": "No numbers provided"}, + {"numbers": [1.5, 2.5, 3.0], "expected": "7.0"}, + {"numbers": [-10, 0, 10], "expected": "0.0"}, + ] + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", + http_client=async_client, + ) + + # call API + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": "what is the current date and time?", + } + ], + model="General Purpose", + ) + print(chat_completion) + + for idx, case in enumerate(test_cases): + prompt: str = build_prompt(case["numbers"]) + print(f"\nSending prompt to Bedrock: {prompt}") + + # call API + chat_completion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": prompt, + } + ], + model="General Purpose", + ) + + print(chat_completion) diff --git a/tests/gateway/tools/test_chat_diagram_generator.py b/tests/gateway/tools/test_chat_diagram_generator.py index be9d72d3b..5b8771356 100644 --- a/tests/gateway/tools/test_chat_diagram_generator.py +++ b/tests/gateway/tools/test_chat_diagram_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_diagram_generator(async_client: httpx.AsyncClient) -> None: ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_er_diagram_generator.py b/tests/gateway/tools/test_chat_er_diagram_generator.py index fba134f66..97f684ac1 100644 --- a/tests/gateway/tools/test_chat_er_diagram_generator.py +++ b/tests/gateway/tools/test_chat_er_diagram_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_er_diagram_generator(async_client: httpx.AsyncClient) -> Non ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_flow_chart_generator.py b/tests/gateway/tools/test_chat_flow_chart_generator.py index db27d2fac..dec5af228 100644 --- a/tests/gateway/tools/test_chat_flow_chart_generator.py +++ b/tests/gateway/tools/test_chat_flow_chart_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_flow_chart_generator(async_client: httpx.AsyncClient) -> Non ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_network_topology_diagram_generator.py b/tests/gateway/tools/test_chat_network_topology_diagram_generator.py index 294d87e30..5e734d09e 100644 --- a/tests/gateway/tools/test_chat_network_topology_diagram_generator.py +++ b/tests/gateway/tools/test_chat_network_topology_diagram_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -47,8 +49,8 @@ async def test_chat_network_topology_diagram_generator( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -163,8 +165,8 @@ async def test_chat_network_topology_diagram_generator_markdown( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_openai_image_generator.py b/tests/gateway/tools/test_chat_openai_image_generator.py index f552bc91a..f102cb07f 100644 --- a/tests/gateway/tools/test_chat_openai_image_generator.py +++ b/tests/gateway/tools/test_chat_openai_image_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_openai_image_generator(async_client: httpx.AsyncClient) -> N ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -123,8 +125,8 @@ async def test_chat_anthropic_image_generator_streaming( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_provider_search.py b/tests/gateway/tools/test_chat_provider_search.py index fb534271b..e1934427c 100644 --- a/tests/gateway/tools/test_chat_provider_search.py +++ b/tests/gateway/tools/test_chat_provider_search.py @@ -2,7 +2,11 @@ import httpx from openai import AsyncOpenAI, AsyncStream -from openai.types.chat import ChatCompletionChunk, ChatCompletion +from openai.types.chat import ( + ChatCompletionChunk, + ChatCompletion, + ChatCompletionUserMessageParam, +) from openai.types.chat.chat_completion import Choice from language_model_gateway.configs.config_schema import ( @@ -10,6 +14,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +26,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +51,8 @@ async def test_chat_provider_search(async_client: httpx.AsyncClient) -> None: ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -78,13 +84,12 @@ async def test_chat_provider_search(async_client: httpx.AsyncClient) -> None: ) # call API + message: ChatCompletionUserMessageParam = { + "role": "user", + "content": "Get me the address of Dr. Scott Rodriguez", + } chat_completion: ChatCompletion = await client.chat.completions.create( - messages=[ - { - "role": "user", - "content": "Get me the address of Dr. Scott Rodriguez", - } - ], + messages=[message], model="General Purpose", ) @@ -125,8 +130,8 @@ async def test_chat_provider_search_streaming( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_chat_sequence_diagram_generator.py b/tests/gateway/tools/test_chat_sequence_diagram_generator.py index 3a14c053d..5c6e70535 100644 --- a/tests/gateway/tools/test_chat_sequence_diagram_generator.py +++ b/tests/gateway/tools/test_chat_sequence_diagram_generator.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -19,7 +22,6 @@ from language_model_gateway.gateway.utilities.environment_reader import ( EnvironmentReader, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_image_generator import MockImageGenerator from tests.gateway.mocks.mock_image_generator_factory import MockImageGeneratorFactory @@ -45,8 +47,8 @@ async def test_chat_sequence_diagram_generator(async_client: httpx.AsyncClient) ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_databricks_sql_tool.py b/tests/gateway/tools/test_databricks_sql_tool.py new file mode 100644 index 000000000..357f17181 --- /dev/null +++ b/tests/gateway/tools/test_databricks_sql_tool.py @@ -0,0 +1,176 @@ +import pytest +from unittest.mock import Mock + +from language_model_gateway.gateway.tools.databricks_sql_tool import DatabricksSQLTool +from language_model_gateway.gateway.tools.databricks_sql_tool import DatabricksSQLInput +from language_model_gateway.gateway.utilities.databricks.databricks_helper import ( + DatabricksHelper, +) + + +@pytest.fixture +def mock_databricks_helper() -> Mock: + """Fixture to create a mock DatabricksHelper""" + return Mock(spec=DatabricksHelper) + + +@pytest.fixture +def databricks_sql_tool(mock_databricks_helper: Mock) -> DatabricksSQLTool: + """Fixture to create a DatabricksSQLTool instance""" + return DatabricksSQLTool(databricks_helper=mock_databricks_helper) + + +@pytest.mark.asyncio +async def test_databricks_sql_tool_successful_query( + databricks_sql_tool: DatabricksSQLTool, mock_databricks_helper: Mock +) -> None: + """ + Test successful query execution + """ + # Arrange + test_query = "SELECT * FROM patients LIMIT 10" + mock_result = "| id | name |\n| --- | --- |\n| 1 | John Doe |" + mock_databricks_helper.execute_query.return_value = mock_result + + # Act + result, artifact = await databricks_sql_tool._arun(test_query) + + # Assert + assert result == mock_result + assert "DatabricksSQLTool: Query Results" in artifact + mock_databricks_helper.execute_query.assert_called_once_with(test_query) + + +@pytest.mark.asyncio +async def test_databricks_sql_tool_empty_query( + databricks_sql_tool: DatabricksSQLTool, mock_databricks_helper: Mock +) -> None: + """ + Test query with empty input + """ + # Arrange + test_query = "" + + # Act & Assert + with pytest.raises(ValueError): + await databricks_sql_tool._arun(test_query) + + +@pytest.mark.asyncio +async def test_databricks_sql_tool_error_handling( + databricks_sql_tool: DatabricksSQLTool, mock_databricks_helper: Mock +) -> None: + """ + Test error handling during query execution + """ + # Arrange + test_query = "SELECT * FROM non_existent_table" + mock_error_result = "Error executing Databricks query: Table not found" + mock_databricks_helper.execute_query.return_value = mock_error_result + + # Act + result, artifact = await databricks_sql_tool._arun(test_query) + + # Assert + assert result == mock_error_result + assert "DatabricksSQLTool: Query Results" in artifact + mock_databricks_helper.execute_query.assert_called_once_with(test_query) + + +@pytest.mark.parametrize( + "query", + [ + "SELECT * FROM patients LIMIT 10", + "GET demographics of patients", + "Find all patients with diabetes diagnosis", + ], +) +@pytest.mark.asyncio +async def test_databricks_sql_tool_multiple_queries( + databricks_sql_tool: DatabricksSQLTool, mock_databricks_helper: Mock, query: str +) -> None: + """ + Parameterized test for multiple query types + """ + # Arrange + mock_result = f"| Result for query: {query} |" + mock_databricks_helper.execute_query.return_value = mock_result + + # Act + result, artifact = await databricks_sql_tool._arun(query) + + # Assert + assert result == mock_result + assert "DatabricksSQLTool: Query Results" in artifact + mock_databricks_helper.execute_query.assert_called_once_with(query) + + +def test_databricks_sql_tool_response_format( + databricks_sql_tool: DatabricksSQLTool, +) -> None: + """ + Test the response format of the tool + """ + # Assert + assert databricks_sql_tool.response_format == "content_and_artifact" + + +def test_databricks_sql_tool_description() -> None: + """ + Test the tool's description + """ + tool = DatabricksSQLTool(databricks_helper=Mock(spec=DatabricksHelper)) + + # Assert + assert "A tool for querying FHIR data from Databricks" in tool.description + assert "USAGE TIPS" in tool.description + assert "limit" in tool.description + assert "Example queries" in tool.description + + +def test_databricks_sql_input_model() -> None: + """ + Test the DatabricksSQLInput Pydantic model + """ + # Test with valid input + valid_input = DatabricksSQLInput(fhir_request="SELECT * FROM patients") + assert valid_input.fhir_request == "SELECT * FROM patients" + + # Test with None input + none_input = DatabricksSQLInput() + assert none_input.fhir_request is None + + +def test_databricks_sql_tool_name() -> None: + """ + Test the tool's name + """ + tool = DatabricksSQLTool(databricks_helper=Mock(spec=DatabricksHelper)) + + # Assert + assert tool.name == "databricks_tool" + + +@pytest.mark.asyncio +async def test_databricks_sql_tool_sync_run_not_implemented( + databricks_sql_tool: DatabricksSQLTool, +) -> None: + """ + Test that the synchronous _run method raises NotImplementedError + """ + # Act & Assert + with pytest.raises(NotImplementedError, match="Use async version of this tool"): + databricks_sql_tool._run(fhir_request="test query") + + +@pytest.mark.parametrize("input_query", [None, "", " "]) +@pytest.mark.asyncio +async def test_databricks_sql_tool_empty_or_none_input( + databricks_sql_tool: DatabricksSQLTool, input_query: str +) -> None: + """ + Test handling of empty or None input + """ + # Act & Assert + with pytest.raises(ValueError, match="Query cannot be empty or None"): + await databricks_sql_tool._arun(input_query) diff --git a/tests/gateway/tools/test_github_pull_request_analyzer_tool.py b/tests/gateway/tools/test_github_pull_request_analyzer_tool.py index a4d184dde..ca027ae4e 100644 --- a/tests/gateway/tools/test_github_pull_request_analyzer_tool.py +++ b/tests/gateway/tools/test_github_pull_request_analyzer_tool.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -22,7 +25,6 @@ from language_model_gateway.gateway.utilities.environment_variables import ( EnvironmentVariables, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_environment_variables import MockEnvironmentVariables from tests.gateway.mocks.mock_image_generator import MockImageGenerator @@ -52,8 +54,8 @@ async def test_github_pull_request_analyzer_tool( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -83,6 +85,7 @@ async def test_github_pull_request_analyzer_tool( api_key="fake-api-key", base_url="http://localhost:5000/api/v1", # change the default port if needed http_client=async_client, + default_headers={"Authorization": "Bearer fake-api-key"}, ) # call API @@ -131,8 +134,8 @@ async def test_github_pull_request_analyzer_tool_streaming( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -162,6 +165,7 @@ async def test_github_pull_request_analyzer_tool_streaming( api_key="fake-api-key", base_url="http://localhost:5000/api/v1", # change the default port if needed http_client=async_client, + default_headers={"Authorization": "Bearer fake-api-key"}, ) # call API @@ -218,8 +222,8 @@ async def test_github_pull_request_analyzer_full_details_tool( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -249,6 +253,7 @@ async def test_github_pull_request_analyzer_full_details_tool( api_key="fake-api-key", base_url="http://localhost:5000/api/v1", # change the default port if needed http_client=async_client, + default_headers={"Authorization": "Bearer fake-api-key"}, ) # call API @@ -256,7 +261,7 @@ async def test_github_pull_request_analyzer_full_details_tool( messages=[ { "role": "user", - "content": "List all the pull requests with title and author for the helix.pipelines repository for past 3 months", + "content": "List all the pull requests with title, author and description for the helix.pipelines repository for past 3 months", } ], model="General Purpose", diff --git a/tests/gateway/tools/test_github_pull_request_diff_tool.py b/tests/gateway/tools/test_github_pull_request_diff_tool.py index 13a096863..08aaf5787 100644 --- a/tests/gateway/tools/test_github_pull_request_diff_tool.py +++ b/tests/gateway/tools/test_github_pull_request_diff_tool.py @@ -12,6 +12,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.models.model_factory import ModelFactory @@ -21,14 +24,13 @@ from language_model_gateway.gateway.utilities.environment_variables import ( EnvironmentVariables, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_environment_variables import MockEnvironmentVariables from tests.gateway.mocks.mock_model_factory import MockModelFactory @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_github_pull_request_diff_tool(async_client: httpx.AsyncClient) -> None: print("") @@ -49,8 +51,8 @@ async def test_github_pull_request_diff_tool(async_client: httpx.AsyncClient) -> ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -109,7 +111,7 @@ async def test_github_pull_request_diff_tool(async_client: httpx.AsyncClient) -> @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_github_pull_request_diff_combined_tool( async_client: httpx.AsyncClient, @@ -131,8 +133,8 @@ async def test_github_pull_request_diff_combined_tool( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ diff --git a/tests/gateway/tools/test_jira_issues_analyzer_tool.py b/tests/gateway/tools/test_jira_issues_analyzer_tool.py index 029965b18..ba034452a 100644 --- a/tests/gateway/tools/test_jira_issues_analyzer_tool.py +++ b/tests/gateway/tools/test_jira_issues_analyzer_tool.py @@ -10,6 +10,9 @@ ModelConfig, AgentConfig, ) +from language_model_gateway.gateway.utilities.cache.config_expiring_cache import ( + ConfigExpiringCache, +) from language_model_gateway.container.simple_container import SimpleContainer from language_model_gateway.gateway.api_container import get_container_async from language_model_gateway.gateway.image_generation.image_generator_factory import ( @@ -22,7 +25,6 @@ from language_model_gateway.gateway.utilities.environment_variables import ( EnvironmentVariables, ) -from language_model_gateway.gateway.utilities.expiring_cache import ExpiringCache from tests.gateway.mocks.mock_chat_model import MockChatModel from tests.gateway.mocks.mock_environment_variables import MockEnvironmentVariables from tests.gateway.mocks.mock_image_generator import MockImageGenerator @@ -52,8 +54,8 @@ async def test_jira_issues_analyzer_tool( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -131,8 +133,8 @@ async def test_jira_issues_analyzer_tool_streaming( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -218,8 +220,8 @@ async def test_jira_issues_analyzer_full_details_tool( ) # set the model configuration for this test - model_configuration_cache: ExpiringCache[List[ChatModelConfig]] = ( - test_container.resolve(ExpiringCache) + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache ) await model_configuration_cache.set( [ @@ -256,7 +258,7 @@ async def test_jira_issues_analyzer_full_details_tool( messages=[ { "role": "user", - "content": "Get full details of the jira issues for the EFS project for past 3 months", + "content": "Get full details of the jira issues for the EFS project for past 3 months sort by updated. Use verbose logging.", } ], model="General Purpose", @@ -276,3 +278,84 @@ async def test_jira_issues_analyzer_full_details_tool( print("====== End of Final Content ======") assert "EFS" in content # assert "data:image/png;base64" in content + + +async def test_jira_issues_analyzer_tool_all_projects( + async_client: httpx.AsyncClient, +) -> None: + print("") + + test_container: SimpleContainer = await get_container_async() + + if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + test_container.register( + EnvironmentVariables, lambda c: MockEnvironmentVariables() + ) + + test_container.register( + ModelFactory, + lambda c: MockModelFactory( + fn_get_model=lambda chat_model_config: MockChatModel( + fn_get_response=lambda messages: "EFS" + ) + ), + ) + + # set the model configuration for this test + model_configuration_cache: ConfigExpiringCache = test_container.resolve( + ConfigExpiringCache + ) + await model_configuration_cache.set( + [ + ChatModelConfig( + id="general_purpose", + name="General Purpose", + description="General Purpose Language Model", + type="langchain", + model=ModelConfig( + provider="bedrock", + model="us.anthropic.claude-3-5-haiku-20241022-v1:0", + ), + tools=[ + AgentConfig(name="current_date"), + AgentConfig(name="jira_issues_analyzer"), + ], + ) + ] + ) + + # Test health endpoint + # response = await async_client.get("/health") + # assert response.status_code == 200 + + # init client and connect to localhost server + client = AsyncOpenAI( + api_key="fake-api-key", + base_url="http://localhost:5000/api/v1", # change the default port if needed + http_client=async_client, + ) + + # call API + chat_completion: ChatCompletion = await client.chat.completions.create( + messages=[ + { + "role": "user", + "content": "Get the jira issues per assignee for past 1 month for all projects", + } + ], + model="General Purpose", + ) + + print(chat_completion) + + # print the top "choice" + choices: List[Choice] = chat_completion.choices + print(choices) + content: Optional[str] = ",".join( + [choice.message.content or "" for choice in choices] + ) + assert content is not None + print("======== Final Content ========") + print(content) + print("====== End of Final Content ======") + assert "EFS" in content diff --git a/tests/gateway/utilities/databricks/__init__.py b/tests/gateway/utilities/databricks/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/gateway/utilities/databricks/test_databricks_helper.py b/tests/gateway/utilities/databricks/test_databricks_helper.py new file mode 100644 index 000000000..b8567f120 --- /dev/null +++ b/tests/gateway/utilities/databricks/test_databricks_helper.py @@ -0,0 +1,115 @@ +import os +import pytest +import pandas as pd +from typing import Dict, Generator +from unittest.mock import Mock, patch, MagicMock + +from language_model_gateway.gateway.utilities.databricks.databricks_helper import ( + DatabricksHelper, +) + + +@pytest.fixture +def databricks_helper() -> DatabricksHelper: + """Fixture to create a DatabricksHelper instance for testing""" + databricks_helper = Mock(spec=DatabricksHelper) + databricks_helper.catalog = "bronze" + databricks_helper.schema = "fhir_rpt" + databricks_helper.logger = Mock() + return databricks_helper + + +@pytest.fixture +def mock_workspace_client( + mock_env_vars: Dict[str, str], +) -> Generator[MagicMock, None, None]: + """Fixture to mock WorkspaceClient with comprehensive mocking""" + with patch( + "language_model_gateway.gateway.utilities.databricks.databricks_helper.WorkspaceClient" + ) as mock_client: + # Create a mock client instance + mock_instance = MagicMock() + mock_client.return_value = mock_instance + + # Create a mock SQL warehouse with a custom execute method + mock_sql_warehouse = MagicMock() + + # Create a mock result that mimics the structure of a Databricks SQL result + mock_result = MagicMock() + mock_result.rows = [{"column1": "value1", "column2": "value2"}] + + # Configure the execute method to either raise an exception or return a result + def mock_execute() -> MagicMock: + # Simulate a long-running query by checking the current time + current_time = os.environ.get("MOCK_CURRENT_TIME", 2) + if float(current_time) > 1: + raise Exception("Simulated long-running query") + return mock_result + + mock_sql_warehouse.execute = MagicMock(side_effect=mock_execute) + mock_instance.sql = mock_sql_warehouse + + yield mock_client + + +@pytest.fixture +def mock_env_vars() -> Generator[Dict[str, str], None, None]: + """Fixture to set up comprehensive mock environment variables for Databricks""" + original_env = os.environ.copy() + try: + # Set all required environment variables + env_vars = { + "DATABRICKS_HOST": "https://mock-databricks-host.cloud.databricks.com", + "DATABRICKS_TOKEN": "mock-token", + "DATABRICKS_SQL_WAREHOUSE_ID": "12345", + } + + # Update environment with mock variables + for key, value in env_vars.items(): + os.environ[key] = value + + yield env_vars + finally: + # Restore original environment + os.environ.clear() + os.environ.update(original_env) + + +def test_init(databricks_helper: DatabricksHelper) -> None: + """Test the initialization of DatabricksHelper""" + assert databricks_helper.catalog == "bronze" + assert databricks_helper.schema == "fhir_rpt" + assert databricks_helper.logger is not None + + +def test_parse_databricks_statement_response() -> None: + """Test parsing of Databricks statement response""" + # Create a mock StatementResponse + mock_schema = Mock() + mock_schema.columns = [Mock(name="column1"), Mock(name="column2")] + mock_manifest = Mock() + mock_manifest.schema = mock_schema + + mock_statement_response = Mock( + manifest=mock_manifest, + result=Mock(data_array=[["value1", "value2"], ["value3", "value4"]]), + ) + + helper = DatabricksHelper() + result_df = helper.parse_databricks_statement_response(mock_statement_response) + + assert isinstance(result_df, pd.DataFrame) + assert result_df.shape == (2, 2) + + +def test_dataframe_to_markdown() -> None: + """Test conversion of DataFrame to markdown""" + df = pd.DataFrame({"Name": ["Alice", "Bob"], "Age": [30, 25]}) + + helper = DatabricksHelper() + markdown_table = helper.dataframe_to_markdown(df) + + assert "| Name | Age |" in markdown_table + assert "| --- | --- |" in markdown_table + assert "| Alice | 30 |" in markdown_table + assert "| Bob | 25 |" in markdown_table diff --git a/tests/gateway/utilities/github/test_github_get_pull_request_diff.py b/tests/gateway/utilities/github/test_github_get_pull_request_diff.py index f7f703fd2..ed93803d7 100644 --- a/tests/gateway/utilities/github/test_github_get_pull_request_diff.py +++ b/tests/gateway/utilities/github/test_github_get_pull_request_diff.py @@ -24,7 +24,7 @@ @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_github_get_pull_request_diff( async_client: httpx.AsyncClient, httpx_mock: HTTPXMock diff --git a/tests/gateway/utilities/github/test_github_get_summarized_pull_requests.py b/tests/gateway/utilities/github/test_github_get_summarized_pull_requests.py index eef5f4e5d..e1e3d5008 100644 --- a/tests/gateway/utilities/github/test_github_get_summarized_pull_requests.py +++ b/tests/gateway/utilities/github/test_github_get_summarized_pull_requests.py @@ -27,11 +27,14 @@ from language_model_gateway.gateway.utilities.github.github_pull_request_per_contributor_info import ( GithubPullRequestPerContributorInfo, ) +from language_model_gateway.gateway.utilities.github.github_pull_request_result import ( + GithubPullRequestResult, +) from tests.gateway.mocks.mock_environment_variables import MockEnvironmentVariables @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> None: print() @@ -42,6 +45,7 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non makedirs(temp_folder) max_repos = 2 + max_pull_requests = 10 test_container: SimpleContainer = await get_container_async() @@ -71,11 +75,9 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non # org_name = "icanbwell" repo_name = "helix.pipelines" - # repos_url = f"https://api.github.com/repos/{org_name}/{repo_name}" - repos_url = f"https://api.github.com/orgs/{org_name}/repos?type=all&sort=pushed&direction=desc&per_page={max_repos}&page=1" httpx_mock.add_response( - url=repos_url, + url=f"https://api.github.com/orgs/{org_name}/repos?type=all&sort=pushed&direction=desc&per_page={max_repos}&page=1", method="GET", headers={ "Authorization": f"Bearer {access_token}", @@ -87,10 +89,7 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non status_code=200, ) - # mock pull API - pull_url: str = ( - f"https://api.github.com/repos/{org_name}/{repo_name}/pulls?state=closed&sort=created&direction=desc" - ) + # mock pull API for first repo sample_pull_content: List[Dict[str, Any]] = [ { "url": "https://api.github.com/repos/icanbwell/helix.pipelines/pulls/1", @@ -116,7 +115,9 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non }, ] httpx_mock.add_response( - url=pull_url, + url=( + f"https://api.github.com/repos/{org_name}/{repo_name}/pulls?state=closed&sort=created&direction=desc&per_page={max_pull_requests}&page=1" + ), method="GET", headers={ "Authorization": f"Bearer {access_token}", @@ -125,10 +126,20 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non content=json.dumps(sample_pull_content).encode(), status_code=200, ) - pull_url = f"https://api.github.com/repos/{org_name}/foo/pulls?state=closed&sort=created&direction=desc" + httpx_mock.add_response( + url=f"https://api.github.com/repos/{org_name}/{repo_name}/pulls?state=closed&sort=created&direction=desc&per_page={max_pull_requests}&page=2", + method="GET", + headers={ + "Authorization": f"Bearer {access_token}", + "Accept": "application/vnd.github+json", + }, + content=json.dumps([]).encode(), + status_code=200, + ) + # now pull requests from second repo sample_pull_content = [] httpx_mock.add_response( - url=pull_url, + url=f"https://api.github.com/repos/{org_name}/foo/pulls?state=closed&sort=created&direction=desc&per_page={max_pull_requests}&page=1", method="GET", headers={ "Authorization": f"Bearer {access_token}", @@ -155,14 +166,15 @@ async def test_github_get_summarized_pull_requests(httpx_mock: HTTPXMock) -> Non ) # Get PR counts with optional parameters - pull_requests: List[GithubPullRequest] = await pr_counter.retrieve_closed_prs( + pull_request_result: GithubPullRequestResult = await pr_counter.retrieve_closed_prs( max_repos=max_repos, # Optional: limit repositories - max_pull_requests=200, # Optional: limit PRs + max_pull_requests=max_pull_requests, # Optional: limit PRs min_created_at=datetime( 2024, 9, 1, tzinfo=timezone.utc ), # Optional: minimum created date include_merged=True, # Include merged PRs ) + pull_requests: List[GithubPullRequest] = pull_request_result.pull_requests pr_counts: Dict[str, GithubPullRequestPerContributorInfo] = ( pr_counter.summarize_prs_by_engineer(pull_requests=pull_requests) ) diff --git a/tests/gateway/utilities/github/test_github_get_summarized_pull_requests_from_one_repo.py b/tests/gateway/utilities/github/test_github_get_summarized_pull_requests_from_one_repo.py index e5aeb600b..35dd90d96 100644 --- a/tests/gateway/utilities/github/test_github_get_summarized_pull_requests_from_one_repo.py +++ b/tests/gateway/utilities/github/test_github_get_summarized_pull_requests_from_one_repo.py @@ -27,11 +27,14 @@ from language_model_gateway.gateway.utilities.github.github_pull_request_per_contributor_info import ( GithubPullRequestPerContributorInfo, ) +from language_model_gateway.gateway.utilities.github.github_pull_request_result import ( + GithubPullRequestResult, +) from tests.gateway.mocks.mock_environment_variables import MockEnvironmentVariables @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_github_get_summarized_pull_requests_from_one_repo( httpx_mock: HTTPXMock, @@ -45,6 +48,8 @@ async def test_github_get_summarized_pull_requests_from_one_repo( test_container: SimpleContainer = await get_container_async() + max_pull_requests = 2 + max_repos = 2 if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): org_name: str = "icanbwell" access_token: Optional[str] = "fake_token" @@ -79,9 +84,7 @@ async def test_github_get_summarized_pull_requests_from_one_repo( ) # mock pull API - pull_url: str = ( - f"https://api.github.com/repos/{org_name}/{repo_name}/pulls?state=closed&sort=created&direction=desc" - ) + pull_url: str = f"https://api.github.com/repos/{org_name}/{repo_name}/pulls?state=closed&sort=created&direction=desc&per_page={max_pull_requests}&page=1" sample_pull_content: List[Dict[str, Any]] = [ { "url": "https://api.github.com/repos/icanbwell/helix.pipelines/pulls/1", @@ -98,7 +101,7 @@ async def test_github_get_summarized_pull_requests_from_one_repo( "url": "https://api.github.com/repos/icanbwell/helix.pipelines/pulls/2", "html_url": "", "diff_url": "", - "number": 2, + "number": max_repos, "state": "closed", "title": "PR 2", "user": {"login": "user2"}, @@ -132,17 +135,19 @@ async def test_github_get_summarized_pull_requests_from_one_repo( ) try: - # Get PR counts with optional parameters - pull_requests: List[GithubPullRequest] = await pr_counter.retrieve_closed_prs( - max_repos=2, # Optional: limit repositories - max_pull_requests=200, # Optional: limit PRs - min_created_at=datetime( - 2024, 9, 1, tzinfo=timezone.utc - ), # Optional: minimum created date - include_merged=True, # Include merged PRs - repo_name="helix.pipelines", + pull_request_result: GithubPullRequestResult = ( + await pr_counter.retrieve_closed_prs( + max_repos=max_repos, # Optional: limit repositories + max_pull_requests=max_pull_requests, # Optional: limit PRs + min_created_at=datetime( + 2024, 9, 1, tzinfo=timezone.utc + ), # Optional: minimum created date + include_merged=True, # Include merged PRs + repo_name="helix.pipelines", + ) ) + pull_requests: List[GithubPullRequest] = pull_request_result.pull_requests pr_counts: Dict[str, GithubPullRequestPerContributorInfo] = ( pr_counter.summarize_prs_by_engineer(pull_requests=pull_requests) ) diff --git a/tests/gateway/utilities/jira/test_jira_issues_helper.py b/tests/gateway/utilities/jira/test_jira_issues_helper.py index ece4fe127..d7ba81fe0 100644 --- a/tests/gateway/utilities/jira/test_jira_issues_helper.py +++ b/tests/gateway/utilities/jira/test_jira_issues_helper.py @@ -22,6 +22,9 @@ JiraIssuesPerAssigneeInfo, ) from language_model_gateway.gateway.utilities.jira.jira_issue import JiraIssue +from language_model_gateway.gateway.utilities.jira.jira_issue_result import ( + JiraIssueResult, +) from language_model_gateway.gateway.utilities.jira.jira_issues_helper import ( JiraIssueHelper, ) @@ -29,7 +32,7 @@ @pytest.mark.httpx_mock( - should_mock=lambda request: os.environ["RUN_TESTS_WITH_REAL_LLM"] != "1" + should_mock=lambda request: os.environ.get("RUN_TESTS_WITH_REAL_LLM") != "1" ) async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: print() @@ -44,6 +47,7 @@ async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: test_container: SimpleContainer = await get_container_async() if not EnvironmentReader.is_environment_variable_set("RUN_TESTS_WITH_REAL_LLM"): + os.environ["JIRA_USERNAME"] = "dummy_username" jira_base_url: str = "https://icanbwell.atlassian.net" access_token: Optional[str] = "fake_token" test_container.register( @@ -51,12 +55,13 @@ async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: ) # Mock Jira search API response - search_url = f"{jira_base_url}/rest/api/3/search?jql=status+%3D+Closed+AND+created+%3E%3D+%272024-09-01%27&startAt=0&maxResults=2&fields=summary&fields=status&fields=created&fields=resolutiondate&fields=assignee&fields=project" + search_url = f"{jira_base_url}/rest/api/3/search/jql" sample_issues_content: Dict[str, Any] = { "total": 2, "issues": [ { "key": "PROJECT-1", + "self": "http://foo/PROJECT-1", "fields": { "summary": "First test issue", "status": {"name": "Closed"}, @@ -68,6 +73,7 @@ async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: }, { "key": "PROJECT-2", + "self": "http://foo/PROJECT-2", "fields": { "summary": "Second test issue", "status": {"name": "Closed"}, @@ -82,7 +88,7 @@ async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( url=search_url, - method="GET", + method="POST", headers={ "Authorization": f"Bearer {access_token}", "Content-Type": "application/json", @@ -114,13 +120,19 @@ async def test_jira_get_summarized_issues(httpx_mock: HTTPXMock) -> None: max_issues = 2 # Get issue counts with optional parameters - issues: List[JiraIssue] = await issue_helper.retrieve_closed_issues( + jira_issue_result: JiraIssueResult = await issue_helper.retrieve_closed_issues( max_projects=max_projects, # Optional: limit projects max_issues=max_issues, # Optional: limit issues min_created_at=datetime( 2024, 9, 1, tzinfo=timezone.utc ), # Optional: minimum created date + include_full_description=True, ) + issues: List[JiraIssue] = jira_issue_result.issues + + assert jira_issue_result.error is None + + assert len(issues) > 0, jira_issue_result.error print("========== Issues ========") for issue in issues: