From f6c9757360604711416759dde3338b5ccfc1b809 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:29 +0000 Subject: [PATCH 01/13] chore(deps): Bump docker/metadata-action from 5.0.0 to 5.5.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.0.0 to 5.5.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.0.0...v5.5.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 821b9aa5..146eb62d 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -102,7 +102,7 @@ jobs: - name: Container meta id: meta - uses: docker/metadata-action@v5.0.0 + uses: docker/metadata-action@v5.5.0 with: images: ${{ env.CONTAINER_REGISTRY_GHCR }}/${{ env.CONTAINER_NAME }} tags: | From 1d762a72341b8c60fe4741e03815df0a08caa94a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:32 +0000 Subject: [PATCH 02/13] chore(deps): Bump fastapi from 0.108.0 to 0.109.0 Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.108.0 to 0.109.0. - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.108.0...0.109.0) --- updated-dependencies: - dependency-name: fastapi dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 44b1942b..3dfb171b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ azure-communication-sms==1.0.1 azure-eventgrid==4.16.0 azure-identity==1.15.0 azure-mgmt-eventgrid==10.2.0 -fastapi==0.108.0 +fastapi==0.109.0 openai==1.7.0 phonenumbers==8.13.27 pydantic-extra-types==2.4.0 From 24bed7ae989db43dcd8a759e5dd6a2e08ca9051d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:33 +0000 Subject: [PATCH 03/13] chore(deps): Bump docker/build-push-action from 5.0.0 to 5.1.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.0.0...v5.1.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 821b9aa5..8425a225 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -125,7 +125,7 @@ jobs: echo "tag=$tag" >> $GITHUB_OUTPUT - name: Build/push container - uses: docker/build-push-action@v5.0.0 + uses: docker/build-push-action@v5.1.0 with: build-args: | VERSION=${{ needs.init.outputs.VERSION_FULL }} From 180d238f9b794f68cc9ebc46a4e85c65b4e9fb6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:37 +0000 Subject: [PATCH 04/13] chore(deps): Bump openai from 1.7.0 to 1.7.1 Bumps [openai](https://github.com/openai/openai-python) from 1.7.0 to 1.7.1. - [Release notes](https://github.com/openai/openai-python/releases) - [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md) - [Commits](https://github.com/openai/openai-python/compare/v1.7.0...v1.7.1) --- updated-dependencies: - dependency-name: openai dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 44b1942b..73365bbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ azure-eventgrid==4.16.0 azure-identity==1.15.0 azure-mgmt-eventgrid==10.2.0 fastapi==0.108.0 -openai==1.7.0 +openai==1.7.1 phonenumbers==8.13.27 pydantic-extra-types==2.4.0 python-dotenv==1.0.0 From 84e7d500448574c850280ee28693daf9ec974981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:41 +0000 Subject: [PATCH 05/13] chore(deps): Bump trufflesecurity/trufflehog from 3.63.1 to 3.63.8 Bumps [trufflesecurity/trufflehog](https://github.com/trufflesecurity/trufflehog) from 3.63.1 to 3.63.8. - [Release notes](https://github.com/trufflesecurity/trufflehog/releases) - [Changelog](https://github.com/trufflesecurity/trufflehog/blob/main/.goreleaser.yml) - [Commits](https://github.com/trufflesecurity/trufflehog/compare/v3.63.1...v3.63.8) --- updated-dependencies: - dependency-name: trufflesecurity/trufflehog dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 821b9aa5..b4fe6fd5 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -56,7 +56,7 @@ jobs: submodules: recursive - name: SAST - Credentials - uses: trufflesecurity/trufflehog@v3.63.1 + uses: trufflesecurity/trufflehog@v3.63.8 with: base: ${{ github.event.repository.default_branch }} extra_args: --only-verified From c2318796554a2ab7d9692de5e7ba98fdeefc72a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 12:59:46 +0000 Subject: [PATCH 06/13] chore(deps): Bump github/codeql-action from 2.22.8 to 3.23.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.8 to 3.23.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2.22.8...v3.23.0) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index 821b9aa5..2efb606e 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -159,7 +159,7 @@ jobs: run: semgrep ci --sarif --output=semgrep.sarif - name: Upload results to GitHub Security - uses: github/codeql-action/upload-sarif@v2.22.8 + uses: github/codeql-action/upload-sarif@v3.23.0 with: sarif_file: semgrep.sarif From d15f38c4ded253c586b01295d7c3d35120c2c739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:20:57 +0100 Subject: [PATCH 07/13] Revert "Merge remote-tracking branch 'origin/dependabot/pip/develop/fastapi-0.109.0' into develop" This reverts commit 09f7ca123b59a2093b49383e22a2dcb381bdf47f, reversing changes made to b8f17d1f56542087ec3d2cabf4280e8be1ee4982. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 242711b2..73365bbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ azure-communication-sms==1.0.1 azure-eventgrid==4.16.0 azure-identity==1.15.0 azure-mgmt-eventgrid==10.2.0 -fastapi==0.109.0 +fastapi==0.108.0 openai==1.7.1 phonenumbers==8.13.27 pydantic-extra-types==2.4.0 From 5d8bfb44f4f8a22449fc7881c742221c66e112de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:23:25 +0100 Subject: [PATCH 08/13] fix: Remove unreliable HttpUrl Pydantic validation --- helpers/config_models/openai.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helpers/config_models/openai.py b/helpers/config_models/openai.py index ad47aa71..4da9d621 100644 --- a/helpers/config_models/openai.py +++ b/helpers/config_models/openai.py @@ -1,7 +1,7 @@ -from pydantic import BaseModel, HttpUrl +from pydantic import BaseModel class OpenAiModel(BaseModel): - endpoint: HttpUrl + endpoint: str gpt_deployment: str gpt_model: str From aa76027933c8d77edb9c044c4b9132a8ea5b15f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:24:21 +0100 Subject: [PATCH 09/13] fix: App crashes when unknown call ID is sent --- main.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index f5560463..98277420 100644 --- a/main.py +++ b/main.py @@ -18,7 +18,7 @@ from contextlib import asynccontextmanager from datetime import datetime from enum import Enum -from fastapi import FastAPI, status, Request +from fastapi import FastAPI, status, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, Response from helpers.config import CONFIG @@ -234,14 +234,19 @@ async def call_inbound_post(request: Request): # See: https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/communication-services/how-tos/call-automation/secure-webhook-endpoint.md async def call_event_post(request: Request, call_id: UUID) -> None: for event_dict in await request.json(): - event = CloudEvent.from_dict(event_dict) + call = get_call_by_id(call_id) + if not call: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Call {call_id} not found", + ) + event = CloudEvent.from_dict(event_dict) connection_id = event.data["callConnectionId"] operation_context = event.data.get("operationContext", None) client = call_automation_client.get_call_connection( call_connection_id=connection_id ) - call = get_call_by_id(call_id) event_type = event.type _logger.debug(f"Call event received {event_type} for call {call}") From b96e6f29b69a22080e89e7098d3176591b886419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:24:57 +0100 Subject: [PATCH 10/13] quality: Code quality --- main.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/main.py b/main.py index 98277420..73d8e5a9 100644 --- a/main.py +++ b/main.py @@ -20,7 +20,7 @@ from enum import Enum from fastapi import FastAPI, status, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import JSONResponse, Response +from fastapi.responses import JSONResponse from helpers.config import CONFIG from helpers.logging import build_logger from helpers.prompts import LLM as LLMPrompt, TTS as TTSPrompt @@ -71,7 +71,9 @@ CONFIG.communication_service.access_key.get_secret_value() ), ) -sms_client = SmsClient(credential=AZ_CREDENTIAL, endpoint=CONFIG.communication_service.endpoint) +sms_client = SmsClient( + credential=AZ_CREDENTIAL, endpoint=CONFIG.communication_service.endpoint +) db = sqlite3.connect(".local.sqlite", check_same_thread=False) EVENTS_DOMAIN = environ.get("EVENTS_DOMAIN").strip("/") @@ -170,10 +172,14 @@ def eventgrid_unregister() -> None: description="Liveness healthckeck, always returns 204, used to check if the API is up.", ) async def health_liveness_get() -> None: - return None + pass -@api.get("/call/initiate", description="Initiate an outbound call to a phone number.") +@api.get( + "/call/initiate", + status_code=status.HTTP_204_NO_CONTENT, + description="Initiate an outbound call to a phone number.", +) def call_initiate_get(phone_number: str) -> None: _logger.info(f"Initiating outbound call to {phone_number}") call_connection_properties = call_automation_client.create_call( @@ -185,7 +191,6 @@ def call_initiate_get(phone_number: str) -> None: _logger.info( f"Created call with connection id: {call_connection_properties.call_connection_id}" ) - return Response(status_code=status.HTTP_204_NO_CONTENT) @api.post( @@ -204,7 +209,7 @@ async def call_inbound_post(request: Request): _logger.info(f"Validating Event Grid subscription ({validation_code})") return JSONResponse( content={"validationResponse": event.data["validationCode"]}, - status_code=200, + status_code=status.HTTP_200_OK, ) elif event_type == SystemEventNames.AcsIncomingCallEventName: @@ -381,7 +386,7 @@ async def call_event_post(request: Request, call_id: UUID) -> None: elif ( event_type == "Microsoft.Communication.CallTransferFailed" ): # Call transfer failed - _logger.debig(f"Call transfer failed event ({call.id})") + _logger.debug(f"Call transfer failed event ({call.id})") result_information = event.data["resultInformation"] sub_code = result_information["subCode"] _logger.info(f"Error during call transfer, subCode {sub_code} ({call.id})") @@ -395,9 +400,7 @@ async def call_event_post(request: Request, call_id: UUID) -> None: save_call(call) -async def intelligence( - call: CallModel, client: CallConnectionClient -) -> None: +async def intelligence(call: CallModel, client: CallConnectionClient) -> None: chat_res = await gpt_chat(call) _logger.info(f"Chat ({call.id}): {chat_res}") @@ -417,7 +420,11 @@ async def intelligence( text=TTSPrompt.GOODBYE, ) - elif chat_res.intent in (IndentAction.NEW_CLAIM, IndentAction.UPDATED_CLAIM, IndentAction.NEW_OR_UPDATED_REMINDER): + elif chat_res.intent in ( + IndentAction.NEW_CLAIM, + IndentAction.UPDATED_CLAIM, + IndentAction.NEW_OR_UPDATED_REMINDER, + ): await handle_play( call=call, client=client, @@ -882,10 +889,14 @@ async def handle_hangup(client: CallConnectionClient, call: CallModel) -> None: ) response = responses[0] - if (response.successful): - _logger.info(f"SMS report sent {response.message_id} to {response.to} ({call.id})") + if response.successful: + _logger.info( + f"SMS report sent {response.message_id} to {response.to} ({call.id})" + ) else: - _logger.warn(f"Failed SMS to {response.to}, status {response.http_status_code}, error {response.error_message} ({call.id})") + _logger.warn( + f"Failed SMS to {response.to}, status {response.http_status_code}, error {response.error_message} ({call.id})" + ) except Exception: _logger.warn(f"SMS error ({call.id})", exc_info=True) @@ -937,7 +948,7 @@ def save_call(call: CallModel): db.commit() -def get_call_by_id(call_id: UUID) -> CallModel: +def get_call_by_id(call_id: UUID) -> Optional[CallModel]: cursor = db.execute( "SELECT data FROM calls WHERE id = ?", (call_id.hex,), From 3088e862d9afb0e11dbc0e776b95eb0a0d9ade99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:28:59 +0100 Subject: [PATCH 11/13] fix: Container random error build --- Dockerfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7db2a947..1e4a844b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,14 @@ # Base container FROM docker.io/library/python:3.11-slim-bullseye@sha256:9f35f3a6420693c209c11bba63dcf103d88e47ebe0b205336b5168c122967edf AS base -RUN rm -f /etc/apt/apt.conf.d/docker-clean \ - && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache -RUN --mount=target=/var/lib/apt/lists,type=cache,sharing=locked \ - apt-get update -q - # Build container FROM base AS build +RUN rm -f /etc/apt/apt.conf.d/docker-clean \ + && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache RUN --mount=target=/var/lib/apt/lists,type=cache,sharing=locked --mount=target=/root/.cache/pip,type=cache,sharing=locked \ - apt-get install -y -q --no-install-recommends \ + apt-get update -q \ + && apt-get install -y -q --no-install-recommends \ gcc \ python3-dev \ && python3 -m pip install --upgrade \ From 98f95055e36d625797114322a58dc7fb31f03daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:36:25 +0100 Subject: [PATCH 12/13] perf: Upgrade to Python 3.12 and Debian Bookworm --- .python-version | 2 +- Dockerfile | 2 +- helpers/config_models/monitoring.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.python-version b/.python-version index ace200aa..ad14e4bc 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -claimaiphonebot311 +claimaiphonebot312 diff --git a/Dockerfile b/Dockerfile index 1e4a844b..8e3be4e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Base container -FROM docker.io/library/python:3.11-slim-bullseye@sha256:9f35f3a6420693c209c11bba63dcf103d88e47ebe0b205336b5168c122967edf AS base +FROM docker.io/library/python:3.12-slim-bookworm@sha256:448eb6cade8c9edfa66b0840829744a10a0131f6e9ef95052913170c8291a348 AS base # Build container FROM base AS build diff --git a/helpers/config_models/monitoring.py b/helpers/config_models/monitoring.py index a9fa6f6a..a7b9e1bb 100644 --- a/helpers/config_models/monitoring.py +++ b/helpers/config_models/monitoring.py @@ -3,7 +3,7 @@ class LoggingLevel(str, Enum): - # Copied from https://docs.python.org/3.11/library/logging.html#logging-levels + # Copied from https://docs.python.org/3.12/library/logging.html#logging-levels CRITICAL = "CRITICAL" DEBUG = "DEBUG" ERROR = "ERROR" From 0ad1a72ca155f54d94fe63170ef94b3b850fd2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Fri, 12 Jan 2024 14:46:11 +0100 Subject: [PATCH 13/13] Revert "Merge pull request #5 from clemlesne/dependabot/github_actions/develop/trufflesecurity/trufflehog-3.63.8" This reverts commit 572f1b301199a124c282540df16e3f6a62936a3e, reversing changes made to c1ac30ddaebfcd6bbd18834e0fc13cae64713710. --- .github/workflows/pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index fc47fcd4..254f19f8 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -56,7 +56,7 @@ jobs: submodules: recursive - name: SAST - Credentials - uses: trufflesecurity/trufflehog@v3.63.8 + uses: trufflesecurity/trufflehog@v3.63.1 with: base: ${{ github.event.repository.default_branch }} extra_args: --only-verified