From e2d80e34ab5d4b5adf19d2c3d143491711753b08 Mon Sep 17 00:00:00 2001 From: dantelmomsft Date: Wed, 24 Apr 2024 19:11:47 +0200 Subject: [PATCH] first commit --- .devcontainer/devcontainer.json | 42 + .gitattributes | 1 + .github/CODE_OF_CONDUCT.md | 9 + .github/ISSUE_TEMPLATE.md | 36 + .github/PULL_REQUEST_TEMPLATE.md | 45 + .github/workflows/app-ci.yaml | 100 + .github/workflows/infra-ci.yaml | 143 + .github/workflows/nightly-jobs.yaml | 104 + .github/workflows/stale-bot.yml | 19 + .gitignore | 156 + CHANGELOG.md | 13 + CODEOWNERS | 7 + CONTRIBUTING.md | 76 + LICENSE | 21 + LICENSE.md | 21 + README.md | 1 + app/backend/.mvn/jvm.config | 4 + app/backend/.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 50709 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + app/backend/Dockerfile | 30 + app/backend/applicationinsights.json | 5 + app/backend/manifest.yml | 11 + .../manifests/backend-deployment.tmpl.yml | 29 + app/backend/manifests/backend-service.yml | 13 + app/backend/manifests/ingress.yml | 27 + app/backend/mvnw | 305 + app/backend/mvnw.cmd | 172 + app/backend/pom.xml | 251 + .../openai/samples/assistant/Application.java | 20 + .../samples/assistant/agent/AgentContext.java | 21 + .../agent/HistoryReportingAgent.java | 165 + .../samples/assistant/agent/IntentAgent.java | 118 + .../assistant/agent/IntentResponse.java | 27 + .../samples/assistant/agent/IntentType.java | 11 + .../samples/assistant/agent/PaymentAgent.java | 158 + .../assistant/common/ChatGPTConversation.java | 45 + .../assistant/common/ChatGPTMessage.java | 25 + .../assistant/common/ChatGPTUtils.java | 98 + .../AzureAuthenticationConfiguration.java | 40 + .../DocumentIntelligenceConfiguration.java | 40 + .../assistant/config/OpenAIConfiguration.java | 81 + .../assistant/controller/ChatAppRequest.java | 10 + .../controller/ChatAppRequestContext.java | 4 + .../controller/ChatAppRequestOverrides.java | 16 + .../assistant/controller/ChatController.java | 104 + .../assistant/controller/ChatResponse.java | 34 + .../assistant/controller/ResponseChoice.java | 5 + .../assistant/controller/ResponseContext.java | 6 + .../assistant/controller/ResponseMessage.java | 4 + .../assistant/controller/auth/AuthSetup.java | 19 + .../controller/content/ContentController.java | 60 + ...DocumentIntelligenceInvoiceScanHelper.java | 127 + .../assistant/plugin/InvoiceScanPlugin.java | 89 + .../assistant/plugin/PaymentPlugin.java | 25 + .../assistant/plugin/PaymentTransaction.java | 4 + .../plugin/TransactionHistoryPlugin.java | 40 + .../assistant/plugin/TransactionService.java | 51 + .../assistant/proxy/BlobStorageProxy.java | 48 + .../samples/assistant/proxy/OpenAIProxy.java | 106 + .../src/main/resources/application.properties | 18 + app/frontend/.dockerignore | 2 + app/frontend/.env.dev | 1 + app/frontend/.env.local | 1 + app/frontend/.env.production | 2 + app/frontend/.npmrc | 1 + app/frontend/.prettierignore | 2 + app/frontend/.prettierrc.json | 6 + app/frontend/Dockerfile | 21 + app/frontend/Dockerfile-aks | 20 + app/frontend/index.html | 13 + .../manifests/frontend-deployment.tmpl.yml | 26 + app/frontend/manifests/frontend-service.yml | 13 + app/frontend/nginx/nginx.conf.template | 13 + app/frontend/package-lock.json | 5592 +++++++++++++++++ app/frontend/package.json | 38 + app/frontend/public/favicon.ico | Bin 0 -> 4286 bytes app/frontend/src/api/api.ts | 51 + app/frontend/src/api/index.ts | 2 + app/frontend/src/api/models.ts | 70 + app/frontend/src/assets/github.svg | 1 + app/frontend/src/assets/search.svg | 1 + app/frontend/src/authConfig.ts | 89 + .../AnalysisPanel/AnalysisPanel.module.css | 6 + .../AnalysisPanel/AnalysisPanel.tsx | 57 + .../AnalysisPanel/AnalysisPanelTabs.tsx | 5 + .../src/components/AnalysisPanel/index.tsx | 2 + .../src/components/Answer/Answer.module.css | 137 + app/frontend/src/components/Answer/Answer.tsx | 99 + .../src/components/Answer/AnswerError.tsx | 23 + .../src/components/Answer/AnswerIcon.tsx | 5 + .../src/components/Answer/AnswerLoading.tsx | 26 + .../src/components/Answer/AnswerParser.tsx | 67 + app/frontend/src/components/Answer/index.ts | 3 + .../ClearChatButton.module.css | 6 + .../ClearChatButton/ClearChatButton.tsx | 20 + .../src/components/ClearChatButton/index.tsx | 1 + .../src/components/Example/Example.module.css | 41 + .../src/components/Example/Example.tsx | 15 + .../src/components/Example/ExampleList.tsx | 30 + app/frontend/src/components/Example/index.tsx | 2 + .../LoginButton/LoginButton.module.css | 5 + .../components/LoginButton/LoginButton.tsx | 39 + .../src/components/LoginButton/index.tsx | 1 + .../QuestionInput/QuestionInput.module.css | 21 + .../QuestionInput/QuestionInput.tsx | 66 + .../src/components/QuestionInput/index.ts | 1 + .../SettingsButton/SettingsButton.module.css | 6 + .../SettingsButton/SettingsButton.tsx | 19 + .../src/components/SettingsButton/index.tsx | 1 + .../SupportingContent.module.css | 30 + .../SupportingContent/SupportingContent.tsx | 24 + .../SupportingContentParser.ts | 17 + .../src/components/SupportingContent/index.ts | 1 + .../TokenClaimsDisplay/TokenClaimsDisplay.tsx | 77 + .../components/TokenClaimsDisplay/index.tsx | 1 + .../UserChatMessage.module.css | 17 + .../UserChatMessage/UserChatMessage.tsx | 13 + .../src/components/UserChatMessage/index.ts | 1 + app/frontend/src/index.css | 33 + app/frontend/src/index.tsx | 68 + app/frontend/src/pages/NoPage.tsx | 5 + app/frontend/src/pages/chat/Chat.module.css | 115 + app/frontend/src/pages/chat/Chat.tsx | 474 ++ .../src/pages/layout/Layout.module.css | 78 + app/frontend/src/pages/layout/Layout.tsx | 51 + .../src/pages/oneshot/OneShot.module.css | 66 + app/frontend/src/pages/oneshot/OneShot.tsx | 324 + app/frontend/src/vite-env.d.ts | 1 + app/frontend/tsconfig.json | 21 + app/frontend/vite.config.ts | 46 + app/package-lock.json | 6 + app/start-compose.ps1 | 56 + app/start-compose.sh | 63 + app/start.ps1 | 49 + app/start.sh | 52 + deploy/app-service/azure.yaml | 24 + deploy/app-service/infra/main.bicep | 342 + deploy/app-service/infra/main.parameters.json | 75 + deploy/app-service/scripts/prepdocs.ps1 | 24 + deploy/app-service/scripts/prepdocs.sh | 19 + deploy/app-service/scripts/roles.ps1 | 30 + deploy/app-service/scripts/roles.sh | 30 + deploy/app-service/scripts/set-env.ps1 | 17 + deploy/app-service/scripts/set-env.sh | 12 + deploy/shared/abbreviations.json | 135 + deploy/shared/ai/cognitiveservices.bicep | 53 + deploy/shared/backend-dashboard.bicep | 392 ++ deploy/shared/event/eventgrid.bicep | 59 + deploy/shared/host/aks-agent-pool.bicep | 18 + deploy/shared/host/aks-managed-cluster.bicep | 140 + deploy/shared/host/aks.bicep | 214 + .../shared/host/appservice-appsettings.bicep | 17 + deploy/shared/host/appservice.bicep | 120 + deploy/shared/host/appserviceplan.bicep | 22 + deploy/shared/host/container-app-upsert.bicep | 105 + deploy/shared/host/container-app.bicep | 162 + .../host/container-apps-environment.bicep | 66 + deploy/shared/host/container-apps.bicep | 38 + deploy/shared/host/container-registry.bicep | 83 + deploy/shared/host/functions.bicep | 86 + .../applicationinsights-dashboard.bicep | 1236 ++++ .../shared/monitor/applicationinsights.bicep | 30 + deploy/shared/monitor/loganalytics.bicep | 22 + deploy/shared/monitor/monitoring.bicep | 32 + deploy/shared/search/search-services.bicep | 63 + deploy/shared/security/keyvault-access.bicep | 22 + deploy/shared/security/keyvault-secret.bicep | 31 + deploy/shared/security/keyvault.bicep | 26 + deploy/shared/security/registry-access.bicep | 19 + deploy/shared/security/role.bicep | 21 + .../shared/servicebus/servicebus-queue.bicep | 44 + deploy/shared/storage/storage-account.bicep | 64 + 172 files changed, 15513 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .gitattributes create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/app-ci.yaml create mode 100644 .github/workflows/infra-ci.yaml create mode 100644 .github/workflows/nightly-jobs.yaml create mode 100644 .github/workflows/stale-bot.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 CODEOWNERS create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 app/backend/.mvn/jvm.config create mode 100644 app/backend/.mvn/wrapper/maven-wrapper.jar create mode 100644 app/backend/.mvn/wrapper/maven-wrapper.properties create mode 100644 app/backend/Dockerfile create mode 100644 app/backend/applicationinsights.json create mode 100644 app/backend/manifest.yml create mode 100644 app/backend/manifests/backend-deployment.tmpl.yml create mode 100644 app/backend/manifests/backend-service.yml create mode 100644 app/backend/manifests/ingress.yml create mode 100644 app/backend/mvnw create mode 100644 app/backend/mvnw.cmd create mode 100644 app/backend/pom.xml create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/Application.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/AgentContext.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/HistoryReportingAgent.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentAgent.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentResponse.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentType.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/PaymentAgent.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTConversation.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTMessage.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTUtils.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/AzureAuthenticationConfiguration.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/DocumentIntelligenceConfiguration.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/OpenAIConfiguration.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequest.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestContext.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestOverrides.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatController.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatResponse.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseChoice.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseContext.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseMessage.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/auth/AuthSetup.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/content/ContentController.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/invoice/DocumentIntelligenceInvoiceScanHelper.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/InvoiceScanPlugin.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentPlugin.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentTransaction.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionHistoryPlugin.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionService.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/BlobStorageProxy.java create mode 100644 app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/OpenAIProxy.java create mode 100644 app/backend/src/main/resources/application.properties create mode 100644 app/frontend/.dockerignore create mode 100644 app/frontend/.env.dev create mode 100644 app/frontend/.env.local create mode 100644 app/frontend/.env.production create mode 100644 app/frontend/.npmrc create mode 100644 app/frontend/.prettierignore create mode 100644 app/frontend/.prettierrc.json create mode 100644 app/frontend/Dockerfile create mode 100644 app/frontend/Dockerfile-aks create mode 100644 app/frontend/index.html create mode 100644 app/frontend/manifests/frontend-deployment.tmpl.yml create mode 100644 app/frontend/manifests/frontend-service.yml create mode 100644 app/frontend/nginx/nginx.conf.template create mode 100644 app/frontend/package-lock.json create mode 100644 app/frontend/package.json create mode 100644 app/frontend/public/favicon.ico create mode 100644 app/frontend/src/api/api.ts create mode 100644 app/frontend/src/api/index.ts create mode 100644 app/frontend/src/api/models.ts create mode 100644 app/frontend/src/assets/github.svg create mode 100644 app/frontend/src/assets/search.svg create mode 100644 app/frontend/src/authConfig.ts create mode 100644 app/frontend/src/components/AnalysisPanel/AnalysisPanel.module.css create mode 100644 app/frontend/src/components/AnalysisPanel/AnalysisPanel.tsx create mode 100644 app/frontend/src/components/AnalysisPanel/AnalysisPanelTabs.tsx create mode 100644 app/frontend/src/components/AnalysisPanel/index.tsx create mode 100644 app/frontend/src/components/Answer/Answer.module.css create mode 100644 app/frontend/src/components/Answer/Answer.tsx create mode 100644 app/frontend/src/components/Answer/AnswerError.tsx create mode 100644 app/frontend/src/components/Answer/AnswerIcon.tsx create mode 100644 app/frontend/src/components/Answer/AnswerLoading.tsx create mode 100644 app/frontend/src/components/Answer/AnswerParser.tsx create mode 100644 app/frontend/src/components/Answer/index.ts create mode 100644 app/frontend/src/components/ClearChatButton/ClearChatButton.module.css create mode 100644 app/frontend/src/components/ClearChatButton/ClearChatButton.tsx create mode 100644 app/frontend/src/components/ClearChatButton/index.tsx create mode 100644 app/frontend/src/components/Example/Example.module.css create mode 100644 app/frontend/src/components/Example/Example.tsx create mode 100644 app/frontend/src/components/Example/ExampleList.tsx create mode 100644 app/frontend/src/components/Example/index.tsx create mode 100644 app/frontend/src/components/LoginButton/LoginButton.module.css create mode 100644 app/frontend/src/components/LoginButton/LoginButton.tsx create mode 100644 app/frontend/src/components/LoginButton/index.tsx create mode 100644 app/frontend/src/components/QuestionInput/QuestionInput.module.css create mode 100644 app/frontend/src/components/QuestionInput/QuestionInput.tsx create mode 100644 app/frontend/src/components/QuestionInput/index.ts create mode 100644 app/frontend/src/components/SettingsButton/SettingsButton.module.css create mode 100644 app/frontend/src/components/SettingsButton/SettingsButton.tsx create mode 100644 app/frontend/src/components/SettingsButton/index.tsx create mode 100644 app/frontend/src/components/SupportingContent/SupportingContent.module.css create mode 100644 app/frontend/src/components/SupportingContent/SupportingContent.tsx create mode 100644 app/frontend/src/components/SupportingContent/SupportingContentParser.ts create mode 100644 app/frontend/src/components/SupportingContent/index.ts create mode 100644 app/frontend/src/components/TokenClaimsDisplay/TokenClaimsDisplay.tsx create mode 100644 app/frontend/src/components/TokenClaimsDisplay/index.tsx create mode 100644 app/frontend/src/components/UserChatMessage/UserChatMessage.module.css create mode 100644 app/frontend/src/components/UserChatMessage/UserChatMessage.tsx create mode 100644 app/frontend/src/components/UserChatMessage/index.ts create mode 100644 app/frontend/src/index.css create mode 100644 app/frontend/src/index.tsx create mode 100644 app/frontend/src/pages/NoPage.tsx create mode 100644 app/frontend/src/pages/chat/Chat.module.css create mode 100644 app/frontend/src/pages/chat/Chat.tsx create mode 100644 app/frontend/src/pages/layout/Layout.module.css create mode 100644 app/frontend/src/pages/layout/Layout.tsx create mode 100644 app/frontend/src/pages/oneshot/OneShot.module.css create mode 100644 app/frontend/src/pages/oneshot/OneShot.tsx create mode 100644 app/frontend/src/vite-env.d.ts create mode 100644 app/frontend/tsconfig.json create mode 100644 app/frontend/vite.config.ts create mode 100644 app/package-lock.json create mode 100644 app/start-compose.ps1 create mode 100644 app/start-compose.sh create mode 100644 app/start.ps1 create mode 100644 app/start.sh create mode 100644 deploy/app-service/azure.yaml create mode 100644 deploy/app-service/infra/main.bicep create mode 100644 deploy/app-service/infra/main.parameters.json create mode 100644 deploy/app-service/scripts/prepdocs.ps1 create mode 100644 deploy/app-service/scripts/prepdocs.sh create mode 100644 deploy/app-service/scripts/roles.ps1 create mode 100644 deploy/app-service/scripts/roles.sh create mode 100644 deploy/app-service/scripts/set-env.ps1 create mode 100644 deploy/app-service/scripts/set-env.sh create mode 100644 deploy/shared/abbreviations.json create mode 100644 deploy/shared/ai/cognitiveservices.bicep create mode 100644 deploy/shared/backend-dashboard.bicep create mode 100644 deploy/shared/event/eventgrid.bicep create mode 100644 deploy/shared/host/aks-agent-pool.bicep create mode 100644 deploy/shared/host/aks-managed-cluster.bicep create mode 100644 deploy/shared/host/aks.bicep create mode 100644 deploy/shared/host/appservice-appsettings.bicep create mode 100644 deploy/shared/host/appservice.bicep create mode 100644 deploy/shared/host/appserviceplan.bicep create mode 100644 deploy/shared/host/container-app-upsert.bicep create mode 100644 deploy/shared/host/container-app.bicep create mode 100644 deploy/shared/host/container-apps-environment.bicep create mode 100644 deploy/shared/host/container-apps.bicep create mode 100644 deploy/shared/host/container-registry.bicep create mode 100644 deploy/shared/host/functions.bicep create mode 100644 deploy/shared/monitor/applicationinsights-dashboard.bicep create mode 100644 deploy/shared/monitor/applicationinsights.bicep create mode 100644 deploy/shared/monitor/loganalytics.bicep create mode 100644 deploy/shared/monitor/monitoring.bicep create mode 100644 deploy/shared/search/search-services.bicep create mode 100644 deploy/shared/security/keyvault-access.bicep create mode 100644 deploy/shared/security/keyvault-secret.bicep create mode 100644 deploy/shared/security/keyvault.bicep create mode 100644 deploy/shared/security/registry-access.bicep create mode 100644 deploy/shared/security/role.bicep create mode 100644 deploy/shared/servicebus/servicebus-queue.bicep create mode 100644 deploy/shared/storage/storage-account.bicep diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a22ded5 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,42 @@ +{ + "name": "Java 17 and maven 3.8.8 DevContainer to build Java RAG example with Azure AI", + "image": "mcr.microsoft.com/devcontainers/java:1-17-bullseye", + "features": { + "azure-cli": "latest", + "ghcr.io/azure/azure-dev/azd:latest": { + "version": "1.7.0" + }, + "ghcr.io/devcontainers/features/java:1": { + "version": "none", + "installMaven": true, + "mavenVersion": "3.8.8" + }, + "ghcr.io/devcontainers/features/node:1": { + "version": "20.5.0" + }, + + "ghcr.io/devcontainers/features/git:1": { + "version": "2.39.1" + }, + "ghcr.io/devcontainers-contrib/features/typescript:2": {}, + "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": { + "version": "1.1.8" + }, + "docker-in-docker": { + "version": "latest", + "moby": true, + "dockerDashComposeVersion": "v1" + } + }, + "customizations": { + "vscode": { + "extensions": [ + "GitHub.vscode-github-actions", + "ms-azuretools.azure-dev", + "ms-azuretools.vscode-bicep", + "vscjava.vscode-java-pack", + "amodio.tsl-problem-matcher" + ] + } + } +} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..526c8a3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf \ No newline at end of file diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..c72a574 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,9 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..09f1145 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,36 @@ + +> Please provide us with the following information: +> --------------------------------------------------------------- + +### This issue is for a: (mark with an `x`) +``` +- [ ] bug report -> please search issues before submitting +- [ ] feature request +- [ ] documentation issue or request +- [ ] regression (a behavior that used to work and stopped in a new release) +``` + +### Minimal steps to reproduce +> + +### Any log messages given by the failure +> + +### Expected/desired behavior +> + +### OS and Version? +> Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) + +### azd version? +> run `azd version` and copy paste here. + +### Versions +> + +### Mention any other details that might be useful + +> --------------------------------------------------------------- +> Thanks! We'll be in touch soon. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..12475f3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,45 @@ +## Purpose + +* ... + +## Does this introduce a breaking change? + +``` +[ ] Yes +[ ] No +``` + +## Pull Request Type +What kind of change does this Pull Request introduce? + + +``` +[ ] Bugfix +[ ] Feature +[ ] Code style update (formatting, local variables) +[ ] Refactoring (no functional changes, no api changes) +[ ] Documentation content changes +[ ] Other... Please describe: +``` + +## How to Test +* Get the code + +``` +git clone [repo-address] +cd [repo-name] +git checkout [branch-name] +npm install +``` + +* Test the code + +``` +``` + +## What to Check +Verify that the following are valid +* ... + +## Other Information + \ No newline at end of file diff --git a/.github/workflows/app-ci.yaml b/.github/workflows/app-ci.yaml new file mode 100644 index 0000000..9f56928 --- /dev/null +++ b/.github/workflows/app-ci.yaml @@ -0,0 +1,100 @@ +name: APP CI/CD Pipeline + +on: + push: + branches: + - main + paths: + - "app/**" + tags: + - v*.*.* + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + outputs: + env-name: ${{steps.set-deploy-env.outputs.DEPLOY_ENVIRONMENT}} + steps: + - uses: actions/checkout@v2 + + - name: Set up Java version + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '17' + cache: 'maven' + + - name: Set environment for branch + id: set-deploy-env + run: | + echo "checking branch name [${{github.ref_name}}]" + if [[ ${{github.ref_name}} == 'main' ]]; then + echo "main branch detected. Set Development environment" + echo "DEPLOY_ENVIRONMENT=Development" >> "$GITHUB_OUTPUT" + elif [[ ${{github.ref_name}} == *'release'* ]]; then + echo "release branch detected. Set Test environment" + echo "DEPLOY_ENVIRONMENT=Test" >> "$GITHUB_OUTPUT" + elif [[ ${{github.ref_name}} == *'v'* ]]; then + echo "tag detected. Set Production environment" + echo "DEPLOY_ENVIRONMENT=Production" >> "$GITHUB_OUTPUT" + else + echo "branch not detected. Set Development environment as default" + echo "DEPLOY_ENVIRONMENT=Development" >> "$GITHUB_OUTPUT" + fi + - name: Build React Frontend + run: | + echo "Building frontend and merge into spring boot static folder. Environment [${{ steps.set-deploy-env.outputs.DEPLOY_ENVIRONMENT }}]" + cd ./app/frontend + npm install + npm run build + mkdir -p ../backend/src/main/resources/static + cp -r ./build/* ../backend/src/main/resources/static + + - name: Verify Indexer project + run: | + echo "Testing indexer project." + cd ./app/indexer + mvn test + + - name: Build Spring Boot App + run: | + echo "Building spring boot app. Environment [${{ steps.set-deploy-env.outputs.DEPLOY_ENVIRONMENT }}]" + cd ./app/backend + mvn package + artifactid=$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout) + jarversion=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + originaljarname="$artifactid-$jarversion.jar" + echo "Renaming $originaljarname to app.jar" + # Renaming jar so it is auto detected by app service + mv ./target/$originaljarname ./target/app.jar + + - name: Upload artifacts for backend deployment jobs + uses: actions/upload-artifact@v2 + with: + name: spring-boot-app + path: | + ./app/backend/target/app.jar + + + deploy: + runs-on: ubuntu-latest + needs: build + environment: + name: ${{ needs.build.outputs.env-name}} + url: ${{ steps.deploy-app.outputs.webapp-url }} + + steps: + - name: Download backend artifact from build job + uses: actions/download-artifact@v2 + with: + name: spring-boot-app + path: ./backend + + - name: 'Deploy backend to Azure Web App' + uses: azure/webapps-deploy@v2 + id: deploy-app + with: + app-name: ${{ vars.AZUREAPPSERVICE_APP_NAME }} + package: ./backend + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE}} diff --git a/.github/workflows/infra-ci.yaml b/.github/workflows/infra-ci.yaml new file mode 100644 index 0000000..68311c4 --- /dev/null +++ b/.github/workflows/infra-ci.yaml @@ -0,0 +1,143 @@ +name: Infra CI Pipeline + +on: + push: + branches: + - main + paths: + - "deploy/**" + + workflow_dispatch: + +# To configure required secrets for connecting to Azure, simply run `azd pipeline config` + +# Set up permissions for deploying with secretless Azure federated credentials +# https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#set-up-azure-login-with-openid-connect-authentication +permissions: + id-token: write + contents: read + security-events: write + +jobs: + validate-bicep: + name: "Infra Biceps Validation" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Filter Changes + uses: dorny/paths-filter@v2 + id: changes + with: + filters: | + app-service: + - 'deploy/app-service/**' + aks: + - 'deploy/aks/**' + aca: + - 'deploy/aca/**' + - name: Build App Service Bicep for linting + if: steps.changes.outputs.app-service == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/app-service/infra/main.bicep --stdout + + - name: Build AKS Bicep for linting + if: steps.changes.outputs.aks == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/aks/infra/main.bicep --stdout + + - name: Build ACA Bicep for linting + if: steps.changes.outputs.aca == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/aca/infra/main.bicep --stdout + + - name: Run Microsoft Security DevOps Analysis + uses: microsoft/security-devops-action@v1 + id: msdo + continue-on-error: true + with: + tools: templateanalyzer + + - name: Upload alerts to Security tab + uses: github/codeql-action/upload-sarif@v2 + if: github.repository == 'Azure-Samples/azure-search-openai-demo-java' + with: + sarif_file: ${{ steps.msdo.outputs.sarifFile }} + + +# deploy: +# name: "Deploy Infra and App using azd" +# runs-on: ubuntu-latest +# environment: +# name: "Development" +# env: +# AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} +# AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} +# AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} +# AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} +# steps: +# - name: Checkout +# uses: actions/checkout@v4 + +# - name: Install azd +# uses: Azure/setup-azd@v0.1.0 + +# - name: Log in with Azure (Federated Credentials) +# if: ${{ env.AZURE_CLIENT_ID != '' }} +# run: | +# azd auth login ` +# --client-id "$Env:AZURE_CLIENT_ID" ` +# --federated-credential-provider "github" ` +# --tenant-id "$Env:AZURE_TENANT_ID" +# shell: pwsh + +# - name: Log in with Azure (Client Credentials) +# if: ${{ env.AZURE_CREDENTIALS != '' }} +# run: | +# $info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable; +# Write-Host "::add-mask::$($info.clientSecret)" + +# azd auth login ` +# --client-id "$($info.clientId)" ` +# --client-secret "$($info.clientSecret)" ` +# --tenant-id "$($info.tenantId)" +# shell: pwsh +# env: +# AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} + +# - name: Provision Infrastructure +# run: azd provision --no-prompt +# env: +# AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} +# AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} +# AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} +# AZURE_FORMRECOGNIZER_RESOURCE_GROUP: ${{ vars.AZURE_FORMRECOGNIZER_RESOURCE_GROUP }} +# AZURE_FORMRECOGNIZER_SERVICE: ${{ vars.AZURE_FORMRECOGNIZER_RESOURCE_GROUP }} +# AZURE_OPENAI_RESOURCE_GROUP: ${{ vars.AZURE_FORMRECOGNIZER_SERVICE }} +# AZURE_OPENAI_SERVICE: ${{ vars.AZURE_OPENAI_SERVICE }} +# AZURE_RESOURCE_GROUP: ${{ vars.AZURE_RESOURCE_GROUP }} +# AZURE_SEARCH_SERVICE: ${{ vars.AZURE_SEARCH_SERVICE }} +# AZURE_SEARCH_SERVICE_RESOURCE_GROUP: ${{ vars.AZURE_SEARCH_SERVICE_RESOURCE_GROUP }} +# AZURE_STORAGE_ACCOUNT: ${{ vars.AZURE_STORAGE_ACCOUNT }} +# AZURE_STORAGE_RESOURCE_GROUP: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }} + +# - name: Deploy Application +# run: azd deploy --no-prompt +# env: +# AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} +# AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} +# AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} +# AZURE_FORMRECOGNIZER_RESOURCE_GROUP: ${{ vars.AZURE_FORMRECOGNIZER_RESOURCE_GROUP }} +# AZURE_FORMRECOGNIZER_SERVICE: ${{ vars.AZURE_FORMRECOGNIZER_RESOURCE_GROUP }} +# AZURE_OPENAI_RESOURCE_GROUP: ${{ vars.AZURE_FORMRECOGNIZER_SERVICE }} +# AZURE_OPENAI_SERVICE: ${{ vars.AZURE_OPENAI_SERVICE }} +# AZURE_RESOURCE_GROUP: ${{ vars.AZURE_RESOURCE_GROUP }} +# AZURE_SEARCH_SERVICE: ${{ vars.AZURE_SEARCH_SERVICE }} +# AZURE_SEARCH_SERVICE_RESOURCE_GROUP: ${{ vars.AZURE_SEARCH_SERVICE_RESOURCE_GROUP }} +# AZURE_STORAGE_ACCOUNT: ${{ vars.AZURE_STORAGE_ACCOUNT }} +# AZURE_STORAGE_RESOURCE_GROUP: ${{ vars.AZURE_STORAGE_RESOURCE_GROUP }} + + diff --git a/.github/workflows/nightly-jobs.yaml b/.github/workflows/nightly-jobs.yaml new file mode 100644 index 0000000..9350a1f --- /dev/null +++ b/.github/workflows/nightly-jobs.yaml @@ -0,0 +1,104 @@ +name: Nightly and CICD Jobs + +on: + pull_request: + branches: [ main ] + schedule: + - cron: '0 0 * * *' # Run at midnight every day + workflow_dispatch: + +permissions: + id-token: write + contents: read + security-events: write + +jobs: + validate-bicep: + name: "Infra Biceps Validation" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Filter Changes + uses: dorny/paths-filter@v2 + id: changes + with: + filters: | + app-service: + - 'deploy/app-service/**' + aks: + - 'deploy/aks/**' + aca: + - 'deploy/aca/**' + - name: Build App Service Bicep for linting + if: steps.changes.outputs.app-service == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/app-service/infra/main.bicep --stdout + + - name: Build AKS Bicep for linting + if: steps.changes.outputs.aks == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/aks/infra/main.bicep --stdout + + - name: Build ACA Bicep for linting + if: steps.changes.outputs.aca == 'true' + uses: azure/CLI@v1 + with: + inlineScript: az config set bicep.use_binary_from_path=false && az bicep build -f deploy/aca/infra/main.bicep --stdout + + - name: Run Microsoft Security DevOps Analysis + uses: microsoft/security-devops-action@v1 + id: msdo + continue-on-error: true + with: + tools: templateanalyzer + + - name: Upload alerts to Security tab + uses: github/codeql-action/upload-sarif@v2 + if: github.repository == 'Azure-Samples/azure-search-openai-demo-java' + with: + sarif_file: ${{ steps.msdo.outputs.sarifFile }} + + frontend: + name: "Front-end validation" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build React Frontend + run: | + echo "Building front-end and merge into Spring Boot static folder." + cd ./app/frontend + npm install + npm run build + mkdir -p ../backend/src/main/resources/static + cp -r ./build/* ../backend/src/main/resources/static + + backend: + name: "Backend validation" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java version + uses: actions/setup-java@v2 + with: + distribution: 'microsoft' + java-version: '17' + cache: 'maven' + + - name: Verify Indexer project + run: | + echo "Testing indexer project." + cd ./app/indexer + mvn test + + - name: Build Spring Boot App + run: | + echo "Building Spring Boot app." + cd ./app/backend + mvn verify diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml new file mode 100644 index 0000000..44dc9ab --- /dev/null +++ b/.github/workflows/stale-bot.yml @@ -0,0 +1,19 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '30 1 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8 + with: + stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this issue will be closed.' + stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed.' + close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.' + close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.' + days-before-issue-stale: 60 + days-before-pr-stale: 60 + days-before-issue-close: -1 + days-before-pr-close: -1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d5428a --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +# Azure az webapp deployment details +.azure +*_env + +# Java IDE +.idea +*.iml + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# NPM +npm-debug.log* +node_modules +static/ + +# Generated manifests +app/backend/manifests/azd-env-configmap.yml +deploy/aks/easyauth/config-output.md +deploy/aks/easyauth/easyauth-ingress.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9f92a3d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +## [project-title] Changelog + + +# x.y.z (yyyy-mm-dd) + +*Features* +* ... + +*Bug Fixes* +* ... + +*Breaking Changes* +* ... diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..1617c3a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,7 @@ +# These owners will be the default owners for everything in +# this repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @dantelmomsft +* @johnoliver +* @brunoborges diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..a145f12 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,76 @@ +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + + - [Code of Conduct](#coc) + - [Issues and Bugs](#issue) + - [Feature Requests](#feature) + - [Submission Guidelines](#submit) + +## Code of Conduct +Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +## Found an Issue? +If you find a bug in the source code or a mistake in the documentation, you can help us by +[submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can +[submit a Pull Request](#submit-pr) with a fix. + +## Want a Feature? +You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub +Repository. If you would like to *implement* a new feature, please submit an issue with +a proposal for your work first, to be sure that we can use it. + +* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). + +## Submission Guidelines + +### Submitting an Issue +Before you submit an issue, search the archive, maybe your question was already answered. + +If your issue appears to be a bug, and hasn't been reported, open a new issue. +Help us to maximize the effort we can spend fixing issues and adding new +features, by not reporting duplicate issues. Providing the following information will increase the +chances of your issue being dealt with quickly: + +* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps +* **Version** - what version is affected (e.g. 0.1.2) +* **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you +* **Browsers and Operating System** - is this a problem with all browsers? +* **Reproduce the Error** - provide a live example or an unambiguous set of steps +* **Related Issues** - has a similar issue been reported before? +* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be + causing the problem (line of code or commit) + +You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/Azure-Samples/azure-search-openai-demo-java/issues/new. + +### Submitting a Pull Request (PR) +Before you submit your Pull Request (PR) consider the following guidelines: + +* Search the repository (https://github.com/Azure-Samples/azure-search-openai-demo-java/pulls) for an open or closed PR + that relates to your submission. You don't want to duplicate effort. + +* Make your changes in a new git fork: + +* Commit your changes using a descriptive commit message +* Push your fork to GitHub: +* In GitHub, create a pull request +* If we suggest changes then: + * Make the required updates. + * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): + + ```shell + git rebase master -i + git push -f + ``` + +That's it! Thank you for your contribution! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..65f32d0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Azure Samples + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..db553e8 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0ed74f7 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Personal Finance Assistant with Azure OpenAI - Java diff --git a/app/backend/.mvn/jvm.config b/app/backend/.mvn/jvm.config new file mode 100644 index 0000000..14a0c1a --- /dev/null +++ b/app/backend/.mvn/jvm.config @@ -0,0 +1,4 @@ +--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED +--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED diff --git a/app/backend/.mvn/wrapper/maven-wrapper.jar b/app/backend/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..968b23b0a9b868f9f049fa8878da83cba2f4adaa GIT binary patch literal 50709 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 I \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ "$MVNW_REPOURL" = true]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/app/backend/mvnw.cmd b/app/backend/mvnw.cmd new file mode 100644 index 0000000..4f5150a --- /dev/null +++ b/app/backend/mvnw.cmd @@ -0,0 +1,172 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.2/maven-wrapper-0.5.2.jar" + ) + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/app/backend/pom.xml b/app/backend/pom.xml new file mode 100644 index 0000000..6c82c3e --- /dev/null +++ b/app/backend/pom.xml @@ -0,0 +1,251 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.13 + + + com.microsoft.openai.samples.assistant + personal-finance-assistant-java + 1.0.0-SNAPSHOT + personal-finance-assistant-java + This sample demonstrate how to create a generative ai multi-agent solution for a banking personal assistant + + 17 + + 4.9.0 + 11.6.0-beta.8 + 1.0.1 + 4.5.1 + 3.11.0 + + 2.40.0 + 1.18.1 + 0.10.14 + 2.22.0 + 4.7.3.6 + + + + + + com.azure.spring + spring-cloud-azure-dependencies + ${spring-cloud-azure.version} + pom + import + + + com.microsoft.semantic-kernel + semantickernel-bom + ${semantic-kernel.version} + import + pom + + + + + org.apache.commons + commons-lang3 + 3.13.0 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.fasterxml.jackson.core + jackson-databind + compile + + + com.fasterxml.jackson.core + jackson-core + compile + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-inline + ${mockito-inline.version} + test + + + + com.azure + azure-identity + 1.11.2 + + + com.azure + azure-core + 1.45.1 + + + + com.azure + azure-ai-documentintelligence + 1.0.0-beta.2 + + + org.json + json + 20240303 + + + + + com.azure + azure-search-documents + ${azure-search.version} + + + com.azure + azure-core-serializer-json-jackson + + + + + + com.azure + azure-storage-blob + + + + + com.microsoft.semantic-kernel + semantickernel-api + + + com.microsoft.semantic-kernel + semantickernel-aiservices-openai + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + bug-check + + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler-plugin.version} + + ${java.version} + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + true + + -XDcompilePolicy=simple + -Xplugin:ErrorProne + -XepOpt:NullAway:AnnotatedPackages=com.microsoft.openai.samples.rag + -Xep:AlmostJavadoc:OFF -Xep:MissingSummary:OFF + -Xep:UnusedVariable:OFF -Xep:EmptyBlockTag:OFF + + + + + com.google.errorprone + error_prone_core + ${google.errorprone.core.version} + + + com.uber.nullaway + nullaway + ${com.uber.nullaway.version} + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${maven.spotless-plugin.version} + + + check + + check + + compile + + + apply + + apply + + process-sources + + + + + + ${google.java.format.version} + + true + + + // Copyright (c) Microsoft. All rights reserved. + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + ${maven.spotbugs-plugin.version} + + spotbugs-exclude.xml + Max + + Normal + + + + + spotbugs + check + + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + + + + + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/Application.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/Application.java new file mode 100644 index 0000000..30b5ec7 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/Application.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + private static final Logger LOG = LoggerFactory.getLogger(Application.class); + + public static void main(String[] args) { + LOG.info( + "Application profile from system property is [{}]", + System.getProperty("spring.profiles.active")); + new SpringApplication(Application.class).run(args); + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/AgentContext.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/AgentContext.java new file mode 100644 index 0000000..27191c1 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/AgentContext.java @@ -0,0 +1,21 @@ +package com.microsoft.openai.samples.assistant.agent; +public class AgentContext { + + private String result; + + + public void AgentContext() { + } + + public void AgentContext(String result) { + this.result = result; + } + + public String getResult() { + return result; + } + public void setResult(String result) { + this.result = result; + } + +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/HistoryReportingAgent.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/HistoryReportingAgent.java new file mode 100644 index 0000000..0a62215 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/HistoryReportingAgent.java @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.agent; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.microsoft.openai.samples.assistant.plugin.TransactionHistoryPlugin; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatMessageContent; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIFunctionToolCall; +import com.microsoft.semantickernel.contextvariables.CaseInsensitiveMap; +import com.microsoft.semantickernel.contextvariables.ContextVariable; +import com.microsoft.semantickernel.orchestration.FunctionResult; +import com.microsoft.semantickernel.orchestration.FunctionResultMetadata; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.ToolCallBehavior; +import com.microsoft.semantickernel.plugin.KernelPluginFactory; +import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; +import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; + +public class HistoryReportingAgent { + private static final Logger LOGGER = LoggerFactory.getLogger(HistoryReportingAgent.class); + private OpenAIAsyncClient client; + + private Kernel kernel; + + private ChatCompletionService chat; + + private String HISTORY_AGENT_SYSTEM_MESSAGE = """ + you are a personal financial advisor who help the user with their recurrent bill payments. To search about the payments history you need to know the payee name. + If the user doesn't provide the payee name, search the last 10 transactions order by date. + If the user want to search last transactions for a specific payee ask to provide the payee name. + """; + + public HistoryReportingAgent(OpenAIAsyncClient client, String modelId){ + this.client = client; + this.chat = OpenAIChatCompletion.builder() + .withModelId(modelId) + .withOpenAIAsyncClient(client) + .build(); + + var plugin = KernelPluginFactory.createFromObject(new TransactionHistoryPlugin(), "TransactionHistoryPlugin"); + + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .withPlugin(plugin) + .build(); + } + public HistoryReportingAgent(String azureClientKey, String clientEndpoint, String modelId){ + this.client = new OpenAIClientBuilder() + .credential(new AzureKeyCredential(azureClientKey)) + .endpoint(clientEndpoint) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .buildAsyncClient(); + + this.chat = OpenAIChatCompletion.builder() + .withModelId(modelId) + .withOpenAIAsyncClient(client) + .build(); + + var plugin = KernelPluginFactory.createFromObject(new TransactionHistoryPlugin(), "TransactionHistoryPlugin"); + + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .withPlugin(plugin) + .build(); + } + + public AgentContext run (ChatHistory userChatHistory) { + LOGGER.info("======== HistoryAndTransaction Agent: Starting ========"); + + AgentContext agentContext = new AgentContext(); + + var agentChatHistory = new ChatHistory(HISTORY_AGENT_SYSTEM_MESSAGE); + userChatHistory.forEach( chatMessageContent -> { + if(chatMessageContent.getAuthorRole() != AuthorRole.SYSTEM) + agentChatHistory.addMessage(chatMessageContent); + }); + + + while (true) { + var messages = this.chat.getChatMessageContentsAsync( + agentChatHistory, + kernel, + InvocationContext.builder() + .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)).build()) + .block(); + + var message = messages.get(0); + agentContext.setResult(message.getContent()); + + + List toolCalls = messages.stream() + .filter(it -> it instanceof OpenAIChatMessageContent) + .map(it -> (OpenAIChatMessageContent) it) + .map(OpenAIChatMessageContent::getToolCall) + .flatMap(List::stream) + .collect(Collectors.toList()); + + if (toolCalls.isEmpty()) { + break; + } + + messages.stream() + .forEach(it -> agentChatHistory.addMessage(it)); + + for (var toolCall : toolCalls) { + + String content = null; + try { + // getFunction will throw an exception if the function is not found + var fn = kernel.getFunction(toolCall.getPluginName(), + toolCall.getFunctionName()); + FunctionResult fnResult = fn + .invokeAsync(kernel, toolCall.getArguments(), null, null).block(); + content = (String) fnResult.getResult(); + } catch (IllegalArgumentException e) { + content = "Unable to find function. Please try again!"; + } + + agentChatHistory.addMessage( + AuthorRole.TOOL, + content, + StandardCharsets.UTF_8, + new FunctionResultMetadata(new CaseInsensitiveMap<>() { + { + put(FunctionResultMetadata.ID, ContextVariable.of(toolCall.getId())); + } + })); + } + } + return agentContext; + } + + + + public static void main(String[] args) throws NoSuchMethodException { + + String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY"); + String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT"); + String MODEL_ID = System.getenv() + .getOrDefault("MODEL_ID", "gpt-3.5-turbo-1106"); + + HistoryReportingAgent agent = new HistoryReportingAgent(AZURE_CLIENT_KEY, CLIENT_ENDPOINT, MODEL_ID); + + agent.run(new ChatHistory()); + + + + } + } + + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentAgent.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentAgent.java new file mode 100644 index 0000000..51c5e7b --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentAgent.java @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.agent; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; +import com.microsoft.semantickernel.orchestration.*; +import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import org.json.JSONObject; + +public class IntentAgent { + + private OpenAIAsyncClient client; + + private Kernel kernel; + + private ChatCompletionService chat; + + private String INTENT_SYSTEM_MESSAGE = """ + You are a personal financial advisor who help the user with their recurrent bill payments. + The user may want to pay the bill uploading a photo of the bill, or it may start the payment checking payments history for a specific payee. + In other cases it may want to just review the payments history. + Based on the conversation you need to identify the user intent and ask the user for the missing information. + The available intents are: + "BillPayment", "RepeatTransaction","TransactionHistory" + If none of the intents are identified provide the user with the list of the available intents. + + If an intent is identified return the output as json format as below + { + "intent": "BillPayment" + } + + If none of the intents are identified ask the user for more clarity and list of the available intents. Use always a json format as output + { + "intent": "None" + "clarify_sentence": "" + } + + Don't add any comments in the output or other characters, just the json format. + """; + + public IntentAgent(OpenAIAsyncClient client, String modelId){ + this.client = client; + this.chat = OpenAIChatCompletion.builder() + .withModelId(modelId) + .withOpenAIAsyncClient(client) + .build(); + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .build(); + } + public IntentAgent(String azureClientKey, String clientEndpoint, String modelId){ + this.client = new OpenAIClientBuilder() + .credential(new AzureKeyCredential(azureClientKey)) + .endpoint(clientEndpoint) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .buildAsyncClient(); + + this.chat = OpenAIChatCompletion.builder() + .withModelId(modelId) + .withOpenAIAsyncClient(client) + .build(); + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .build(); + } + + public IntentResponse run(ChatHistory userChatHistory){ + var agentChatHistory = new ChatHistory(); + agentChatHistory.addAll(userChatHistory); + agentChatHistory.addSystemMessage(INTENT_SYSTEM_MESSAGE); + + + var messages = chat.getChatMessageContentsAsync( + agentChatHistory, + kernel, + InvocationContext.builder().withPromptExecutionSettings( + PromptExecutionSettings.builder() + .withTemperature(0.0) + .withTopP(1) + .withMaxTokens(200) + .build()) + .build()) + .block(); + + var message = messages.get(0); + + JSONObject json = new JSONObject(message.getContent()); + IntentType intentType = IntentType.valueOf(json.get("intent").toString()); + + return new IntentResponse(intentType,json); + } + + public static void main(String[] args) throws NoSuchMethodException { + + String AZURE_CLIENT_KEY = System.getenv("AZURE_CLIENT_KEY"); + String CLIENT_ENDPOINT = System.getenv("CLIENT_ENDPOINT"); + String MODEL_ID = System.getenv() + .getOrDefault("MODEL_ID", "gpt-3.5-turbo-1106"); + + IntentAgent agent = new IntentAgent(AZURE_CLIENT_KEY, CLIENT_ENDPOINT, MODEL_ID); + var chatHistory = new ChatHistory(); + // agent.run("when did I pay my last electricity bill?"); + //chatHistory.addUserMessage("when did I pay my last electricity bill?"); + chatHistory.addUserMessage("I want to pay my electricity bill"); + agent.run( chatHistory); + + } + } + + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentResponse.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentResponse.java new file mode 100644 index 0000000..a478c8b --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentResponse.java @@ -0,0 +1,27 @@ +package com.microsoft.openai.samples.assistant.agent; + + + +import org.json.JSONObject; + +public class IntentResponse { + + private IntentType intentType; + + private JSONObject jsonData; + + + + public IntentResponse(IntentType intentType, JSONObject jsonData) { + this.intentType = intentType; + this.jsonData = jsonData; + } + + public IntentType getIntentType() { + return intentType; + } + + public JSONObject getJsonData() { + return jsonData; + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentType.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentType.java new file mode 100644 index 0000000..9ecf129 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/IntentType.java @@ -0,0 +1,11 @@ +package com.microsoft.openai.samples.assistant.agent; + +public enum IntentType { + + BillPayment, + RepeatTransaction, + TransactionHistory, + None; + + +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/PaymentAgent.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/PaymentAgent.java new file mode 100644 index 0000000..21cf6cd --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/agent/PaymentAgent.java @@ -0,0 +1,158 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.agent; + +import com.azure.ai.documentintelligence.DocumentIntelligenceClient; +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.microsoft.openai.samples.assistant.controller.ChatController; +import com.microsoft.openai.samples.assistant.invoice.DocumentIntelligenceInvoiceScanHelper; +import com.microsoft.openai.samples.assistant.plugin.InvoiceScanPlugin; +import com.microsoft.openai.samples.assistant.plugin.PaymentPlugin; +import com.microsoft.openai.samples.assistant.plugin.TransactionHistoryPlugin; +import com.microsoft.openai.samples.assistant.proxy.BlobStorageProxy; +import com.microsoft.semantickernel.Kernel; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatCompletion; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIChatMessageContent; +import com.microsoft.semantickernel.aiservices.openai.chatcompletion.OpenAIFunctionToolCall; +import com.microsoft.semantickernel.contextvariables.CaseInsensitiveMap; +import com.microsoft.semantickernel.contextvariables.ContextVariable; +import com.microsoft.semantickernel.orchestration.FunctionResult; +import com.microsoft.semantickernel.orchestration.FunctionResultMetadata; +import com.microsoft.semantickernel.orchestration.InvocationContext; +import com.microsoft.semantickernel.orchestration.ToolCallBehavior; +import com.microsoft.semantickernel.plugin.KernelPluginFactory; +import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; +import com.microsoft.semantickernel.services.chatcompletion.ChatCompletionService; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; + +public class PaymentAgent { + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentAgent.class); + private OpenAIAsyncClient client; + + private Kernel kernel; + + private ChatCompletionService chat; + + private String PAYMENT_AGENT_SYSTEM_MESSAGE = """ + you are a personal financial advisor who help the user with their recurrent bill payments. The user may want to pay the bill uploading a photo of the bill, or it may start the payment checking transactions history for a specific payee. + For the bill payment you need to know the: bill id or invoice number, payee name, the total amount and the bill expiration date. + if you don't have enough information to pay the bill ask the user to provide the missing information. + you have the below functions available: + - paymentHistory: returns the list of the last payments based on the payee name + - payBill: it pays the bill based on the bill id or invoice number, payee name, total amount + - invoiceScan: it scans the invoice or bill photo to extract data + + Always check if the bill has been paid already based on payment history before asking to execute the bill payment. + Always ask for the payment method to use: direct debit, credit card, or bank transfer + Before executing the payBill function provide the user with the bill details and ask for confirmation. + If the payment succeeds provide the user with the payment confirmation. If not provide the user with the error message. + + """; + + public PaymentAgent(OpenAIAsyncClient client, String modelId, DocumentIntelligenceClient documentIntelligenceClient, BlobStorageProxy blobStorageProxy) { + this.client = client; + this.chat = OpenAIChatCompletion.builder() + .withModelId(modelId) + .withOpenAIAsyncClient(client) + .build(); + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .build(); + + var paymentPlugin = KernelPluginFactory.createFromObject(new PaymentPlugin(), "PaymentPlugin"); + var historyPlugin = KernelPluginFactory.createFromObject(new TransactionHistoryPlugin(), "TransactionHistoryPlugin"); + var invoiceScanPlugin = KernelPluginFactory.createFromObject(new InvoiceScanPlugin(new DocumentIntelligenceInvoiceScanHelper(documentIntelligenceClient,blobStorageProxy)), "InvoiceScanPlugin"); + + + kernel = Kernel.builder() + .withAIService(ChatCompletionService.class, chat) + .withPlugin(paymentPlugin) + .withPlugin(historyPlugin) + .withPlugin(invoiceScanPlugin) + .build(); + } + + + public AgentContext run (ChatHistory userChatHistory) { + LOGGER.info("======== Payment Agent: Starting ========"); + + AgentContext agentContext = new AgentContext(); + + var agentChatHistory = new ChatHistory(PAYMENT_AGENT_SYSTEM_MESSAGE); + + userChatHistory.forEach( chatMessageContent -> { + if(chatMessageContent.getAuthorRole() != AuthorRole.SYSTEM) + agentChatHistory.addMessage(chatMessageContent); + }); + + + + while (true) { + var messages = this.chat.getChatMessageContentsAsync( + agentChatHistory, + kernel, + InvocationContext.builder() + .withToolCallBehavior(ToolCallBehavior.allowAllKernelFunctions(true)).build()) + .block(); + + var message = messages.get(0); + + agentContext.setResult(message.getContent()); + + + List toolCalls = messages.stream() + .filter(it -> it instanceof OpenAIChatMessageContent) + .map(it -> (OpenAIChatMessageContent) it) + .map(OpenAIChatMessageContent::getToolCall) + .flatMap(List::stream) + .collect(Collectors.toList()); + + if (toolCalls.isEmpty()) { + break; + } + + messages.stream() + .forEach(it -> agentChatHistory.addMessage(it)); + + for (var toolCall : toolCalls) { + + String content = null; + try { + // getFunction will throw an exception if the function is not found + var fn = kernel.getFunction(toolCall.getPluginName(), + toolCall.getFunctionName()); + FunctionResult fnResult = fn + .invokeAsync(kernel, toolCall.getArguments(), null, null).block(); + content = (String) fnResult.getResult(); + } catch (IllegalArgumentException e) { + content = "Unable to find function. Please try again!"; + } + + agentChatHistory.addMessage( + AuthorRole.TOOL, + content, + StandardCharsets.UTF_8, + new FunctionResultMetadata(new CaseInsensitiveMap<>() { + { + put(FunctionResultMetadata.ID, ContextVariable.of(toolCall.getId())); + } + })); + } + } + return agentContext; + } + + + } + + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTConversation.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTConversation.java new file mode 100644 index 0000000..169d2c8 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTConversation.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.common; + +import com.azure.ai.openai.models.*; + +import java.util.List; + +public class ChatGPTConversation { + + private List messages; + private Integer tokenCount = 0; + + public ChatGPTConversation(List messages) { + this.messages = messages; + } + + public List toOpenAIChatMessages() { + return this.messages.stream() + .map( + message -> { + + ChatRole role = ChatRole.fromString( + message.role().toString()); + ChatRequestMessage chatMessage = null; + + if (role.equals(ChatRole.USER)) { + chatMessage = new ChatRequestUserMessage(message.content()); + } else if (role.equals(ChatRole.ASSISTANT)) { + chatMessage = new ChatRequestAssistantMessage(message.content()); + } else if (role.equals(ChatRole.SYSTEM)) { + chatMessage = new ChatRequestSystemMessage(message.content()); + } + return chatMessage; + }) + .toList(); + } + + public List getMessages() { + return messages; + } + + public void setMessages(List messages) { + this.messages = messages; + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTMessage.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTMessage.java new file mode 100644 index 0000000..a01f74c --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTMessage.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.common; + +import com.azure.core.util.ExpandableStringEnum; + +import java.util.Collection; + +public record ChatGPTMessage(ChatRole role, String content) { + + public static final class ChatRole extends ExpandableStringEnum { + public static final ChatRole SYSTEM = fromString("system"); + + public static final ChatRole ASSISTANT = fromString("assistant"); + + public static final ChatRole USER = fromString("user"); + + public static ChatRole fromString(String name) { + return fromString(name, ChatRole.class); + } + + public static Collection values() { + return values(ChatRole.class); + } + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTUtils.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTUtils.java new file mode 100644 index 0000000..e1fa121 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/common/ChatGPTUtils.java @@ -0,0 +1,98 @@ +package com.microsoft.openai.samples.assistant.common; + +import com.azure.ai.openai.models.*; +import com.microsoft.semantickernel.services.chatcompletion.AuthorRole; +import com.microsoft.semantickernel.services.chatcompletion.ChatMessageContent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ChatGPTUtils { + + public static ChatCompletionsOptions buildDefaultChatCompletionsOptions(List messages) { + ChatCompletionsOptions completionsOptions = new ChatCompletionsOptions(messages); + + completionsOptions.setMaxTokens(1024); + completionsOptions.setTemperature(0.1); + completionsOptions.setTopP(1.0); + //completionsOptions.setStop(new ArrayList<>(List.of("\n"))); + completionsOptions.setLogitBias(new HashMap<>()); + completionsOptions.setN(1); + completionsOptions.setStream(false); + completionsOptions.setUser("search-openai-demo-java"); + completionsOptions.setPresencePenalty(0.0); + completionsOptions.setFrequencyPenalty(0.0); + + return completionsOptions; + } + + private static final String IM_START_USER = "<|im_start|>user"; + private static final String IM_START_ASSISTANT = "<|im_start|>assistant"; + private static final String IM_START_SYSTEM = "<|im_start|>system"; + + public static String formatAsChatML(List messages) { + StringBuilder sb = new StringBuilder(); + messages.forEach(message -> { + String content = null; + if (message instanceof ChatRequestUserMessage) { + sb.append(IM_START_USER).append("\n"); + content = ((ChatRequestUserMessage) message).getContent().toString(); + } else if (message instanceof ChatRequestSystemMessage) { + sb.append(IM_START_SYSTEM).append("\n"); + content = ((ChatRequestSystemMessage) message).getContent(); + } else if (message instanceof ChatRequestAssistantMessage) { + sb.append(IM_START_ASSISTANT).append("\n"); + content = ((ChatRequestAssistantMessage) message).getContent(); + } + + if (content != null) { + sb.append(content).append("\n").append("|im_end|").append("\n"); + } + }); + return sb.toString(); + } + + public static List parseChatML(String chatML) { + List messages = new ArrayList<>(); + String[] messageTokens = chatML.split("\\|im_end\\|\\n"); + + for (String messageToken : messageTokens) { + String[] lines = messageToken.trim().split("\n"); + + if (lines.length >= 2) { + AuthorRole role = AuthorRole.SYSTEM; + if (IM_START_USER.equals(lines[0])) { + role = AuthorRole.USER; + } else if (IM_START_ASSISTANT.equals(lines[0])) { + role = AuthorRole.ASSISTANT; + } + + StringBuilder content = new StringBuilder(); + for (int i = 1; i < lines.length; ++i) { + content.append(lines[i]); + if (i < lines.length - 1) { + content.append("\n"); + } + } + + messages.add(new ChatMessageContent<>(role, content.toString())); + } + } + + return messages; + } + + public static String getLastUserQuestion(List messages) { + List userMessages = messages + .stream() + .filter(message -> message.role() == ChatGPTMessage.ChatRole.USER) + .toList(); + + if (!userMessages.isEmpty()) { + return userMessages.get(userMessages.size() - 1).content(); + } else { + return ""; + } + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/AzureAuthenticationConfiguration.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/AzureAuthenticationConfiguration.java new file mode 100644 index 0000000..a1dc228 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/AzureAuthenticationConfiguration.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.config; + +import com.azure.core.credential.TokenCredential; +import com.azure.identity.AzureCliCredentialBuilder; +import com.azure.identity.EnvironmentCredentialBuilder; +import com.azure.identity.ManagedIdentityCredentialBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +public class AzureAuthenticationConfiguration { + + @Value("${azure.identity.client-id}") + String clientId; + + @Profile("dev") + @Bean + public TokenCredential localTokenCredential() { + return new AzureCliCredentialBuilder().build(); + } + + @Profile("docker") + @Bean + public TokenCredential servicePrincipalTokenCredential() { + return new EnvironmentCredentialBuilder().build(); + } + + @Bean + @Profile("default") + public TokenCredential managedIdentityTokenCredential() { + if (this.clientId.equals("system-managed-identity")) + return new ManagedIdentityCredentialBuilder().build(); + else + return new ManagedIdentityCredentialBuilder().clientId(this.clientId).build(); + + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/DocumentIntelligenceConfiguration.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/DocumentIntelligenceConfiguration.java new file mode 100644 index 0000000..3983020 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/DocumentIntelligenceConfiguration.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.config; + +import com.azure.ai.documentintelligence.DocumentIntelligenceClient; +import com.azure.ai.documentintelligence.DocumentIntelligenceClientBuilder; +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.credential.TokenCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DocumentIntelligenceConfiguration { + + @Value("${documentintelligence.service}") + String documentIntelligenceServiceName; + + final TokenCredential tokenCredential; + + public DocumentIntelligenceConfiguration(TokenCredential tokenCredential) { + this.tokenCredential = tokenCredential; + } + + @Bean + public DocumentIntelligenceClient documentIntelligenceClient() { + String endpoint = "https://%s.cognitiveservices.azure.com".formatted(documentIntelligenceServiceName); + + return new DocumentIntelligenceClientBuilder() + .credential(tokenCredential) + .endpoint(endpoint) + .buildClient(); + } + +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/OpenAIConfiguration.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/OpenAIConfiguration.java new file mode 100644 index 0000000..9488d5a --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/config/OpenAIConfiguration.java @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.config; + +import com.azure.ai.openai.OpenAIAsyncClient; +import com.azure.ai.openai.OpenAIClient; +import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.TokenCredential; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class OpenAIConfiguration { + + @Value("${openai.service}") + String openAIServiceName; + + @Value("${openai.chatgpt.deployment}") + private String gptChatDeploymentModelId; + + final TokenCredential tokenCredential; + + public OpenAIConfiguration(TokenCredential tokenCredential) { + this.tokenCredential = tokenCredential; + } + + @Bean + @ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "true") + public OpenAIClient openAItracingEnabledClient() { + String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName); + + var httpLogOptions = new HttpLogOptions(); + // httpLogOptions.setPrettyPrintBody(true); + httpLogOptions.setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS); + + return new OpenAIClientBuilder() + .endpoint(endpoint) + .credential(tokenCredential) + .httpLogOptions(httpLogOptions) + .buildClient(); + } + + @Bean + @ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "false") + public OpenAIClient openAIDefaultClient() { + String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName); + return new OpenAIClientBuilder() + .endpoint(endpoint) + .credential(tokenCredential) + .buildClient(); + } + + @Bean + @ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "true") + public OpenAIAsyncClient tracingEnabledAsyncClient() { + String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName); + + var httpLogOptions = new HttpLogOptions(); + httpLogOptions.setPrettyPrintBody(true); + httpLogOptions.setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS); + + return new OpenAIClientBuilder() + .endpoint(endpoint) + .credential(tokenCredential) + .httpLogOptions(httpLogOptions) + .buildAsyncClient(); + } + + @Bean + @ConditionalOnProperty(name = "openai.tracing.enabled", havingValue = "false") + public OpenAIAsyncClient defaultAsyncClient() { + String endpoint = "https://%s.openai.azure.com".formatted(openAIServiceName); + return new OpenAIClientBuilder() + .endpoint(endpoint) + .credential(tokenCredential) + .buildAsyncClient(); + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequest.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequest.java new file mode 100644 index 0000000..0a50218 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequest.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +import java.util.List; + +public record ChatAppRequest( + List messages, + ChatAppRequestContext context, + boolean stream, + String approach) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestContext.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestContext.java new file mode 100644 index 0000000..04f1cff --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestContext.java @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +public record ChatAppRequestContext(ChatAppRequestOverrides overrides) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestOverrides.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestOverrides.java new file mode 100644 index 0000000..2d10422 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatAppRequestOverrides.java @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +public record ChatAppRequestOverrides( + boolean semantic_ranker, + boolean semantic_captions, + String exclude_category, + int top, + float temperature, + String prompt_template, + String prompt_template_prefix, + String prompt_template_suffix, + boolean suggest_followup_questions, + boolean use_oid_security_filter, + boolean use_groups_security_filter, + String semantic_kernel_mode) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatController.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatController.java new file mode 100644 index 0000000..3707a0a --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatController.java @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +import com.azure.ai.documentintelligence.DocumentIntelligenceClient; +import com.azure.ai.openai.OpenAIAsyncClient; +import com.microsoft.openai.samples.assistant.agent.*; + + +import com.microsoft.openai.samples.assistant.proxy.BlobStorageProxy; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + + + +import java.util.List; + +@RestController +public class ChatController { + + private static final Logger LOGGER = LoggerFactory.getLogger(ChatController.class); + + private final IntentAgent intentAgent; + private final PaymentAgent paymentAgent; + private final HistoryReportingAgent historyReportingAgent; + + public ChatController(OpenAIAsyncClient openAIAsyncClient, DocumentIntelligenceClient documentIntelligenceClient, BlobStorageProxy blobStorageProxy, @Value("${openai.chatgpt.deployment}") String gptChatDeploymentModelId){ + this.intentAgent = new IntentAgent(openAIAsyncClient,gptChatDeploymentModelId); + this.paymentAgent = new PaymentAgent(openAIAsyncClient,gptChatDeploymentModelId,documentIntelligenceClient,blobStorageProxy); + this.historyReportingAgent = new HistoryReportingAgent(openAIAsyncClient,gptChatDeploymentModelId); + + } + + + @PostMapping(value = "/api/chat", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity openAIAsk(@RequestBody ChatAppRequest chatRequest) { + if (chatRequest.stream()) { + LOGGER.warn( + "Requested a content-type of application/json however also requested streaming." + + " Please use a content-type of application/ndjson"); + throw new ResponseStatusException( + HttpStatus.BAD_REQUEST, + "Requested a content-type of application/json however also requested streaming." + + " Please use a content-type of application/ndjson"); + } + + LOGGER.info("Received request for chat api with approach[{}]", chatRequest.approach()); + + if (chatRequest.messages() == null || chatRequest.messages().isEmpty()) { + LOGGER.warn("history cannot be null in Chat request"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); + } + + ChatHistory chatHistory = convertSKChatHistory(chatRequest.messages()); + + LOGGER.info("Processing chat conversation..", chatHistory.getLastMessage().get().getContent()); + + IntentResponse response = intentAgent.run(chatHistory); + + LOGGER.info("Intent Type for chat conversation: {}", response.getIntentType()); + if (response.getIntentType() == IntentType.None) { + chatHistory.addAssistantMessage(response.getJsonData().get("clarify_sentence").toString()); + } + + + if (response.getIntentType() == IntentType.BillPayment || response.getIntentType() == IntentType.RepeatTransaction) { + var agentContext = paymentAgent.run(chatHistory); + chatHistory.addAssistantMessage(agentContext.getResult()); + } + + if (response.getIntentType() == IntentType.TransactionHistory) { + var agentContext = historyReportingAgent.run(chatHistory); + chatHistory.addAssistantMessage(agentContext.getResult()); + } + + return ResponseEntity.ok( + ChatResponse.buildChatResponse(chatHistory)); + } + + private ChatHistory convertSKChatHistory(List protocolChatHistory) { + ChatHistory chatHistory = new ChatHistory(false); + protocolChatHistory.forEach( + historyChat -> { + if("user".equals(historyChat.role())) + chatHistory.addUserMessage(historyChat.content()); + + if("assistant".equals(historyChat.role())) + chatHistory.addAssistantMessage(historyChat.content()); + }); + + return chatHistory; + + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatResponse.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatResponse.java new file mode 100644 index 0000000..ec1ee2a --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ChatResponse.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + + +import com.microsoft.openai.samples.assistant.common.ChatGPTMessage; +import com.microsoft.semantickernel.services.chatcompletion.ChatHistory; + +import java.util.Collections; +import java.util.List; + +public record ChatResponse(List choices) { + + public static ChatResponse buildChatResponse(ChatHistory chatHistory) { + List dataPoints = Collections.emptyList(); + + + + String thoughts = ""; + + + return new ChatResponse( + List.of( + new ResponseChoice( + 0, + new ResponseMessage( + chatHistory.getLastMessage().get().getContent(), + ChatGPTMessage.ChatRole.ASSISTANT.toString()), + new ResponseContext(thoughts, dataPoints), + new ResponseMessage( + chatHistory.getLastMessage().get().getContent(), + ChatGPTMessage.ChatRole.ASSISTANT.toString())))); + } + +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseChoice.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseChoice.java new file mode 100644 index 0000000..448222e --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseChoice.java @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +public record ResponseChoice( + int index, ResponseMessage message, ResponseContext context, ResponseMessage delta) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseContext.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseContext.java new file mode 100644 index 0000000..f063fdd --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseContext.java @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +import java.util.List; + +public record ResponseContext(String thoughts, List data_points) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseMessage.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseMessage.java new file mode 100644 index 0000000..074cef1 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/ResponseMessage.java @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller; + +public record ResponseMessage(String content, String role) {} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/auth/AuthSetup.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/auth/AuthSetup.java new file mode 100644 index 0000000..9e01deb --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/auth/AuthSetup.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller.auth; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class AuthSetup { + + @GetMapping("/api/auth_setup") + public String authSetup() { + return """ + { + "useLogin": false + } + """ + .stripIndent(); + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/content/ContentController.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/content/ContentController.java new file mode 100644 index 0000000..572d5cc --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/controller/content/ContentController.java @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.controller.content; + + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; + +import com.microsoft.openai.samples.assistant.proxy.BlobStorageProxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.MimeTypeUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ContentController { + + private static final Logger LOGGER = LoggerFactory.getLogger(ContentController.class); + private final BlobStorageProxy blobStorageProxy; + + ContentController(BlobStorageProxy blobStorageProxy) { + this.blobStorageProxy = blobStorageProxy; + } + + @GetMapping("/api/content/{fileName}") + public ResponseEntity getContent(@PathVariable String fileName) { + LOGGER.info("Received request for content with name [{}] ]", fileName); + + if (!StringUtils.hasText(fileName)) { + LOGGER.warn("file name cannot be null"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); + } + + String mimeType = URLConnection.guessContentTypeFromName(fileName); + + MediaType contentType = new MediaType(MimeTypeUtils.parseMimeType(mimeType)); + + InputStream fileInputStream; + + try { + fileInputStream = new ByteArrayInputStream(blobStorageProxy.getFileAsBytes(fileName)); + } catch (IOException ex) { + LOGGER.error("Cannot retrieve file [{}] from blob.{}", fileName, ex.getMessage()); + return ResponseEntity.notFound().build(); + } + + return ResponseEntity.ok() + .header("Content-Disposition", "inline; filename=%s".formatted(fileName)) + .contentType(contentType) + .body(new InputStreamResource(fileInputStream)); + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/invoice/DocumentIntelligenceInvoiceScanHelper.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/invoice/DocumentIntelligenceInvoiceScanHelper.java new file mode 100644 index 0000000..db0eae7 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/invoice/DocumentIntelligenceInvoiceScanHelper.java @@ -0,0 +1,127 @@ +package com.microsoft.openai.samples.assistant.invoice; + + + +import com.azure.ai.documentintelligence.DocumentIntelligenceClient; +import com.azure.ai.documentintelligence.DocumentIntelligenceClientBuilder; +import com.azure.ai.documentintelligence.models.*; +import com.azure.core.credential.AzureKeyCredential; +import com.azure.core.util.polling.SyncPoller; +import com.microsoft.openai.samples.assistant.agent.HistoryReportingAgent; +import com.microsoft.openai.samples.assistant.proxy.BlobStorageProxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; + +public class DocumentIntelligenceInvoiceScanHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(DocumentIntelligenceInvoiceScanHelper.class); + + private final DocumentIntelligenceClient client; + + private final BlobStorageProxy blobStorageProxy; + + private final String modelId; + + public DocumentIntelligenceInvoiceScanHelper(DocumentIntelligenceClient client, BlobStorageProxy blobStorageProxy){ + this.client = client; + this.modelId = "prebuilt-invoice"; + this.blobStorageProxy = blobStorageProxy; + } + + public Map scan(String blobName) throws IOException { + + LOGGER.info("Retrieving blob file with name [{}]", blobName); + + byte[] blobData = blobStorageProxy.getFileAsBytes(blobName); + + LOGGER.info("Found blob file with name [{}] and size [{}]", blobName,blobData.length); + SyncPoller analyzeInvoicePoller = + client.beginAnalyzeDocument("prebuilt-invoice", + null, + null, + null, + null, + null, + null, new AnalyzeDocumentRequest().setBase64Source(blobStorageProxy.getFileAsBytes(blobName))); + + return internalScan(analyzeInvoicePoller); + + } + public Map scan (File file) throws IOException { + + SyncPoller analyzeInvoicePoller = + client.beginAnalyzeDocument("prebuilt-invoice", + null, + null, + null, + null, + null, + null, new AnalyzeDocumentRequest().setBase64Source(Files.readAllBytes(file.toPath()))); + + return internalScan(analyzeInvoicePoller); + + } + + private Map internalScan(SyncPoller analyzeInvoicePoller) { + AnalyzeResult analyzeInvoiceResult = analyzeInvoicePoller.getFinalResult().getAnalyzeResult(); + + LOGGER.info("Document intelligence analysis completed.Start extracting data.." ); + + Map scanData = new HashMap<>(); + + for (int i = 0; i < analyzeInvoiceResult.getDocuments().size(); i++) { + Document analyzedInvoice = analyzeInvoiceResult.getDocuments().get(i); + Map invoiceFields = analyzedInvoice.getFields(); + + DocumentField vendorNameField = invoiceFields.get("VendorName"); + if (vendorNameField != null) { + if (DocumentFieldType.STRING == vendorNameField.getType()) { + scanData.put("VendorName", vendorNameField.getValueString()); + } + } + + DocumentField vendorAddressField = invoiceFields.get("VendorAddress"); + if (vendorAddressField != null) { + scanData.put("VendorAddress", vendorAddressField.getContent()); + } + + DocumentField customerNameField = invoiceFields.get("CustomerName"); + if (customerNameField != null) { + scanData.put("CustomerName", customerNameField.getValueString()); + } + + DocumentField customerAddressRecipientField = invoiceFields.get("CustomerAddressRecipient"); + if (customerAddressRecipientField != null) { + scanData.put("CustomerAddressRecipient", customerAddressRecipientField.getValueString()); + } + + DocumentField invoiceIdField = invoiceFields.get("InvoiceId"); + if (invoiceIdField != null) { + scanData.put("InvoiceId", invoiceIdField.getValueString()); + } + + DocumentField invoiceDateField = invoiceFields.get("InvoiceDate"); + if (invoiceDateField != null) { + scanData.put("InvoiceDate", invoiceDateField.getValueDate().toString()); + + } + + DocumentField invoiceTotalField = invoiceFields.get("InvoiceTotal"); + if (invoiceTotalField != null) { + scanData.put("InvoiceTotal", invoiceTotalField.getContent()); + + } + + + + } + return scanData; + } + + +} \ No newline at end of file diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/InvoiceScanPlugin.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/InvoiceScanPlugin.java new file mode 100644 index 0000000..aded68f --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/InvoiceScanPlugin.java @@ -0,0 +1,89 @@ +package com.microsoft.openai.samples.assistant.plugin; + +import com.microsoft.openai.samples.assistant.agent.HistoryReportingAgent; +import com.microsoft.openai.samples.assistant.invoice.DocumentIntelligenceInvoiceScanHelper; +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + + +/** + * reference: https://learn.microsoft.com/en-us/java/api/overview/azure/ai-openai-readme?view=azure-java-preview + * + * { + * "enhancements": { + * "ocr": { + * "enabled": true + * }, + * "grounding": { + * "enabled": true + * } + * }, + * "data_sources": [ + * { + * "type": "AzureComputerVision", + * "parameters": { + * "endpoint": "", + * "key": "" + * } + * }], + * "messages": [ + * { + * "role": "system", + * "content": "You are a helpful assistant." + * }, + * { + * "role": "user", + * "content": [ + * { + * "type": "text", + * "text": "Describe this picture:" + * }, + * { + * "type": "image_url", + * "image_url": { + * "url":"" + * } + * } + * ] + * } + * ], + * "max_tokens": 100, + * "stream": false + * } + */ +public class InvoiceScanPlugin { + + private static final Logger LOGGER = LoggerFactory.getLogger(InvoiceScanPlugin.class); + private final DocumentIntelligenceInvoiceScanHelper documentIntelligenceInvoiceScanHelper; + public InvoiceScanPlugin(DocumentIntelligenceInvoiceScanHelper documentIntelligenceInvoiceScanHelper) { + this.documentIntelligenceInvoiceScanHelper = documentIntelligenceInvoiceScanHelper; + } + @DefineKernelFunction(name = "scanInvoice", description = "Extract the invoice or bill data scanning a photo or image") + public String scanInvoice( + @KernelFunctionParameter(name = "filaPath", description = "the path to the file containing the image or photo") String filePath) { + + Map scanData = null; + + try{ + scanData = documentIntelligenceInvoiceScanHelper.scan(filePath); + } catch (Exception e) { + LOGGER.warn("Error extracting data from invoice {}:", filePath,e); + scanData = new HashMap<>(); + } + + LOGGER.info("Data extracted from invoice {}:{}", filePath,scanData); + return scanData.toString(); + + } + + + + +} + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentPlugin.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentPlugin.java new file mode 100644 index 0000000..5b28797 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentPlugin.java @@ -0,0 +1,25 @@ +package com.microsoft.openai.samples.assistant.plugin; + +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; + +import java.util.ArrayList; +import java.util.List; + +public class PaymentPlugin { + + + @DefineKernelFunction(name = "payBill", description = "Gets the last payment transactions based on the payee, recipient name") + public String submitBillPayment( + @KernelFunctionParameter(name = "recipientName", description = "Name of the payee, recipient") String recipientName, + @KernelFunctionParameter(name = "documentId", description = " the bill id or invoice number") String documentID, + @KernelFunctionParameter(name = "amount", description = "the total amount to pay") String amount) { + + System.out.println("Bill payment executed for recipient: " + recipientName + " with documentId: " + documentID + " and amount: " + amount); + + return "Payment Successful"; + + } + +} + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentTransaction.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentTransaction.java new file mode 100644 index 0000000..9121ca0 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/PaymentTransaction.java @@ -0,0 +1,4 @@ +package com.microsoft.openai.samples.assistant.plugin; + +public record PaymentTransaction(String transactionId, String documentId, String recipientName, String amount, String transactionDatetime) {} + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionHistoryPlugin.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionHistoryPlugin.java new file mode 100644 index 0000000..d836ad3 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionHistoryPlugin.java @@ -0,0 +1,40 @@ +package com.microsoft.openai.samples.assistant.plugin; + +import com.microsoft.semantickernel.semanticfunctions.annotations.DefineKernelFunction; +import com.microsoft.semantickernel.semanticfunctions.annotations.KernelFunctionParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class TransactionHistoryPlugin { + private static final Logger LOGGER = LoggerFactory.getLogger(TransactionHistoryPlugin.class); + private final TransactionService transactionService; + public TransactionHistoryPlugin(){ + this.transactionService = new TransactionService(); + } + + @DefineKernelFunction(name = "getTransactionsByRecepient", description = "Gets the last payment transactions based on the payee, recipient name") + public String getTransactionsByRecepient( + @KernelFunctionParameter(name = "recipientName", description = "Name of the payee, recipient") String recipientName) { + String transactionsByRecipient = transactionService.getTransactionsByRecipientName(recipientName).toString(); + LOGGER.info("Transactions for [{}]:{} ",recipientName,transactionsByRecipient); + return transactionsByRecipient; + + + } + + + @DefineKernelFunction(name = "getTransactions", description = "Gets the last payment transactions") + public String getTransactions() { + String lastTransactions = transactionService.getlastTransactions().toString(); + LOGGER.info("Last transactions:{} ",lastTransactions); + return lastTransactions; + + + } + + +} + diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionService.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionService.java new file mode 100644 index 0000000..e138b90 --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/plugin/TransactionService.java @@ -0,0 +1,51 @@ +package com.microsoft.openai.samples.assistant.plugin; + +import java.util.ArrayList; +import java.util.List; + +public class TransactionService { + + private List plumberTransactions = new ArrayList<>(); + + private List electricianTransactions = new ArrayList<>(); + + private List lastTransactions = new ArrayList<>(); + + public TransactionService(){ + + plumberTransactions.add(new PaymentTransaction("11", "0001", "Bill ThePlumber", "100.00", "2024-4-01T12:00:00Z")); + plumberTransactions.add(new PaymentTransaction("21", "0002", "Bill ThePlumber", "200.00", "2024-1-02T12:00:00Z")); + plumberTransactions.add(new PaymentTransaction("31", "0003", "Bill ThePlumber", "300.00", "2023-10-03T12:00:00Z")); + plumberTransactions.add(new PaymentTransaction("41", "0004", "Bill ThePlumber", "400.00", "2023-8-04T12:00:00Z")); + plumberTransactions.add(new PaymentTransaction("51", "0005", "Bill ThePlumber", "500.00", "2023-4-05T12:00:00Z")); + + + electricianTransactions.add(new PaymentTransaction("12", "0001", "Jane TheElectrician", "100.00", "2024-3-01T12:00:00Z")); + electricianTransactions.add(new PaymentTransaction("22", "0002", "Jane TheElectrician", "200.00", "2023-1-02T12:00:00Z")); + electricianTransactions.add(new PaymentTransaction("32", "0003", "Jane TheElectrician", "300.00", "2022-10-03T12:00:00Z")); + electricianTransactions.add(new PaymentTransaction("42", "0004", "Jane TheElectrician", "400.00", "2022-8-04T12:00:00Z")); + electricianTransactions.add(new PaymentTransaction("52", "0005", "Jane TheElectrician", "500.00", "2020-4-05T12:00:00Z")); + + + lastTransactions.add(new PaymentTransaction("11", "0001", "Bill ThePlumber", "100.00", "2024-4-01T12:00:00Z")); + lastTransactions.add(new PaymentTransaction("22", "0002", "Jane TheElectrician", "200.00", "2024-3-02T12:00:00Z")); + lastTransactions.add(new PaymentTransaction("33", "0003", "Bob TheCarpenter", "300.00", "2023-10-03T12:00:00Z")); + lastTransactions.add(new PaymentTransaction("43", "0004", "Alice ThePainter", "400.00", "2023-8-04T12:00:00Z")); + lastTransactions.add(new PaymentTransaction("53", "0005", "Charlie TheMechanic", "500.00", "2023-4-05T12:00:00Z")); + } + public List getTransactionsByRecipientName(String name) { + switch (name){ + case "Bill ThePlumber": + return plumberTransactions; + case "Jane TheElectrician": + return electricianTransactions; + default: + return lastTransactions; + } + } + + public List getlastTransactions() { + return lastTransactions; + } + +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/BlobStorageProxy.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/BlobStorageProxy.java new file mode 100644 index 0000000..dbf601e --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/BlobStorageProxy.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.proxy; + +import com.azure.core.credential.TokenCredential; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobContainerClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * This class is a proxy to the Blob storage API. It is responsible for: - calling the API - + * handling errors and retry strategy - add monitoring points - add circuit breaker with exponential + * backoff + */ +@Component +public class BlobStorageProxy { + + private final BlobContainerClient client; + + public BlobStorageProxy( + @Value("${storage-account.service}") String storageAccountServiceName, + @Value("${blob.container.name}") String containerName, + TokenCredential tokenCredential) { + + String endpoint = "https://%s.blob.core.windows.net".formatted(storageAccountServiceName); + this.client = + new BlobContainerClientBuilder() + .endpoint(endpoint) + .credential(tokenCredential) + .containerName(containerName) + .buildClient(); + } + + public byte[] getFileAsBytes(String fileName) throws IOException { + var blobClient = client.getBlobClient(fileName); + int dataSize = (int) blobClient.getProperties().getBlobSize(); + + // There is no need to close ByteArrayOutputStream. + // https://docs.oracle.com/javase/8/docs/api/java/io/ByteArrayOutputStream.html + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(dataSize); + blobClient.downloadStream(outputStream); + + return outputStream.toByteArray(); + } +} diff --git a/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/OpenAIProxy.java b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/OpenAIProxy.java new file mode 100644 index 0000000..182cd9d --- /dev/null +++ b/app/backend/src/main/java/com/microsoft/openai/samples/assistant/proxy/OpenAIProxy.java @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. +package com.microsoft.openai.samples.assistant.proxy; + +import com.azure.ai.openai.OpenAIClient; +import com.azure.ai.openai.models.*; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.util.IterableStream; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; + +/** + * This class is a proxy to the OpenAI API to simplify cross-cutting concerns management (security, + * load balancing, monitoring, resiliency). It is responsible for: - calling the OpenAI API - + * handling errors and retry strategy - load balance requests across open AI instances - add + * monitoring points - add circuit breaker with exponential backoff + * + *

