diff --git a/README.md b/README.md index 1865d1e1..4a3c7b16 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ This application is made from multiple components: - A serverless API built with [Azure Functions](https://learn.microsoft.com/azure/azure-functions/functions-overview?pivots=programming-language-javascript) and using [LangChain.js](https://js.langchain.com/) to ingest the documents and generate responses to the user chat queries. The code is located in the `packages/api` folder. -- A database to store the text extracted from the documents and the vectors generated by LangChain.js, using [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/azure/cosmos-db/nosql/). +- A database to store chat sessions and the text extracted from the documents and the vectors generated by LangChain.js, using [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/azure/cosmos-db/nosql/). - A file storage to store the source documents, using [Azure Blob Storage](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-introduction). @@ -54,6 +54,7 @@ We use the [HTTP protocol for AI chat apps](https://aka.ms/chatprotocol) to comm - **Serverless Architecture**: Utilizes Azure Functions and Azure Static Web Apps for a fully serverless deployment. - **Retrieval-Augmented Generation (RAG)**: Combines the power of Azure Cosmos DB and LangChain.js to provide relevant and accurate responses. +- **Chat Sessions History**: Maintains a personal chat history for each user, allowing them to revisit previous conversations. - **Scalable and Cost-Effective**: Leverages Azure's serverless offerings to provide a scalable and cost-effective solution. - **Local Development**: Supports local development using Ollama for testing without any cloud costs. diff --git a/docs/images/architecture-local.drawio.png b/docs/images/architecture-local.drawio.png index eaa59152..404318ff 100644 Binary files a/docs/images/architecture-local.drawio.png and b/docs/images/architecture-local.drawio.png differ diff --git a/docs/images/architecture.drawio.png b/docs/images/architecture.drawio.png index 5c4120d9..a994ba5d 100644 Binary files a/docs/images/architecture.drawio.png and b/docs/images/architecture.drawio.png differ diff --git a/docs/readme.md b/docs/readme.md index 0f0ce018..aad1f7c2 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -35,7 +35,7 @@ This application is made from multiple components: - A serverless API built with [Azure Functions](https://learn.microsoft.com/azure/azure-functions/functions-overview?pivots=programming-language-javascript) and using [LangChain.js](https://js.langchain.com/) to ingest the documents and generate responses to the user chat queries. The code is located in the `packages/api` folder. -- A database to store the text extracted from the documents and the vectors generated by LangChain.js, using [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/azure/cosmos-db/nosql/). +- A database to store chat sessions and the text extracted from the documents and the vectors generated by LangChain.js, using [Azure Cosmos DB for NoSQL](https://learn.microsoft.com/azure/cosmos-db/nosql/). - A file storage to store the source documents, using [Azure Blob Storage](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-introduction). @@ -77,9 +77,9 @@ You can now open the web app in your browser and start chatting with the bot. Our API is composed of two main endpoints: -- `/documents`: This endpoint allows to upload a PDF documents in the database. Using LangChain.js, we extract the text from the PDF file, split it into smaller chunks, and generate vectors for each chunk. We store the text and the vectors in the database for later use. +- `POST /documents`: This endpoint allows to upload a PDF documents in the database. Using LangChain.js, we extract the text from the PDF file, split it into smaller chunks, and generate vectors for each chunk. We store the text and the vectors in the database for later use. -- `/chat`: This endpoint receives a list of messages, the last being the user query and returns a response generated by the LLM. It uses the documents stored in the database to generate the response. We use LangChain.js components to connect to the database, load the documents and perform a vector search after vectorizing the user query. After that, the most relevant documents are injected into the prompt, and we generate the response. While this process seems complex, LangChain.js does all the heavy lifting for us so we can focus on the application flow. +- `POST /chats`: This endpoint receives a list of messages, the last being the user query and returns a response generated by the LLM. It uses the documents stored in the database to generate the response. We use LangChain.js components to connect to the database, load the documents and perform a vector search after vectorizing the user query. After that, the most relevant documents are injected into the prompt, and we generate the response. While this process seems complex, LangChain.js does all the heavy lifting for us so we can focus on the application flow. The `/documents` endpoint is used to ingest the documents after the application is deployed by uploading the PDFs, using either `curl` commands or the Node.js script we built (have a look at the `postup` hook in the `azure.yaml` file). diff --git a/infra/core/database/cosmos/cosmos-account.bicep b/infra/core/database/cosmos/cosmos-account.bicep deleted file mode 100644 index 96e97ee7..00000000 --- a/infra/core/database/cosmos/cosmos-account.bicep +++ /dev/null @@ -1,40 +0,0 @@ -metadata description = 'Creates an Azure Cosmos DB account.' -param name string -param location string = resourceGroup().location -param tags object = {} - -@allowed([ 'GlobalDocumentDB', 'MongoDB', 'Parse' ]) -param kind string - -param disableLocalAuth bool = false - -resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2023-11-15' = { - name: name - kind: kind - location: location - tags: tags - properties: { - consistencyPolicy: { defaultConsistencyLevel: 'Session' } - locations: [ - { - locationName: location - failoverPriority: 0 - isZoneRedundant: false - } - ] - databaseAccountOfferType: 'Standard' - enableAutomaticFailover: false - enableMultipleWriteLocations: false - apiProperties: (kind == 'MongoDB') ? { serverVersion: '4.2' } : {} - capabilities: [ - { name: 'EnableServerless' } - { name: 'EnableNoSQLVectorSearch' } - ] - minimalTlsVersion: 'Tls12' - disableLocalAuth: disableLocalAuth - } -} - -output endpoint string = cosmos.properties.documentEndpoint -output id string = cosmos.id -output name string = cosmos.name diff --git a/infra/core/database/cosmos/sql/cosmos-sql-account.bicep b/infra/core/database/cosmos/sql/cosmos-sql-account.bicep deleted file mode 100644 index a3944250..00000000 --- a/infra/core/database/cosmos/sql/cosmos-sql-account.bicep +++ /dev/null @@ -1,21 +0,0 @@ -metadata description = 'Creates an Azure Cosmos DB for NoSQL account.' -param name string -param location string = resourceGroup().location -param tags object = {} - -param disableLocalAuth bool = false - -module cosmos '../../cosmos/cosmos-account.bicep' = { - name: 'cosmos-account' - params: { - name: name - location: location - tags: tags - kind: 'GlobalDocumentDB' - disableLocalAuth: disableLocalAuth - } -} - -output endpoint string = cosmos.outputs.endpoint -output id string = cosmos.outputs.id -output name string = cosmos.outputs.name diff --git a/infra/core/database/cosmos/sql/cosmos-sql-db.bicep b/infra/core/database/cosmos/sql/cosmos-sql-db.bicep deleted file mode 100644 index 77117232..00000000 --- a/infra/core/database/cosmos/sql/cosmos-sql-db.bicep +++ /dev/null @@ -1,73 +0,0 @@ -metadata description = 'Creates an Azure Cosmos DB for NoSQL account with a database.' -param accountName string -param databaseName string -param location string = resourceGroup().location -param tags object = {} - -param containers array = [] -param principalIds array = [] -param disableLocalAuth bool = false - -module cosmos 'cosmos-sql-account.bicep' = { - name: 'cosmos-sql-account' - params: { - name: accountName - location: location - tags: tags - disableLocalAuth: disableLocalAuth - } -} - -resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = { - name: '${accountName}/${databaseName}' - properties: { - resource: { id: databaseName } - } - - resource list 'containers' = [for container in containers: { - name: container.name - properties: { - resource: { - id: container.id - partitionKey: { paths: [ container.partitionKey ] } - } - options: {} - } - }] - - dependsOn: [ - cosmos - ] -} - -module roleDefinition 'cosmos-sql-role-def.bicep' = { - name: 'cosmos-sql-role-definition' - params: { - accountName: accountName - } - dependsOn: [ - cosmos - database - ] -} - -// We need batchSize(1) here because sql role assignments have to be done sequentially -@batchSize(1) -module userRole 'cosmos-sql-role-assign.bicep' = [for principalId in principalIds: if (!empty(principalId)) { - name: 'cosmos-sql-user-role-${uniqueString(principalId)}' - params: { - accountName: accountName - roleDefinitionId: roleDefinition.outputs.id - principalId: principalId - } - dependsOn: [ - cosmos - database - ] -}] - -output accountId string = cosmos.outputs.id -output accountName string = cosmos.outputs.name -output databaseName string = databaseName -output endpoint string = cosmos.outputs.endpoint -output roleDefinitionId string = roleDefinition.outputs.id diff --git a/infra/main.bicep b/infra/main.bicep index 7f58390d..e0febdd5 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -220,7 +220,7 @@ module openAi 'core/ai/cognitiveservices.bicep' = if (empty(openAiUrl)) { version: chatModelVersion } sku: { - name: 'Standard' + name: 'GlobalStandard' capacity: chatDeploymentCapacity } } @@ -237,22 +237,63 @@ module openAi 'core/ai/cognitiveservices.bicep' = if (empty(openAiUrl)) { } } -module cosmosDb './core/database/cosmos/sql/cosmos-sql-db.bicep' = { +module cosmosDb 'br/public:avm/res/document-db/database-account:0.9.0' = { name: 'cosmosDb' scope: resourceGroup params: { - accountName: !empty(cosmosDbServiceName) ? cosmosDbServiceName : '${abbrs.documentDBDatabaseAccounts}${resourceToken}' - location: location + name: !empty(cosmosDbServiceName) ? cosmosDbServiceName : '${abbrs.documentDBDatabaseAccounts}${resourceToken}' tags: tags - containers: [ + locations: [ { - name: 'vectorSearchContainer' - id: 'vectorSearchContainer' - partitionKey: '/id' + locationName: location + failoverPriority: 0 + isZoneRedundant: false } ] - databaseName: 'vectorSearchDB' - disableLocalAuth: true + managedIdentities: { + systemAssigned: true + } + capabilitiesToAdd: [ + 'EnableServerless' + 'EnableNoSQLVectorSearch' + ] + networkRestrictions: { + ipRules: [] + virtualNetworkRules: [] + publicNetworkAccess: 'Enabled' + } + sqlDatabases: [ + { + containers: [ + { + name: 'vectorSearchContainer' + paths: [ + '/id' + ] + } + ] + name: 'vectorSearchDB' + } + { + containers: [ + { + name: 'chatHistoryContainer' + paths: [ + '/userId' + ] + } + ] + name: 'chatHistoryDB' + } + ] + } +} + +module dbRoleDefinition './core/database/cosmos/sql/cosmos-sql-role-def.bicep' = { + scope: resourceGroup + name: 'db-contrib-role-definition' + params: { + accountName: cosmosDb.outputs.name } } @@ -287,10 +328,10 @@ module dbContribRoleUser './core/database/cosmos/sql/cosmos-sql-role-assign.bice scope: resourceGroup name: 'db-contrib-role-user' params: { - accountName: cosmosDb.outputs.accountName + accountName: cosmosDb.outputs.name principalId: principalId // Cosmos DB Data Contributor - roleDefinitionId: cosmosDb.outputs.roleDefinitionId + roleDefinitionId: dbRoleDefinition.outputs.id } } @@ -321,10 +362,10 @@ module dbContribRoleApi './core/database/cosmos/sql/cosmos-sql-role-assign.bicep scope: resourceGroup name: 'db-contrib-role-api' params: { - accountName: cosmosDb.outputs.accountName + accountName: cosmosDb.outputs.name principalId: api.outputs.identityPrincipalId // Cosmos DB Data Contributor - roleDefinitionId: cosmosDb.outputs.roleDefinitionId + roleDefinitionId: dbRoleDefinition.outputs.id } } diff --git a/infra/main.parameters.json b/infra/main.parameters.json index a69ab3c0..c67cb0b3 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -21,10 +21,10 @@ "value": "${AZURE_OPENAI_API_VERSION=2024-02-01}" }, "chatModelName": { - "value": "${AZURE_OPENAI_API_MODEL=gpt-4}" + "value": "${AZURE_OPENAI_API_MODEL=gpt-4o-mini}" }, "chatModelVersion": { - "value": "${AZURE_OPENAI_API_MODEL_VERSION=turbo-2024-04-09}" + "value": "${AZURE_OPENAI_API_MODEL_VERSION=2024-07-18}" }, "embeddingsModelName": { "value": "${AZURE_OPENAI_API_EMBEDDINGS_MODEL=text-embedding-ada-002}" diff --git a/package-lock.json b/package-lock.json index e768ae46..25ce9cef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,9 +42,9 @@ } }, "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { - "version": "18.19.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.67.tgz", - "integrity": "sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", "license": "MIT", "peer": true, "dependencies": { @@ -360,6 +360,15 @@ "node": ">=16" } }, + "node_modules/@azure/msal-node/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@azure/search-documents": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/@azure/search-documents/-/search-documents-12.1.0.tgz", @@ -430,19 +439,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@browserbasehq/sdk": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@browserbasehq/sdk/-/sdk-2.0.0.tgz", @@ -460,9 +456,9 @@ } }, "node_modules/@browserbasehq/sdk/node_modules/@types/node": { - "version": "18.19.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.67.tgz", - "integrity": "sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", "license": "MIT", "peer": true, "dependencies": { @@ -477,16 +473,16 @@ "peer": true }, "node_modules/@browserbasehq/stagehand": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@browserbasehq/stagehand/-/stagehand-1.5.0.tgz", - "integrity": "sha512-7rMOCxNj/vJLbmduD4iAGqtRjInf/nTFHwQfzv70On316gh1tuKl35x3b2M8acL+HDc4Gw8sPKPNNRq7ibhpnA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@browserbasehq/stagehand/-/stagehand-1.6.0.tgz", + "integrity": "sha512-seDmCtokkCf+5xaJ2IOjxcNAGm5PrOR8m+hgtDuMxfByE9o1pQdFYtNkjDFfI9oBbIB2EF3RQJTxkQHT9s6QRA==", "license": "MIT", "peer": true, "dependencies": { "@anthropic-ai/sdk": "^0.27.3", "@browserbasehq/sdk": "^2.0.0", "sharp": "^0.33.5", - "zod-to-json-schema": "^3.23.3" + "zod-to-json-schema": "^3.23.5" }, "peerDependencies": { "@playwright/test": "^1.42.1", @@ -496,6 +492,12 @@ "zod": "^3.23.8" } }, + "node_modules/@cfworker/json-schema": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.0.3.tgz", + "integrity": "sha512-ZykIcDTVv5UNmKWSTLAs3VukO6NDJkkSKxrgUTDPBkAlORVT3H9n5DbRjRl8xIotklscHdbLIa0b9+y3mQq73g==", + "license": "MIT" + }, "node_modules/@emnapi/runtime": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", @@ -1089,9 +1091,9 @@ } }, "node_modules/@ibm-cloud/watsonx-ai/node_modules/@types/node": { - "version": "18.19.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.67.tgz", - "integrity": "sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", "license": "MIT", "peer": true, "dependencies": { @@ -1560,9 +1562,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", "peer": true, @@ -1647,9 +1649,9 @@ } }, "node_modules/@langchain/community": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.17.tgz", - "integrity": "sha512-ZcpSC1ZHfFk7ZJE5Ze9kh2bHOCzY/G03tlCqkwexDVB1C7/Iu9wvLqKtSQVMdYW2MfBJJGfeToDeWJ3FIULHbg==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.18.tgz", + "integrity": "sha512-hKXjf+K9NKZW/Ji3Y03npWDtvewPLGdevkGDtDKEBgxBMyDXN/AXxI0vt0mVAI3qsbeLmyzF3yLI7UZEN+S6fA==", "license": "MIT", "dependencies": { "@langchain/openai": ">=0.2.0 <0.4.0", @@ -2170,11 +2172,12 @@ } }, "node_modules/@langchain/core": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.20.tgz", - "integrity": "sha512-29yg7dccRkJ1MdGFW4FSp6+yM8LoisBHWjXsoi+hTRTQBael3yhjnevrNtVjhF8FMAt/rDQan6bHsGCQkwcScA==", + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.23.tgz", + "integrity": "sha512-Aut43dEJYH/ibccSErFOLQzymkBG4emlN16P0OHWwx02bDosOR9ilZly4JJiCSYcprn2X2H8nee6P/4VMg1oQA==", "license": "MIT", "dependencies": { + "@cfworker/json-schema": "^4.0.2", "ansi-styles": "^5.0.0", "camelcase": "6", "decamelize": "1.2.0", @@ -2217,9 +2220,9 @@ } }, "node_modules/@langchain/ollama": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.1.2.tgz", - "integrity": "sha512-WCeogCFjdWf6jGwLt12cxkSpm5eVamv43b48DIlbJ4np9vChwVlZZB6FU7uEXNrJ9c0dsoa6877hJ5mYHdbJvw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.1.3.tgz", + "integrity": "sha512-j7STBQXzfT3HtU3pUXh7cp5lz2W8BA0mba0eC8zPjZo009VfLI/bE3cO90zjRFVY9ZloWU6r+jzL92Z2tPkQbQ==", "license": "MIT", "dependencies": { "ollama": "^0.5.9", @@ -2363,13 +2366,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0.tgz", - "integrity": "sha512-DMulbwQURa8rNIQrf94+jPJQ4FmOVdpE5ZppRNvWVjvhC+6sOeo28r8MgIpQRYouXRtt/FCCXU7zn20jnHR4Qw==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", + "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", "license": "Apache-2.0", "peer": true, "dependencies": { - "playwright": "1.49.0" + "playwright": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -2379,9 +2382,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz", - "integrity": "sha512-wLJuPLT6grGZsy34g4N1yRfYeouklTgPhH1gWXCYspenKYD0s3cR99ZevOGw5BexMNywkbV3UkjADisozBmpPQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", + "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", "cpu": [ "arm" ], @@ -2393,9 +2396,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.0.tgz", - "integrity": "sha512-eiNkznlo0dLmVG/6wf+Ifi/v78G4d4QxRhuUl+s8EWZpDewgk7PX3ZyECUXU0Zq/Ca+8nU8cQpNC4Xgn2gFNDA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", + "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", "cpu": [ "arm64" ], @@ -2407,9 +2410,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.0.tgz", - "integrity": "sha512-lmKx9yHsppblnLQZOGxdO66gT77bvdBtr/0P+TPOseowE7D9AJoBw8ZDULRasXRWf1Z86/gcOdpBrV6VDUY36Q==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", + "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", "cpu": [ "arm64" ], @@ -2421,9 +2424,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.0.tgz", - "integrity": "sha512-8hxgfReVs7k9Js1uAIhS6zq3I+wKQETInnWQtgzt8JfGx51R1N6DRVy3F4o0lQwumbErRz52YqwjfvuwRxGv1w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", + "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", "cpu": [ "x64" ], @@ -2435,9 +2438,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.0.tgz", - "integrity": "sha512-lA1zZB3bFx5oxu9fYud4+g1mt+lYXCoch0M0V/xhqLoGatbzVse0wlSQ1UYOWKpuSu3gyN4qEc0Dxf/DII1bhQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", + "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", "cpu": [ "arm64" ], @@ -2449,9 +2452,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.0.tgz", - "integrity": "sha512-aI2plavbUDjCQB/sRbeUZWX9qp12GfYkYSJOrdYTL/C5D53bsE2/nBPuoiJKoWp5SN78v2Vr8ZPnB+/VbQ2pFA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", + "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", "cpu": [ "x64" ], @@ -2463,9 +2466,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.0.tgz", - "integrity": "sha512-WXveUPKtfqtaNvpf0iOb0M6xC64GzUX/OowbqfiCSXTdi/jLlOmH0Ba94/OkiY2yTGTwteo4/dsHRfh5bDCZ+w==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", + "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", "cpu": [ "arm" ], @@ -2477,9 +2480,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.0.tgz", - "integrity": "sha512-yLc3O2NtOQR67lI79zsSc7lk31xjwcaocvdD1twL64PK1yNaIqCeWI9L5B4MFPAVGEVjH5k1oWSGuYX1Wutxpg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", + "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", "cpu": [ "arm" ], @@ -2491,9 +2494,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.0.tgz", - "integrity": "sha512-+P9G9hjEpHucHRXqesY+3X9hD2wh0iNnJXX/QhS/J5vTdG6VhNYMxJ2rJkQOxRUd17u5mbMLHM7yWGZdAASfcg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", + "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", "cpu": [ "arm64" ], @@ -2505,9 +2508,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.0.tgz", - "integrity": "sha512-1xsm2rCKSTpKzi5/ypT5wfc+4bOGa/9yI/eaOLW0oMs7qpC542APWhl4A37AENGZ6St6GBMWhCCMM6tXgTIplw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", + "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", "cpu": [ "arm64" ], @@ -2518,10 +2521,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", + "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.0.tgz", - "integrity": "sha512-zgWxMq8neVQeXL+ouSf6S7DoNeo6EPgi1eeqHXVKQxqPy1B2NvTbaOUWPn/7CfMKL7xvhV0/+fq/Z/J69g1WAQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", + "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", "cpu": [ "ppc64" ], @@ -2533,9 +2550,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.0.tgz", - "integrity": "sha512-VEdVYacLniRxbRJLNtzwGt5vwS0ycYshofI7cWAfj7Vg5asqj+pt+Q6x4n+AONSZW/kVm+5nklde0qs2EUwU2g==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", + "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", "cpu": [ "riscv64" ], @@ -2547,9 +2564,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.0.tgz", - "integrity": "sha512-LQlP5t2hcDJh8HV8RELD9/xlYtEzJkm/aWGsauvdO2ulfl3QYRjqrKW+mGAIWP5kdNCBheqqqYIGElSRCaXfpw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", + "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", "cpu": [ "s390x" ], @@ -2561,9 +2578,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.0.tgz", - "integrity": "sha512-Nl4KIzteVEKE9BdAvYoTkW19pa7LR/RBrT6F1dJCV/3pbjwDcaOq+edkP0LXuJ9kflW/xOK414X78r+K84+msw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", + "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", "cpu": [ "x64" ], @@ -2575,9 +2592,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.0.tgz", - "integrity": "sha512-eKpJr4vBDOi4goT75MvW+0dXcNUqisK4jvibY9vDdlgLx+yekxSm55StsHbxUsRxSTt3JEQvlr3cGDkzcSP8bw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", + "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", "cpu": [ "x64" ], @@ -2589,9 +2606,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.0.tgz", - "integrity": "sha512-Vi+WR62xWGsE/Oj+mD0FNAPY2MEox3cfyG0zLpotZdehPFXwz6lypkGs5y38Jd/NVSbOD02aVad6q6QYF7i8Bg==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", + "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", "cpu": [ "arm64" ], @@ -2603,9 +2620,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.0.tgz", - "integrity": "sha512-kN/Vpip8emMLn/eOza+4JwqDZBL6MPNpkdaEsgUtW1NYN3DZvZqSQrbKzJcTL6hd8YNmFTn7XGWMwccOcJBL0A==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", + "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", "cpu": [ "ia32" ], @@ -2617,9 +2634,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.0.tgz", - "integrity": "sha512-Bvno2/aZT6usSa7lRDL2+hMjVAGjuqaymF1ApZm31JXzniR/hvr14jpU+/z4X6Gt5BPlzosscyJZGUvguXIqeQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", + "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", "cpu": [ "x64" ], @@ -2726,9 +2743,9 @@ "peer": true }, "node_modules/@types/node": { - "version": "22.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", - "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -3046,19 +3063,12 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", + "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", "dev": true, "license": "ISC" }, - "node_modules/@vscode/web-custom-data": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/@vscode/web-custom-data/-/web-custom-data-0.4.13.tgz", - "integrity": "sha512-2ZUIRfhofZ/npLlf872EBnPmn27Kt4M2UssmQIfnJvgGgMYZJ5fvtHEDnttBBf2hnVtBgNCqZMVHJA+wsFVqTA==", - "dev": true, - "license": "MIT" - }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -3287,13 +3297,10 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } @@ -4164,17 +4171,47 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.2.tgz", + "integrity": "sha512-0lk0PHFe/uz0vl527fG9CgdE9WdafjDbCXvBbs+LUv000TVt2Jjhqbs4Jwm8gz070w8xXyEAxrPOMullsxXeGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "get-intrinsic": "^1.2.5" }, "engines": { "node": ">= 0.4" @@ -4206,9 +4243,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", + "version": "1.0.30001688", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz", + "integrity": "sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==", "dev": true, "funding": [ { @@ -4672,9 +4709,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4835,21 +4872,6 @@ "node": ">=8" } }, - "node_modules/didyoumean2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/didyoumean2/-/didyoumean2-4.1.0.tgz", - "integrity": "sha512-qTBmfQoXvhKO75D/05C8m+fteQmn4U46FWYiLhXtZQInzitXLWY0EQ/2oKnpAz9g2lQWW8jYcLcT+hPJGT+kig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.2", - "leven": "^3.1.0", - "lodash.deburr": "^4.1.0" - }, - "engines": { - "node": ">=10.13" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4898,6 +4920,21 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", + "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4915,9 +4952,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.68", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz", - "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==", + "version": "1.5.73", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz", + "integrity": "sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==", "dev": true, "license": "ISC" }, @@ -5072,14 +5109,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -5435,19 +5469,19 @@ } }, "node_modules/eslint-import-resolver-webpack": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.9.tgz", - "integrity": "sha512-yGngeefNiHXau2yzKKs2BNON4HLpxBabY40BGL/vUSKZtqzjlVsTTZm57jhHULhm+mJEwKsEIIN3NXup5AiiBQ==", + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.10.tgz", + "integrity": "sha512-ciVTEg7sA56wRMR772PyjcBRmyBMLS46xgzQZqt6cWBEKc7cK65ZSSLCTLVRu2gGtKyXUb5stwf4xxLBfERLFA==", "dev": true, "license": "MIT", "dependencies": { "debug": "^3.2.7", "enhanced-resolve": "^0.9.1", "find-root": "^1.1.0", - "hasown": "^2.0.0", + "hasown": "^2.0.2", "interpret": "^1.4.0", - "is-core-module": "^2.13.1", - "is-regex": "^1.1.4", + "is-core-module": "^2.15.1", + "is-regex": "^1.2.0", "lodash": "^4.17.21", "resolve": "^2.0.0-next.5", "semver": "^5.7.2" @@ -5693,9 +5727,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.14.0.tgz", - "integrity": "sha512-maxPLMEA0rPmRpoOlxEclKng4UpDe+N5BJS4t24I3UKnN109Qcivnfs37KMy84G0af3bxjog5lKctP5ObsvcTA==", + "version": "17.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.0.tgz", + "integrity": "sha512-xF3zJkOfLlFOm5TvmqmsnA9/fO+/z2pYs0dkuKXKN/ymS6UB1yEcaoIkqxLKQ9Dw/WmLX/Tdh6/5ZS5azVixFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6827,17 +6861,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7016,14 +7055,11 @@ } }, "node_modules/gopd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.1.0.tgz", - "integrity": "sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" }, @@ -7079,13 +7115,13 @@ } }, "node_modules/has-proto": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", - "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "dunder-proto": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7157,12 +7193,12 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -7530,12 +7566,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -7794,14 +7832,14 @@ } }, "node_modules/is-regex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.0.tgz", - "integrity": "sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "gopd": "^1.1.0", + "call-bound": "^1.0.2", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" }, @@ -8111,9 +8149,9 @@ "license": "Apache-2.0" }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { @@ -8248,9 +8286,9 @@ } }, "node_modules/langchain": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.6.tgz", - "integrity": "sha512-erZOIKXzwCOrQHqY9AyjkQmaX62zUap1Sigw1KrwMUOnVoLKkVNRmAyxFlNZDZ9jLs/58MaQcaT9ReJtbj3x6w==", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.7.tgz", + "integrity": "sha512-6/Gkk9Zez3HkbsETFxZVo1iKLmaK3OzkDseC5MYFKVmYFDXFAOyJR3srJ9P61xF8heVdsPixqYIsejBn7/9dXg==", "license": "MIT", "dependencies": { "@langchain/openai": ">=0.1.0 <0.4.0", @@ -8258,7 +8296,7 @@ "js-tiktoken": "^1.0.12", "js-yaml": "^4.1.0", "jsonpointer": "^5.0.1", - "langsmith": "^0.2.0", + "langsmith": "^0.2.8", "openapi-types": "^12.1.3", "p-retry": "4", "uuid": "^10.0.0", @@ -8341,9 +8379,9 @@ } }, "node_modules/langsmith": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.2.8.tgz", - "integrity": "sha512-wKVNZoYtd8EqQWUEsfDZlZ77rH7vVqgNtONXRwynUp7ZFMFUIPhSlqE9pXqrmYPE8ZTBFj7diag2lFgUuaOEKw==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.2.13.tgz", + "integrity": "sha512-16EOM5nhU6GlMCKGm5sgBIAKOKzS2d30qcDZmF21kSLZJiUhUNTROwvYdqgZLrGfIIzmSMJHCKA7RFd5qf50uw==", "license": "MIT", "dependencies": { "@types/uuid": "^10.0.0", @@ -8384,16 +8422,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -8445,22 +8473,22 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", - "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "version": "15.2.11", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", + "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.6", + "debug": "~4.4.0", "execa": "~8.0.1", - "lilconfig": "~3.1.2", - "listr2": "~8.2.4", + "lilconfig": "~3.1.3", + "listr2": "~8.2.5", "micromatch": "~4.0.8", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.5.0" + "yaml": "~2.6.1" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -8514,105 +8542,6 @@ "lit-html": "^3.2.0" } }, - "node_modules/lit-analyzer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lit-analyzer/-/lit-analyzer-2.0.3.tgz", - "integrity": "sha512-XiAjnwVipNrKav7r3CSEZpWt+mwYxrhPRVC7h8knDmn/HWTzzWJvPe+mwBcL2brn4xhItAMzZhFC8tzzqHKmiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vscode/web-custom-data": "^0.4.2", - "chalk": "^2.4.2", - "didyoumean2": "4.1.0", - "fast-glob": "^3.2.11", - "parse5": "5.1.0", - "ts-simple-type": "~2.0.0-next.0", - "vscode-css-languageservice": "4.3.0", - "vscode-html-languageservice": "3.1.0", - "web-component-analyzer": "^2.0.0" - }, - "bin": { - "lit-analyzer": "cli.js" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT" - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/lit-analyzer/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, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/lit-element": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz", @@ -8674,13 +8603,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.deburr": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.deburr/-/lodash.deburr-4.1.0.tgz", - "integrity": "sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -8852,6 +8774,16 @@ "node": "20 || >=22" } }, + "node_modules/math-intrinsics": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/memory-fs": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", @@ -9027,13 +8959,13 @@ "license": "MIT" }, "node_modules/mongodb": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.11.0.tgz", - "integrity": "sha512-yVbPw0qT268YKhG241vAMLaDQAPbRyTgo++odSgGc9kXnzOujQI60Iyj23B9sQQFPSvmNPvMZ3dsFz0aN55KgA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", + "integrity": "sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.0", + "bson": "^6.10.1", "mongodb-connection-string-url": "^3.0.0" }, "engines": { @@ -9041,7 +8973,7 @@ }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", @@ -9223,9 +9155,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -9404,9 +9336,9 @@ } }, "node_modules/ollama": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.5.10.tgz", - "integrity": "sha512-M5O4u6S6yZeeKFrKA7ZfGGLjK54otOVGPrOUc3N64zSTpz9J+x/nh93dmD6Py7YLgXzq9I6Nq+PDDoaqJuV3LQ==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.5.11.tgz", + "integrity": "sha512-lDAKcpmBU3VAOGF05NcQipHNKTdpKfAHpZ7bjCsElkUkmX7SNZImi6lwIxz/l1zQtLq0S3wuLneRuiXxX2KIew==", "license": "MIT", "dependencies": { "whatwg-fetch": "^3.6.20" @@ -9489,9 +9421,9 @@ } }, "node_modules/open-editor/node_modules/execa": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.1.tgz", - "integrity": "sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", + "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9612,9 +9544,9 @@ } }, "node_modules/openai": { - "version": "4.75.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.75.0.tgz", - "integrity": "sha512-8cWaK3td0qLspaflKWD6AvpQnl0gynWFbHg7sMAgiu//F20I4GJlCCpllDrECO6WFSuY8HXJj8gji3urw2BGGg==", + "version": "4.76.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.76.1.tgz", + "integrity": "sha512-ci63/WFEMd6QjjEVeH0pV7hnFS6CCqhgJydSti4Aak/8uo2SpgzKjteUDaY+OkwziVj11mi6j+0mRUIiGKUzWw==", "license": "Apache-2.0", "dependencies": { "@types/node": "^18.11.18", @@ -9638,9 +9570,9 @@ } }, "node_modules/openai/node_modules/@types/node": { - "version": "18.19.67", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.67.tgz", - "integrity": "sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==", + "version": "18.19.68", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", + "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -9826,13 +9758,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true, - "license": "MIT" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9983,13 +9908,13 @@ } }, "node_modules/playwright": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz", - "integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", + "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", "license": "Apache-2.0", "peer": true, "dependencies": { - "playwright-core": "1.49.0" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -10002,9 +9927,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz", - "integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", + "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", "license": "Apache-2.0", "peer": true, "bin": { @@ -10420,19 +10345,20 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", - "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", + "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", + "dunder-proto": "^1.0.0", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "which-builtin-type": "^1.1.4" + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.0" }, "engines": { "node": ">= 0.4" @@ -10441,13 +10367,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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==", - "dev": true, - "license": "MIT" - }, "node_modules/regexp-tree": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", @@ -10648,9 +10567,9 @@ } }, "node_modules/rollup": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.0.tgz", - "integrity": "sha512-G9GOrmgWHBma4YfCcX8PjH0qhXSdH8B4HDE2o4/jaxj93S4DPCIDoLcXz99eWMji4hB29UFCEd7B2gwGJDR9cQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", + "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", "dev": true, "license": "MIT", "dependencies": { @@ -10664,24 +10583,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.28.0", - "@rollup/rollup-android-arm64": "4.28.0", - "@rollup/rollup-darwin-arm64": "4.28.0", - "@rollup/rollup-darwin-x64": "4.28.0", - "@rollup/rollup-freebsd-arm64": "4.28.0", - "@rollup/rollup-freebsd-x64": "4.28.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.28.0", - "@rollup/rollup-linux-arm-musleabihf": "4.28.0", - "@rollup/rollup-linux-arm64-gnu": "4.28.0", - "@rollup/rollup-linux-arm64-musl": "4.28.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.28.0", - "@rollup/rollup-linux-riscv64-gnu": "4.28.0", - "@rollup/rollup-linux-s390x-gnu": "4.28.0", - "@rollup/rollup-linux-x64-gnu": "4.28.0", - "@rollup/rollup-linux-x64-musl": "4.28.0", - "@rollup/rollup-win32-arm64-msvc": "4.28.0", - "@rollup/rollup-win32-ia32-msvc": "4.28.0", - "@rollup/rollup-win32-x64-msvc": "4.28.0", + "@rollup/rollup-android-arm-eabi": "4.28.1", + "@rollup/rollup-android-arm64": "4.28.1", + "@rollup/rollup-darwin-arm64": "4.28.1", + "@rollup/rollup-darwin-x64": "4.28.1", + "@rollup/rollup-freebsd-arm64": "4.28.1", + "@rollup/rollup-freebsd-x64": "4.28.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", + "@rollup/rollup-linux-arm-musleabihf": "4.28.1", + "@rollup/rollup-linux-arm64-gnu": "4.28.1", + "@rollup/rollup-linux-arm64-musl": "4.28.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", + "@rollup/rollup-linux-riscv64-gnu": "4.28.1", + "@rollup/rollup-linux-s390x-gnu": "4.28.1", + "@rollup/rollup-linux-x64-gnu": "4.28.1", + "@rollup/rollup-linux-x64-musl": "4.28.1", + "@rollup/rollup-win32-arm64-msvc": "4.28.1", + "@rollup/rollup-win32-ia32-msvc": "4.28.1", + "@rollup/rollup-win32-x64-msvc": "4.28.1", "fsevents": "~2.3.2" } }, @@ -10733,15 +10653,16 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -10951,16 +10872,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -11280,16 +11258,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11299,16 +11280,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11559,9 +11544,9 @@ } }, "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -11725,13 +11710,6 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-simple-type": { - "version": "2.0.0-next.0", - "resolved": "https://registry.npmjs.org/ts-simple-type/-/ts-simple-type-2.0.0-next.0.tgz", - "integrity": "sha512-A+hLX83gS+yH6DtzNAhzZbPfU+D9D8lHlTSd7GeoMRBjOt3GRylDqLTYbdmjA4biWvq2xSfpqfIDj2l0OA/BVg==", - "dev": true, - "license": "MIT" - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -12017,12 +11995,16 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/validate-npm-package-license": { @@ -12037,9 +12019,9 @@ } }, "node_modules/vite": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.2.tgz", - "integrity": "sha512-XdQ+VsY2tJpBsKGs0wf3U/+azx8BBpYRHFAyKm5VeEZNOJZRB63q7Sc8Iup3k0TrN3KO6QgyzFf+opSbfY1y0g==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.3.tgz", + "integrity": "sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==", "dev": true, "license": "MIT", "dependencies": { @@ -12123,60 +12105,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/vscode-css-languageservice": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-4.3.0.tgz", - "integrity": "sha512-BkQAMz4oVHjr0oOAz5PdeE72txlLQK7NIwzmclfr+b6fj6I8POwB+VoXvrZLTbWt9hWRgfvgiQRkh5JwrjPJ5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "3.16.0-next.2", - "vscode-nls": "^4.1.2", - "vscode-uri": "^2.1.2" - } - }, - "node_modules/vscode-html-languageservice": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-3.1.0.tgz", - "integrity": "sha512-QAyRHI98bbEIBCqTzZVA0VblGU40na0txggongw5ZgTj9UVsVk5XbLT16O9OTcbqBGSqn0oWmFDNjK/XGIDcqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "3.16.0-next.2", - "vscode-nls": "^4.1.2", - "vscode-uri": "^2.1.2" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.16.0-next.2", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz", - "integrity": "sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-nls": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz", - "integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz", - "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==", - "dev": true, - "license": "MIT" - }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", @@ -12192,37 +12120,6 @@ "node": ">=10.13.0" } }, - "node_modules/web-component-analyzer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/web-component-analyzer/-/web-component-analyzer-2.0.0.tgz", - "integrity": "sha512-UEvwfpD+XQw99sLKiH5B1T4QwpwNyWJxp59cnlRwFfhUW6JsQpw5jMeMwi7580sNou8YL3kYoS7BWLm+yJ/jVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "^3.2.2", - "ts-simple-type": "2.0.0-next.0", - "typescript": "~5.2.0", - "yargs": "^17.7.2" - }, - "bin": { - "wca": "cli.js", - "web-component-analyzer": "cli.js" - } - }, - "node_modules/web-component-analyzer/node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", @@ -12246,9 +12143,9 @@ } }, "node_modules/webpack": { - "version": "5.97.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.0.tgz", - "integrity": "sha512-CWT8v7ShSfj7tGs4TLRtaOLmOCPWhoKEvp+eA7FVx8Xrjb3XfT0aXdxDItnRZmE8sHcH+a8ayDrJCOjXKxVFfQ==", + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", "dev": true, "license": "MIT", "peer": true, @@ -12665,9 +12562,9 @@ } }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -12787,21 +12684,21 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.23.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.5.tgz", - "integrity": "sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz", + "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==", "license": "ISC", "peerDependencies": { - "zod": "^3.23.3" + "zod": "^3.24.1" } }, "packages/api": { @@ -12818,11 +12715,12 @@ "@langchain/ollama": "^0.1.2", "@langchain/openai": "^0.3.14", "@langchain/textsplitters": "^0.1.0", - "@microsoft/ai-chat-protocol": "^1.0.0-alpha.20240418.1", + "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240814.1", "dotenv": "^16.4.5", "faiss-node": "^0.5.1", "langchain": "^0.3.6", - "pdf-parse": "^1.1.1" + "pdf-parse": "^1.1.1", + "uuid": "^11.0.3" }, "devDependencies": { "@types/node": "^20.x", @@ -12831,9 +12729,9 @@ } }, "packages/api/node_modules/@types/node": { - "version": "20.17.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.9.tgz", - "integrity": "sha512-0JOXkRyLanfGPE2QRCwgxhzlBAvaRdCNMcvbd7jFfpmD4eEXll7LRwy5ymJmyeZqk7Nh7eD2LeUyQ68BbndmXw==", + "version": "20.17.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", + "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", "dev": true, "license": "MIT", "dependencies": { @@ -12851,11 +12749,10 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240610.1", + "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240814.1", "lit": "^3.0.0" }, "devDependencies": { - "lit-analyzer": "^2.0.1", "vite": "^6.0.2" } } diff --git a/package.json b/package.json index 3ce7dff2..f2dccb60 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,7 @@ }, "lint-staged": { "*.{js,ts,md,yaml,yml,html,css}": "prettier --write", - "*.{js,ts}": "xo --fix", - "packages/webapp/src/components/*.{js,ts}": "npx lit-analyzer" + "*.{js,ts}": "xo --fix" }, "xo": { "space": true, @@ -86,6 +85,7 @@ "import/no-unassigned-import": "off", "import/extensions": "off", "n/prefer-global/process": "off", + "no-new-func": "off", "unicorn/prefer-module": "off", "unicorn/no-new-array": "off", "unicorn/prevent-abbreviations": [ @@ -93,7 +93,8 @@ { "allowList": { "combineDocsChain": true, - "env": true + "env": true, + "Db": true } } ] diff --git a/packages/api/.gitignore b/packages/api/.gitignore index 5c71bb0a..26fd395e 100644 --- a/packages/api/.gitignore +++ b/packages/api/.gitignore @@ -100,3 +100,6 @@ __azurite_db*__.json # Faiss folder .faiss/ + +# Chat history +.history/ diff --git a/packages/api/api.http b/packages/api/api.http index ae915975..050c51f6 100644 --- a/packages/api/api.http +++ b/packages/api/api.http @@ -21,7 +21,7 @@ Content-Type: application/pdf GET {{api_host}}/api/documents/support.pdf ### Chat with the bot -POST {{api_host}}/api/chat/stream +POST {{api_host}}/api/chats/stream?userId=1 Content-Type: application/json { @@ -31,4 +31,16 @@ Content-Type: application/json "role": "user" } ], + "context": { + "sessionId": "123" + } } + +### Retrieve all chat sessions +GET {{api_host}}/api/chats?userId=1 + +### Retrieve a chat session +GET {{api_host}}/api/chats/123?userId=1 + +### Delete a chat session +DELETE {{api_host}}/api/chats/123?userId=1 diff --git a/packages/api/package.json b/packages/api/package.json index a50a0efa..105f12d0 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -24,11 +24,12 @@ "@langchain/ollama": "^0.1.2", "@langchain/openai": "^0.3.14", "@langchain/textsplitters": "^0.1.0", - "@microsoft/ai-chat-protocol": "^1.0.0-alpha.20240418.1", + "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240814.1", "dotenv": "^16.4.5", "faiss-node": "^0.5.1", "langchain": "^0.3.6", - "pdf-parse": "^1.1.1" + "pdf-parse": "^1.1.1", + "uuid": "^11.0.3" }, "devDependencies": { "@types/node": "^20.x", diff --git a/packages/api/src/functions/chats-delete.ts b/packages/api/src/functions/chats-delete.ts new file mode 100644 index 00000000..c2848f6e --- /dev/null +++ b/packages/api/src/functions/chats-delete.ts @@ -0,0 +1,57 @@ +import process from 'node:process'; +import { HttpRequest, HttpResponseInit, InvocationContext, app } from '@azure/functions'; +import { AzureCosmsosDBNoSQLChatMessageHistory } from '@langchain/azure-cosmosdb'; +import { FileSystemChatMessageHistory } from '@langchain/community/stores/message/file_system'; +import 'dotenv/config'; +import { badRequest, ok, notFound } from '../http-response.js'; +import { getCredentials, getUserId } from '../security.js'; + +async function deleteChats(request: HttpRequest, context: InvocationContext): Promise { + const azureCosmosDbEndpoint = process.env.AZURE_COSMOSDB_NOSQL_ENDPOINT; + const { sessionId } = request.params; + const userId = getUserId(request); + + if (!userId) { + return badRequest('Invalid or missing userId in the request'); + } + + if (!sessionId) { + return badRequest('Invalid or missing sessionId in the request'); + } + + try { + let chatHistory; + + if (azureCosmosDbEndpoint) { + const credentials = getCredentials(); + chatHistory = new AzureCosmsosDBNoSQLChatMessageHistory({ + sessionId, + userId, + credentials, + }); + } else { + // If no environment variables are set, it means we are running locally + context.log('No Azure CosmosDB endpoint set, using local file'); + + chatHistory = new FileSystemChatMessageHistory({ + sessionId, + userId, + }); + } + + await chatHistory.clear(); + return ok(); + } catch (_error: unknown) { + const error = _error as Error; + context.error(`Error when processing chats-delete request: ${error.message}`); + + return notFound('Session not found'); + } +} + +app.http('chats-delete', { + route: 'chats/{sessionId}', + methods: ['DELETE'], + authLevel: 'anonymous', + handler: deleteChats, +}); diff --git a/packages/api/src/functions/chats-get.ts b/packages/api/src/functions/chats-get.ts new file mode 100644 index 00000000..a5ce892e --- /dev/null +++ b/packages/api/src/functions/chats-get.ts @@ -0,0 +1,66 @@ +import process from 'node:process'; +import { HttpRequest, HttpResponseInit, InvocationContext, app } from '@azure/functions'; +import { AzureCosmsosDBNoSQLChatMessageHistory } from '@langchain/azure-cosmosdb'; +import { FileSystemChatMessageHistory } from '@langchain/community/stores/message/file_system'; +import 'dotenv/config'; +import { badRequest, ok, notFound } from '../http-response.js'; +import { getCredentials, getUserId } from '../security.js'; + +async function getChats(request: HttpRequest, context: InvocationContext): Promise { + const azureCosmosDbEndpoint = process.env.AZURE_COSMOSDB_NOSQL_ENDPOINT; + const { sessionId } = request.params; + const userId = getUserId(request); + + if (!userId) { + return badRequest('Invalid or missing userId in the request'); + } + + try { + let chatHistory; + + if (azureCosmosDbEndpoint) { + const credentials = getCredentials(); + chatHistory = new AzureCosmsosDBNoSQLChatMessageHistory({ + sessionId, + userId, + credentials, + }); + } else { + // If no environment variables are set, it means we are running locally + context.log('No Azure CosmosDB endpoint set, using local file'); + + chatHistory = new FileSystemChatMessageHistory({ + sessionId, + userId, + }); + } + + if (sessionId) { + const messages = await chatHistory.getMessages(); + const chatMessages = messages.map((message) => ({ + role: message.getType() === 'human' ? 'user' : 'assistant', + content: message.content, + })); + return ok(chatMessages); + } + + const sessions = await chatHistory.getAllSessions(); + const chatSessions = sessions.map((session) => ({ + id: session.id, + title: session.context?.title, + })); + return ok(chatSessions); + } catch (_error: unknown) { + const error = _error as Error; + context.error(`Error when processing chats-get request: ${error.message}`); + + return notFound('Session not found'); + } +} + +app.http('chats-get', { + route: 'chats/{sessionId?}', + methods: ['GET'], + authLevel: 'anonymous', + handler: getChats, +}); diff --git a/packages/api/src/functions/chat-post.ts b/packages/api/src/functions/chats-post.ts similarity index 64% rename from packages/api/src/functions/chat-post.ts rename to packages/api/src/functions/chats-post.ts index f0ff67b1..5b381c2a 100644 --- a/packages/api/src/functions/chat-post.ts +++ b/packages/api/src/functions/chats-post.ts @@ -3,19 +3,22 @@ import { HttpRequest, InvocationContext, HttpResponseInit, app } from '@azure/fu import { AIChatCompletionRequest, AIChatCompletionDelta } from '@microsoft/ai-chat-protocol'; import { AzureOpenAIEmbeddings, AzureChatOpenAI } from '@langchain/openai'; import { Embeddings } from '@langchain/core/embeddings'; +import { AzureCosmsosDBNoSQLChatMessageHistory, AzureCosmosDBNoSQLVectorStore } from '@langchain/azure-cosmosdb'; +import { FileSystemChatMessageHistory } from '@langchain/community/stores/message/file_system'; import { BaseChatModel } from '@langchain/core/language_models/chat_models'; +import { RunnableWithMessageHistory } from '@langchain/core/runnables'; import { VectorStore } from '@langchain/core/vectorstores'; import { ChatOllama, OllamaEmbeddings } from '@langchain/ollama'; import { FaissStore } from '@langchain/community/vectorstores/faiss'; import { ChatPromptTemplate, PromptTemplate } from '@langchain/core/prompts'; import { createStuffDocumentsChain } from 'langchain/chains/combine_documents'; -import { AzureCosmosDBNoSQLVectorStore } from '@langchain/azure-cosmosdb'; +import { v4 as uuidv4 } from 'uuid'; import 'dotenv/config'; import { badRequest, data, serviceUnavailable } from '../http-response.js'; import { ollamaChatModel, ollamaEmbeddingsModel, faissStoreFolder } from '../constants.js'; -import { getAzureOpenAiTokenProvider, getCredentials } from '../security.js'; +import { getAzureOpenAiTokenProvider, getCredentials, getUserId } from '../security.js'; -const systemPrompt = `Assistant helps the Consto Real Estate company customers with questions and support requests. Be brief in your answers. Answer only plain text, DO NOT use Markdown. +const ragSystemPrompt = `Assistant helps the Consto Real Estate company customers with questions and support requests. Be brief in your answers. Answer only plain text, DO NOT use Markdown. Answer ONLY with information from the sources below. If there isn't enough information in the sources, say you don't know. Do not generate answers that don't use the sources. If asking a clarifying question to the user would help, ask the question. If the user question is not in English, answer in the language used in the question. @@ -33,12 +36,15 @@ Make sure the last question ends with ">>". SOURCES: {context}`; -export async function postChat(request: HttpRequest, context: InvocationContext): Promise { +const titleSystemPrompt = `Create a title for this chat session, based on the user question. The title should be less than 32 characters. Do NOT use double-quotes.`; + +export async function postChats(request: HttpRequest, context: InvocationContext): Promise { const azureOpenAiEndpoint = process.env.AZURE_OPENAI_API_ENDPOINT; try { const requestBody = (await request.json()) as AIChatCompletionRequest; - const { messages } = requestBody; + const { messages, context: chatContext } = requestBody; + const userId = getUserId(request, requestBody); if (!messages || messages.length === 0 || !messages.at(-1)?.content) { return badRequest('Invalid or missing messages in the request body'); @@ -47,6 +53,9 @@ export async function postChat(request: HttpRequest, context: InvocationContext) let embeddings: Embeddings; let model: BaseChatModel; let store: VectorStore; + let chatHistory; + const sessionId = ((chatContext as any)?.sessionId as string) || uuidv4(); + context.log(`userId: ${userId}, sessionId: ${sessionId}`); if (azureOpenAiEndpoint) { const credentials = getCredentials(); @@ -60,6 +69,13 @@ export async function postChat(request: HttpRequest, context: InvocationContext) azureADTokenProvider, }); store = new AzureCosmosDBNoSQLVectorStore(embeddings, { credentials }); + + // Initialize chat history + chatHistory = new AzureCosmsosDBNoSQLChatMessageHistory({ + sessionId, + userId, + credentials, + }); } else { // If no environment variables are set, it means we are running locally context.log('No Azure OpenAI endpoint set, using Ollama models and local DB'); @@ -69,25 +85,52 @@ export async function postChat(request: HttpRequest, context: InvocationContext) model: ollamaChatModel, }); store = await FaissStore.load(faissStoreFolder, embeddings); + chatHistory = new FileSystemChatMessageHistory({ + sessionId, + userId, + }); } // Create the chain that combines the prompt with the documents const ragChain = await createStuffDocumentsChain({ llm: model, prompt: ChatPromptTemplate.fromMessages([ - ['system', systemPrompt], + ['system', ragSystemPrompt], ['human', '{input}'], ]), documentPrompt: PromptTemplate.fromTemplate('[{source}]: {page_content}\n'), }); + // Handle chat history + const ragChainWithHistory = new RunnableWithMessageHistory({ + runnable: ragChain, + inputMessagesKey: 'input', + historyMessagesKey: 'chat_history', + getMessageHistory: async () => chatHistory, + }); // Retriever to search for the documents in the database const retriever = store.asRetriever(3); const question = messages.at(-1)!.content; - const responseStream = await ragChain.stream({ - input: question, - context: await retriever.invoke(question), - }); - const jsonStream = Readable.from(createJsonStream(responseStream)); + const responseStream = await ragChainWithHistory.stream( + { + input: question, + context: await retriever.invoke(question), + }, + { configurable: { sessionId } }, + ); + const jsonStream = Readable.from(createJsonStream(responseStream, sessionId)); + + // Create a short title for this chat session + const { title } = await chatHistory.getContext(); + if (!title) { + const response = await ChatPromptTemplate.fromMessages([ + ['system', titleSystemPrompt], + ['human', '{input}'], + ]) + .pipe(model) + .invoke({ input: question }); + context.log(`Title for session: ${response.content as string}`); + chatHistory.setContext({ title: response.content }); + } return data(jsonStream, { 'Content-Type': 'application/x-ndjson', @@ -102,7 +145,7 @@ export async function postChat(request: HttpRequest, context: InvocationContext) } // Transform the response chunks into a JSON stream -async function* createJsonStream(chunks: AsyncIterable) { +async function* createJsonStream(chunks: AsyncIterable, sessionId: string) { for await (const chunk of chunks) { if (!chunk) continue; @@ -111,6 +154,9 @@ async function* createJsonStream(chunks: AsyncIterable) { content: chunk, role: 'assistant', }, + context: { + sessionId, + }, }; // Format response chunks in Newline delimited JSON @@ -120,9 +166,9 @@ async function* createJsonStream(chunks: AsyncIterable) { } app.setup({ enableHttpStream: true }); -app.http('chat-post', { - route: 'chat/stream', +app.http('chats-post', { + route: 'chats/stream', methods: ['POST'], authLevel: 'anonymous', - handler: postChat, + handler: postChats, }); diff --git a/packages/api/src/http-response.ts b/packages/api/src/http-response.ts index e644d37c..68b60ba0 100644 --- a/packages/api/src/http-response.ts +++ b/packages/api/src/http-response.ts @@ -27,11 +27,13 @@ export function serviceUnavailable(message: string): HttpResponseInit { }; } -export function ok(body: Record): HttpResponseInit { - return { - status: 200, - jsonBody: body, - }; +export function ok(body?: object): HttpResponseInit { + return body + ? { + status: 200, + jsonBody: body, + } + : { status: 204 }; } export function data(body: Uint8Array | AsyncIterable, headers: Record): HttpResponseInit { diff --git a/packages/api/src/security.ts b/packages/api/src/security.ts index 0c2a1fe6..e6e3ef03 100644 --- a/packages/api/src/security.ts +++ b/packages/api/src/security.ts @@ -1,3 +1,4 @@ +import { HttpRequest } from '@azure/functions'; import { DefaultAzureCredential, getBearerTokenProvider } from '@azure/identity'; const azureOpenAiScope = 'https://cognitiveservices.azure.com/.default'; @@ -15,3 +16,19 @@ export function getCredentials(): DefaultAzureCredential { export function getAzureOpenAiTokenProvider() { return getBearerTokenProvider(getCredentials(), azureOpenAiScope); } + +export function getUserId(request: HttpRequest, body?: any): string | undefined { + let userId: string | undefined; + + // Get the user ID from Azure easy auth if it's available + try { + const token = Buffer.from(request.headers.get('x-ms-client-principal') ?? '', 'base64').toString('ascii'); + const infos = token && JSON.parse(token); + userId = infos?.userId; + } catch {} + + // Get the user ID from the request as a fallback + userId ??= body?.context?.userId ?? request.query.get('userId') ?? undefined; + + return userId; +} diff --git a/packages/webapp/assets/delete.svg b/packages/webapp/assets/delete.svg new file mode 100644 index 00000000..f6cd3e1b --- /dev/null +++ b/packages/webapp/assets/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/webapp/assets/panel.svg b/packages/webapp/assets/panel.svg new file mode 100644 index 00000000..f7bf52e7 --- /dev/null +++ b/packages/webapp/assets/panel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/webapp/index.html b/packages/webapp/index.html index e58a6818..ba06730f 100644 --- a/packages/webapp/index.html +++ b/packages/webapp/index.html @@ -17,8 +17,14 @@ font-size: 16px; margin: 0; background: var(--azc-bg); + display: flex; + flex-direction: column; + width: 100%; + height: 100%; } nav { + display: flex; + flex: 0 1 auto; background: #333; color: #fff; padding: 16px; @@ -30,7 +36,6 @@ 'Helvetica Neue', sans-serif; font-size: 1.25rem; - display: flex; align-items: center; & img { @@ -38,8 +43,14 @@ margin-right: 0.5em; } } + main { + container-type: size; + flex: 1; + position: relative; + display: flex; + } azc-chat { - display: block; + flex: 1; max-width: 1024px; margin: 0 auto; } @@ -50,7 +61,27 @@ AI Chat with Enterprise Data - +
+ + +
+ diff --git a/packages/webapp/package.json b/packages/webapp/package.json index f3b455d0..2d546d23 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -8,17 +8,15 @@ "dev": "vite --port 8000 --host", "build": "vite build", "watch": "vite build --watch --minify false", - "lint": "lit-analyzer", "clean": "npx rimraf dist" }, "author": "Microsoft", "license": "MIT", "dependencies": { - "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240610.1", + "@microsoft/ai-chat-protocol": "^1.0.0-beta.20240814.1", "lit": "^3.0.0" }, "devDependencies": { - "lit-analyzer": "^2.0.1", "vite": "^6.0.2" }, "files": [ diff --git a/packages/webapp/src/api.ts b/packages/webapp/src/api.ts index 0b9e41c8..d8df5360 100644 --- a/packages/webapp/src/api.ts +++ b/packages/webapp/src/api.ts @@ -4,14 +4,15 @@ export const apiBaseUrl: string = import.meta.env.VITE_API_URL || ''; export type ChatRequestOptions = { messages: AIChatMessage[]; + context?: Record; chunkIntervalMs: number; apiUrl: string; }; export async function* getCompletion(options: ChatRequestOptions) { const apiUrl = options.apiUrl || apiBaseUrl; - const client = new AIChatProtocolClient(`${apiUrl}/api/chat`); - const result = await client.getStreamedCompletion(options.messages); + const client = new AIChatProtocolClient(`${apiUrl}/api/chats`); + const result = await client.getStreamedCompletion(options.messages, { context: options.context }); for await (const response of result) { if (!response.delta) { diff --git a/packages/webapp/src/components/chat.ts b/packages/webapp/src/components/chat.ts index 750e24c9..72cb55a2 100644 --- a/packages/webapp/src/components/chat.ts +++ b/packages/webapp/src/components/chat.ts @@ -34,7 +34,7 @@ export type ChatComponentOptions = ChatRequestOptions & { }; }; -export const defaultOptions: ChatComponentOptions = { +export const chatDefaultOptions: ChatComponentOptions = { chunkIntervalMs: 30, apiUrl: '', enablePromptSuggestions: true, @@ -72,15 +72,18 @@ export const defaultOptions: ChatComponentOptions = { export class ChatComponent extends LitElement { @property({ type: Object, - converter: (value) => ({ ...defaultOptions, ...JSON.parse(value ?? '{}') }), + converter: (value) => ({ ...chatDefaultOptions, ...JSON.parse(value ?? '{}') }), }) - options: ChatComponentOptions = defaultOptions; + options: ChatComponentOptions = chatDefaultOptions; @property() question = ''; @property({ type: Array }) messages: AIChatMessage[] = []; + @property() userId = ''; + @property() sessionId = ''; @state() protected hasError = false; @state() protected isLoading = false; @state() protected isStreaming = false; + @query('.chat-container') protected chatContainerElement!: HTMLElement; @query('.messages') protected messagesElement!: HTMLElement; @query('.chat-input') protected chatInputElement!: HTMLElement; @@ -94,6 +97,12 @@ export class ChatComponent extends LitElement { window.open(path, '_blank'); } + onNewChatClicked() { + this.messages = []; + this.sessionId = ''; + this.fireMessagesUpdatedEvent(); + } + async onKeyPressed(event: KeyboardEvent) { if (event.key === 'Enter') { event.preventDefault(); @@ -121,7 +130,14 @@ export class ChatComponent extends LitElement { this.isLoading = true; this.scrollToLastMessage(); try { - const response = getCompletion({ ...this.options, messages: this.messages }); + const response = getCompletion({ + ...this.options, + messages: this.messages, + context: { + userId: this.userId, + sessionId: this.sessionId, + }, + }); const chunks = response as AsyncGenerator; const { messages } = this; const message: AIChatMessage = { @@ -133,12 +149,17 @@ export class ChatComponent extends LitElement { this.isStreaming = true; message.content += chunk.delta.content; this.messages = [...messages, message]; - this.scrollToLastMessage(); + } + + const sessionId = (chunk.context as any)?.sessionId; + if (!this.sessionId && sessionId) { + this.sessionId = sessionId; } } this.isLoading = false; this.isStreaming = false; + this.fireMessagesUpdatedEvent(); } catch (error) { this.hasError = true; this.isLoading = false; @@ -149,11 +170,7 @@ export class ChatComponent extends LitElement { override requestUpdate(name?: string, oldValue?: any) { if (name === 'messages') { - const messagesUpdatedEvent = new CustomEvent('messagesUpdated', { - detail: { messages: this.messages }, - bubbles: true, - }); - this.dispatchEvent(messagesUpdatedEvent); + this.scrollToLastMessage(); } else if (name === 'hasError' || name === 'isLoading' || name === 'isStreaming') { const state = { hasError: this.hasError, @@ -170,13 +187,21 @@ export class ChatComponent extends LitElement { super.requestUpdate(name, oldValue); } + protected fireMessagesUpdatedEvent() { + const messagesUpdatedEvent = new CustomEvent('messagesUpdated', { + detail: { messages: this.messages }, + bubbles: true, + }); + this.dispatchEvent(messagesUpdatedEvent); + } + protected scrollToLastMessage() { // Need to be delayed to run after the DOM refresh setTimeout(() => { const { bottom } = this.messagesElement.getBoundingClientRect(); const { top } = this.chatInputElement.getBoundingClientRect(); if (bottom > top) { - window.scrollBy(0, bottom - top); + this.chatContainerElement.scrollBy(0, bottom - top); } }, 0); } @@ -283,7 +308,7 @@ export class ChatComponent extends LitElement { + `; + + protected renderChatEntry = (entry: ChatSession) => html` + { + event.preventDefault(); + this.onChatClicked(entry.id); + }} + title=${entry.title} + > + ${entry.title} + + + `; + + protected override render() { + return html` + ${this.open ? nothing : this.renderPanelButton(true)} `; + } + + static override styles = css` + :host { + /* Base properties */ + --primary: var(--azc-primary, #07f); + --bg: var(--azc-bg, #eee); + --error: var(--azc-error, #e30); + --text-color: var(--azc-text-color, #000); + --space-md: var(--azc-space-md, 12px); + --space-xl: var(--azc-space-xl, calc(var(--space-md) * 2)); + --space-xs: var(--azc-space-xs, calc(var(--space-md) / 2)); + --space-xxs: var(--azc-space-xs, calc(var(--space-md) / 4)); + --border-radius: var(--azc-border-radius, 16px); + --focus-outline: var(--azc-focus-outline, 2px solid); + --overlay-color: var(--azc-overlay-color, rgba(0 0 0 / 40%)); + + /* Component-specific properties */ + --panel-bg: var(--azc-panel-bg, #fff); + --panel-width: var(--azc-panel-width, 300px); + --panel-shadow: var(--azc-panel-shadow, 0 0 10px rgba(0, 0, 0, 0.1)); + --error-color: var(--azc-error-color, var(--error)); + --error-border: var(--azc-error-border, none); + --error-bg: var(--azc-error-bg, var(--card-bg)); + --icon-button-color: var(--azc-icon-button-color, var(--text-color)); + --icon-button-bg: var(--azc-icon-button-bg, none); + --icon-button-bg-hover: var(--azc-icon-button-bg, rgba(0, 0, 0, 0.07)); + --panel-button-color: var(--azc-panel-button-color, var(--text-color)); + --panel-button-bg: var(--azc-panel-button-bg, var(--bg)); + --panel-button-bg-hover: var(--azc-panel-button-bg, hsl(from var(--panel-button-bg) h s calc(l - 6))); + --chat-entry-bg: var(--azc-chat-entry-bg, none); + --chat-entry-bg-hover: var(--azc-chat-entry-bg-hover, #f0f0f0); + + width: 0; + transition: width 0.3s ease; + overflow: hidden; + } + :host([open]) { + width: var(--panel-width); + } + :host(:not([open])) .panel-button { + position: absolute; + top: 0; + left: 0; + z-index: 1; + margin: var(--space-xs); + background: var(--panel-button-bg); + color: var(--panel-button-color); + + &:hover { + background: var(--panel-button-bg-hover); + } + } + @media (width < 800px) { + :host([open]) { + width: 0; + + & .chats-panel { + left: 0; + } + } + .chats-panel { + position: absolute; + top: 0; + left: calc(var(--panel-width) * -1.2); + z-index: 1; + box-shadow: var(--panel-shadow); + transition: left 0.3s ease; + } + } + *:focus-visible { + outline: var(--focus-outline) var(--primary); + } + .animation { + animation: 0.3s ease; + } + svg { + fill: currentColor; + width: 100%; + } + button { + font-size: 1rem; + border-radius: calc(var(--border-radius) / 2); + outline: var(--focus-outline) transparent; + transition: outline 0.3s ease; + + &:not(:disabled) { + cursor: pointer; + } + } + h2 { + margin: var(--space-md) 0 0 0; + padding: var(--space-xs) var(--space-md); + font-size: 0.9rem; + font-weight: 600; + } + .buttons { + display: flex; + justify-content: space-between; + padding: var(--space-xs); + position: sticky; + top: 0; + background: var(--panel-bg); + box-shadow: 0 var(--space-xs) var(--space-xs) var(--panel-bg); + } + .chats-panel { + width: var(--panel-width); + height: 100%; + background: var(--panel-bg); + font-family: + 'Segoe UI', + -apple-system, + BlinkMacSystemFont, + Roboto, + 'Helvetica Neue', + sans-serif; + overflow: auto; + } + .chats { + margin: 0; + padding: 0; + font-size: 0.9rem; + } + .chat-title { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + .chat-entry { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-xxs) var(--space-xxs) var(--space-xxs) var(--space-xs); + margin: 0 var(--space-xs); + border-radius: calc(var(--border-radius) / 2); + color: var(--text-color); + text-decoration: none; + background: var(--chat-entry-bg); + + & .icon-button { + flex: 0 0 auto; + padding: var(--space-xxs); + width: 28px; + height: 28px; + } + + &:hover { + background: var(--chat-entry-bg-hover); + } + + &:not(:focus):not(:hover) .icon-button:not(:focus) { + opacity: 0; + } + } + .message { + padding: var(--space-xs) var(--space-md); + } + .error { + color: var(--error-color); + } + .icon-button { + width: 36px; + height: 36px; + padding: var(--space-xs); + background: none; + border: none; + background: var(--icon-button-bg); + color: var(--icon-button-color); + font-size: 1.5rem; + &:hover:not(:disabled) { + background: var(--icon-button-bg-hover); + color: var(--icon-button-color); + } + } + .loader-animation { + position: absolute; + width: var(--panel-width); + height: 2px; + overflow: hidden; + background-color: var(--primary); + transform: scaleX(0); + transform-origin: center left; + animation: cubic-bezier(0.85, 0, 0.15, 1) 2s infinite load-animation; + } + + @keyframes load-animation { + 0% { + transform: scaleX(0); + transform-origin: center left; + } + 50% { + transform: scaleX(1); + transform-origin: center left; + } + 51% { + transform: scaleX(1); + transform-origin: center right; + } + 100% { + transform: scaleX(0); + transform-origin: center right; + } + } + @media (prefers-reduced-motion: reduce) { + :host, + .chats-panel { + transition: none; + } + .animation { + animation: none; + } + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + 'azc-history': HistoryComponent; + } +} diff --git a/packages/webapp/src/index.ts b/packages/webapp/src/index.ts index dbf60cfc..0f762626 100644 --- a/packages/webapp/src/index.ts +++ b/packages/webapp/src/index.ts @@ -1,3 +1,4 @@ export * from './api.js'; export * from './components/chat.js'; +export * from './components/history.js'; export * from './message-parser.js';