It also makes unit testing easy using mockito to provide mock implementation for this bean. + */ +@Component +public class OpenAIProxy { + + private final OpenAIClient client; + + @Value("${openai.chatgpt.deployment}") + private String gptChatDeploymentModelId; + + @Value("${openai.embedding.deployment}") + private String embeddingDeploymentModelId; + + public OpenAIProxy(OpenAIClient client) { + this.client = client; + } + + public Completions getCompletions(CompletionsOptions completionsOptions) { + Completions completions; + try { + completions = client.getCompletions(this.gptChatDeploymentModelId, completionsOptions); + } catch (HttpResponseException e) { + throw new ResponseStatusException( + e.getResponse().getStatusCode(), "Error calling OpenAI API:" + e.getValue(), e); + } + return completions; + } + + public Completions getCompletions(String prompt) { + + Completions completions; + try { + completions = client.getCompletions(this.gptChatDeploymentModelId, prompt); + } catch (HttpResponseException e) { + throw new ResponseStatusException( + e.getResponse().getStatusCode(), + "Error calling OpenAI API:" + e.getMessage(), + e); + } + return completions; + } + + public ChatCompletions getChatCompletions(ChatCompletionsOptions chatCompletionsOptions) { + ChatCompletions chatCompletions; + try { + chatCompletions = + client.getChatCompletions( + this.gptChatDeploymentModelId, chatCompletionsOptions); + } catch (HttpResponseException e) { + throw new ResponseStatusException( + e.getResponse().getStatusCode(), + "Error calling OpenAI API:" + e.getMessage(), + e); + } + return chatCompletions; + } + + public IterableStream getChatCompletionsStream( + ChatCompletionsOptions chatCompletionsOptions) { + try { + return client.getChatCompletionsStream( + this.gptChatDeploymentModelId, chatCompletionsOptions); + } catch (HttpResponseException e) { + throw new ResponseStatusException( + e.getResponse().getStatusCode(), + "Error calling OpenAI API:" + e.getMessage(), + e); + } + } + + public Embeddings getEmbeddings(List texts) { + Embeddings embeddings; + try { + EmbeddingsOptions embeddingsOptions = new EmbeddingsOptions(texts); + embeddingsOptions.setUser("search-openai-demo-java"); + embeddingsOptions.setModel(this.embeddingDeploymentModelId); + embeddingsOptions.setInputType("query"); + embeddings = client.getEmbeddings(this.embeddingDeploymentModelId, embeddingsOptions); + } catch (HttpResponseException e) { + throw new ResponseStatusException( + e.getResponse().getStatusCode(), + "Error calling OpenAI API:" + e.getMessage(), + e); + } + return embeddings; + } +} diff --git a/app/backend/src/main/resources/application.properties b/app/backend/src/main/resources/application.properties new file mode 100644 index 0000000..2133743 --- /dev/null +++ b/app/backend/src/main/resources/application.properties @@ -0,0 +1,18 @@ +#Used to enable mocked class to take precedence over real class in unit tests +spring.main.lazy-initialization=true + +openai.service=${AZURE_OPENAI_SERVICE} +openai.chatgpt.deployment=${AZURE_OPENAI_CHATGPT_DEPLOYMENT:chat} +openai.tracing.enabled=${AZURE_OPENAI_TRACING_ENABLED:true} + +documentintelligence.service=${AZURE_DOCUMENT_INTELLIGENCE_SERVICE:example} + + +storage-account.service=${AZURE_STORAGE_ACCOUNT} +blob.container.name=${AZURE_STORAGE_CONTAINER:content} + +logging.level.com.microsoft.openai.samples.rag.ask.approaches.semantickernel=DEBUG +server.error.include-message=always + +# Support for User Assigned Managed identity +azure.identity.client-id=${AZURE_CLIENT_ID:system-managed-identity} \ No newline at end of file diff --git a/app/frontend/.dockerignore b/app/frontend/.dockerignore new file mode 100644 index 0000000..a1ee4db --- /dev/null +++ b/app/frontend/.dockerignore @@ -0,0 +1,2 @@ +manifests +node_modules \ No newline at end of file diff --git a/app/frontend/.env.dev b/app/frontend/.env.dev new file mode 100644 index 0000000..e34f261 --- /dev/null +++ b/app/frontend/.env.dev @@ -0,0 +1 @@ +VITE_BACKEND_URI=http://127.0.0.1:8081/api diff --git a/app/frontend/.env.local b/app/frontend/.env.local new file mode 100644 index 0000000..e34f261 --- /dev/null +++ b/app/frontend/.env.local @@ -0,0 +1 @@ +VITE_BACKEND_URI=http://127.0.0.1:8081/api diff --git a/app/frontend/.env.production b/app/frontend/.env.production new file mode 100644 index 0000000..c00db2d --- /dev/null +++ b/app/frontend/.env.production @@ -0,0 +1,2 @@ +VITE_BACKEND_URI=/api + diff --git a/app/frontend/.npmrc b/app/frontend/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/app/frontend/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/app/frontend/.prettierignore b/app/frontend/.prettierignore new file mode 100644 index 0000000..fc355bc --- /dev/null +++ b/app/frontend/.prettierignore @@ -0,0 +1,2 @@ +# Ignore JSON +**/*.json diff --git a/app/frontend/.prettierrc.json b/app/frontend/.prettierrc.json new file mode 100644 index 0000000..b7d6774 --- /dev/null +++ b/app/frontend/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "tabWidth": 4, + "printWidth": 160, + "arrowParens": "avoid", + "trailingComma": "none" +} diff --git a/app/frontend/Dockerfile b/app/frontend/Dockerfile new file mode 100644 index 0000000..670144c --- /dev/null +++ b/app/frontend/Dockerfile @@ -0,0 +1,21 @@ +FROM node:18-alpine AS build + +# make the 'app' folder the current working directory +WORKDIR /app + +COPY . . + + +# install project dependencies +RUN npm install +RUN npm run build + +FROM nginx:alpine + +WORKDIR /usr/share/nginx/html +COPY --from=build /app/build . +COPY --from=build /app/nginx/nginx.conf.template /etc/nginx/conf.d + +EXPOSE 80 + +CMD ["/bin/sh", "-c", "envsubst < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf && nginx -g \"daemon off;\""] diff --git a/app/frontend/Dockerfile-aks b/app/frontend/Dockerfile-aks new file mode 100644 index 0000000..3041dbf --- /dev/null +++ b/app/frontend/Dockerfile-aks @@ -0,0 +1,20 @@ +FROM node:18-alpine AS build + +# make the 'app' folder the current working directory +WORKDIR /app + +COPY . . + + +# install project dependencies +RUN npm install +RUN npm run build + +FROM nginx:alpine + +WORKDIR /usr/share/nginx/html +COPY --from=build /app/build . + +EXPOSE 80 + +CMD ["/bin/sh", "-c", "nginx -g \"daemon off;\""] \ No newline at end of file diff --git a/app/frontend/index.html b/app/frontend/index.html new file mode 100644 index 0000000..e4081a0 --- /dev/null +++ b/app/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + GPT + Enterprise data | Java Sample + + +

+ + + diff --git a/app/frontend/manifests/frontend-deployment.tmpl.yml b/app/frontend/manifests/frontend-deployment.tmpl.yml new file mode 100644 index 0000000..1eac564 --- /dev/null +++ b/app/frontend/manifests/frontend-deployment.tmpl.yml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend-deployment + namespace: azure-open-ai + labels: + app: frontend +spec: + replicas: 1 + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: {{.Env.SERVICE_FRONTEND_IMAGE_NAME}} + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + envFrom: + - configMapRef: + name: azd-env-configmap diff --git a/app/frontend/manifests/frontend-service.yml b/app/frontend/manifests/frontend-service.yml new file mode 100644 index 0000000..2fabe3f --- /dev/null +++ b/app/frontend/manifests/frontend-service.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend-service + namespace: azure-open-ai +spec: + type: ClusterIP + ports: + - protocol: TCP + port: 80 + targetPort: 80 + selector: + app: frontend diff --git a/app/frontend/nginx/nginx.conf.template b/app/frontend/nginx/nginx.conf.template new file mode 100644 index 0000000..cafa824 --- /dev/null +++ b/app/frontend/nginx/nginx.conf.template @@ -0,0 +1,13 @@ +server { + listen 80; + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + location /api { + proxy_ssl_server_name on; + proxy_http_version 1.1; + proxy_pass $REACT_APP_API_BASE_URL; + } +} \ No newline at end of file diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json new file mode 100644 index 0000000..f7a19b7 --- /dev/null +++ b/app/frontend/package-lock.json @@ -0,0 +1,5592 @@ +{ + "name": "frontend", + "version": "1.0.0-alpha", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "1.0.0-alpha", + "dependencies": { + "@azure/msal-browser": "^3.1.0", + "@azure/msal-react": "^2.0.4", + "@fluentui/react": "^8.112.5", + "@fluentui/react-components": "^9.37.3", + "@fluentui/react-icons": "^2.0.221", + "@react-spring/web": "^9.7.3", + "dompurify": "^3.0.6", + "ndjson-readablestream": "^1.0.7", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.18.0", + "scheduler": "^0.20.2" + }, + "devDependencies": { + "@types/dompurify": "^3.0.3", + "@types/react": "^18.2.34", + "@types/react-dom": "^18.2.14", + "@vitejs/plugin-react": "^4.1.1", + "prettier": "^3.0.3", + "typescript": "^5.2.2", + "vite": "^4.5.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.2.0.tgz", + "integrity": "sha512-le2qutddMiq0i3ErQaLKuwP1DpNgdd9iXPs3fSCsLuBrdGg9B4/j4ArCAHCwgxA82Ydj9BcqtMIL5BSWwU+P5A==", + "dependencies": { + "@azure/msal-common": "14.1.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.1.0.tgz", + "integrity": "sha512-xphmhcfl5VL+uq5//VKMwQn+wfEZLMKNpFCcMi8Ur8ej5UT166g6chBsxgMzc9xo9Y24R9FB3m/tjDiV03xMIA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-react": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-2.0.4.tgz", + "integrity": "sha512-BujRm5FBDWYXyr3pnmubS4dIqZMlurYVtV2AyztoeAFUd+nh3XQZD9knHBqTyu53IDjhCCvUPUke/jSkv5WGlg==", + "dependencies": { + "@rollup/plugin-typescript": "^11.1.0", + "rollup": "^3.20.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@azure/msal-browser": "^3.2.0", + "react": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", + "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz", + "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz", + "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz", + "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz", + "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz", + "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz", + "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz", + "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz", + "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz", + "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz", + "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz", + "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz", + "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz", + "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz", + "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz", + "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz", + "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz", + "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz", + "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz", + "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz", + "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz", + "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", + "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", + "dependencies": { + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/devtools": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/devtools/-/devtools-0.2.1.tgz", + "integrity": "sha512-8PHJLbD6VhBh+LJ1uty/Bz30qs02NXCE5u8WpOhSewlYXUWl03GNXknr9AS2yaAWJEQaY27x7eByJs44gODBcw==", + "peerDependencies": { + "@floating-ui/dom": ">=1.5.4" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", + "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", + "dependencies": { + "@floating-ui/core": "^1.5.3", + "@floating-ui/utils": "^0.2.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, + "node_modules/@fluentui/date-time-utilities": { + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-8.5.16.tgz", + "integrity": "sha512-l+mLfJ2VhdHjBpELLLPDaWgT7GMLynm2aqR7SttbEb6Jh7hc/7ck1MWm93RTb3gYVHYai8SENqimNcvIxHt/zg==", + "dependencies": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/dom-utilities": { + "version": "2.2.14", + "resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-2.2.14.tgz", + "integrity": "sha512-+4DVm5sNfJh+l8fM+7ylpOkGNZkNr4X1z1uKQPzRJ1PRhlnvc6vLpWNNicGwpjTbgufSrVtGKXwP5sf++r81lg==", + "dependencies": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/font-icons-mdl2": { + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/@fluentui/font-icons-mdl2/-/font-icons-mdl2-8.5.31.tgz", + "integrity": "sha512-jioHZ9XUfR9vUT5XnxdCrJ+hoC9TpYim+4YdtlUE/euI8kdW1tDZ5zqlSNk1GLDR34n03R09yWj5gVDCcMJbyQ==", + "dependencies": { + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/foundation-legacy": { + "version": "8.2.51", + "resolved": "https://registry.npmjs.org/@fluentui/foundation-legacy/-/foundation-legacy-8.2.51.tgz", + "integrity": "sha512-z/jrp1imV66/D2MGpN/55LGk/Istymk5tN+XUFHDENDi+9zyb2MgSxFshp774DJIrg3vVlyuS8oo+dBuTM3UbQ==", + "dependencies": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/keyboard-key": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.4.14.tgz", + "integrity": "sha512-XzZHcyFEM20H23h3i15UpkHi2AhRBriXPGAHq0Jm98TKFppXehedjjEFuUsh+CyU5JKBhDalWp8TAQ1ArpNzow==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/keyboard-keys": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.7.tgz", + "integrity": "sha512-vaQ+lOveQTdoXJYqDQXWb30udSfTVcIuKk1rV0X0eGAgcHeSDeP1HxMy+OgHOQZH3OiBH4ZYeWxb+tmfiDiygQ==", + "dependencies": { + "@swc/helpers": "^0.5.1" + } + }, + "node_modules/@fluentui/merge-styles": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/@fluentui/merge-styles/-/merge-styles-8.5.15.tgz", + "integrity": "sha512-4CdKwo4k1Un2QLulpSVIz/KMgLNBMgin4NPyapmKDMVuO1OOxJUqfocubRGNO5x9mKgAMMYwBKGO9i0uxMMpJw==", + "dependencies": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/priority-overflow": { + "version": "9.1.11", + "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.1.11.tgz", + "integrity": "sha512-sdrpavvKX2kepQ1d6IaI3ObLq5SAQBPRHPGx2+wiMWL7cEx9vGGM0fmeicl3soqqmM5uwCmWnZk9QZv9XOY98w==", + "dependencies": { + "@swc/helpers": "^0.5.1" + } + }, + "node_modules/@fluentui/react": { + "version": "8.114.4", + "resolved": "https://registry.npmjs.org/@fluentui/react/-/react-8.114.4.tgz", + "integrity": "sha512-dVpfFSpWUxdyqWlCVSXX5d34S760h4MaQjGR2/TPavtcJRRpJDHbBN2Hn7s4riA6YX5N7bTdN372UvIVbBbzuw==", + "dependencies": { + "@fluentui/date-time-utilities": "^8.5.16", + "@fluentui/font-icons-mdl2": "^8.5.31", + "@fluentui/foundation-legacy": "^8.2.51", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/react-focus": "^8.8.38", + "@fluentui/react-hooks": "^8.6.36", + "@fluentui/react-portal-compat-context": "^9.0.11", + "@fluentui/react-window-provider": "^2.2.18", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/theme": "^2.6.41", + "@fluentui/utilities": "^8.13.24", + "@microsoft/load-themed-styles": "^1.10.26", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-accordion": { + "version": "9.3.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.3.38.tgz", + "integrity": "sha512-BB8d9+Jr0v4SW58OJTIyvsxhA/iOBbvIkQZlVHKqt4tL8dHOIFPrApw5WqQqaSYJsEwt4HxmlNU4Dv8qRughbg==", + "dependencies": { + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-alert": { + "version": "9.0.0-beta.104", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.104.tgz", + "integrity": "sha512-Z8BGSyzEKok5wlJF2cUc8GUj2q+c1D+119YF0WtHLiieh7pwOHjBcDJOHqnaVnQNbhetIA3NUht2z0e1wgOK5w==", + "dependencies": { + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-aria": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.7.3.tgz", + "integrity": "sha512-YwyPNEcBDCdY6YzhrIrtlSrLs2Le7X1jLq9em8OnqHeiO22dBmg5xlBJoAMwJ8awCpI9xhu1PhU/2VJY4YqNuA==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-avatar": { + "version": "9.6.9", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.6.9.tgz", + "integrity": "sha512-3aZeUhGOg+UlHsp2x//G4VKRWKclcsZvX6L9UVnHsA/nQqRw7C5Bfo9iFNsEeJ3R5W5mFA6LyEFWedJ7QdAmdQ==", + "dependencies": { + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-tooltip": "^9.4.11", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-badge": { + "version": "9.2.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.2.22.tgz", + "integrity": "sha512-zzimP5mZiiCOm8expUTzD6yvvKbnKq22PK/L6+oNpifrvQnDwJF/0nwXQVjA3+icNoYTaHe/q0fFivpXV+Js6g==", + "dependencies": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-breadcrumb": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.0.11.tgz", + "integrity": "sha512-L+AQqZz1gqkScD8IW1CjZWGNrDaHDc/gSv+PrvgSZeGDPibGj6TnLygJ7BKM+rQ+Hc2SbCogKbERpQZCbrSFvA==", + "dependencies": { + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-link": "^9.2.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-button": { + "version": "9.3.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.3.65.tgz", + "integrity": "sha512-3VOt29AugkfR7VMnkKON449E7Sn/nvc6BBT4kJDGKQY+Nm5d2p9e4HmHp1UaM9zRPt47lagTY2WFJNrKKSe/BA==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-card": { + "version": "9.0.64", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.0.64.tgz", + "integrity": "sha512-TB/Zk+tLDUPNyAd2y8BvN0T2nroimtBOpB5GTK72E5sWPk0kaKIHwBEfXxNFGdGXcw0TAmVNqYi4ks37vh0Rgg==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-checkbox": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.2.8.tgz", + "integrity": "sha512-L4aWzeZdi98d0ZhgNPtxghfhasQv1qlxIRMaPxtwvk5TN6i9YmRF8vf5Pmf0PESjT+zp3VPcisHcIfcqG26SmQ==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-combobox": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.7.0.tgz", + "integrity": "sha512-YmTdg04rvsg2+Dkw3ob+YLnS9rm3TLVMMNYTH0T64/FM3qirHntIXGbhMZXP5Cdo14gzQwr/e78NjBRKfYO4Wg==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-components": { + "version": "9.45.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.45.0.tgz", + "integrity": "sha512-Y+Laj1dvRcCp/nWT0DExRXoh7oKTX458g6oltrGjhIHikq4D6/kssK5tfhCyknPLwIlVSYi5J+G6L3NfvI8a8w==", + "dependencies": { + "@fluentui/react-accordion": "^9.3.38", + "@fluentui/react-alert": "9.0.0-beta.104", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-breadcrumb": "^9.0.11", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-card": "^9.0.64", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-combobox": "^9.7.0", + "@fluentui/react-dialog": "^9.9.7", + "@fluentui/react-divider": "^9.2.58", + "@fluentui/react-drawer": "^9.1.1", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-image": "^9.1.55", + "@fluentui/react-infobutton": "9.0.0-beta.88", + "@fluentui/react-infolabel": "^9.0.16", + "@fluentui/react-input": "^9.4.60", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-link": "^9.2.7", + "@fluentui/react-menu": "^9.12.45", + "@fluentui/react-message-bar": "^9.0.16", + "@fluentui/react-overflow": "^9.1.8", + "@fluentui/react-persona": "^9.2.68", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-progress": "^9.1.60", + "@fluentui/react-provider": "^9.13.8", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-select": "^9.1.60", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-skeleton": "^9.0.48", + "@fluentui/react-slider": "^9.1.65", + "@fluentui/react-spinbutton": "^9.2.60", + "@fluentui/react-spinner": "^9.3.38", + "@fluentui/react-switch": "^9.1.65", + "@fluentui/react-table": "^9.11.5", + "@fluentui/react-tabs": "^9.4.6", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-tags": "^9.0.22", + "@fluentui/react-text": "^9.4.7", + "@fluentui/react-textarea": "^9.3.60", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-toast": "^9.3.27", + "@fluentui/react-toolbar": "^9.1.66", + "@fluentui/react-tooltip": "^9.4.11", + "@fluentui/react-tree": "^9.4.25", + "@fluentui/react-utilities": "^9.16.1", + "@fluentui/react-virtualizer": "9.0.0-alpha.66", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-context-selector": { + "version": "9.1.49", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.1.49.tgz", + "integrity": "sha512-u4wRNfnyfuZDalVEESBPFQ0Ue4yYu+ozkPQvuEV6kriQGnAQQyyVbIidOCuP7Sja0nBwgM8eAzK0uX/slmmj3Q==", + "dependencies": { + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-dialog": { + "version": "9.9.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.9.7.tgz", + "integrity": "sha512-5/6MeaHOYpx8Vt0auMJGLCjn6O1IYtl6IhwdwRNXL6AS1o4F24IKXdWZPtiHWuvzbuZAQd3+5nRDUE5KC9We6A==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-divider": { + "version": "9.2.58", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.2.58.tgz", + "integrity": "sha512-y1ECy1zM4imKhpyOyUGugB+J30tfySO5hhrsIcpaiUQxRjE4IhZf2ZG6EqAQYLinJ+hV06yLZoazekljlvk6yw==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-drawer": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.1.1.tgz", + "integrity": "sha512-3zvbbeaLLJZa4MXRpW8Ta4DFZ5457Tq9/4a0CqsIW/+8EuwtJwO+FB5a0DS6j0q6kN4mjkWF19OvzMkJsSTRVw==", + "dependencies": { + "@fluentui/react-dialog": "^9.9.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-motion-preview": "^0.5.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-field": { + "version": "9.1.50", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.1.50.tgz", + "integrity": "sha512-2mbx7YReMWvrgi3set9KepLLgMyNJ7StLu/HiHMM3jkcgPt3mGfwoJEsEKt+xd8eUAo4b82F7t+tHI4f9yzJaQ==", + "dependencies": { + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-focus": { + "version": "8.8.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.8.38.tgz", + "integrity": "sha512-vnsaY7hJSPIJBxm5Pj0FrcFDumV6kKgFVpsKsEKJzb1D88rDDLcmvz9jWUx68a3ru6idEbZYmyePGT1IiRsAug==", + "dependencies": { + "@fluentui/keyboard-key": "^0.4.14", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-hooks": { + "version": "8.6.36", + "resolved": "https://registry.npmjs.org/@fluentui/react-hooks/-/react-hooks-8.6.36.tgz", + "integrity": "sha512-kI0Z4Q4xHUs4SOmmI5n5OH5fPckqMSCovTRpiuxzCO2TNzLmfC861+nqf4Ygw/ChqNm2gWNZZfUADfnNAEsq+Q==", + "dependencies": { + "@fluentui/react-window-provider": "^2.2.18", + "@fluentui/set-version": "^8.2.14", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-icons": { + "version": "2.0.225", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.225.tgz", + "integrity": "sha512-L9phN3bAMlZCa5+/ObGjIO+5GI8M50ym766sraSq92jaJwgAXrCJDLWuDGWZRGrC63DcagtR2culptj3q7gMMg==", + "dependencies": { + "@griffel/react": "^1.0.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-image": { + "version": "9.1.55", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.1.55.tgz", + "integrity": "sha512-hYP61OWLuGSJNPOGJXtphbiDESfLB+/vsODKQsJhrDRJ2CSNMAfNznPHucqGRRN6AWQOI/BynJDS5F22Y//7CQ==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-infobutton": { + "version": "9.0.0-beta.88", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.88.tgz", + "integrity": "sha512-NVZyfrLtoFNu7cGkp2ORWsxJiCk1JgN4CVBDj03QSIh14EsPMwphYgDwfQ8TZOF2Nub0DGtC7/tF8IUlb/aP6g==", + "dependencies": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-infolabel": { + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.0.16.tgz", + "integrity": "sha512-UCY+2vB4vOn0LfVhbgkyNG0EiuKIe0PdxEAtLU2PqosHLkaLKnYDKJdiIS/oaFmyNtGHmMxRkigvZpZ7h74f9g==", + "dependencies": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-input": { + "version": "9.4.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.4.60.tgz", + "integrity": "sha512-kuk24K0X0gckTCssXoiWvZsTFVpZJv+WPl2fkjxeffzmFfBZtJUFQkXeC4/hcAg+aScjZnEtqjHjwDEbjZqkeA==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-jsx-runtime": { + "version": "9.0.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.27.tgz", + "integrity": "sha512-9wxsWxVI7RLXsdK+7lzp7TK0FJKnrrj+Igxn0prqAvXdBRiFcuycoCJaHzC4Ka+Hsiol8NQg6xaIR59a28lmyQ==", + "dependencies": { + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "react": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-label": { + "version": "9.1.58", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.1.58.tgz", + "integrity": "sha512-0ouSMop4vpXJzMvAyfmIr3TgDM/W1k+GFm8ZPD5fDQCopSJ+h3kvUZg5pqaXpBwamvZ16+qRARfTNITp2U7Rjw==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-link": { + "version": "9.2.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.2.7.tgz", + "integrity": "sha512-z4X9dcUc/7FlqDxbGKbOfWubru+QimtzgMtlVxZ30pkC959hfIbFpbBY6Me76UOuFiOZxUPdfyY/73ekhhhVxw==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-menu": { + "version": "9.12.45", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.12.45.tgz", + "integrity": "sha512-qhpmuvAB4DUmmC5lNMakVvZjTdj/GZnH6WctNGZp94iCZLhcnIQcM9l0PvRpUpU1v3irXRyE5QV+x+wXC0awTw==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-message-bar": { + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.0.16.tgz", + "integrity": "sha512-R1VnqcFwu0pM2Yk8rjkN48Lx/n44UFD13BuY8/JeEuU8XQ8hLnEBVtdHjzRPJk+iM5in2ScMMQj4Z0nWyCRM1Q==", + "dependencies": { + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-motion-preview": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-preview/-/react-motion-preview-0.5.10.tgz", + "integrity": "sha512-6iwF3N4hB6IxCoFVusgA2mp6mrTknwcsVGNYEQw1YF5WgGOMF3M0N1xNpN61/SYziT6HSUaI38NaA7LI3Dp3Sw==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-overflow": { + "version": "9.1.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.1.8.tgz", + "integrity": "sha512-W8L68+0bUtfGr72LRx+U05EZLO0E8VMfscDiNKiEjDrOqdBnqNAIDN86825wrN77HH2wvILN07EhPOauqzz8YQ==", + "dependencies": { + "@fluentui/priority-overflow": "^9.1.11", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-persona": { + "version": "9.2.68", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.2.68.tgz", + "integrity": "sha512-CYtDiZ34GGaw7lZ85uHZOuYXzkY21VHN6cUlGY1TJn98+Xz+y7JoVLIG7KZHHp2JzmmjtwjvgnqAdOun5LrWig==", + "dependencies": { + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-popover": { + "version": "9.8.33", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.8.33.tgz", + "integrity": "sha512-0yPX6KCdMEGmrvJnQles5iTKN0OZ2vNSPVdkbyEKIUKj5DrNK1cMZEV/7Tgrtn922fx3/74FLMqEpEDTdrvQ/Q==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-portal": { + "version": "9.4.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.4.10.tgz", + "integrity": "sha512-k8fTRv9wTPSPCuNBFE2HxIhXsVYoG6Azb6Ib2xaDK+nczoW2WbsmNmwBJGEGi8UKjIoQzV+95KsYQ9me+uqKPA==", + "dependencies": { + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "use-disposable": "^1.0.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-portal-compat-context": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal-compat-context/-/react-portal-compat-context-9.0.11.tgz", + "integrity": "sha512-ubvW/ej0O+Pago9GH3mPaxzUgsNnBoqvghNamWjyKvZIViyaXUG6+sgcAl721R+qGAFac+A20akI5qDJz/xtdg==", + "dependencies": { + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "react": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-positioning": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.12.4.tgz", + "integrity": "sha512-qQAjHF/FJFs2TyK0x08t0iFtDQlGNGH0OFC3jrG1xIFEe3nFPoeYeNT3zxOmj+D7bvlcJTIITcoe++YQTnCf4w==", + "dependencies": { + "@floating-ui/devtools": "0.2.1", + "@floating-ui/dom": "^1.2.0", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-progress": { + "version": "9.1.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.1.60.tgz", + "integrity": "sha512-9wC7lWdo3S8rhxKWlIhcYAzsZNw+rL2HvNJTvEvFxXcOG7nJxP/3mGclV/jCCwDoPDnt9BT+40pGK84eD0BNIA==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-provider": { + "version": "9.13.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.13.8.tgz", + "integrity": "sha512-FCvDMjs/BNAcqJuHU+kN/lqLB2RDQ/LQo29ltfLKFlTR1nTUNJvPMOVhjj6eEt+t81628LOYhbbaXOj9rYtfGg==", + "dependencies": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/core": "^1.14.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-radio": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.2.3.tgz", + "integrity": "sha512-8eKeUL0ZNr792Q6NGWPp7dpOV2IFcjAQ2oWR2/bruQVu8LMzYYKe2o6pQWdCag6UGPZuszkms9Xl7zPdDQBUdA==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-select": { + "version": "9.1.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.1.60.tgz", + "integrity": "sha512-4HfRRTlGStOgtO00RY6jmOwz6MXnoa9gtjkV7StLmJZ2U5NTjVUrnp2dP1Vjb6hO13xaihWGEYyYKnsQ3R7kIw==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-shared-contexts": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.14.0.tgz", + "integrity": "sha512-P9yhg31WYfB1W66/gD3+qVCLBsyIEcOzQvKVaIQvd9UhF67lNW4kMXUB6YVOk5PV0Og4hXnkH/vuHl7YMD9RHw==", + "dependencies": { + "@fluentui/react-theme": "^9.1.16", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "react": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-skeleton": { + "version": "9.0.48", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.0.48.tgz", + "integrity": "sha512-P0Rw5hIOn5CrZIWg7nVoK3gamxFhZI80KcRVaWap4O3gLo5C8nKHJWOtyBQZ5WKH+S6hoEGZ2USL6CoyXslxeQ==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-slider": { + "version": "9.1.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.1.65.tgz", + "integrity": "sha512-7kuJMIojxCmNOuiRmQwh9iiXx8zwxkrgvsWmReRIBX0WB6w1VqMcuuikq2Z2ISgNPmepCX8W+qDfx8Ne4F/HtQ==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-spinbutton": { + "version": "9.2.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.2.60.tgz", + "integrity": "sha512-0IIxEH0CTf4fNMoyvMa37bc63+0ZlznlsNy8lF3hujAT8Z9sUKVMH68e6tGUuXGJIkCUyDKU8HA+9FF2DyPvNA==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-spinner": { + "version": "9.3.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.3.38.tgz", + "integrity": "sha512-dPJr7/rgU2Qe/K2BciJTAEwEd0ytGpCw3VOVyK2T25w7Jw5RAHmgP+mbw+7se44Mr6sd1LH76mh5sfmQ3tODgw==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-switch": { + "version": "9.1.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.1.65.tgz", + "integrity": "sha512-P0DwogD6hZJ3O005zCFPDoFXuzkrpKMrAeQGh9X0fqFP5JyHXVCgAAZQOLcphbbT9QukoEF5irN2Z4L9gBn57A==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-table": { + "version": "9.11.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.11.5.tgz", + "integrity": "sha512-roQRITOtl1aqXlachS2oTraVE45x3KdDrX0KyQGCdcQRxNprXJW6dIK9QjlbAL6yAsAMDafmFA4y9uRxl408dQ==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-tabs": { + "version": "9.4.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.4.6.tgz", + "integrity": "sha512-LQvibLeJFyqKKiOjZUkRvbfLtsVosUhNUdh1SCQUPxQVpEPSK6XgwK0A1+jjoVhKn+PAJakxRINgnvqQD8pQBA==", + "dependencies": { + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0", + "scheduler": "^0.19.0 || ^0.20.0" + } + }, + "node_modules/@fluentui/react-tabster": { + "version": "9.17.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.17.3.tgz", + "integrity": "sha512-cFcUYrkGW15w5yXzCPTTVG/7x5kNXxnhQXuh8SPyCc9JZeG7XI3+hy1T37PsXGxNS4KN9ePHkBHzgDfYO4gzYQ==", + "dependencies": { + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "keyborg": "^2.3.0", + "tabster": "^5.0.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-tags": { + "version": "9.0.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.0.22.tgz", + "integrity": "sha512-gQIOCVu3HIfGjtAmwOnwBEnTsNyRBU8Pvs6EugpUyyqkRjzbm5TnL3LtiUy4f6/+NuaRqcYAvhwpdUhrlciwcA==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-text": { + "version": "9.4.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.4.7.tgz", + "integrity": "sha512-c6uJ98B35L8sviYxhQj1i+LW+HVNDdco2ImS9VLv/Duo4HiYs1G2y1YhtBDDiGxLe2moIvfg9ajDzMZV29aXFw==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-textarea": { + "version": "9.3.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.3.60.tgz", + "integrity": "sha512-wH4MBWT4EOgNH9FXTjcgH34oANUaoduhmVjffnxaPl3R767Ak0fZPG7kky7yrLMjTDUSwILsEj/q+hsN6o+7Ag==", + "dependencies": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-theme": { + "version": "9.1.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-theme/-/react-theme-9.1.16.tgz", + "integrity": "sha512-QK2dGE5aQXN1UGdiEmGKpYGP3tHXIchLvFf8DEEOWnF4XBc9SiEPNFYkvLMJjHxZmDz4D670rsOPe0r5jFDEKQ==", + "dependencies": { + "@fluentui/tokens": "1.0.0-alpha.13", + "@swc/helpers": "^0.5.1" + } + }, + "node_modules/@fluentui/react-toast": { + "version": "9.3.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.3.27.tgz", + "integrity": "sha512-DbRAYyL5Bd/pcFiGHPpK+rQMyc4LBll9YBy496l97dGDO2HmqFuiwP74V1KznxLcr4inCNWwThIJws5VLFsJLg==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-toolbar": { + "version": "9.1.66", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.1.66.tgz", + "integrity": "sha512-ooNTp1R5MBZwiVK8fiJu29gE48vUx4NbXdwB2yHcCprasG3asjuoKQfOYM4+1NfFA0DetVrbK8L46IBeZyeBvA==", + "dependencies": { + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-divider": "^9.2.58", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-tooltip": { + "version": "9.4.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.4.11.tgz", + "integrity": "sha512-HXm8yYuAHJuczeFExco0WQSjO3DzDj5AJxqICHF8qtbtihUKfWpPnKM1qQWR+yJR2zc2jzvOEIzZXEkxSG+fSg==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-tree": { + "version": "9.4.25", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.4.25.tgz", + "integrity": "sha512-7IMqnOiNFMRuPujnbxJUYD8AEh0z1OGXkdNkAeLyj3pkwuvQs9+TbaNtv5Z372YN+kwYF4EYalYcPuNsRlx7cQ==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-utilities": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.16.1.tgz", + "integrity": "sha512-2wdwmgTFcVy14ZLbRNJ8Q6dCCBLekkJ8Znnok68gKRLDcwpPT3UjSraoU+DGjOA5BMfPppZBU8Yb5GqdIfd48g==", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "react": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-virtualizer": { + "version": "9.0.0-alpha.66", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.66.tgz", + "integrity": "sha512-x/ZOAIAwctt7pvOBIzS4iZGU0ahiPhQFS7iAHksFkF9LimneaV92A/02dW0Cy4v7dv9wZNoosQwhS05Yx3DVDQ==", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <19.0.0", + "@types/react-dom": ">=16.9.0 <19.0.0", + "react": ">=16.14.0 <19.0.0", + "react-dom": ">=16.14.0 <19.0.0" + } + }, + "node_modules/@fluentui/react-window-provider": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-2.2.18.tgz", + "integrity": "sha512-nBKqxd0P8NmIR0qzFvka1urE2LVbUm6cse1I1T7TcOVNYa5jDf5BrO06+JRZfwbn00IJqOnIVoP0qONqceypWQ==", + "dependencies": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/set-version": { + "version": "8.2.14", + "resolved": "https://registry.npmjs.org/@fluentui/set-version/-/set-version-8.2.14.tgz", + "integrity": "sha512-f/QWJnSeyfAjGAqq57yjMb6a5ejPlwfzdExPmzFBuEOuupi8hHbV8Yno12XJcTW4I0KXEQGw+PUaM1aOf/j7jw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/style-utilities": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/@fluentui/style-utilities/-/style-utilities-8.10.2.tgz", + "integrity": "sha512-ocELtMb/85nBa3rSfiAIwYx6TydN+3rQqv1P0H/L7etYNNtxOfS86JSWfn8zAsHMejbwUKJ1ZsIKs47c598XGQ==", + "dependencies": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/theme": "^2.6.41", + "@fluentui/utilities": "^8.13.24", + "@microsoft/load-themed-styles": "^1.10.26", + "tslib": "^2.1.0" + } + }, + "node_modules/@fluentui/theme": { + "version": "2.6.41", + "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-2.6.41.tgz", + "integrity": "sha512-h9RguEzqzJ0+59ys5Kkp7JtsjhDUxBLmQunu5rpHp5Mp788OtEjI/n1a9FIcOAL/priPSQwXN7RbuDpeP7+aSw==", + "dependencies": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@fluentui/tokens": { + "version": "1.0.0-alpha.13", + "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.13.tgz", + "integrity": "sha512-IzYysTTBkAH7tQZxYKpzhxYnTJkvwXhjhTOpmERgnqTFifHTP8/vaQjJAAm7dI/9zlDx1oN+y/I+KzL9bDLHZQ==", + "dependencies": { + "@swc/helpers": "^0.5.1" + } + }, + "node_modules/@fluentui/utilities": { + "version": "8.13.24", + "resolved": "https://registry.npmjs.org/@fluentui/utilities/-/utilities-8.13.24.tgz", + "integrity": "sha512-/jo6hWCzTGCx06l2baAMwsjjBZ/dyMouls53uNaQLUGUUhUwXh/DcDDXMqLRJB3MaH9zvgfvRw61iKmm2s9fIA==", + "dependencies": { + "@fluentui/dom-utilities": "^2.2.14", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@griffel/core": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.15.2.tgz", + "integrity": "sha512-RlsIXoSS3gaYykUgxFpwKAs/DV9cRUKp3CW1kt3iPAtsDTWn/o+8bT1jvBws/tMM2GBu/Uc0EkaIzUPqD7uA+Q==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@griffel/style-types": "^1.0.3", + "csstype": "^3.1.3", + "rtl-css-js": "^1.16.1", + "stylis": "^4.2.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@griffel/react": { + "version": "1.5.20", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.20.tgz", + "integrity": "sha512-1P2yaPctENFSCwyPIYXBmgpNH68c0lc/jwSzPij1QATHDK1AASKuSeq6hW108I67RKjhRyHCcALshdZ3GcQXSg==", + "dependencies": { + "@griffel/core": "^1.15.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.8.0 <19.0.0" + } + }, + "node_modules/@griffel/style-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.0.3.tgz", + "integrity": "sha512-AzbbYV/EobNIBtfMtyu2edFin895gjVxtu1nsRhTETUAIb0/LCZoue3Jd/kFLuPwe95rv5WRUBiQpVwJsrrFcw==", + "dependencies": { + "csstype": "^3.1.3" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@microsoft/load-themed-styles": { + "version": "1.10.295", + "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.295.tgz", + "integrity": "sha512-W+IzEBw8a6LOOfRJM02dTT7BDZijxm+Z7lhtOAz1+y9vQm1Kdz9jlAO+qCEKsfxtUOmKilW8DIRqFw2aUgKeGg==" + }, + "node_modules/@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "dependencies": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-spring/donate" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "dependencies": { + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "node_modules/@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "dependencies": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz", + "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz", + "integrity": "sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA==", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", + "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", + "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/dompurify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.3.tgz", + "integrity": "sha512-odiGr/9/qMqjcBOe5UhcNLOFHSYmKFOyr+bJ/Xu3Qp4k1pNPAlNLUVNNLcLfjQI7+W7ObX58EdD3H+3p3voOvA==", + "dev": true, + "dependencies": { + "@types/trusted-types": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", + "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001579", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", + "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dompurify": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", + "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.639", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.639.tgz", + "integrity": "sha512-CkKf3ZUVZchr+zDpAlNLEEy2NJJ9T64ULWaDgy3THXXlPVPkLu3VOs9Bac44nebVtdwl2geSj6AxTtGDOxoXhg==", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz", + "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.11", + "@esbuild/android-arm64": "0.18.11", + "@esbuild/android-x64": "0.18.11", + "@esbuild/darwin-arm64": "0.18.11", + "@esbuild/darwin-x64": "0.18.11", + "@esbuild/freebsd-arm64": "0.18.11", + "@esbuild/freebsd-x64": "0.18.11", + "@esbuild/linux-arm": "0.18.11", + "@esbuild/linux-arm64": "0.18.11", + "@esbuild/linux-ia32": "0.18.11", + "@esbuild/linux-loong64": "0.18.11", + "@esbuild/linux-mips64el": "0.18.11", + "@esbuild/linux-ppc64": "0.18.11", + "@esbuild/linux-riscv64": "0.18.11", + "@esbuild/linux-s390x": "0.18.11", + "@esbuild/linux-x64": "0.18.11", + "@esbuild/netbsd-x64": "0.18.11", + "@esbuild/openbsd-x64": "0.18.11", + "@esbuild/sunos-x64": "0.18.11", + "@esbuild/win32-arm64": "0.18.11", + "@esbuild/win32-ia32": "0.18.11", + "@esbuild/win32-x64": "0.18.11" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyborg": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.4.1.tgz", + "integrity": "sha512-B9EZwDd36WKlIq6JmimaTsTDx5E0aUqZcxtgTfK66ut1FbRXYhBmiB7Al2qKzB7CCX9C49sTBiiyVzsXCA6J4Q==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/ndjson-readablestream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ndjson-readablestream/-/ndjson-readablestream-1.0.7.tgz", + "integrity": "sha512-4DDTwYTV4yRnCoXparQTF3JeahTNkLVy7XlA0RHXzAqQ3uU8vcu97bNW8rXAQOKQVJGs2aZoX+7cbvfs0LENEA==" + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz", + "integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==", + "dependencies": { + "@remix-run/router": "1.14.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz", + "integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==", + "dependencies": { + "@remix-run/router": "1.14.2", + "react-router": "6.21.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tabster": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-5.2.0.tgz", + "integrity": "sha512-cSi3a0gGeM9Co/gTKHlhTFfiitwVjcA+kP9lJux0U7QaRrZox1yYrfbwZhJXM7N0fux7BgvCYaOxME5k0EQ0tA==", + "dependencies": { + "keyborg": "^2.2.0", + "tslib": "^2.3.1" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-disposable": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/use-disposable/-/use-disposable-1.0.2.tgz", + "integrity": "sha512-UMaXVlV77dWOu4GqAFNjRzHzowYKUKbJBQfCexvahrYeIz4OkUYUjna4Tjjdf92NH8Nm8J7wEfFRgTIwYjO5jg==", + "peerDependencies": { + "@types/react": ">=16.8.0 <19.0.0", + "@types/react-dom": ">=16.8.0 <19.0.0", + "react": ">=16.8.0 <19.0.0", + "react-dom": ">=16.8.0 <19.0.0" + } + }, + "node_modules/vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@azure/msal-browser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.2.0.tgz", + "integrity": "sha512-le2qutddMiq0i3ErQaLKuwP1DpNgdd9iXPs3fSCsLuBrdGg9B4/j4ArCAHCwgxA82Ydj9BcqtMIL5BSWwU+P5A==", + "requires": { + "@azure/msal-common": "14.1.0" + } + }, + "@azure/msal-common": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.1.0.tgz", + "integrity": "sha512-xphmhcfl5VL+uq5//VKMwQn+wfEZLMKNpFCcMi8Ur8ej5UT166g6chBsxgMzc9xo9Y24R9FB3m/tjDiV03xMIA==" + }, + "@azure/msal-react": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-2.0.4.tgz", + "integrity": "sha512-BujRm5FBDWYXyr3pnmubS4dIqZMlurYVtV2AyztoeAFUd+nh3XQZD9knHBqTyu53IDjhCCvUPUke/jSkv5WGlg==", + "requires": { + "@rollup/plugin-typescript": "^11.1.0", + "rollup": "^3.20.2" + } + }, + "@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + } + }, + "@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dev": true, + "requires": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "dev": true + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/runtime": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "@esbuild/android-arm": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz", + "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz", + "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz", + "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz", + "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz", + "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz", + "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz", + "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz", + "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz", + "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz", + "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz", + "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz", + "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz", + "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz", + "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz", + "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz", + "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz", + "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz", + "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz", + "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz", + "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz", + "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz", + "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==", + "dev": true, + "optional": true + }, + "@floating-ui/core": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", + "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", + "requires": { + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/devtools": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/devtools/-/devtools-0.2.1.tgz", + "integrity": "sha512-8PHJLbD6VhBh+LJ1uty/Bz30qs02NXCE5u8WpOhSewlYXUWl03GNXknr9AS2yaAWJEQaY27x7eByJs44gODBcw==", + "requires": {} + }, + "@floating-ui/dom": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", + "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", + "requires": { + "@floating-ui/core": "^1.5.3", + "@floating-ui/utils": "^0.2.0" + } + }, + "@floating-ui/utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", + "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" + }, + "@fluentui/date-time-utilities": { + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-8.5.16.tgz", + "integrity": "sha512-l+mLfJ2VhdHjBpELLLPDaWgT7GMLynm2aqR7SttbEb6Jh7hc/7ck1MWm93RTb3gYVHYai8SENqimNcvIxHt/zg==", + "requires": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "@fluentui/dom-utilities": { + "version": "2.2.14", + "resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-2.2.14.tgz", + "integrity": "sha512-+4DVm5sNfJh+l8fM+7ylpOkGNZkNr4X1z1uKQPzRJ1PRhlnvc6vLpWNNicGwpjTbgufSrVtGKXwP5sf++r81lg==", + "requires": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "@fluentui/font-icons-mdl2": { + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/@fluentui/font-icons-mdl2/-/font-icons-mdl2-8.5.31.tgz", + "integrity": "sha512-jioHZ9XUfR9vUT5XnxdCrJ+hoC9TpYim+4YdtlUE/euI8kdW1tDZ5zqlSNk1GLDR34n03R09yWj5gVDCcMJbyQ==", + "requires": { + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "@fluentui/foundation-legacy": { + "version": "8.2.51", + "resolved": "https://registry.npmjs.org/@fluentui/foundation-legacy/-/foundation-legacy-8.2.51.tgz", + "integrity": "sha512-z/jrp1imV66/D2MGpN/55LGk/Istymk5tN+XUFHDENDi+9zyb2MgSxFshp774DJIrg3vVlyuS8oo+dBuTM3UbQ==", + "requires": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "@fluentui/keyboard-key": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.4.14.tgz", + "integrity": "sha512-XzZHcyFEM20H23h3i15UpkHi2AhRBriXPGAHq0Jm98TKFppXehedjjEFuUsh+CyU5JKBhDalWp8TAQ1ArpNzow==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@fluentui/keyboard-keys": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.7.tgz", + "integrity": "sha512-vaQ+lOveQTdoXJYqDQXWb30udSfTVcIuKk1rV0X0eGAgcHeSDeP1HxMy+OgHOQZH3OiBH4ZYeWxb+tmfiDiygQ==", + "requires": { + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/merge-styles": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/@fluentui/merge-styles/-/merge-styles-8.5.15.tgz", + "integrity": "sha512-4CdKwo4k1Un2QLulpSVIz/KMgLNBMgin4NPyapmKDMVuO1OOxJUqfocubRGNO5x9mKgAMMYwBKGO9i0uxMMpJw==", + "requires": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "@fluentui/priority-overflow": { + "version": "9.1.11", + "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.1.11.tgz", + "integrity": "sha512-sdrpavvKX2kepQ1d6IaI3ObLq5SAQBPRHPGx2+wiMWL7cEx9vGGM0fmeicl3soqqmM5uwCmWnZk9QZv9XOY98w==", + "requires": { + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react": { + "version": "8.114.4", + "resolved": "https://registry.npmjs.org/@fluentui/react/-/react-8.114.4.tgz", + "integrity": "sha512-dVpfFSpWUxdyqWlCVSXX5d34S760h4MaQjGR2/TPavtcJRRpJDHbBN2Hn7s4riA6YX5N7bTdN372UvIVbBbzuw==", + "requires": { + "@fluentui/date-time-utilities": "^8.5.16", + "@fluentui/font-icons-mdl2": "^8.5.31", + "@fluentui/foundation-legacy": "^8.2.51", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/react-focus": "^8.8.38", + "@fluentui/react-hooks": "^8.6.36", + "@fluentui/react-portal-compat-context": "^9.0.11", + "@fluentui/react-window-provider": "^2.2.18", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/theme": "^2.6.41", + "@fluentui/utilities": "^8.13.24", + "@microsoft/load-themed-styles": "^1.10.26", + "tslib": "^2.1.0" + } + }, + "@fluentui/react-accordion": { + "version": "9.3.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.3.38.tgz", + "integrity": "sha512-BB8d9+Jr0v4SW58OJTIyvsxhA/iOBbvIkQZlVHKqt4tL8dHOIFPrApw5WqQqaSYJsEwt4HxmlNU4Dv8qRughbg==", + "requires": { + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-alert": { + "version": "9.0.0-beta.104", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.104.tgz", + "integrity": "sha512-Z8BGSyzEKok5wlJF2cUc8GUj2q+c1D+119YF0WtHLiieh7pwOHjBcDJOHqnaVnQNbhetIA3NUht2z0e1wgOK5w==", + "requires": { + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-aria": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.7.3.tgz", + "integrity": "sha512-YwyPNEcBDCdY6YzhrIrtlSrLs2Le7X1jLq9em8OnqHeiO22dBmg5xlBJoAMwJ8awCpI9xhu1PhU/2VJY4YqNuA==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-avatar": { + "version": "9.6.9", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.6.9.tgz", + "integrity": "sha512-3aZeUhGOg+UlHsp2x//G4VKRWKclcsZvX6L9UVnHsA/nQqRw7C5Bfo9iFNsEeJ3R5W5mFA6LyEFWedJ7QdAmdQ==", + "requires": { + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-tooltip": "^9.4.11", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-badge": { + "version": "9.2.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.2.22.tgz", + "integrity": "sha512-zzimP5mZiiCOm8expUTzD6yvvKbnKq22PK/L6+oNpifrvQnDwJF/0nwXQVjA3+icNoYTaHe/q0fFivpXV+Js6g==", + "requires": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-breadcrumb": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.0.11.tgz", + "integrity": "sha512-L+AQqZz1gqkScD8IW1CjZWGNrDaHDc/gSv+PrvgSZeGDPibGj6TnLygJ7BKM+rQ+Hc2SbCogKbERpQZCbrSFvA==", + "requires": { + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-link": "^9.2.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-button": { + "version": "9.3.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.3.65.tgz", + "integrity": "sha512-3VOt29AugkfR7VMnkKON449E7Sn/nvc6BBT4kJDGKQY+Nm5d2p9e4HmHp1UaM9zRPt47lagTY2WFJNrKKSe/BA==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-card": { + "version": "9.0.64", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.0.64.tgz", + "integrity": "sha512-TB/Zk+tLDUPNyAd2y8BvN0T2nroimtBOpB5GTK72E5sWPk0kaKIHwBEfXxNFGdGXcw0TAmVNqYi4ks37vh0Rgg==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-checkbox": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.2.8.tgz", + "integrity": "sha512-L4aWzeZdi98d0ZhgNPtxghfhasQv1qlxIRMaPxtwvk5TN6i9YmRF8vf5Pmf0PESjT+zp3VPcisHcIfcqG26SmQ==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-combobox": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.7.0.tgz", + "integrity": "sha512-YmTdg04rvsg2+Dkw3ob+YLnS9rm3TLVMMNYTH0T64/FM3qirHntIXGbhMZXP5Cdo14gzQwr/e78NjBRKfYO4Wg==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-components": { + "version": "9.45.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.45.0.tgz", + "integrity": "sha512-Y+Laj1dvRcCp/nWT0DExRXoh7oKTX458g6oltrGjhIHikq4D6/kssK5tfhCyknPLwIlVSYi5J+G6L3NfvI8a8w==", + "requires": { + "@fluentui/react-accordion": "^9.3.38", + "@fluentui/react-alert": "9.0.0-beta.104", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-breadcrumb": "^9.0.11", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-card": "^9.0.64", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-combobox": "^9.7.0", + "@fluentui/react-dialog": "^9.9.7", + "@fluentui/react-divider": "^9.2.58", + "@fluentui/react-drawer": "^9.1.1", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-image": "^9.1.55", + "@fluentui/react-infobutton": "9.0.0-beta.88", + "@fluentui/react-infolabel": "^9.0.16", + "@fluentui/react-input": "^9.4.60", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-link": "^9.2.7", + "@fluentui/react-menu": "^9.12.45", + "@fluentui/react-message-bar": "^9.0.16", + "@fluentui/react-overflow": "^9.1.8", + "@fluentui/react-persona": "^9.2.68", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-progress": "^9.1.60", + "@fluentui/react-provider": "^9.13.8", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-select": "^9.1.60", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-skeleton": "^9.0.48", + "@fluentui/react-slider": "^9.1.65", + "@fluentui/react-spinbutton": "^9.2.60", + "@fluentui/react-spinner": "^9.3.38", + "@fluentui/react-switch": "^9.1.65", + "@fluentui/react-table": "^9.11.5", + "@fluentui/react-tabs": "^9.4.6", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-tags": "^9.0.22", + "@fluentui/react-text": "^9.4.7", + "@fluentui/react-textarea": "^9.3.60", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-toast": "^9.3.27", + "@fluentui/react-toolbar": "^9.1.66", + "@fluentui/react-tooltip": "^9.4.11", + "@fluentui/react-tree": "^9.4.25", + "@fluentui/react-utilities": "^9.16.1", + "@fluentui/react-virtualizer": "9.0.0-alpha.66", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-context-selector": { + "version": "9.1.49", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.1.49.tgz", + "integrity": "sha512-u4wRNfnyfuZDalVEESBPFQ0Ue4yYu+ozkPQvuEV6kriQGnAQQyyVbIidOCuP7Sja0nBwgM8eAzK0uX/slmmj3Q==", + "requires": { + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-dialog": { + "version": "9.9.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.9.7.tgz", + "integrity": "sha512-5/6MeaHOYpx8Vt0auMJGLCjn6O1IYtl6IhwdwRNXL6AS1o4F24IKXdWZPtiHWuvzbuZAQd3+5nRDUE5KC9We6A==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + } + }, + "@fluentui/react-divider": { + "version": "9.2.58", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.2.58.tgz", + "integrity": "sha512-y1ECy1zM4imKhpyOyUGugB+J30tfySO5hhrsIcpaiUQxRjE4IhZf2ZG6EqAQYLinJ+hV06yLZoazekljlvk6yw==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-drawer": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.1.1.tgz", + "integrity": "sha512-3zvbbeaLLJZa4MXRpW8Ta4DFZ5457Tq9/4a0CqsIW/+8EuwtJwO+FB5a0DS6j0q6kN4mjkWF19OvzMkJsSTRVw==", + "requires": { + "@fluentui/react-dialog": "^9.9.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-motion-preview": "^0.5.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-field": { + "version": "9.1.50", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.1.50.tgz", + "integrity": "sha512-2mbx7YReMWvrgi3set9KepLLgMyNJ7StLu/HiHMM3jkcgPt3mGfwoJEsEKt+xd8eUAo4b82F7t+tHI4f9yzJaQ==", + "requires": { + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-focus": { + "version": "8.8.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-8.8.38.tgz", + "integrity": "sha512-vnsaY7hJSPIJBxm5Pj0FrcFDumV6kKgFVpsKsEKJzb1D88rDDLcmvz9jWUx68a3ru6idEbZYmyePGT1IiRsAug==", + "requires": { + "@fluentui/keyboard-key": "^0.4.14", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/style-utilities": "^8.10.2", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "@fluentui/react-hooks": { + "version": "8.6.36", + "resolved": "https://registry.npmjs.org/@fluentui/react-hooks/-/react-hooks-8.6.36.tgz", + "integrity": "sha512-kI0Z4Q4xHUs4SOmmI5n5OH5fPckqMSCovTRpiuxzCO2TNzLmfC861+nqf4Ygw/ChqNm2gWNZZfUADfnNAEsq+Q==", + "requires": { + "@fluentui/react-window-provider": "^2.2.18", + "@fluentui/set-version": "^8.2.14", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "@fluentui/react-icons": { + "version": "2.0.225", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.225.tgz", + "integrity": "sha512-L9phN3bAMlZCa5+/ObGjIO+5GI8M50ym766sraSq92jaJwgAXrCJDLWuDGWZRGrC63DcagtR2culptj3q7gMMg==", + "requires": { + "@griffel/react": "^1.0.0", + "tslib": "^2.1.0" + } + }, + "@fluentui/react-image": { + "version": "9.1.55", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.1.55.tgz", + "integrity": "sha512-hYP61OWLuGSJNPOGJXtphbiDESfLB+/vsODKQsJhrDRJ2CSNMAfNznPHucqGRRN6AWQOI/BynJDS5F22Y//7CQ==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-infobutton": { + "version": "9.0.0-beta.88", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.88.tgz", + "integrity": "sha512-NVZyfrLtoFNu7cGkp2ORWsxJiCk1JgN4CVBDj03QSIh14EsPMwphYgDwfQ8TZOF2Nub0DGtC7/tF8IUlb/aP6g==", + "requires": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-infolabel": { + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.0.16.tgz", + "integrity": "sha512-UCY+2vB4vOn0LfVhbgkyNG0EiuKIe0PdxEAtLU2PqosHLkaLKnYDKJdiIS/oaFmyNtGHmMxRkigvZpZ7h74f9g==", + "requires": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-popover": "^9.8.33", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-input": { + "version": "9.4.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.4.60.tgz", + "integrity": "sha512-kuk24K0X0gckTCssXoiWvZsTFVpZJv+WPl2fkjxeffzmFfBZtJUFQkXeC4/hcAg+aScjZnEtqjHjwDEbjZqkeA==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-jsx-runtime": { + "version": "9.0.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.27.tgz", + "integrity": "sha512-9wxsWxVI7RLXsdK+7lzp7TK0FJKnrrj+Igxn0prqAvXdBRiFcuycoCJaHzC4Ka+Hsiol8NQg6xaIR59a28lmyQ==", + "requires": { + "@fluentui/react-utilities": "^9.16.1", + "@swc/helpers": "^0.5.1", + "react-is": "^17.0.2" + } + }, + "@fluentui/react-label": { + "version": "9.1.58", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.1.58.tgz", + "integrity": "sha512-0ouSMop4vpXJzMvAyfmIr3TgDM/W1k+GFm8ZPD5fDQCopSJ+h3kvUZg5pqaXpBwamvZ16+qRARfTNITp2U7Rjw==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-link": { + "version": "9.2.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.2.7.tgz", + "integrity": "sha512-z4X9dcUc/7FlqDxbGKbOfWubru+QimtzgMtlVxZ30pkC959hfIbFpbBY6Me76UOuFiOZxUPdfyY/73ekhhhVxw==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-menu": { + "version": "9.12.45", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.12.45.tgz", + "integrity": "sha512-qhpmuvAB4DUmmC5lNMakVvZjTdj/GZnH6WctNGZp94iCZLhcnIQcM9l0PvRpUpU1v3irXRyE5QV+x+wXC0awTw==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-message-bar": { + "version": "9.0.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.0.16.tgz", + "integrity": "sha512-R1VnqcFwu0pM2Yk8rjkN48Lx/n44UFD13BuY8/JeEuU8XQ8hLnEBVtdHjzRPJk+iM5in2ScMMQj4Z0nWyCRM1Q==", + "requires": { + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + } + }, + "@fluentui/react-motion-preview": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-preview/-/react-motion-preview-0.5.10.tgz", + "integrity": "sha512-6iwF3N4hB6IxCoFVusgA2mp6mrTknwcsVGNYEQw1YF5WgGOMF3M0N1xNpN61/SYziT6HSUaI38NaA7LI3Dp3Sw==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-overflow": { + "version": "9.1.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.1.8.tgz", + "integrity": "sha512-W8L68+0bUtfGr72LRx+U05EZLO0E8VMfscDiNKiEjDrOqdBnqNAIDN86825wrN77HH2wvILN07EhPOauqzz8YQ==", + "requires": { + "@fluentui/priority-overflow": "^9.1.11", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-persona": { + "version": "9.2.68", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.2.68.tgz", + "integrity": "sha512-CYtDiZ34GGaw7lZ85uHZOuYXzkY21VHN6cUlGY1TJn98+Xz+y7JoVLIG7KZHHp2JzmmjtwjvgnqAdOun5LrWig==", + "requires": { + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-badge": "^9.2.22", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-popover": { + "version": "9.8.33", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.8.33.tgz", + "integrity": "sha512-0yPX6KCdMEGmrvJnQles5iTKN0OZ2vNSPVdkbyEKIUKj5DrNK1cMZEV/7Tgrtn922fx3/74FLMqEpEDTdrvQ/Q==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-portal": { + "version": "9.4.10", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.4.10.tgz", + "integrity": "sha512-k8fTRv9wTPSPCuNBFE2HxIhXsVYoG6Azb6Ib2xaDK+nczoW2WbsmNmwBJGEGi8UKjIoQzV+95KsYQ9me+uqKPA==", + "requires": { + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "use-disposable": "^1.0.1" + } + }, + "@fluentui/react-portal-compat-context": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal-compat-context/-/react-portal-compat-context-9.0.11.tgz", + "integrity": "sha512-ubvW/ej0O+Pago9GH3mPaxzUgsNnBoqvghNamWjyKvZIViyaXUG6+sgcAl721R+qGAFac+A20akI5qDJz/xtdg==", + "requires": { + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-positioning": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.12.4.tgz", + "integrity": "sha512-qQAjHF/FJFs2TyK0x08t0iFtDQlGNGH0OFC3jrG1xIFEe3nFPoeYeNT3zxOmj+D7bvlcJTIITcoe++YQTnCf4w==", + "requires": { + "@floating-ui/devtools": "0.2.1", + "@floating-ui/dom": "^1.2.0", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-progress": { + "version": "9.1.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.1.60.tgz", + "integrity": "sha512-9wC7lWdo3S8rhxKWlIhcYAzsZNw+rL2HvNJTvEvFxXcOG7nJxP/3mGclV/jCCwDoPDnt9BT+40pGK84eD0BNIA==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-provider": { + "version": "9.13.8", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.13.8.tgz", + "integrity": "sha512-FCvDMjs/BNAcqJuHU+kN/lqLB2RDQ/LQo29ltfLKFlTR1nTUNJvPMOVhjj6eEt+t81628LOYhbbaXOj9rYtfGg==", + "requires": { + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/core": "^1.14.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-radio": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.2.3.tgz", + "integrity": "sha512-8eKeUL0ZNr792Q6NGWPp7dpOV2IFcjAQ2oWR2/bruQVu8LMzYYKe2o6pQWdCag6UGPZuszkms9Xl7zPdDQBUdA==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-select": { + "version": "9.1.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.1.60.tgz", + "integrity": "sha512-4HfRRTlGStOgtO00RY6jmOwz6MXnoa9gtjkV7StLmJZ2U5NTjVUrnp2dP1Vjb6hO13xaihWGEYyYKnsQ3R7kIw==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-shared-contexts": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.14.0.tgz", + "integrity": "sha512-P9yhg31WYfB1W66/gD3+qVCLBsyIEcOzQvKVaIQvd9UhF67lNW4kMXUB6YVOk5PV0Og4hXnkH/vuHl7YMD9RHw==", + "requires": { + "@fluentui/react-theme": "^9.1.16", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-skeleton": { + "version": "9.0.48", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.0.48.tgz", + "integrity": "sha512-P0Rw5hIOn5CrZIWg7nVoK3gamxFhZI80KcRVaWap4O3gLo5C8nKHJWOtyBQZ5WKH+S6hoEGZ2USL6CoyXslxeQ==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-slider": { + "version": "9.1.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.1.65.tgz", + "integrity": "sha512-7kuJMIojxCmNOuiRmQwh9iiXx8zwxkrgvsWmReRIBX0WB6w1VqMcuuikq2Z2ISgNPmepCX8W+qDfx8Ne4F/HtQ==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-spinbutton": { + "version": "9.2.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.2.60.tgz", + "integrity": "sha512-0IIxEH0CTf4fNMoyvMa37bc63+0ZlznlsNy8lF3hujAT8Z9sUKVMH68e6tGUuXGJIkCUyDKU8HA+9FF2DyPvNA==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-spinner": { + "version": "9.3.38", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.3.38.tgz", + "integrity": "sha512-dPJr7/rgU2Qe/K2BciJTAEwEd0ytGpCw3VOVyK2T25w7Jw5RAHmgP+mbw+7se44Mr6sd1LH76mh5sfmQ3tODgw==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-switch": { + "version": "9.1.65", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.1.65.tgz", + "integrity": "sha512-P0DwogD6hZJ3O005zCFPDoFXuzkrpKMrAeQGh9X0fqFP5JyHXVCgAAZQOLcphbbT9QukoEF5irN2Z4L9gBn57A==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-label": "^9.1.58", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-table": { + "version": "9.11.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.11.5.tgz", + "integrity": "sha512-roQRITOtl1aqXlachS2oTraVE45x3KdDrX0KyQGCdcQRxNprXJW6dIK9QjlbAL6yAsAMDafmFA4y9uRxl408dQ==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-tabs": { + "version": "9.4.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.4.6.tgz", + "integrity": "sha512-LQvibLeJFyqKKiOjZUkRvbfLtsVosUhNUdh1SCQUPxQVpEPSK6XgwK0A1+jjoVhKn+PAJakxRINgnvqQD8pQBA==", + "requires": { + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-tabster": { + "version": "9.17.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.17.3.tgz", + "integrity": "sha512-cFcUYrkGW15w5yXzCPTTVG/7x5kNXxnhQXuh8SPyCc9JZeG7XI3+hy1T37PsXGxNS4KN9ePHkBHzgDfYO4gzYQ==", + "requires": { + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "keyborg": "^2.3.0", + "tabster": "^5.0.1" + } + }, + "@fluentui/react-tags": { + "version": "9.0.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.0.22.tgz", + "integrity": "sha512-gQIOCVu3HIfGjtAmwOnwBEnTsNyRBU8Pvs6EugpUyyqkRjzbm5TnL3LtiUy4f6/+NuaRqcYAvhwpdUhrlciwcA==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-text": { + "version": "9.4.7", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.4.7.tgz", + "integrity": "sha512-c6uJ98B35L8sviYxhQj1i+LW+HVNDdco2ImS9VLv/Duo4HiYs1G2y1YhtBDDiGxLe2moIvfg9ajDzMZV29aXFw==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-textarea": { + "version": "9.3.60", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.3.60.tgz", + "integrity": "sha512-wH4MBWT4EOgNH9FXTjcgH34oANUaoduhmVjffnxaPl3R767Ak0fZPG7kky7yrLMjTDUSwILsEj/q+hsN6o+7Ag==", + "requires": { + "@fluentui/react-field": "^9.1.50", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-theme": { + "version": "9.1.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-theme/-/react-theme-9.1.16.tgz", + "integrity": "sha512-QK2dGE5aQXN1UGdiEmGKpYGP3tHXIchLvFf8DEEOWnF4XBc9SiEPNFYkvLMJjHxZmDz4D670rsOPe0r5jFDEKQ==", + "requires": { + "@fluentui/tokens": "1.0.0-alpha.13", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-toast": { + "version": "9.3.27", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.3.27.tgz", + "integrity": "sha512-DbRAYyL5Bd/pcFiGHPpK+rQMyc4LBll9YBy496l97dGDO2HmqFuiwP74V1KznxLcr4inCNWwThIJws5VLFsJLg==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1", + "react-transition-group": "^4.4.1" + } + }, + "@fluentui/react-toolbar": { + "version": "9.1.66", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.1.66.tgz", + "integrity": "sha512-ooNTp1R5MBZwiVK8fiJu29gE48vUx4NbXdwB2yHcCprasG3asjuoKQfOYM4+1NfFA0DetVrbK8L46IBeZyeBvA==", + "requires": { + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-divider": "^9.2.58", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-tooltip": { + "version": "9.4.11", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.4.11.tgz", + "integrity": "sha512-HXm8yYuAHJuczeFExco0WQSjO3DzDj5AJxqICHF8qtbtihUKfWpPnKM1qQWR+yJR2zc2jzvOEIzZXEkxSG+fSg==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-portal": "^9.4.10", + "@fluentui/react-positioning": "^9.12.4", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-tree": { + "version": "9.4.25", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.4.25.tgz", + "integrity": "sha512-7IMqnOiNFMRuPujnbxJUYD8AEh0z1OGXkdNkAeLyj3pkwuvQs9+TbaNtv5Z372YN+kwYF4EYalYcPuNsRlx7cQ==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-aria": "^9.7.3", + "@fluentui/react-avatar": "^9.6.9", + "@fluentui/react-button": "^9.3.65", + "@fluentui/react-checkbox": "^9.2.8", + "@fluentui/react-context-selector": "^9.1.49", + "@fluentui/react-icons": "^2.0.224", + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-radio": "^9.2.3", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-tabster": "^9.17.3", + "@fluentui/react-theme": "^9.1.16", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-utilities": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.16.1.tgz", + "integrity": "sha512-2wdwmgTFcVy14ZLbRNJ8Q6dCCBLekkJ8Znnok68gKRLDcwpPT3UjSraoU+DGjOA5BMfPppZBU8Yb5GqdIfd48g==", + "requires": { + "@fluentui/keyboard-keys": "^9.0.7", + "@fluentui/react-shared-contexts": "^9.14.0", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-virtualizer": { + "version": "9.0.0-alpha.66", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.66.tgz", + "integrity": "sha512-x/ZOAIAwctt7pvOBIzS4iZGU0ahiPhQFS7iAHksFkF9LimneaV92A/02dW0Cy4v7dv9wZNoosQwhS05Yx3DVDQ==", + "requires": { + "@fluentui/react-jsx-runtime": "^9.0.27", + "@fluentui/react-shared-contexts": "^9.14.0", + "@fluentui/react-utilities": "^9.16.1", + "@griffel/react": "^1.5.14", + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/react-window-provider": { + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-2.2.18.tgz", + "integrity": "sha512-nBKqxd0P8NmIR0qzFvka1urE2LVbUm6cse1I1T7TcOVNYa5jDf5BrO06+JRZfwbn00IJqOnIVoP0qONqceypWQ==", + "requires": { + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "@fluentui/set-version": { + "version": "8.2.14", + "resolved": "https://registry.npmjs.org/@fluentui/set-version/-/set-version-8.2.14.tgz", + "integrity": "sha512-f/QWJnSeyfAjGAqq57yjMb6a5ejPlwfzdExPmzFBuEOuupi8hHbV8Yno12XJcTW4I0KXEQGw+PUaM1aOf/j7jw==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@fluentui/style-utilities": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/@fluentui/style-utilities/-/style-utilities-8.10.2.tgz", + "integrity": "sha512-ocELtMb/85nBa3rSfiAIwYx6TydN+3rQqv1P0H/L7etYNNtxOfS86JSWfn8zAsHMejbwUKJ1ZsIKs47c598XGQ==", + "requires": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/theme": "^2.6.41", + "@fluentui/utilities": "^8.13.24", + "@microsoft/load-themed-styles": "^1.10.26", + "tslib": "^2.1.0" + } + }, + "@fluentui/theme": { + "version": "2.6.41", + "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-2.6.41.tgz", + "integrity": "sha512-h9RguEzqzJ0+59ys5Kkp7JtsjhDUxBLmQunu5rpHp5Mp788OtEjI/n1a9FIcOAL/priPSQwXN7RbuDpeP7+aSw==", + "requires": { + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "@fluentui/utilities": "^8.13.24", + "tslib": "^2.1.0" + } + }, + "@fluentui/tokens": { + "version": "1.0.0-alpha.13", + "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.13.tgz", + "integrity": "sha512-IzYysTTBkAH7tQZxYKpzhxYnTJkvwXhjhTOpmERgnqTFifHTP8/vaQjJAAm7dI/9zlDx1oN+y/I+KzL9bDLHZQ==", + "requires": { + "@swc/helpers": "^0.5.1" + } + }, + "@fluentui/utilities": { + "version": "8.13.24", + "resolved": "https://registry.npmjs.org/@fluentui/utilities/-/utilities-8.13.24.tgz", + "integrity": "sha512-/jo6hWCzTGCx06l2baAMwsjjBZ/dyMouls53uNaQLUGUUhUwXh/DcDDXMqLRJB3MaH9zvgfvRw61iKmm2s9fIA==", + "requires": { + "@fluentui/dom-utilities": "^2.2.14", + "@fluentui/merge-styles": "^8.5.15", + "@fluentui/set-version": "^8.2.14", + "tslib": "^2.1.0" + } + }, + "@griffel/core": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.15.2.tgz", + "integrity": "sha512-RlsIXoSS3gaYykUgxFpwKAs/DV9cRUKp3CW1kt3iPAtsDTWn/o+8bT1jvBws/tMM2GBu/Uc0EkaIzUPqD7uA+Q==", + "requires": { + "@emotion/hash": "^0.9.0", + "@griffel/style-types": "^1.0.3", + "csstype": "^3.1.3", + "rtl-css-js": "^1.16.1", + "stylis": "^4.2.0", + "tslib": "^2.1.0" + } + }, + "@griffel/react": { + "version": "1.5.20", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.20.tgz", + "integrity": "sha512-1P2yaPctENFSCwyPIYXBmgpNH68c0lc/jwSzPij1QATHDK1AASKuSeq6hW108I67RKjhRyHCcALshdZ3GcQXSg==", + "requires": { + "@griffel/core": "^1.15.2", + "tslib": "^2.1.0" + } + }, + "@griffel/style-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.0.3.tgz", + "integrity": "sha512-AzbbYV/EobNIBtfMtyu2edFin895gjVxtu1nsRhTETUAIb0/LCZoue3Jd/kFLuPwe95rv5WRUBiQpVwJsrrFcw==", + "requires": { + "csstype": "^3.1.3" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@microsoft/load-themed-styles": { + "version": "1.10.295", + "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.295.tgz", + "integrity": "sha512-W+IzEBw8a6LOOfRJM02dTT7BDZijxm+Z7lhtOAz1+y9vQm1Kdz9jlAO+qCEKsfxtUOmKilW8DIRqFw2aUgKeGg==" + }, + "@react-spring/animated": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.3.tgz", + "integrity": "sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==", + "requires": { + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/core": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.3.tgz", + "integrity": "sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/shared": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.3.tgz", + "integrity": "sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==", + "requires": { + "@react-spring/types": "~9.7.3" + } + }, + "@react-spring/types": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.3.tgz", + "integrity": "sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==" + }, + "@react-spring/web": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.3.tgz", + "integrity": "sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==", + "requires": { + "@react-spring/animated": "~9.7.3", + "@react-spring/core": "~9.7.3", + "@react-spring/shared": "~9.7.3", + "@react-spring/types": "~9.7.3" + } + }, + "@remix-run/router": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz", + "integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==" + }, + "@rollup/plugin-typescript": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz", + "integrity": "sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA==", + "requires": { + "@rollup/pluginutils": "^5.0.1", + "resolve": "^1.22.1" + } + }, + "@rollup/pluginutils": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz", + "integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==", + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@swc/helpers": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz", + "integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==", + "requires": { + "tslib": "^2.4.0" + } + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/dompurify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.3.tgz", + "integrity": "sha512-odiGr/9/qMqjcBOe5UhcNLOFHSYmKFOyr+bJ/Xu3Qp4k1pNPAlNLUVNNLcLfjQI7+W7ObX58EdD3H+3p3voOvA==", + "dev": true, + "requires": { + "@types/trusted-types": "*" + } + }, + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "@types/react": { + "version": "18.2.48", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", + "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "@types/trusted-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", + "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==", + "dev": true + }, + "@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "requires": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "caniuse-lite": { + "version": "1.0.30001579", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", + "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "dompurify": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", + "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + }, + "electron-to-chromium": { + "version": "1.4.639", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.639.tgz", + "integrity": "sha512-CkKf3ZUVZchr+zDpAlNLEEy2NJJ9T64ULWaDgy3THXXlPVPkLu3VOs9Bac44nebVtdwl2geSj6AxTtGDOxoXhg==", + "dev": true + }, + "esbuild": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz", + "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.11", + "@esbuild/android-arm64": "0.18.11", + "@esbuild/android-x64": "0.18.11", + "@esbuild/darwin-arm64": "0.18.11", + "@esbuild/darwin-x64": "0.18.11", + "@esbuild/freebsd-arm64": "0.18.11", + "@esbuild/freebsd-x64": "0.18.11", + "@esbuild/linux-arm": "0.18.11", + "@esbuild/linux-arm64": "0.18.11", + "@esbuild/linux-ia32": "0.18.11", + "@esbuild/linux-loong64": "0.18.11", + "@esbuild/linux-mips64el": "0.18.11", + "@esbuild/linux-ppc64": "0.18.11", + "@esbuild/linux-riscv64": "0.18.11", + "@esbuild/linux-s390x": "0.18.11", + "@esbuild/linux-x64": "0.18.11", + "@esbuild/netbsd-x64": "0.18.11", + "@esbuild/openbsd-x64": "0.18.11", + "@esbuild/sunos-x64": "0.18.11", + "@esbuild/win32-arm64": "0.18.11", + "@esbuild/win32-ia32": "0.18.11", + "@esbuild/win32-x64": "0.18.11" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "requires": { + "has": "^1.0.3" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "keyborg": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.4.1.tgz", + "integrity": "sha512-B9EZwDd36WKlIq6JmimaTsTDx5E0aUqZcxtgTfK66ut1FbRXYhBmiB7Al2qKzB7CCX9C49sTBiiyVzsXCA6J4Q==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true + }, + "ndjson-readablestream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ndjson-readablestream/-/ndjson-readablestream-1.0.7.tgz", + "integrity": "sha512-4DDTwYTV4yRnCoXparQTF3JeahTNkLVy7XlA0RHXzAqQ3uU8vcu97bNW8rXAQOKQVJGs2aZoX+7cbvfs0LENEA==" + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "dependencies": { + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "requires": { + "loose-envify": "^1.1.0" + } + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "dev": true + }, + "react-router": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz", + "integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==", + "requires": { + "@remix-run/router": "1.14.2" + } + }, + "react-router-dom": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz", + "integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==", + "requires": { + "@remix-run/router": "1.14.2", + "react-router": "6.21.3" + } + }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "tabster": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-5.2.0.tgz", + "integrity": "sha512-cSi3a0gGeM9Co/gTKHlhTFfiitwVjcA+kP9lJux0U7QaRrZox1yYrfbwZhJXM7N0fux7BgvCYaOxME5k0EQ0tA==", + "requires": { + "keyborg": "^2.2.0", + "tslib": "^2.3.1" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==" + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "use-disposable": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/use-disposable/-/use-disposable-1.0.2.tgz", + "integrity": "sha512-UMaXVlV77dWOu4GqAFNjRzHzowYKUKbJBQfCexvahrYeIz4OkUYUjna4Tjjdf92NH8Nm8J7wEfFRgTIwYjO5jg==", + "requires": {} + }, + "vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "dev": true, + "requires": { + "esbuild": "^0.18.10", + "fsevents": "~2.3.2", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } +} diff --git a/app/frontend/package.json b/app/frontend/package.json new file mode 100644 index 0000000..5ee802e --- /dev/null +++ b/app/frontend/package.json @@ -0,0 +1,38 @@ +{ + "name": "frontend", + "private": true, + "version": "1.0.0-alpha", + "type": "module", + "engines": { + "node": ">=14.0.0" + }, + "scripts": { + "dev": "vite --port=8081", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@azure/msal-react": "^2.0.4", + "@azure/msal-browser": "^3.1.0", + "@fluentui/react": "^8.112.5", + "@fluentui/react-components": "^9.37.3", + "@fluentui/react-icons": "^2.0.221", + "@react-spring/web": "^9.7.3", + "dompurify": "^3.0.6", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.18.0", + "ndjson-readablestream": "^1.0.7", + "scheduler": "^0.20.2" + }, + "devDependencies": { + "@types/dompurify": "^3.0.3", + "@types/react": "^18.2.34", + "@types/react-dom": "^18.2.14", + "@vitejs/plugin-react": "^4.1.1", + "prettier": "^3.0.3", + "typescript": "^5.2.2", + "vite": "^4.5.3" + + } +} diff --git a/app/frontend/public/favicon.ico b/app/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f1fe50511ca0c33d95783506d4af99426dfc10bf GIT binary patch literal 4286 zcmeH}dr(y88OA?KWOvysX{UdrX?5Dk2n0}AK@g0WnRH4JL8DO=m3RY_c8nwq(U1w# zblPb%a#2_oP(cAfxywyJkeD=zq)sBaX_L6ZDzLE2?us@Vd!D}Eo;|v0z+{sC8JwT* z@$8=Sd*0_P<1*$&e`d{M{BKsRW9;XQF@J(ivBd;G&wsM$wa4g1&W}I$8|c~T?c4qQ zLmRqMWkp?SJ~>@Ge6l;!e6l+@sXjS`p?#Yy_Wl*$JQ~=;HeYy=6c%Kf!Ux=ZJCigSyTk z@tp5xu(*$Rv#qzA zCYq+a+3TcxoJ^Ce$lKy}3f$YeO^%kWGB1yf?-Yd+b-GCy?h&Her946SKixNPvpa9IcjOKAV%$L~XVuJSBK@)riCNcWK@xgMq+ z?}$zr@0#{ippo;eLLg9`>`T4KB0qhVZRCBs{N(Qa>}`v?~M8s1&(j@Mdf-W`qI5^mopg#Jp315 zrrozt2Y-DO)|zmb%gA3A1T*Cra^>Jzf&`w0I%)NEdLGlRDcsjUKJFw0K9AAfeD`xN zc;nKm;@*6B4)6ZGUF1*o!oNxaVX3D5j|3ATFdwEIyo<6R!CXoiTv>usJe{7$4JoRJ z$#=UhMUL7{3ZZtRLg4ON+Py#hC%E!D!>4-~=-G?ilb?6rvz_>(29~;T3?H3?>y;t6 zULJyL1fS-^Ap-B@T3PTNnp1W!<*47}+fcJnff{o1&MT6XXrtdpzBljugO|N9kiowE z{53XyDU&%bq%&tj5*vFzd)6&`bEN36;u(mFIk?7g=OBNhSU$XXRg;InLv3i%1j#nLsCrxz|BZ_s13hTNRv zp%^(9>dG=)J(sfZ40HZ%t_add*F0z*U9W85pY=-eaw<4UDxq8iG;v_1tWvs%t#w|7 zr9KRn`cRD4k((H;B`C`<$Ub7={&qviNoaN@Xk4<&v4WzOz?$qwRZ0H z`mkU}X9UKY^%y%rG*X5}J;5`GolqZkYjfz7|94H7rEIObvTTj=p7W6C6%MUd3kS(x zuv~?`@#;czU8vD{DgxuJ^Dx%p&OkXVt}HaEld-1I^65O&oiAOZP2{^CTCD>29b8SU zqUXL!jRSO?{X1X0nWzzloAv*>(KBBdZwn{p2|UL*&*9EuY0|^mtWTKEGu?Ue`;gP= z@~zU4Q-flf#pEw}T7%aX_~6Lze}UU)qv1FeAy`j_b6{-`2W6o?!o>_NdWWqwQa+vM zLFbE~QJ0rIO`kRL6?u@KphiZN9B1t95$Z8m4lv1`#f0NBJTa3 zJjgZGYsOWYr;1jpVO*&};R+GsN-h5Oq!NFL_roYTZ@ses6Q|~jbWx5@^7A|d&tYqe z_{MjZsa#W?GbHL}7*=SkE_b3zP0 zKv{%|Zt9>r>TBPZzN^#oeFX`+xcvz_xDno1qQalz{9x^k!kzbG;CMRm>}=nfhTa|d<;SUz6D>;@op6L5%Yt)m;AZ0 zx*30u^)v0%D^Z*I8{o4gxb@E%O!m8>9Fr1#)XCZC&+Wa7{x9828UDOf8=JXQXZWm1 zpNq?jvnTtbvv2mtWZyjRp7ig@^U=At`lIu2o{N4`y6(sM;0ECS$(q^gm8H!hm{*pD zdG)H8cQ0e!CdOnEcE+?W=v`lWWzBTK*vz|(Es_uzdtCyI;T~CDfJCpiq{V*$i&S=H literal 0 HcmV?d00001 diff --git a/app/frontend/src/api/api.ts b/app/frontend/src/api/api.ts new file mode 100644 index 0000000..fb8f511 --- /dev/null +++ b/app/frontend/src/api/api.ts @@ -0,0 +1,51 @@ +import { ChatAppResponse, ChatAppResponseOrError, ChatAppRequest } from "./models"; +import { useLogin } from "../authConfig"; + +const BACKEND_URI = import.meta.env.VITE_BACKEND_URI ? import.meta.env.VITE_BACKEND_URI : ""; + +function getHeaders(idToken: string | undefined, stream:boolean): Record { + var headers: Record = { + "Content-Type": "application/json" + }; + // If using login, add the id token of the logged in account as the authorization + if (useLogin) { + if (idToken) { + headers["Authorization"] = `Bearer ${idToken}` + } + } + + if (stream) { + headers["Accept"] = "application/x-ndjson"; + } else { + headers["Accept"] = "application/json"; + } + + return headers; +} + +export async function askApi(request: ChatAppRequest, idToken: string | undefined): Promise { + const response = await fetch(`${BACKEND_URI}/ask`, { + method: "POST", + headers: getHeaders(idToken, request.stream || false), + body: JSON.stringify(request) + }); + + const parsedResponse: ChatAppResponseOrError = await response.json(); + if (response.status > 299 || !response.ok) { + throw Error(parsedResponse.error || "Unknown error"); + } + + return parsedResponse as ChatAppResponse; +} + +export async function chatApi(request: ChatAppRequest, idToken: string | undefined): Promise { + return await fetch(`${BACKEND_URI}/chat`, { + method: "POST", + headers: getHeaders(idToken, request.stream || false), + body: JSON.stringify(request) + }); +} + +export function getCitationFilePath(citation: string): string { + return `${BACKEND_URI}/content/${citation}`; +} diff --git a/app/frontend/src/api/index.ts b/app/frontend/src/api/index.ts new file mode 100644 index 0000000..0475d35 --- /dev/null +++ b/app/frontend/src/api/index.ts @@ -0,0 +1,2 @@ +export * from "./api"; +export * from "./models"; diff --git a/app/frontend/src/api/models.ts b/app/frontend/src/api/models.ts new file mode 100644 index 0000000..c468488 --- /dev/null +++ b/app/frontend/src/api/models.ts @@ -0,0 +1,70 @@ +export const enum Approaches { + JAVA_OPENAI_SDK = "jos", + JAVA_SEMANTIC_KERNEL = "jsk", + JAVA_SEMANTIC_KERNEL_PLANNER = "jskp" +} + +export const enum RetrievalMode { + Hybrid = "hybrid", + Vectors = "vectors", + Text = "text" +} + +export const enum SKMode { + Chains = "chains", + Planner = "planner" +} + +export type ChatAppRequestOverrides = { + retrieval_mode?: RetrievalMode; + semantic_ranker?: boolean; + semantic_captions?: boolean; + exclude_category?: string; + top?: number; + temperature?: number; + prompt_template?: string; + prompt_template_prefix?: string; + prompt_template_suffix?: string; + suggest_followup_questions?: boolean; + use_oid_security_filter?: boolean; + use_groups_security_filter?: boolean; + semantic_kernel_mode?: SKMode; +}; + +export type ResponseMessage = { + content: string; + role: string; +}; + +export type ResponseContext = { + thoughts: string | null; + data_points: string[]; +}; + +export type ResponseChoice = { + index: number; + message: ResponseMessage; + context: ResponseContext; + session_state: any; +}; + +export type ChatAppResponseOrError = { + choices?: ResponseChoice[]; + error?: string; +}; + +export type ChatAppResponse = { + choices: ResponseChoice[]; +}; + +export type ChatAppRequestContext = { + overrides?: ChatAppRequestOverrides; +}; + +export type ChatAppRequest = { + messages: ResponseMessage[]; + approach: Approaches; + context?: ChatAppRequestContext; + stream?: boolean; + session_state: any; +}; diff --git a/app/frontend/src/assets/github.svg b/app/frontend/src/assets/github.svg new file mode 100644 index 0000000..d5e6491 --- /dev/null +++ b/app/frontend/src/assets/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/frontend/src/assets/search.svg b/app/frontend/src/assets/search.svg new file mode 100644 index 0000000..feadc50 --- /dev/null +++ b/app/frontend/src/assets/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/frontend/src/authConfig.ts b/app/frontend/src/authConfig.ts new file mode 100644 index 0000000..7e583ab --- /dev/null +++ b/app/frontend/src/authConfig.ts @@ -0,0 +1,89 @@ +// Refactored from https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/blob/main/1-Authentication/1-sign-in/SPA/src/authConfig.js + +import { AuthenticationResult, IPublicClientApplication } from "@azure/msal-browser"; + +const BACKEND_URI = import.meta.env.VITE_BACKEND_URI ? import.meta.env.VITE_BACKEND_URI : ""; + +interface AuthSetup { + // Set to true if login elements should be shown in the UI + useLogin: boolean; + /** + * Configuration object to be passed to MSAL instance on creation. + * For a full list of MSAL.js configuration parameters, visit: + * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md + */ + msalConfig: { + auth: { + clientId: string; // Client app id used for login + authority: string; // Directory to use for login https://learn.microsoft.com/azure/active-directory/develop/msal-client-application-configuration#authority + redirectUri: string; // Points to window.location.origin. You must register this URI on Azure Portal/App Registration. + postLogoutRedirectUri: string; // Indicates the page to navigate after logout. + navigateToLoginRequestUrl: boolean; // If "true", will navigate back to the original request location before processing the auth code response. + }; + cache: { + cacheLocation: string; // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs. + storeAuthStateInCookie: boolean; // Set this to "true" if you are having issues on IE11 or Edge + }; + }; + loginRequest: { + /** + * Scopes you add here will be prompted for user consent during sign-in. + * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request. + * For more information about OIDC scopes, visit: + * https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes + */ + scopes: Array; + }; + tokenRequest: { + scopes: Array; + }; +} + +// Fetch the auth setup JSON data from the API if not already cached +async function fetchAuthSetup(): Promise { + const response = await fetch(`${BACKEND_URI}/auth_setup`); + if (!response.ok) { + throw new Error(`auth setup response was not ok: ${response.status}`); + } + return await response.json(); +} + +const authSetup = await fetchAuthSetup(); + +export const useLogin = authSetup.useLogin; + +/** + * Configuration object to be passed to MSAL instance on creation. + * For a full list of MSAL.js configuration parameters, visit: + * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md + */ +export const msalConfig = authSetup.msalConfig; + +/** + * Scopes you add here will be prompted for user consent during sign-in. + * By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request. + * For more information about OIDC scopes, visit: + * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes + */ +export const loginRequest = authSetup.loginRequest; + +const tokenRequest = authSetup.tokenRequest; + +// Build an absolute redirect URI using the current window's location and the relative redirect URI from auth setup +export const getRedirectUri = () => { + return window.location.origin + authSetup.msalConfig.auth.redirectUri; +}; + +// Get an access token for use with the API server. +// ID token received when logging in may not be used for this purpose because it has the incorrect audience +export const getToken = (client: IPublicClientApplication): Promise => { + return client + .acquireTokenSilent({ + ...tokenRequest, + redirectUri: getRedirectUri() + }) + .catch(error => { + console.log(error); + return undefined; + }); +}; diff --git a/app/frontend/src/components/AnalysisPanel/AnalysisPanel.module.css b/app/frontend/src/components/AnalysisPanel/AnalysisPanel.module.css new file mode 100644 index 0000000..909ac03 --- /dev/null +++ b/app/frontend/src/components/AnalysisPanel/AnalysisPanel.module.css @@ -0,0 +1,6 @@ +.thoughtProcess { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; + word-wrap: break-word; + padding-top: 12px; + padding-bottom: 12px; +} diff --git a/app/frontend/src/components/AnalysisPanel/AnalysisPanel.tsx b/app/frontend/src/components/AnalysisPanel/AnalysisPanel.tsx new file mode 100644 index 0000000..4b99a41 --- /dev/null +++ b/app/frontend/src/components/AnalysisPanel/AnalysisPanel.tsx @@ -0,0 +1,57 @@ +import { Pivot, PivotItem } from "@fluentui/react"; +import DOMPurify from "dompurify"; + +import styles from "./AnalysisPanel.module.css"; + +import { SupportingContent } from "../SupportingContent"; +import { ChatAppResponse } from "../../api"; +import { AnalysisPanelTabs } from "./AnalysisPanelTabs"; + +interface Props { + className: string; + activeTab: AnalysisPanelTabs; + onActiveTabChanged: (tab: AnalysisPanelTabs) => void; + activeCitation: string | undefined; + citationHeight: string; + answer: ChatAppResponse; +} + +const pivotItemDisabledStyle = { disabled: true, style: { color: "grey" } }; + +export const AnalysisPanel = ({ answer, activeTab, activeCitation, citationHeight, className, onActiveTabChanged }: Props) => { + const isDisabledThoughtProcessTab: boolean = !answer.choices[0].context.thoughts; + const isDisabledSupportingContentTab: boolean = !answer.choices[0].context.data_points.length; + const isDisabledCitationTab: boolean = !activeCitation; + + const sanitizedThoughts = DOMPurify.sanitize(answer.choices[0].context.thoughts!); + + return ( + pivotItem && onActiveTabChanged(pivotItem.props.itemKey! as AnalysisPanelTabs)} + > + +
+
+ + + + +