From e4c4490175ee9f83a75963a0679918b547e9622c Mon Sep 17 00:00:00 2001 From: Yeuoly Date: Thu, 9 Jan 2025 17:27:05 +0800 Subject: [PATCH 01/28] refactor --- .github/workflows/build-push.yml | 1 + .github/workflows/db-migration-test.yml | 1 + .github/workflows/style.yml | 2 +- .../core/helper/test_marketplace.py | 2 +- .../core/prompt/test_prompt_transform.py | 82 ++--- .../unit_tests/core/test_provider_manager.py | 328 +++++++++--------- 6 files changed, 211 insertions(+), 205 deletions(-) diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index 8e5279fb67..6e5255011b 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -5,6 +5,7 @@ on: branches: - "main" - "deploy/dev" + - "plugins/beta" release: types: [published] diff --git a/.github/workflows/db-migration-test.yml b/.github/workflows/db-migration-test.yml index 3d881c4c3d..7c8263b10a 100644 --- a/.github/workflows/db-migration-test.yml +++ b/.github/workflows/db-migration-test.yml @@ -4,6 +4,7 @@ on: pull_request: branches: - main + - plugins/beta paths: - api/migrations/** - .github/workflows/db-migration-test.yml diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index b5e63a8870..9276d1f2fd 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -4,6 +4,7 @@ on: pull_request: branches: - main + - plugins/beta concurrency: group: style-${{ github.head_ref || github.run_id }} @@ -82,7 +83,6 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' run: yarn run lint - superlinter: name: SuperLinter runs-on: ubuntu-latest diff --git a/api/tests/unit_tests/core/helper/test_marketplace.py b/api/tests/unit_tests/core/helper/test_marketplace.py index 51011a574a..6ccce7ac9f 100644 --- a/api/tests/unit_tests/core/helper/test_marketplace.py +++ b/api/tests/unit_tests/core/helper/test_marketplace.py @@ -2,6 +2,6 @@ from core.helper.marketplace import download_plugin_pkg def test_download_plugin_pkg(): - pkg = download_plugin_pkg("yeuoly/google:0.0.1@4ff79ee644987e5b744d9c5b7a735d459fe66f26b28724326a7834d7e459e708") + pkg = download_plugin_pkg("langgenius/bing:0.0.1@e58735424d2104f208c2bd683c5142e0332045b425927067acf432b26f3d970b") assert pkg is not None assert len(pkg) > 0 diff --git a/api/tests/unit_tests/core/prompt/test_prompt_transform.py b/api/tests/unit_tests/core/prompt/test_prompt_transform.py index 89c14463bb..16896a0c6c 100644 --- a/api/tests/unit_tests/core/prompt/test_prompt_transform.py +++ b/api/tests/unit_tests/core/prompt/test_prompt_transform.py @@ -1,52 +1,52 @@ -from unittest.mock import MagicMock +# from unittest.mock import MagicMock -from core.app.app_config.entities import ModelConfigEntity -from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle -from core.model_runtime.entities.message_entities import UserPromptMessage -from core.model_runtime.entities.model_entities import AIModelEntity, ModelPropertyKey, ParameterRule -from core.model_runtime.entities.provider_entities import ProviderEntity -from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel -from core.prompt.prompt_transform import PromptTransform +# from core.app.app_config.entities import ModelConfigEntity +# from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle +# from core.model_runtime.entities.message_entities import UserPromptMessage +# from core.model_runtime.entities.model_entities import AIModelEntity, ModelPropertyKey, ParameterRule +# from core.model_runtime.entities.provider_entities import ProviderEntity +# from core.model_runtime.model_providers.__base.large_language_model import LargeLanguageModel +# from core.prompt.prompt_transform import PromptTransform -def test__calculate_rest_token(): - model_schema_mock = MagicMock(spec=AIModelEntity) - parameter_rule_mock = MagicMock(spec=ParameterRule) - parameter_rule_mock.name = "max_tokens" - model_schema_mock.parameter_rules = [parameter_rule_mock] - model_schema_mock.model_properties = {ModelPropertyKey.CONTEXT_SIZE: 62} +# def test__calculate_rest_token(): +# model_schema_mock = MagicMock(spec=AIModelEntity) +# parameter_rule_mock = MagicMock(spec=ParameterRule) +# parameter_rule_mock.name = "max_tokens" +# model_schema_mock.parameter_rules = [parameter_rule_mock] +# model_schema_mock.model_properties = {ModelPropertyKey.CONTEXT_SIZE: 62} - large_language_model_mock = MagicMock(spec=LargeLanguageModel) - large_language_model_mock.get_num_tokens.return_value = 6 +# large_language_model_mock = MagicMock(spec=LargeLanguageModel) +# large_language_model_mock.get_num_tokens.return_value = 6 - provider_mock = MagicMock(spec=ProviderEntity) - provider_mock.provider = "openai" +# provider_mock = MagicMock(spec=ProviderEntity) +# provider_mock.provider = "openai" - provider_configuration_mock = MagicMock(spec=ProviderConfiguration) - provider_configuration_mock.provider = provider_mock - provider_configuration_mock.model_settings = None +# provider_configuration_mock = MagicMock(spec=ProviderConfiguration) +# provider_configuration_mock.provider = provider_mock +# provider_configuration_mock.model_settings = None - provider_model_bundle_mock = MagicMock(spec=ProviderModelBundle) - provider_model_bundle_mock.model_type_instance = large_language_model_mock - provider_model_bundle_mock.configuration = provider_configuration_mock +# provider_model_bundle_mock = MagicMock(spec=ProviderModelBundle) +# provider_model_bundle_mock.model_type_instance = large_language_model_mock +# provider_model_bundle_mock.configuration = provider_configuration_mock - model_config_mock = MagicMock(spec=ModelConfigEntity) - model_config_mock.model = "gpt-4" - model_config_mock.credentials = {} - model_config_mock.parameters = {"max_tokens": 50} - model_config_mock.model_schema = model_schema_mock - model_config_mock.provider_model_bundle = provider_model_bundle_mock +# model_config_mock = MagicMock(spec=ModelConfigEntity) +# model_config_mock.model = "gpt-4" +# model_config_mock.credentials = {} +# model_config_mock.parameters = {"max_tokens": 50} +# model_config_mock.model_schema = model_schema_mock +# model_config_mock.provider_model_bundle = provider_model_bundle_mock - prompt_transform = PromptTransform() +# prompt_transform = PromptTransform() - prompt_messages = [UserPromptMessage(content="Hello, how are you?")] - rest_tokens = prompt_transform._calculate_rest_token(prompt_messages, model_config_mock) +# prompt_messages = [UserPromptMessage(content="Hello, how are you?")] +# rest_tokens = prompt_transform._calculate_rest_token(prompt_messages, model_config_mock) - # Validate based on the mock configuration and expected logic - expected_rest_tokens = ( - model_schema_mock.model_properties[ModelPropertyKey.CONTEXT_SIZE] - - model_config_mock.parameters["max_tokens"] - - large_language_model_mock.get_num_tokens.return_value - ) - assert rest_tokens == expected_rest_tokens - assert rest_tokens == 6 +# # Validate based on the mock configuration and expected logic +# expected_rest_tokens = ( +# model_schema_mock.model_properties[ModelPropertyKey.CONTEXT_SIZE] +# - model_config_mock.parameters["max_tokens"] +# - large_language_model_mock.get_num_tokens.return_value +# ) +# assert rest_tokens == expected_rest_tokens +# assert rest_tokens == 6 diff --git a/api/tests/unit_tests/core/test_provider_manager.py b/api/tests/unit_tests/core/test_provider_manager.py index 44284e03d0..90d5a6f15b 100644 --- a/api/tests/unit_tests/core/test_provider_manager.py +++ b/api/tests/unit_tests/core/test_provider_manager.py @@ -1,186 +1,190 @@ -from core.entities.provider_entities import ModelSettings -from core.model_runtime.entities.model_entities import ModelType -from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory -from core.provider_manager import ProviderManager -from models.provider import LoadBalancingModelConfig, ProviderModelSetting +# from core.entities.provider_entities import ModelSettings +# from core.model_runtime.entities.model_entities import ModelType +# from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory +# from core.provider_manager import ProviderManager +# from models.provider import LoadBalancingModelConfig, ProviderModelSetting -def test__to_model_settings(mocker): - # Get all provider entities - model_provider_factory = ModelProviderFactory("test_tenant") - provider_entities = model_provider_factory.get_providers() +# def test__to_model_settings(mocker): +# # Get all provider entities +# model_provider_factory = ModelProviderFactory("test_tenant") +# provider_entities = model_provider_factory.get_providers() - provider_entity = None - for provider in provider_entities: - if provider.provider == "openai": - provider_entity = provider +# provider_entity = None +# for provider in provider_entities: +# if provider.provider == "openai": +# provider_entity = provider - # Mocking the inputs - provider_model_settings = [ - ProviderModelSetting( - id="id", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - enabled=True, - load_balancing_enabled=True, - ) - ] - load_balancing_model_configs = [ - LoadBalancingModelConfig( - id="id1", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - name="__inherit__", - encrypted_config=None, - enabled=True, - ), - LoadBalancingModelConfig( - id="id2", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - name="first", - encrypted_config='{"openai_api_key": "fake_key"}', - enabled=True, - ), - ] +# # Mocking the inputs +# provider_model_settings = [ +# ProviderModelSetting( +# id="id", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# enabled=True, +# load_balancing_enabled=True, +# ) +# ] +# load_balancing_model_configs = [ +# LoadBalancingModelConfig( +# id="id1", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# name="__inherit__", +# encrypted_config=None, +# enabled=True, +# ), +# LoadBalancingModelConfig( +# id="id2", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# name="first", +# encrypted_config='{"openai_api_key": "fake_key"}', +# enabled=True, +# ), +# ] - mocker.patch( - "core.helper.model_provider_cache.ProviderCredentialsCache.get", return_value={"openai_api_key": "fake_key"} - ) +# mocker.patch( +# "core.helper.model_provider_cache.ProviderCredentialsCache.get", return_value={"openai_api_key": "fake_key"} +# ) - provider_manager = ProviderManager() +# provider_manager = ProviderManager() - # Running the method - result = provider_manager._to_model_settings(provider_entity, provider_model_settings, load_balancing_model_configs) +# # Running the method +# result = provider_manager._to_model_settings(provider_entity, +# provider_model_settings, load_balancing_model_configs) - # Asserting that the result is as expected - assert len(result) == 1 - assert isinstance(result[0], ModelSettings) - assert result[0].model == "gpt-4" - assert result[0].model_type == ModelType.LLM - assert result[0].enabled is True - assert len(result[0].load_balancing_configs) == 2 - assert result[0].load_balancing_configs[0].name == "__inherit__" - assert result[0].load_balancing_configs[1].name == "first" +# # Asserting that the result is as expected +# assert len(result) == 1 +# assert isinstance(result[0], ModelSettings) +# assert result[0].model == "gpt-4" +# assert result[0].model_type == ModelType.LLM +# assert result[0].enabled is True +# assert len(result[0].load_balancing_configs) == 2 +# assert result[0].load_balancing_configs[0].name == "__inherit__" +# assert result[0].load_balancing_configs[1].name == "first" -def test__to_model_settings_only_one_lb(mocker): - # Get all provider entities - model_provider_factory = ModelProviderFactory("test_tenant") - provider_entities = model_provider_factory.get_providers() +# def test__to_model_settings_only_one_lb(mocker): +# # Get all provider entities +# model_provider_factory = ModelProviderFactory("test_tenant") +# provider_entities = model_provider_factory.get_providers() - provider_entity = None - for provider in provider_entities: - if provider.provider == "openai": - provider_entity = provider +# provider_entity = None +# for provider in provider_entities: +# if provider.provider == "openai": +# provider_entity = provider - # Mocking the inputs - provider_model_settings = [ - ProviderModelSetting( - id="id", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - enabled=True, - load_balancing_enabled=True, - ) - ] - load_balancing_model_configs = [ - LoadBalancingModelConfig( - id="id1", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - name="__inherit__", - encrypted_config=None, - enabled=True, - ) - ] +# # Mocking the inputs +# provider_model_settings = [ +# ProviderModelSetting( +# id="id", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# enabled=True, +# load_balancing_enabled=True, +# ) +# ] +# load_balancing_model_configs = [ +# LoadBalancingModelConfig( +# id="id1", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# name="__inherit__", +# encrypted_config=None, +# enabled=True, +# ) +# ] - mocker.patch( - "core.helper.model_provider_cache.ProviderCredentialsCache.get", return_value={"openai_api_key": "fake_key"} - ) +# mocker.patch( +# "core.helper.model_provider_cache.ProviderCredentialsCache.get", return_value={"openai_api_key": "fake_key"} +# ) - provider_manager = ProviderManager() +# provider_manager = ProviderManager() - # Running the method - result = provider_manager._to_model_settings(provider_entity, provider_model_settings, load_balancing_model_configs) +# # Running the method +# result = provider_manager._to_model_settings( +# provider_entity, provider_model_settings, load_balancing_model_configs) - # Asserting that the result is as expected - assert len(result) == 1 - assert isinstance(result[0], ModelSettings) - assert result[0].model == "gpt-4" - assert result[0].model_type == ModelType.LLM - assert result[0].enabled is True - assert len(result[0].load_balancing_configs) == 0 +# # Asserting that the result is as expected +# assert len(result) == 1 +# assert isinstance(result[0], ModelSettings) +# assert result[0].model == "gpt-4" +# assert result[0].model_type == ModelType.LLM +# assert result[0].enabled is True +# assert len(result[0].load_balancing_configs) == 0 -def test__to_model_settings_lb_disabled(mocker): - # Get all provider entities - model_provider_factory = ModelProviderFactory("test_tenant") - provider_entities = model_provider_factory.get_providers() +# def test__to_model_settings_lb_disabled(mocker): +# # Get all provider entities +# model_provider_factory = ModelProviderFactory("test_tenant") +# provider_entities = model_provider_factory.get_providers() - provider_entity = None - for provider in provider_entities: - if provider.provider == "openai": - provider_entity = provider +# provider_entity = None +# for provider in provider_entities: +# if provider.provider == "openai": +# provider_entity = provider - # Mocking the inputs - provider_model_settings = [ - ProviderModelSetting( - id="id", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - enabled=True, - load_balancing_enabled=False, - ) - ] - load_balancing_model_configs = [ - LoadBalancingModelConfig( - id="id1", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - name="__inherit__", - encrypted_config=None, - enabled=True, - ), - LoadBalancingModelConfig( - id="id2", - tenant_id="tenant_id", - provider_name="openai", - model_name="gpt-4", - model_type="text-generation", - name="first", - encrypted_config='{"openai_api_key": "fake_key"}', - enabled=True, - ), - ] +# # Mocking the inputs +# provider_model_settings = [ +# ProviderModelSetting( +# id="id", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# enabled=True, +# load_balancing_enabled=False, +# ) +# ] +# load_balancing_model_configs = [ +# LoadBalancingModelConfig( +# id="id1", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# name="__inherit__", +# encrypted_config=None, +# enabled=True, +# ), +# LoadBalancingModelConfig( +# id="id2", +# tenant_id="tenant_id", +# provider_name="openai", +# model_name="gpt-4", +# model_type="text-generation", +# name="first", +# encrypted_config='{"openai_api_key": "fake_key"}', +# enabled=True, +# ), +# ] - mocker.patch( - "core.helper.model_provider_cache.ProviderCredentialsCache.get", return_value={"openai_api_key": "fake_key"} - ) +# mocker.patch( +# "core.helper.model_provider_cache.ProviderCredentialsCache.get", +# return_value={"openai_api_key": "fake_key"} +# ) - provider_manager = ProviderManager() +# provider_manager = ProviderManager() - # Running the method - result = provider_manager._to_model_settings(provider_entity, provider_model_settings, load_balancing_model_configs) +# # Running the method +# result = provider_manager._to_model_settings(provider_entity, +# provider_model_settings, load_balancing_model_configs) - # Asserting that the result is as expected - assert len(result) == 1 - assert isinstance(result[0], ModelSettings) - assert result[0].model == "gpt-4" - assert result[0].model_type == ModelType.LLM - assert result[0].enabled is True - assert len(result[0].load_balancing_configs) == 0 +# # Asserting that the result is as expected +# assert len(result) == 1 +# assert isinstance(result[0], ModelSettings) +# assert result[0].model == "gpt-4" +# assert result[0].model_type == ModelType.LLM +# assert result[0].enabled is True +# assert len(result[0].load_balancing_configs) == 0 From 3c014f3ae52b21974350e8eb6e187a780925a4ce Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Thu, 9 Jan 2025 18:47:41 +0800 Subject: [PATCH 02/28] Feat/plugins (#12547) Co-authored-by: AkaraChen Co-authored-by: Yi Co-authored-by: Joel Co-authored-by: JzoNg Co-authored-by: twwu Co-authored-by: kurokobo Co-authored-by: Hiroshi Fujita --- .devcontainer/post_create_command.sh | 5 +- .github/workflows/style.yml | 6 +- .github/workflows/tool-test-sdks.yaml | 6 +- .../translate-i18n-base-on-english.yml | 4 +- .github/workflows/web-tests.yml | 6 +- .gitignore | 3 + api/core/helper/ssrf_proxy.py | 9 +- .../datasource/vdb/lindorm/lindorm_vector.py | 45 +- api/core/rag/extractor/word_extractor.py | 2 +- .../question_classifier_node.py | 33 +- .../test_http_request_executor.py | 6 +- .../http_request/test_http_request_node.py | 11 +- docker/.env.example | 2 +- docker/docker-compose-template.yaml | 12 +- docker/docker-compose.yaml | 2 + sdks/nodejs-client/babel.config.json | 5 - web/.env.example | 6 + web/.eslintignore | 7 - web/.eslintrc.json | 31 - web/.gitignore | 7 +- web/.husky/pre-commit | 7 +- web/.storybook/main.ts | 28 +- web/.storybook/preview.tsx | 42 +- web/.vscode/settings.example.json | 3 +- web/Dockerfile | 17 +- web/README.md | 20 +- .../[appId]/annotations/page.tsx | 2 +- .../[appId]/develop/page.tsx | 2 +- .../[appId]/overview/chartView.tsx | 2 +- .../[appId]/overview/page.tsx | 2 +- .../overview/tracing/config-button.tsx | 30 +- .../[appId]/overview/tracing/config-popup.tsx | 22 +- .../[appId]/overview/tracing/field.tsx | 2 +- .../[appId]/overview/tracing/panel.tsx | 99 +- .../tracing/provider-config-modal.tsx | 19 +- .../overview/tracing/provider-panel.tsx | 21 +- .../overview/tracing/toggle-fold-btn.tsx | 45 - web/app/(commonLayout)/datasets/Container.tsx | 2 +- web/app/(commonLayout)/plugins/page.tsx | 20 + web/app/account/avatar.tsx | 2 +- web/app/components/app-sidebar/basic.tsx | 8 +- web/app/components/app/annotation/filter.tsx | 4 +- web/app/components/app/annotation/list.tsx | 2 +- .../base/feature-panel/index.tsx | 2 +- .../conversation-history/history-panel.tsx | 2 +- .../config-prompt/simple-prompt-input.tsx | 2 +- .../config-var/config-modal/field.tsx | 2 +- .../config-var/config-modal/index.tsx | 2 +- .../config-var/config-string/index.tsx | 4 +- .../app/configuration/config-var/index.tsx | 11 +- .../config-var/select-type-item/index.tsx | 2 +- .../config/agent/agent-tools/index.tsx | 272 +- .../agent-tools/setting-built-in-tool.tsx | 216 +- .../config/automatic/get-automatic-res.tsx | 2 +- .../app/configuration/config/index.tsx | 2 +- .../dataset-config/params-config/index.tsx | 4 +- .../dataset-config/settings-modal/index.tsx | 2 +- .../debug-with-multiple-model/chat-item.tsx | 2 +- .../text-generation-item.tsx | 2 +- .../debug/debug-with-single-model/index.tsx | 4 +- .../app/configuration/debug/index.tsx | 2 +- .../chat-group/opening-statement/index.tsx | 1 - .../components/app/configuration/index.tsx | 43 +- .../prompt-value-panel/index.tsx | 2 +- .../toolbox/annotation/config-param.tsx | 124 - .../app/configuration/toolbox/index.tsx | 45 - .../tools/external-data-tool-modal.tsx | 4 +- .../app/create-from-dsl-modal/index.tsx | 10 +- .../components/app/duplicate-modal/index.tsx | 2 +- web/app/components/app/log/list.tsx | 3 + .../app/overview/apikey-info-panel/index.tsx | 10 +- .../apikey-info-panel/progress/index.tsx | 29 - .../progress/style.module.css | 16 - web/app/components/app/overview/appCard.tsx | 49 +- web/app/components/app/overview/appChart.tsx | 14 +- .../app/overview/customize/index.tsx | 36 +- .../app/overview/embedded/index.tsx | 51 +- .../app/overview/settings/index.tsx | 55 +- .../app/overview/settings/style.module.css | 18 - web/app/components/app/store.ts | 4 +- .../components/app/switch-app-modal/index.tsx | 2 +- .../app/text-generate/item/index.tsx | 2 +- .../components/app/workflow-log/detail.tsx | 2 +- .../components/app/workflow-log/filter.tsx | 2 +- .../components/base/action-button/index.css | 16 +- .../components/base/action-button/index.tsx | 2 +- .../components/base/app-icon/style.module.css | 23 + .../base/audio-btn/audio.player.manager.ts | 3 +- web/app/components/base/audio-btn/audio.ts | 2 +- web/app/components/base/audio-btn/index.tsx | 2 +- .../base/audio-gallery/AudioPlayer.module.css | 26 +- .../base/audio-gallery/AudioPlayer.tsx | 2 +- web/app/components/base/badge.tsx | 13 +- web/app/components/base/badge/index.css | 28 + web/app/components/base/badge/index.tsx | 81 + web/app/components/base/button/add-button.tsx | 2 +- .../base/chat/__tests__/utils.spec.ts | 2 +- .../config-panel/form-input.tsx | 2 +- .../base/chat/chat-with-history/context.tsx | 2 +- .../base/chat/chat-with-history/index.tsx | 4 +- .../base/chat/chat/answer/agent-content.tsx | 2 +- .../base/chat/chat/answer/basic-content.tsx | 2 +- .../base/chat/chat/answer/index.tsx | 2 +- .../base/chat/chat/answer/operation.tsx | 2 +- .../chat/chat/answer/workflow-process.tsx | 21 - web/app/components/base/chat/chat/hooks.ts | 2 +- web/app/components/base/chat/chat/index.tsx | 2 +- .../components/base/chat/chat/question.tsx | 2 +- .../base/chat/chat/thought/index.tsx | 2 +- web/app/components/base/chat/chat/type.ts | 22 +- .../config-panel/form-input.tsx | 2 +- .../base/chat/embedded-chatbot/context.tsx | 2 +- web/app/components/base/chat/types.ts | 20 +- web/app/components/base/copy-btn/index.tsx | 21 +- .../components/base/copy-feedback/index.tsx | 23 +- web/app/components/base/drawer/index.tsx | 8 +- web/app/components/base/dropdown/index.tsx | 12 +- .../components/base/emoji-picker/Inner.tsx | 26 +- .../components/base/emoji-picker/index.tsx | 5 +- .../base/emoji-picker/style.module.css | 12 - .../moderation/moderation-setting-modal.tsx | 2 +- web/app/components/base/features/store.ts | 6 +- web/app/components/base/features/types.ts | 6 +- .../file-from-link-or-local/index.tsx | 2 +- web/app/components/base/grid-mask/index.tsx | 8 +- web/app/components/base/icons/IconBase.tsx | 2 + .../icons/assets/public/common/highlight.svg | 9 + .../assets/public/common/sparkles-soft.svg | 6 + .../assets/vender/other/anthropic-text.svg | 78 + .../base/icons/assets/vender/other/group.svg | 8 + .../base/icons/assets/vender/other/openai.svg | 9 + .../assets/vender/plugin/box-sparkle-fill.svg | 9 + .../assets/vender/plugin/left-corner.svg | 3 + .../assets/vender/solid/files/file-zip.svg | 6 + .../assets/vender/solid/general/github.svg | 5 + .../mediaAndDevices/audio-support-icon.svg | 3 + .../mediaAndDevices/document-support-icon.svg | 3 + .../mediaAndDevices/video-support-icon.svg | 3 + .../icons/assets/vender/workflow/agent.svg | 8 + .../base/icons/{script.js => script.mjs} | 11 +- .../icons/src/image/llm/BaichuanTextCn.tsx | 2 +- .../base/icons/src/image/llm/Minimax.tsx | 2 +- .../base/icons/src/image/llm/MinimaxText.tsx | 2 +- .../base/icons/src/image/llm/Tongyi.tsx | 2 +- .../base/icons/src/image/llm/TongyiText.tsx | 2 +- .../base/icons/src/image/llm/TongyiTextCn.tsx | 2 +- .../base/icons/src/image/llm/Wxyy.tsx | 2 +- .../base/icons/src/image/llm/WxyyText.tsx | 2 +- .../base/icons/src/image/llm/WxyyTextCn.tsx | 2 +- .../icons/src/public/common/Highlight.json | 67 + .../icons/src/public/common/Highlight.tsx | 16 + .../icons/src/public/common/SparklesSoft.json | 47 + .../icons/src/public/common/SparklesSoft.tsx | 16 + .../base/icons/src/public/common/index.ts | 2 + .../icons/src/vender/other/AnthropicText.json | 539 + .../icons/src/vender/other/AnthropicText.tsx | 16 + .../base/icons/src/vender/other/Group.json | 66 + .../base/icons/src/vender/other/Group.tsx | 16 + .../base/icons/src/vender/other/Openai.json | 80 + .../base/icons/src/vender/other/Openai.tsx | 16 + .../base/icons/src/vender/other/index.ts | 3 + .../src/vender/plugin/BoxSparkleFill.json | 66 + .../src/vender/plugin/BoxSparkleFill.tsx | 16 + .../icons/src/vender/plugin/LeftCorner.json | 27 + .../icons/src/vender/plugin/LeftCorner.tsx | 16 + .../base/icons/src/vender/plugin/index.ts | 2 + .../icons/src/vender/solid/files/FileZip.json | 47 + .../icons/src/vender/solid/files/FileZip.tsx | 16 + .../icons/src/vender/solid/files/index.ts | 1 + .../src/vender/solid/general/Github.json | 36 + .../icons/src/vender/solid/general/Github.tsx | 16 + .../icons/src/vender/solid/general/index.ts | 1 + .../mediaAndDevices/AudioSupportIcon.json | 26 + .../mediaAndDevices/AudioSupportIcon.tsx | 16 + .../mediaAndDevices/DocumentSupportIcon.json | 26 + .../mediaAndDevices/DocumentSupportIcon.tsx | 16 + .../mediaAndDevices/VideoSupportIcon.json | 26 + .../mediaAndDevices/VideoSupportIcon.tsx | 16 + .../src/vender/solid/mediaAndDevices/index.ts | 3 + .../base/icons/src/vender/workflow/Agent.json | 53 + .../base/icons/src/vender/workflow/Agent.tsx | 16 + .../base/icons/src/vender/workflow/index.ts | 1 + .../base/image-uploader/image-preview.tsx | 4 +- .../components/base/install-button/index.tsx | 27 + web/app/components/base/list-empty/index.tsx | 7 +- web/app/components/base/logo/logo-site.tsx | 12 +- web/app/components/base/markdown.tsx | 84 +- web/app/components/base/mermaid/index.tsx | 10 +- .../base/message-log-modal/index.tsx | 2 +- web/app/components/base/modal/index.tsx | 2 +- web/app/components/base/pagination/hook.ts | 2 +- web/app/components/base/pagination/index.tsx | 12 +- web/app/components/base/popover/index.tsx | 6 +- .../base/portal-to-follow-elem/index.tsx | 6 +- .../components/base/premium-badge/index.css | 48 + .../components/base/premium-badge/index.tsx | 78 + .../components/base/prompt-editor/index.tsx | 2 +- .../plugins/component-picker-block/index.tsx | 2 +- .../plugins/custom-text/node.tsx | 8 +- .../plugins/variable-value-block/node.tsx | 7 +- .../plugins/workflow-variable-block/node.tsx | 2 +- web/app/components/base/qrcode/index.tsx | 32 +- .../components/base/qrcode/style.module.css | 61 - web/app/components/base/radio/ui.tsx | 2 +- web/app/components/base/select/index.tsx | 25 +- web/app/components/base/skeleton/index.tsx | 2 +- web/app/components/base/sort/index.tsx | 2 +- .../base/tab-slider-plain/index.tsx | 6 +- web/app/components/base/tab-slider/index.tsx | 103 +- web/app/components/base/tag-input/index.tsx | 2 +- .../components/base/tag-management/filter.tsx | 2 +- .../components/base/tag-management/index.tsx | 2 +- .../base/tag-management/selector.tsx | 4 +- .../base/tag-management/tag-item-editor.tsx | 2 +- .../components/base/text-generation/types.ts | 14 +- web/app/components/base/toast/index.tsx | 24 +- web/app/components/base/tooltip/content.tsx | 22 + .../components/base/video-gallery/index.tsx | 2 +- .../billing/header-billing-btn/index.tsx | 24 +- .../components/billing/upgrade-btn/index.tsx | 32 +- .../empty-dataset-creation-modal/index.tsx | 2 +- .../datasets/create/step-one/index.tsx | 2 +- .../create/step-two/language-select/index.tsx | 2 +- .../jina-reader/base/checkbox-with-label.tsx | 2 +- .../jina-reader/base/error-message.tsx | 2 +- .../create/website/jina-reader/base/field.tsx | 2 +- .../create/website/jina-reader/base/input.tsx | 4 +- .../website/jina-reader/base/options-wrap.tsx | 2 +- .../website/jina-reader/base/url-input.tsx | 2 +- .../jina-reader/crawled-result-item.tsx | 2 +- .../website/jina-reader/crawled-result.tsx | 2 +- .../create/website/jina-reader/crawling.tsx | 2 +- .../documents/detail/completed/index.tsx | 2 +- .../documents/detail/metadata/index.tsx | 4 +- .../documents/detail/new-segment-modal.tsx | 156 + .../documents/detail/settings/index.tsx | 2 +- .../components/datasets/documents/index.tsx | 2 +- .../datasets/documents/rename-modal.tsx | 2 +- .../external-api/external-api-modal/Form.tsx | 2 + .../datasets/hit-testing/textarea.tsx | 2 +- .../datasets/rename-modal/index.tsx | 2 +- .../datasets/settings/form/index.tsx | 2 +- .../settings/permission-selector/index.tsx | 2 +- web/app/components/develop/md.tsx | 2 +- .../develop/secret-key/input-copy.tsx | 12 +- .../develop/secret-key/secret-key-button.tsx | 2 +- .../secret-key/secret-key-generate.tsx | 8 +- .../develop/secret-key/secret-key-modal.tsx | 40 +- .../explore/create-app-modal/index.tsx | 2 +- .../header/account-dropdown/index.tsx | 5 - .../workplace-selector/index.tsx | 67 +- .../header/account-setting/index.module.css | 8 - .../header/account-setting/index.tsx | 111 +- .../account-setting/members-page/index.tsx | 2 +- .../header/account-setting/menu-dialog.tsx | 59 + .../model-provider-page/declarations.ts | 16 +- .../model-provider-page/hooks.ts | 114 + .../model-provider-page/index.tsx | 234 +- .../model-provider-page/model-icon/index.tsx | 38 +- .../model-provider-page/model-modal/Form.tsx | 312 +- .../model-provider-page/model-modal/Input.tsx | 16 +- .../model-provider-page/model-modal/index.tsx | 25 +- .../model-provider-page/model-name/index.tsx | 64 +- .../agent-model-trigger.tsx | 186 + .../configuration-button.tsx | 32 + .../model-parameter-modal/index.tsx | 27 +- .../model-parameter-modal/model-display.tsx | 25 + .../model-parameter-modal/parameter-item.tsx | 53 +- .../presets-parameter.tsx | 20 +- .../status-indicators.tsx | 99 + .../model-parameter-modal/trigger.tsx | 14 +- .../deprecated-model-trigger.tsx | 40 +- .../model-selector/empty-trigger.tsx | 18 +- .../model-selector/feature-icon.tsx | 47 +- .../model-selector/index.tsx | 13 +- .../model-selector/model-trigger.tsx | 60 +- .../model-selector/popup-item.tsx | 122 +- .../model-selector/popup.tsx | 67 +- .../model-selector/rerank-trigger.tsx | 27 - .../provider-added-card/add-model-button.tsx | 6 +- .../provider-added-card/cooldown-timer.tsx | 6 +- .../provider-added-card/credential-panel.tsx | 10 +- .../provider-added-card/index.tsx | 78 +- .../provider-added-card/model-list-item.tsx | 16 +- .../provider-added-card/model-list.tsx | 15 +- .../model-load-balancing-configs.tsx | 24 +- .../model-load-balancing-modal.tsx | 12 +- .../provider-added-card/priority-selector.tsx | 19 +- .../provider-added-card/priority-use-tip.tsx | 4 +- .../provider-added-card/quota-panel.tsx | 8 +- .../provider-added-card/tab.tsx | 45 - .../provider-card/index.module.css | 4 - .../provider-card/index.tsx | 103 - .../provider-icon/index.tsx | 29 +- .../system-model-selector/index.tsx | 42 +- .../model-provider-page/utils.ts | 4 +- web/app/components/header/app-nav/index.tsx | 2 +- web/app/components/header/index.tsx | 118 +- web/app/components/header/nav/index.tsx | 2 +- .../plugins-nav/downloading-icon.module.css | 44 + .../header/plugins-nav/downloading-icon.tsx | 17 + .../components/header/plugins-nav/index.tsx | 66 + .../plugins/base/key-value-item.tsx | 66 + .../plugins/card/base/card-icon.tsx | 66 + .../plugins/card/base/corner-mark.tsx | 12 + .../plugins/card/base/description.tsx | 31 + .../plugins/card/base/download-count.tsx | 19 + .../components/plugins/card/base/org-info.tsx | 30 + .../plugins/card/base/placeholder.tsx | 51 + .../components/plugins/card/base/title.tsx | 13 + web/app/components/plugins/card/card-mock.ts | 160 + .../plugins/card/card-more-info.tsx | 36 + web/app/components/plugins/card/index.tsx | 92 + web/app/components/plugins/constants.ts | 27 + web/app/components/plugins/hooks.ts | 94 + .../install-plugin/base/check-task-status.ts | 63 + .../plugins/install-plugin/base/installed.tsx | 60 + .../install-plugin/base/loading-error.tsx | 45 + .../plugins/install-plugin/base/loading.tsx | 23 + .../install-plugin/base/use-get-icon.ts | 16 + .../plugins/install-plugin/base/version.tsx | 34 + .../plugins/install-plugin/hooks.ts | 107 + .../hooks/use-check-installed.tsx | 32 + .../hooks/use-fold-anim-into.ts | 57 + .../install-plugin/hooks/use-hide-logic.ts | 40 + .../hooks/use-refresh-plugin-list.tsx | 45 + .../install-plugin/install-bundle/index.tsx | 75 + .../install-bundle/item/github-item.tsx | 62 + .../install-bundle/item/loaded-item.tsx | 51 + .../install-bundle/item/marketplace-item.tsx | 36 + .../install-bundle/item/package-item.tsx | 41 + .../install-bundle/ready-to-install.tsx | 57 + .../install-bundle/steps/install-multi.tsx | 218 + .../install-bundle/steps/install.tsx | 116 + .../install-bundle/steps/installed.tsx | 65 + .../install-from-github/index.tsx | 234 + .../install-from-github/steps/loaded.tsx | 180 + .../steps/selectPackage.tsx | 125 + .../install-from-github/steps/setURL.tsx | 56 + .../install-from-local-package/index.tsx | 133 + .../ready-to-install.tsx | 75 + .../steps/install.tsx | 162 + .../steps/uploading.tsx | 99 + .../install-from-marketplace/index.tsx | 124 + .../steps/install.tsx | 158 + .../plugins/install-plugin/utils.ts | 59 + .../plugins/marketplace/constants.ts | 4 + .../plugins/marketplace/context.tsx | 314 + .../plugins/marketplace/description/index.tsx | 49 + .../plugins/marketplace/empty/index.tsx | 63 + .../plugins/marketplace/empty/line.tsx | 21 + .../components/plugins/marketplace/hooks.ts | 176 + .../components/plugins/marketplace/index.tsx | 68 + .../marketplace/intersection-line/hooks.ts | 30 + .../marketplace/intersection-line/index.tsx | 21 + .../plugins/marketplace/list/card-wrapper.tsx | 103 + .../plugins/marketplace/list/index.tsx | 79 + .../marketplace/list/list-with-collection.tsx | 84 + .../plugins/marketplace/list/list-wrapper.tsx | 73 + .../marketplace/plugin-type-switch.tsx | 100 + .../plugins/marketplace/search-box/index.tsx | 70 + .../search-box/search-box-wrapper.tsx | 45 + .../marketplace/search-box/tags-filter.tsx | 138 + .../marketplace/sort-dropdown/index.tsx | 94 + .../components/plugins/marketplace/types.ts | 59 + .../components/plugins/marketplace/utils.ts | 124 + .../permission-setting-modal/modal.tsx | 93 + .../permission-setting-modal/style.module.css | 7 + .../plugin-detail-panel/action-list.tsx | 112 + .../agent-strategy-list.tsx | 58 + .../app-selector/app-inputs-form.tsx | 125 + .../app-selector/app-inputs-panel.tsx | 180 + .../app-selector/app-picker.tsx | 123 + .../app-selector/app-trigger.tsx | 48 + .../app-selector/index.tsx | 143 + .../plugin-detail-panel/detail-header.tsx | 306 + .../plugin-detail-panel/endpoint-card.tsx | 219 + .../plugin-detail-panel/endpoint-list.tsx | 122 + .../plugin-detail-panel/endpoint-modal.tsx | 96 + .../plugins/plugin-detail-panel/index.tsx | 62 + .../plugin-detail-panel/model-list.tsx | 46 + .../model-selector/index.tsx | 250 + .../model-selector/llm-params-panel.tsx | 126 + .../model-selector/tts-params-panel.tsx | 67 + .../multiple-tool-selector/index.tsx | 149 + .../operation-dropdown.tsx | 101 + .../plugin-detail-panel/strategy-detail.tsx | 164 + .../plugin-detail-panel/strategy-item.tsx | 50 + .../tool-selector/hooks.ts | 14 + .../tool-selector/index.tsx | 374 + .../tool-selector/tool-credentials-form.tsx | 97 + .../tool-selector/tool-item.tsx | 163 + .../tool-selector/tool-trigger.tsx | 63 + .../plugins/plugin-detail-panel/utils.ts | 21 + .../components/plugins/plugin-item/action.tsx | 159 + .../components/plugins/plugin-item/index.tsx | 187 + .../plugins/plugin-mutation-model/index.tsx | 79 + .../plugins/plugin-page/context.tsx | 95 + .../plugins/plugin-page/debug-info.tsx | 63 + .../plugins/plugin-page/empty/index.tsx | 120 + .../filter-management/category-filter.tsx | 127 + .../plugin-page/filter-management/constant.ts | 11 + .../plugin-page/filter-management/index.tsx | 45 + .../filter-management/search-box.tsx | 30 + .../plugin-page/filter-management/store.ts | 27 + .../filter-management/tag-filter.tsx | 122 + .../components/plugins/plugin-page/index.tsx | 276 + .../plugin-page/install-plugin-dropdown.tsx | 139 + .../plugins/plugin-page/list/index.tsx | 23 + .../plugins/plugin-page/plugin-info.tsx | 41 + .../plugins/plugin-page/plugin-tasks/hooks.ts | 100 + .../plugin-page/plugin-tasks/index.tsx | 194 + .../plugins/plugin-page/plugins-panel.tsx | 70 + .../plugins/plugin-page/use-permission.ts | 45 + .../plugins/plugin-page/use-uploader.ts | 86 + web/app/components/plugins/provider-card.tsx | 97 + web/app/components/plugins/types.ts | 435 + .../plugins/update-plugin/from-github.tsx | 26 + .../update-plugin/from-market-place.tsx | 164 + .../plugins/update-plugin/index.tsx | 33 + .../update-plugin/plugin-version-picker.tsx | 118 + web/app/components/plugins/utils.ts | 12 + .../share/text-generation/index.tsx | 9 +- .../share/text-generation/result/index.tsx | 2 +- web/app/components/swr-initor.tsx | 2 +- .../config-credentials.tsx | 64 +- .../get-schema.tsx | 15 +- .../edit-custom-collection-modal/index.tsx | 46 +- .../edit-custom-collection-modal/modal.tsx | 360 + .../edit-custom-collection-modal/test-api.tsx | 38 +- web/app/components/tools/labels/constant.ts | 4 +- web/app/components/tools/labels/filter.tsx | 52 +- web/app/components/tools/labels/selector.tsx | 43 +- web/app/components/tools/labels/store.ts | 15 - web/app/components/tools/marketplace/hooks.ts | 117 + .../components/tools/marketplace/index.tsx | 117 + web/app/components/tools/provider-list.tsx | 187 +- .../tools/provider/custom-create-card.tsx | 12 +- web/app/components/tools/provider/detail.tsx | 362 +- .../components/tools/provider/tool-item.tsx | 7 +- .../setting/build-in/config-credentials.tsx | 30 +- web/app/components/tools/types.ts | 15 +- .../components/tools/utils/to-form-schema.ts | 2 +- .../tools/workflow-tool/configure-button.tsx | 4 + .../workflow-tool/confirm-modal/index.tsx | 13 +- .../confirm-modal/style.module.css | 3 - .../components/tools/workflow-tool/index.tsx | 42 +- .../tools/workflow-tool/method-selector.tsx | 26 +- web/app/components/workflow/block-icon.tsx | 3 + .../workflow/block-selector/all-tools.tsx | 142 +- .../workflow/block-selector/constants.tsx | 5 + .../workflow/block-selector/hooks.ts | 2 +- .../workflow/block-selector/index-bar.tsx | 49 +- .../workflow/block-selector/index.tsx | 41 +- .../market-place-plugin/action.tsx | 87 + .../market-place-plugin/item.tsx | 77 + .../market-place-plugin/list.tsx | 129 + .../workflow/block-selector/tabs.tsx | 11 + .../workflow/block-selector/tool-picker.tsx | 170 + .../block-selector/tool/action-item.tsx | 72 + .../tool/tool-list-flat-view/list.tsx | 61 + .../tool/tool-list-tree-view/item.tsx | 44 + .../tool/tool-list-tree-view/list.tsx | 53 + .../workflow/block-selector/tool/tool.tsx | 126 + .../workflow/block-selector/tools.tsx | 158 +- .../workflow/block-selector/types.ts | 4 + .../block-selector/use-sticky-scroll.ts | 45 + .../block-selector/view-type-select.tsx | 58 + web/app/components/workflow/constants.ts | 18 +- .../workflow/hooks/use-checklist.ts | 18 +- .../hooks/use-workflow-run-event/index.ts | 12 + .../use-workflow-agent-log.ts | 50 + .../use-workflow-failed.ts | 26 + .../use-workflow-finished.ts | 35 + .../use-workflow-node-finished.ts | 72 + .../use-workflow-node-iteration-finished.ts | 46 + .../use-workflow-node-iteration-next.ts | 35 + .../use-workflow-node-iteration-started.ts | 85 + .../use-workflow-node-retry.ts | 39 + .../use-workflow-node-started.ts | 89 + .../use-workflow-run-event.ts | 44 + .../use-workflow-started.ts | 58 + .../use-workflow-text-chunk.ts | 25 + .../use-workflow-text-replace.ts | 23 + .../workflow/hooks/use-workflow-run.ts | 581 +- .../components/workflow/hooks/use-workflow.ts | 1 - web/app/components/workflow/index.tsx | 2 + .../nodes/_base/components/add-button.tsx | 2 +- .../components/agent-strategy-selector.tsx | 228 + .../nodes/_base/components/agent-strategy.tsx | 218 + .../components/before-run-form/form-item.tsx | 2 +- .../_base/components/before-run-form/form.tsx | 2 +- .../components/before-run-form/index.tsx | 31 +- .../components/collapse/field-collapse.tsx | 3 +- .../nodes/_base/components/editor/base.tsx | 2 +- .../code-editor/editor-support-vars.tsx | 2 +- .../workflow/nodes/_base/components/field.tsx | 9 +- .../workflow/nodes/_base/components/group.tsx | 25 + .../nodes/_base/components/info-panel.tsx | 4 +- .../components/input-number-with-slider.tsx | 2 +- .../_base/components/input-var-type-icon.tsx | 2 +- .../components/install-plugin-button.tsx | 45 + .../nodes/_base/components/memory-config.tsx | 2 +- .../_base/components/node-status-icon.tsx | 43 + .../nodes/_base/components/output-vars.tsx | 4 +- .../nodes/_base/components/prompt/editor.tsx | 37 +- .../nodes/_base/components/setting-item.tsx | 28 + .../workflow/nodes/_base/components/split.tsx | 2 +- .../components/switch-plugin-version.tsx | 126 + .../nodes/_base/components/variable-tag.tsx | 2 +- .../components/variable/output-var-list.tsx | 2 +- .../nodes/_base/components/variable/utils.ts | 71 +- .../variable/var-reference-vars.tsx | 10 +- .../nodes/_base/hooks/use-one-step-run.ts | 54 +- .../nodes/agent/components/model-bar.tsx | 75 + .../nodes/agent/components/tool-icon.tsx | 81 + .../workflow/nodes/agent/default.ts | 54 + .../components/workflow/nodes/agent/node.tsx | 113 + .../components/workflow/nodes/agent/panel.tsx | 154 + .../components/workflow/nodes/agent/types.ts | 11 + .../workflow/nodes/agent/use-config.ts | 190 + .../components/operation-selector.tsx | 2 +- .../assigner/components/var-list/index.tsx | 4 +- .../workflow/nodes/assigner/node.tsx | 2 +- .../workflow/nodes/assigner/panel.tsx | 4 +- .../components/workflow/nodes/code/panel.tsx | 2 +- .../components/workflow/nodes/constants.ts | 4 + .../nodes/document-extractor/default.ts | 2 +- .../nodes/document-extractor/node.tsx | 2 +- .../nodes/document-extractor/use-config.ts | 2 +- .../components/workflow/nodes/end/default.ts | 2 +- .../components/workflow/nodes/end/panel.tsx | 4 +- .../http/components/authorization/index.tsx | 2 +- .../nodes/http/components/edit-body/index.tsx | 2 +- .../nodes/http/components/key-value/index.tsx | 2 +- .../key-value/key-value-edit/index.tsx | 2 +- .../key-value/key-value-edit/input-item.tsx | 2 +- .../key-value/key-value-edit/item.tsx | 2 +- .../nodes/http/components/timeout/index.tsx | 4 +- .../components/workflow/nodes/http/panel.tsx | 9 +- .../components/workflow/nodes/http/types.ts | 8 +- .../if-else/components/condition-add.tsx | 2 +- .../condition-list/condition-item.tsx | 2 +- .../condition-list/condition-operator.tsx | 2 +- .../components/condition-list/index.tsx | 2 +- .../components/condition-number-input.tsx | 2 +- .../if-else/components/condition-value.tsx | 2 +- .../workflow/nodes/if-else/types.ts | 4 +- .../workflow/nodes/iteration/panel.tsx | 35 +- .../components/dataset-item.tsx | 2 +- .../list-operator/components/limit-config.tsx | 2 +- .../workflow/nodes/list-operator/node.tsx | 2 +- .../workflow/nodes/list-operator/panel.tsx | 2 +- .../components/workflow/nodes/llm/node.tsx | 1 + .../components/workflow/nodes/llm/panel.tsx | 9 +- .../components/extract-parameter/update.tsx | 2 +- .../components/reasoning-mode-picker.tsx | 2 +- .../nodes/parameter-extractor/node.tsx | 1 + .../nodes/parameter-extractor/types.ts | 2 +- .../nodes/question-classifier/node.tsx | 1 + .../nodes/question-classifier/types.ts | 2 +- .../nodes/start/components/var-item.tsx | 2 +- .../nodes/tool/components/input-var-list.tsx | 77 +- .../components/workflow/nodes/tool/node.tsx | 19 +- .../components/workflow/nodes/tool/panel.tsx | 29 +- .../components/workflow/nodes/tool/types.ts | 3 +- .../workflow/nodes/tool/use-config.ts | 27 +- .../components/var-group-item.tsx | 2 +- .../nodes/variable-assigner/panel.tsx | 2 +- .../components/array-value-list.tsx | 2 +- .../components/variable-modal.tsx | 4 +- .../conversation-variable-modal.tsx | 2 +- .../workflow/panel/debug-and-preview/hooks.ts | 143 +- .../panel/env-panel/variable-modal.tsx | 2 +- .../workflow/panel/inputs-panel.tsx | 2 +- .../workflow/panel/workflow-preview.tsx | 282 +- .../workflow/plugin-dependency/hooks.ts | 17 + .../workflow/plugin-dependency/index.tsx | 24 + .../workflow/plugin-dependency/store.ts | 11 + .../workflow/run/agent-log/agent-log-item.tsx | 126 + .../run/agent-log/agent-log-nav-more.tsx | 61 + .../workflow/run/agent-log/agent-log-nav.tsx | 78 + .../run/agent-log/agent-log-trigger.tsx | 49 + .../run/agent-log/agent-result-panel.tsx | 60 + .../workflow/run/agent-log/index.tsx | 2 + web/app/components/workflow/run/hooks.ts | 88 + web/app/components/workflow/run/index.tsx | 171 +- .../workflow/run/iteration-log/index.tsx | 2 + .../iteration-log/iteration-log-trigger.tsx | 57 + .../iteration-result-panel.tsx | 106 +- web/app/components/workflow/run/node.tsx | 113 +- .../components/workflow/run/output-panel.tsx | 2 +- .../components/workflow/run/result-panel.tsx | 72 +- .../components/workflow/run/result-text.tsx | 2 +- .../workflow/run/retry-log/index.tsx | 2 + .../run/retry-log/retry-log-trigger.tsx | 41 + .../{ => retry-log}/retry-result-panel.tsx | 2 +- .../workflow/run/special-result-panel.tsx | 73 + web/app/components/workflow/run/status.tsx | 2 +- .../components/workflow/run/tracing-panel.tsx | 218 +- .../run/utils/format-log/agent/data.ts | 182 + .../run/utils/format-log/agent/index.spec.ts | 16 + .../run/utils/format-log/agent/index.ts | 99 + .../format-log/graph-to-log-struct.spec.ts | 128 + .../utils/format-log/graph-to-log-struct.ts | 304 + .../run/utils/format-log/index.spec.ts | 10 + .../workflow/run/utils/format-log/index.ts | 27 + .../utils/format-log/iteration/index.spec.ts | 22 + .../run/utils/format-log/iteration/index.ts | 55 + .../utils/format-log/parallel/index.spec.ts | 39 + .../run/utils/format-log/parallel/index.ts | 175 + .../run/utils/format-log/retry/index.spec.ts | 21 + .../run/utils/format-log/retry/index.ts | 35 + web/app/components/workflow/store.ts | 2 +- web/app/components/workflow/types.ts | 1 + .../components/workflow/update-dsl-modal.tsx | 23 +- web/app/components/workflow/utils.ts | 16 +- web/app/dev-preview/page.tsx | 19 + web/app/layout.tsx | 2 + .../repos/[owner]/[repo]/releases/route.ts | 36 + web/app/signin/_header.tsx | 2 +- web/app/signin/oneMoreStep.tsx | 2 +- web/app/styles/globals.css | 17 +- web/config/index.ts | 22 +- web/context/modal-context.tsx | 25 +- web/context/provider-context.tsx | 6 +- web/docker/entrypoint.sh | 2 + web/eslint.config.mjs | 183 + web/hooks/use-i18n.ts | 14 + web/hooks/use-metadata.ts | 28 +- web/hooks/use-mitt.ts | 74 + web/hooks/use-pay.tsx | 68 +- web/hooks/use-timestamp.ts | 6 +- web/i18n/de-DE/plugin-tags.ts | 4 + web/i18n/de-DE/plugin.ts | 4 + web/i18n/en-US/app.ts | 6 + web/i18n/en-US/common.ts | 17 +- web/i18n/en-US/plugin-tags.ts | 25 + web/i18n/en-US/plugin.ts | 206 + web/i18n/en-US/run-log.ts | 2 + web/i18n/en-US/tools.ts | 9 +- web/i18n/en-US/workflow.ts | 74 +- web/i18n/es-ES/plugin-tags.ts | 4 + web/i18n/es-ES/plugin.ts | 4 + web/i18n/fa-IR/plugin-tags.ts | 4 + web/i18n/fa-IR/plugin.ts | 4 + web/i18n/fr-FR/plugin-tags.ts | 4 + web/i18n/fr-FR/plugin.ts | 4 + web/i18n/hi-IN/plugin-tags.ts | 4 + web/i18n/hi-IN/plugin.ts | 4 + web/i18n/hi-IN/share-app.ts | 2 + web/i18n/i18next-config.ts | 2 + web/i18n/it-IT/plugin-tags.ts | 4 + web/i18n/it-IT/plugin.ts | 4 + web/i18n/ja-JP/plugin-tags.ts | 4 + web/i18n/ja-JP/plugin.ts | 4 + web/i18n/ko-KR/plugin-tags.ts | 4 + web/i18n/ko-KR/plugin.ts | 4 + web/i18n/pl-PL/plugin-tags.ts | 4 + web/i18n/pl-PL/plugin.ts | 4 + web/i18n/pt-BR/plugin-tags.ts | 4 + web/i18n/pt-BR/plugin.ts | 4 + web/i18n/ro-RO/plugin-tags.ts | 4 + web/i18n/ro-RO/plugin.ts | 4 + web/i18n/ru-RU/plugin-tags.ts | 4 + web/i18n/ru-RU/plugin.ts | 4 + .../sl-SI/plugin-tags.ts} | 0 web/i18n/sl-SI/plugin.ts | 0 web/i18n/th-TH/plugin-tags.ts | 4 + web/i18n/th-TH/plugin.ts | 4 + web/i18n/tr-TR/plugin-tags.ts | 4 + web/i18n/tr-TR/plugin.ts | 4 + web/i18n/uk-UA/plugin-tags.ts | 4 + web/i18n/uk-UA/plugin.ts | 4 + web/i18n/vi-VN/plugin-tags.ts | 4 + web/i18n/vi-VN/plugin.ts | 4 + web/i18n/zh-Hans/app.ts | 6 + web/i18n/zh-Hans/common.ts | 15 +- web/i18n/zh-Hans/plugin-tags.ts | 25 + web/i18n/zh-Hans/plugin.ts | 206 + web/i18n/zh-Hans/run-log.ts | 2 + web/i18n/zh-Hans/tools.ts | 7 +- web/i18n/zh-Hans/workflow.ts | 74 +- web/i18n/zh-Hant/plugin-tags.ts | 4 + web/i18n/zh-Hant/plugin.ts | 4 + web/models/app.ts | 2 + web/models/common.ts | 56 +- web/models/debug.ts | 50 +- web/package.json | 180 +- web/pnpm-lock.yaml | 18306 ++++++++++++++++ web/public/logo/logo.png | Bin 0 -> 6249 bytes web/service/base.ts | 198 +- web/service/common.ts | 6 +- web/service/debug.ts | 4 +- web/service/fetch.ts | 205 + web/service/plugins.ts | 108 + web/service/strategy.ts | 10 + web/service/tools.ts | 4 + web/service/use-apps.ts | 27 + web/service/use-common.ts | 14 + web/service/use-endpoints.ts | 149 + web/service/use-models.ts | 17 + web/service/use-plugins.ts | 432 + web/service/use-strategy.ts | 36 + web/service/use-tools.ts | 121 + web/service/use-workflow.ts | 13 +- web/tailwind-common-config.ts | 113 + web/tailwind.config.js | 120 +- web/themes/dark.css | 1 + web/themes/manual-dark.css | 49 +- web/themes/manual-light.css | 49 +- web/types/app.ts | 21 +- web/types/feature.ts | 2 + web/types/workflow.ts | 145 +- web/utils/format.ts | 11 + web/utils/get-icon.ts | 5 + web/utils/index.ts | 10 + web/utils/semver.ts | 9 + web/yarn.lock | 7740 ++++--- 719 files changed, 48585 insertions(+), 8553 deletions(-) delete mode 100644 sdks/nodejs-client/babel.config.json delete mode 100644 web/.eslintignore delete mode 100644 web/.eslintrc.json delete mode 100644 web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx create mode 100644 web/app/(commonLayout)/plugins/page.tsx delete mode 100644 web/app/components/app/configuration/toolbox/annotation/config-param.tsx delete mode 100644 web/app/components/app/configuration/toolbox/index.tsx delete mode 100644 web/app/components/app/overview/apikey-info-panel/progress/index.tsx delete mode 100644 web/app/components/app/overview/apikey-info-panel/progress/style.module.css delete mode 100644 web/app/components/app/overview/settings/style.module.css create mode 100644 web/app/components/base/app-icon/style.module.css create mode 100644 web/app/components/base/badge/index.css create mode 100644 web/app/components/base/badge/index.tsx delete mode 100644 web/app/components/base/emoji-picker/style.module.css create mode 100644 web/app/components/base/icons/assets/public/common/highlight.svg create mode 100644 web/app/components/base/icons/assets/public/common/sparkles-soft.svg create mode 100644 web/app/components/base/icons/assets/vender/other/anthropic-text.svg create mode 100644 web/app/components/base/icons/assets/vender/other/group.svg create mode 100644 web/app/components/base/icons/assets/vender/other/openai.svg create mode 100644 web/app/components/base/icons/assets/vender/plugin/box-sparkle-fill.svg create mode 100644 web/app/components/base/icons/assets/vender/plugin/left-corner.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/files/file-zip.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/general/github.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/mediaAndDevices/audio-support-icon.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/mediaAndDevices/document-support-icon.svg create mode 100644 web/app/components/base/icons/assets/vender/solid/mediaAndDevices/video-support-icon.svg create mode 100644 web/app/components/base/icons/assets/vender/workflow/agent.svg rename web/app/components/base/icons/{script.js => script.mjs} (94%) create mode 100644 web/app/components/base/icons/src/public/common/Highlight.json create mode 100644 web/app/components/base/icons/src/public/common/Highlight.tsx create mode 100644 web/app/components/base/icons/src/public/common/SparklesSoft.json create mode 100644 web/app/components/base/icons/src/public/common/SparklesSoft.tsx create mode 100644 web/app/components/base/icons/src/vender/other/AnthropicText.json create mode 100644 web/app/components/base/icons/src/vender/other/AnthropicText.tsx create mode 100644 web/app/components/base/icons/src/vender/other/Group.json create mode 100644 web/app/components/base/icons/src/vender/other/Group.tsx create mode 100644 web/app/components/base/icons/src/vender/other/Openai.json create mode 100644 web/app/components/base/icons/src/vender/other/Openai.tsx create mode 100644 web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.json create mode 100644 web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx create mode 100644 web/app/components/base/icons/src/vender/plugin/LeftCorner.json create mode 100644 web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx create mode 100644 web/app/components/base/icons/src/vender/plugin/index.ts create mode 100644 web/app/components/base/icons/src/vender/solid/files/FileZip.json create mode 100644 web/app/components/base/icons/src/vender/solid/files/FileZip.tsx create mode 100644 web/app/components/base/icons/src/vender/solid/general/Github.json create mode 100644 web/app/components/base/icons/src/vender/solid/general/Github.tsx create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.json create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.json create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.json create mode 100644 web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx create mode 100644 web/app/components/base/icons/src/vender/workflow/Agent.json create mode 100644 web/app/components/base/icons/src/vender/workflow/Agent.tsx create mode 100644 web/app/components/base/install-button/index.tsx create mode 100644 web/app/components/base/premium-badge/index.css create mode 100644 web/app/components/base/premium-badge/index.tsx delete mode 100644 web/app/components/base/qrcode/style.module.css create mode 100644 web/app/components/base/tooltip/content.tsx create mode 100644 web/app/components/datasets/documents/detail/new-segment-modal.tsx delete mode 100644 web/app/components/header/account-setting/index.module.css create mode 100644 web/app/components/header/account-setting/menu-dialog.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/configuration-button.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/model-display.tsx create mode 100644 web/app/components/header/account-setting/model-provider-page/model-parameter-modal/status-indicators.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/model-selector/rerank-trigger.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/provider-added-card/tab.tsx delete mode 100644 web/app/components/header/account-setting/model-provider-page/provider-card/index.module.css delete mode 100644 web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx create mode 100644 web/app/components/header/plugins-nav/downloading-icon.module.css create mode 100644 web/app/components/header/plugins-nav/downloading-icon.tsx create mode 100644 web/app/components/header/plugins-nav/index.tsx create mode 100644 web/app/components/plugins/base/key-value-item.tsx create mode 100644 web/app/components/plugins/card/base/card-icon.tsx create mode 100644 web/app/components/plugins/card/base/corner-mark.tsx create mode 100644 web/app/components/plugins/card/base/description.tsx create mode 100644 web/app/components/plugins/card/base/download-count.tsx create mode 100644 web/app/components/plugins/card/base/org-info.tsx create mode 100644 web/app/components/plugins/card/base/placeholder.tsx create mode 100644 web/app/components/plugins/card/base/title.tsx create mode 100644 web/app/components/plugins/card/card-mock.ts create mode 100644 web/app/components/plugins/card/card-more-info.tsx create mode 100644 web/app/components/plugins/card/index.tsx create mode 100644 web/app/components/plugins/constants.ts create mode 100644 web/app/components/plugins/hooks.ts create mode 100644 web/app/components/plugins/install-plugin/base/check-task-status.ts create mode 100644 web/app/components/plugins/install-plugin/base/installed.tsx create mode 100644 web/app/components/plugins/install-plugin/base/loading-error.tsx create mode 100644 web/app/components/plugins/install-plugin/base/loading.tsx create mode 100644 web/app/components/plugins/install-plugin/base/use-get-icon.ts create mode 100644 web/app/components/plugins/install-plugin/base/version.tsx create mode 100644 web/app/components/plugins/install-plugin/hooks.ts create mode 100644 web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx create mode 100644 web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts create mode 100644 web/app/components/plugins/install-plugin/hooks/use-hide-logic.ts create mode 100644 web/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/index.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx create mode 100644 web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-github/index.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-github/steps/selectPackage.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-github/steps/setURL.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-local-package/index.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-local-package/ready-to-install.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx create mode 100644 web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx create mode 100644 web/app/components/plugins/install-plugin/utils.ts create mode 100644 web/app/components/plugins/marketplace/constants.ts create mode 100644 web/app/components/plugins/marketplace/context.tsx create mode 100644 web/app/components/plugins/marketplace/description/index.tsx create mode 100644 web/app/components/plugins/marketplace/empty/index.tsx create mode 100644 web/app/components/plugins/marketplace/empty/line.tsx create mode 100644 web/app/components/plugins/marketplace/hooks.ts create mode 100644 web/app/components/plugins/marketplace/index.tsx create mode 100644 web/app/components/plugins/marketplace/intersection-line/hooks.ts create mode 100644 web/app/components/plugins/marketplace/intersection-line/index.tsx create mode 100644 web/app/components/plugins/marketplace/list/card-wrapper.tsx create mode 100644 web/app/components/plugins/marketplace/list/index.tsx create mode 100644 web/app/components/plugins/marketplace/list/list-with-collection.tsx create mode 100644 web/app/components/plugins/marketplace/list/list-wrapper.tsx create mode 100644 web/app/components/plugins/marketplace/plugin-type-switch.tsx create mode 100644 web/app/components/plugins/marketplace/search-box/index.tsx create mode 100644 web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx create mode 100644 web/app/components/plugins/marketplace/search-box/tags-filter.tsx create mode 100644 web/app/components/plugins/marketplace/sort-dropdown/index.tsx create mode 100644 web/app/components/plugins/marketplace/types.ts create mode 100644 web/app/components/plugins/marketplace/utils.ts create mode 100644 web/app/components/plugins/permission-setting-modal/modal.tsx create mode 100644 web/app/components/plugins/permission-setting-modal/style.module.css create mode 100644 web/app/components/plugins/plugin-detail-panel/action-list.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/agent-strategy-list.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-form.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/app-selector/app-trigger.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/detail-header.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/index.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/model-list.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/model-selector/llm-params-panel.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/model-selector/tts-params-panel.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/operation-dropdown.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/strategy-item.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/tool-selector/hooks.ts create mode 100644 web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/tool-selector/tool-item.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger.tsx create mode 100644 web/app/components/plugins/plugin-detail-panel/utils.ts create mode 100644 web/app/components/plugins/plugin-item/action.tsx create mode 100644 web/app/components/plugins/plugin-item/index.tsx create mode 100644 web/app/components/plugins/plugin-mutation-model/index.tsx create mode 100644 web/app/components/plugins/plugin-page/context.tsx create mode 100644 web/app/components/plugins/plugin-page/debug-info.tsx create mode 100644 web/app/components/plugins/plugin-page/empty/index.tsx create mode 100644 web/app/components/plugins/plugin-page/filter-management/category-filter.tsx create mode 100644 web/app/components/plugins/plugin-page/filter-management/constant.ts create mode 100644 web/app/components/plugins/plugin-page/filter-management/index.tsx create mode 100644 web/app/components/plugins/plugin-page/filter-management/search-box.tsx create mode 100644 web/app/components/plugins/plugin-page/filter-management/store.ts create mode 100644 web/app/components/plugins/plugin-page/filter-management/tag-filter.tsx create mode 100644 web/app/components/plugins/plugin-page/index.tsx create mode 100644 web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx create mode 100644 web/app/components/plugins/plugin-page/list/index.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-info.tsx create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts create mode 100644 web/app/components/plugins/plugin-page/plugin-tasks/index.tsx create mode 100644 web/app/components/plugins/plugin-page/plugins-panel.tsx create mode 100644 web/app/components/plugins/plugin-page/use-permission.ts create mode 100644 web/app/components/plugins/plugin-page/use-uploader.ts create mode 100644 web/app/components/plugins/provider-card.tsx create mode 100644 web/app/components/plugins/types.ts create mode 100644 web/app/components/plugins/update-plugin/from-github.tsx create mode 100644 web/app/components/plugins/update-plugin/from-market-place.tsx create mode 100644 web/app/components/plugins/update-plugin/index.tsx create mode 100644 web/app/components/plugins/update-plugin/plugin-version-picker.tsx create mode 100644 web/app/components/plugins/utils.ts create mode 100644 web/app/components/tools/edit-custom-collection-modal/modal.tsx delete mode 100644 web/app/components/tools/labels/store.ts create mode 100644 web/app/components/tools/marketplace/hooks.ts create mode 100644 web/app/components/tools/marketplace/index.tsx delete mode 100644 web/app/components/tools/workflow-tool/confirm-modal/style.module.css create mode 100644 web/app/components/workflow/block-selector/market-place-plugin/action.tsx create mode 100644 web/app/components/workflow/block-selector/market-place-plugin/item.tsx create mode 100644 web/app/components/workflow/block-selector/market-place-plugin/list.tsx create mode 100644 web/app/components/workflow/block-selector/tool-picker.tsx create mode 100644 web/app/components/workflow/block-selector/tool/action-item.tsx create mode 100644 web/app/components/workflow/block-selector/tool/tool-list-flat-view/list.tsx create mode 100644 web/app/components/workflow/block-selector/tool/tool-list-tree-view/item.tsx create mode 100644 web/app/components/workflow/block-selector/tool/tool-list-tree-view/list.tsx create mode 100644 web/app/components/workflow/block-selector/tool/tool.tsx create mode 100644 web/app/components/workflow/block-selector/use-sticky-scroll.ts create mode 100644 web/app/components/workflow/block-selector/view-type-select.tsx create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/index.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-agent-log.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-failed.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-finished.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-finished.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-finished.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-next.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-started.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-retry.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-started.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-started.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-chunk.ts create mode 100644 web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-replace.ts create mode 100644 web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/agent-strategy.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/group.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/install-plugin-button.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/node-status-icon.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/setting-item.tsx create mode 100644 web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx create mode 100644 web/app/components/workflow/nodes/agent/components/model-bar.tsx create mode 100644 web/app/components/workflow/nodes/agent/components/tool-icon.tsx create mode 100644 web/app/components/workflow/nodes/agent/default.ts create mode 100644 web/app/components/workflow/nodes/agent/node.tsx create mode 100644 web/app/components/workflow/nodes/agent/panel.tsx create mode 100644 web/app/components/workflow/nodes/agent/types.ts create mode 100644 web/app/components/workflow/nodes/agent/use-config.ts create mode 100644 web/app/components/workflow/plugin-dependency/hooks.ts create mode 100644 web/app/components/workflow/plugin-dependency/index.tsx create mode 100644 web/app/components/workflow/plugin-dependency/store.ts create mode 100644 web/app/components/workflow/run/agent-log/agent-log-item.tsx create mode 100644 web/app/components/workflow/run/agent-log/agent-log-nav-more.tsx create mode 100644 web/app/components/workflow/run/agent-log/agent-log-nav.tsx create mode 100644 web/app/components/workflow/run/agent-log/agent-log-trigger.tsx create mode 100644 web/app/components/workflow/run/agent-log/agent-result-panel.tsx create mode 100644 web/app/components/workflow/run/agent-log/index.tsx create mode 100644 web/app/components/workflow/run/hooks.ts create mode 100644 web/app/components/workflow/run/iteration-log/index.tsx create mode 100644 web/app/components/workflow/run/iteration-log/iteration-log-trigger.tsx rename web/app/components/workflow/run/{ => iteration-log}/iteration-result-panel.tsx (56%) create mode 100644 web/app/components/workflow/run/retry-log/index.tsx create mode 100644 web/app/components/workflow/run/retry-log/retry-log-trigger.tsx rename web/app/components/workflow/run/{ => retry-log}/retry-result-panel.tsx (96%) create mode 100644 web/app/components/workflow/run/special-result-panel.tsx create mode 100644 web/app/components/workflow/run/utils/format-log/agent/data.ts create mode 100644 web/app/components/workflow/run/utils/format-log/agent/index.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/agent/index.ts create mode 100644 web/app/components/workflow/run/utils/format-log/graph-to-log-struct.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/graph-to-log-struct.ts create mode 100644 web/app/components/workflow/run/utils/format-log/index.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/index.ts create mode 100644 web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/iteration/index.ts create mode 100644 web/app/components/workflow/run/utils/format-log/parallel/index.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/parallel/index.ts create mode 100644 web/app/components/workflow/run/utils/format-log/retry/index.spec.ts create mode 100644 web/app/components/workflow/run/utils/format-log/retry/index.ts create mode 100644 web/app/dev-preview/page.tsx create mode 100644 web/app/repos/[owner]/[repo]/releases/route.ts create mode 100644 web/eslint.config.mjs create mode 100644 web/hooks/use-i18n.ts create mode 100644 web/hooks/use-mitt.ts create mode 100644 web/i18n/de-DE/plugin-tags.ts create mode 100644 web/i18n/de-DE/plugin.ts create mode 100644 web/i18n/en-US/plugin-tags.ts create mode 100644 web/i18n/en-US/plugin.ts create mode 100644 web/i18n/es-ES/plugin-tags.ts create mode 100644 web/i18n/es-ES/plugin.ts create mode 100644 web/i18n/fa-IR/plugin-tags.ts create mode 100644 web/i18n/fa-IR/plugin.ts create mode 100644 web/i18n/fr-FR/plugin-tags.ts create mode 100644 web/i18n/fr-FR/plugin.ts create mode 100644 web/i18n/hi-IN/plugin-tags.ts create mode 100644 web/i18n/hi-IN/plugin.ts create mode 100644 web/i18n/it-IT/plugin-tags.ts create mode 100644 web/i18n/it-IT/plugin.ts create mode 100644 web/i18n/ja-JP/plugin-tags.ts create mode 100644 web/i18n/ja-JP/plugin.ts create mode 100644 web/i18n/ko-KR/plugin-tags.ts create mode 100644 web/i18n/ko-KR/plugin.ts create mode 100644 web/i18n/pl-PL/plugin-tags.ts create mode 100644 web/i18n/pl-PL/plugin.ts create mode 100644 web/i18n/pt-BR/plugin-tags.ts create mode 100644 web/i18n/pt-BR/plugin.ts create mode 100644 web/i18n/ro-RO/plugin-tags.ts create mode 100644 web/i18n/ro-RO/plugin.ts create mode 100644 web/i18n/ru-RU/plugin-tags.ts create mode 100644 web/i18n/ru-RU/plugin.ts rename web/{app/components/header/account-setting/model-provider-page/model-parameter-modal/stop-sequence.tsx => i18n/sl-SI/plugin-tags.ts} (100%) create mode 100644 web/i18n/sl-SI/plugin.ts create mode 100644 web/i18n/th-TH/plugin-tags.ts create mode 100644 web/i18n/th-TH/plugin.ts create mode 100644 web/i18n/tr-TR/plugin-tags.ts create mode 100644 web/i18n/tr-TR/plugin.ts create mode 100644 web/i18n/uk-UA/plugin-tags.ts create mode 100644 web/i18n/uk-UA/plugin.ts create mode 100644 web/i18n/vi-VN/plugin-tags.ts create mode 100644 web/i18n/vi-VN/plugin.ts create mode 100644 web/i18n/zh-Hans/plugin-tags.ts create mode 100644 web/i18n/zh-Hans/plugin.ts create mode 100644 web/i18n/zh-Hant/plugin-tags.ts create mode 100644 web/i18n/zh-Hant/plugin.ts create mode 100644 web/pnpm-lock.yaml create mode 100644 web/public/logo/logo.png create mode 100644 web/service/fetch.ts create mode 100644 web/service/plugins.ts create mode 100644 web/service/strategy.ts create mode 100644 web/service/use-apps.ts create mode 100644 web/service/use-common.ts create mode 100644 web/service/use-endpoints.ts create mode 100644 web/service/use-models.ts create mode 100644 web/service/use-plugins.ts create mode 100644 web/service/use-strategy.ts create mode 100644 web/service/use-tools.ts create mode 100644 web/tailwind-common-config.ts create mode 100644 web/utils/get-icon.ts create mode 100644 web/utils/semver.ts diff --git a/.devcontainer/post_create_command.sh b/.devcontainer/post_create_command.sh index e80f9d30aa..d879876d8a 100755 --- a/.devcontainer/post_create_command.sh +++ b/.devcontainer/post_create_command.sh @@ -1,11 +1,12 @@ #!/bin/bash -cd web && npm install +npm add -g pnpm@9.12.2 +cd web && pnpm install pipx install poetry echo 'alias start-api="cd /workspaces/dify/api && poetry run python -m flask run --host 0.0.0.0 --port=5001 --debug"' >> ~/.bashrc echo 'alias start-worker="cd /workspaces/dify/api && poetry run python -m celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,generation,mail,ops_trace,app_deletion"' >> ~/.bashrc -echo 'alias start-web="cd /workspaces/dify/web && npm run dev"' >> ~/.bashrc +echo 'alias start-web="cd /workspaces/dify/web && pnpm dev"' >> ~/.bashrc echo 'alias start-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify up -d"' >> ~/.bashrc echo 'alias stop-containers="cd /workspaces/dify/docker && docker-compose -f docker-compose.middleware.yaml -p dify down"' >> ~/.bashrc diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 9276d1f2fd..433647b155 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -72,16 +72,16 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' with: node-version: 20 - cache: yarn + cache: pnpm cache-dependency-path: ./web/package.json - name: Web dependencies if: steps.changed-files.outputs.any_changed == 'true' - run: yarn install --frozen-lockfile + run: pnpm install --frozen-lockfile - name: Web style check if: steps.changed-files.outputs.any_changed == 'true' - run: yarn run lint + run: pnpm run lint superlinter: name: SuperLinter diff --git a/.github/workflows/tool-test-sdks.yaml b/.github/workflows/tool-test-sdks.yaml index fb4bcb9d66..d3a4592eb5 100644 --- a/.github/workflows/tool-test-sdks.yaml +++ b/.github/workflows/tool-test-sdks.yaml @@ -32,10 +32,10 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: '' - cache-dependency-path: 'yarn.lock' + cache-dependency-path: 'pnpm-lock.yaml' - name: Install Dependencies - run: yarn install + run: pnpm install - name: Test - run: yarn test + run: pnpm test diff --git a/.github/workflows/translate-i18n-base-on-english.yml b/.github/workflows/translate-i18n-base-on-english.yml index 3f51b3b2c7..b45793a05f 100644 --- a/.github/workflows/translate-i18n-base-on-english.yml +++ b/.github/workflows/translate-i18n-base-on-english.yml @@ -38,11 +38,11 @@ jobs: - name: Install dependencies if: env.FILES_CHANGED == 'true' - run: yarn install --frozen-lockfile + run: pnpm install --frozen-lockfile - name: Run npm script if: env.FILES_CHANGED == 'true' - run: npm run auto-gen-i18n + run: pnpm run auto-gen-i18n - name: Create Pull Request if: env.FILES_CHANGED == 'true' diff --git a/.github/workflows/web-tests.yml b/.github/workflows/web-tests.yml index 5aee64b8e6..d9f310c811 100644 --- a/.github/workflows/web-tests.yml +++ b/.github/workflows/web-tests.yml @@ -34,13 +34,13 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' with: node-version: 20 - cache: yarn + cache: pnpm cache-dependency-path: ./web/package.json - name: Install dependencies if: steps.changed-files.outputs.any_changed == 'true' - run: yarn install --frozen-lockfile + run: pnpm install --frozen-lockfile - name: Run tests if: steps.changed-files.outputs.any_changed == 'true' - run: yarn test + run: pnpm test diff --git a/.gitignore b/.gitignore index ca95df4515..4d4af6efed 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,6 @@ api/.vscode .idea/ .vscode + +# pnpm +/.pnpm-store diff --git a/api/core/helper/ssrf_proxy.py b/api/core/helper/ssrf_proxy.py index 2e422cf444..c7a834a6b9 100644 --- a/api/core/helper/ssrf_proxy.py +++ b/api/core/helper/ssrf_proxy.py @@ -60,17 +60,20 @@ def make_request(method, url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs): if response.status_code not in STATUS_FORCELIST: return response else: - logging.warning(f"Received status code {response.status_code} for URL {url} which is in the force list") + logging.warning( + f"Received status code {response.status_code} for URL {url} which is in the force list") except httpx.RequestError as e: - logging.warning(f"Request to URL {url} failed on attempt {retries + 1}: {e}") + logging.warning(f"Request to URL {url} failed on attempt { + retries + 1}: {e}") if max_retries == 0: raise retries += 1 if retries <= max_retries: time.sleep(BACKOFF_FACTOR * (2 ** (retries - 1))) - raise MaxRetriesExceededError(f"Reached maximum retries ({max_retries}) for URL {url}") + raise MaxRetriesExceededError( + f"Reached maximum retries ({max_retries}) for URL {url}") def get(url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs): diff --git a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py index d7a14207e9..3b3e47578a 100644 --- a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py +++ b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py @@ -17,7 +17,8 @@ from extensions.ext_redis import redis_client from models.dataset import Dataset logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.INFO, + format="%(asctime)s - %(levelname)s - %(message)s") logging.getLogger("lindorm").setLevel(logging.WARN) ROUTING_FIELD = "routing_field" @@ -134,7 +135,8 @@ class LindormVectorStore(BaseVector): self._client.delete(index=self._collection_name, id=id, params=params) self.refresh() else: - logger.warning(f"DELETE BY ID: ID {id} does not exist in the index.") + logger.warning( + f"DELETE BY ID: ID {id} does not exist in the index.") def delete(self) -> None: if self._using_ugc: @@ -145,7 +147,8 @@ class LindormVectorStore(BaseVector): self.refresh() else: if self._client.indices.exists(index=self._collection_name): - self._client.indices.delete(index=self._collection_name, params={"timeout": 60}) + self._client.indices.delete( + index=self._collection_name, params={"timeout": 60}) logger.info("Delete index success") else: logger.warning(f"Index '{self._collection_name}' does not exist. No deletion performed.") @@ -168,7 +171,8 @@ class LindormVectorStore(BaseVector): raise ValueError("All elements in query_vector should be floats") top_k = kwargs.get("top_k", 10) - query = default_vector_search_query(query_vector=query_vector, k=top_k, **kwargs) + query = default_vector_search_query( + query_vector=query_vector, k=top_k, **kwargs) try: params = {} if self._using_ugc: @@ -220,7 +224,8 @@ class LindormVectorStore(BaseVector): routing=routing, routing_field=self._routing_field, ) - response = self._client.search(index=self._collection_name, body=full_text_query) + response = self._client.search( + index=self._collection_name, body=full_text_query) docs = [] for hit in response["hits"]["hits"]: docs.append( @@ -238,7 +243,8 @@ class LindormVectorStore(BaseVector): with redis_client.lock(lock_name, timeout=20): collection_exist_cache_key = f"vector_indexing_{self._collection_name}" if redis_client.get(collection_exist_cache_key): - logger.info(f"Collection {self._collection_name} already exists.") + logger.info( + f"Collection {self._collection_name} already exists.") return if self._client.indices.exists(index=self._collection_name): logger.info(f"{self._collection_name.lower()} already exists.") @@ -258,10 +264,13 @@ class LindormVectorStore(BaseVector): hnsw_ef_construction = kwargs.pop("hnsw_ef_construction", 500) ivfpq_m = kwargs.pop("ivfpq_m", dimension) nlist = kwargs.pop("nlist", 1000) - centroids_use_hnsw = kwargs.pop("centroids_use_hnsw", True if nlist >= 5000 else False) + centroids_use_hnsw = kwargs.pop( + "centroids_use_hnsw", True if nlist >= 5000 else False) centroids_hnsw_m = kwargs.pop("centroids_hnsw_m", 24) - centroids_hnsw_ef_construct = kwargs.pop("centroids_hnsw_ef_construct", 500) - centroids_hnsw_ef_search = kwargs.pop("centroids_hnsw_ef_search", 100) + centroids_hnsw_ef_construct = kwargs.pop( + "centroids_hnsw_ef_construct", 500) + centroids_hnsw_ef_search = kwargs.pop( + "centroids_hnsw_ef_search", 100) mapping = default_text_mapping( dimension, method_name, @@ -281,7 +290,8 @@ class LindormVectorStore(BaseVector): using_ugc=self._using_ugc, **kwargs, ) - self._client.indices.create(index=self._collection_name.lower(), body=mapping) + self._client.indices.create( + index=self._collection_name.lower(), body=mapping) redis_client.set(collection_exist_cache_key, 1, ex=3600) # logger.info(f"create index success: {self._collection_name}") @@ -347,7 +357,8 @@ def default_text_mapping(dimension: int, method_name: str, **kwargs: Any) -> dic } if excludes_from_source: - mapping["mappings"]["_source"] = {"excludes": excludes_from_source} # e.g. {"excludes": ["vector_field"]} + # e.g. {"excludes": ["vector_field"]} + mapping["mappings"]["_source"] = {"excludes": excludes_from_source} if using_ugc and method_name == "ivfpq": mapping["settings"]["index"]["knn_routing"] = True @@ -385,7 +396,8 @@ def default_text_search_query( # build complex search_query when either of must/must_not/should/filter is specified if must: if not isinstance(must, list): - raise RuntimeError(f"unexpected [must] clause with {type(filters)}") + raise RuntimeError( + f"unexpected [must] clause with {type(filters)}") if query_clause not in must: must.append(query_clause) else: @@ -395,19 +407,22 @@ def default_text_search_query( if must_not: if not isinstance(must_not, list): - raise RuntimeError(f"unexpected [must_not] clause with {type(filters)}") + raise RuntimeError( + f"unexpected [must_not] clause with {type(filters)}") boolean_query["must_not"] = must_not if should: if not isinstance(should, list): - raise RuntimeError(f"unexpected [should] clause with {type(filters)}") + raise RuntimeError( + f"unexpected [should] clause with {type(filters)}") boolean_query["should"] = should if minimum_should_match != 0: boolean_query["minimum_should_match"] = minimum_should_match if filters: if not isinstance(filters, list): - raise RuntimeError(f"unexpected [filter] clause with {type(filters)}") + raise RuntimeError( + f"unexpected [filter] clause with {type(filters)}") boolean_query["filter"] = filters search_query = {"size": k, "query": {"bool": boolean_query}} diff --git a/api/core/rag/extractor/word_extractor.py b/api/core/rag/extractor/word_extractor.py index d93de5fef9..08adad3dd0 100644 --- a/api/core/rag/extractor/word_extractor.py +++ b/api/core/rag/extractor/word_extractor.py @@ -50,7 +50,7 @@ class WordExtractor(BaseExtractor): self.web_path = self.file_path # TODO: use a better way to handle the file - self.temp_file = tempfile.NamedTemporaryFile() # noqa: SIM115 + self.temp_file = tempfile.NamedTemporaryFile() self.temp_file.write(r.content) self.file_path = self.temp_file.name elif not os.path.isfile(self.file_path): diff --git a/api/core/workflow/nodes/question_classifier/question_classifier_node.py b/api/core/workflow/nodes/question_classifier/question_classifier_node.py index 0ec44eefac..9aa43f58d5 100644 --- a/api/core/workflow/nodes/question_classifier/question_classifier_node.py +++ b/api/core/workflow/nodes/question_classifier/question_classifier_node.py @@ -44,11 +44,13 @@ class QuestionClassifierNode(LLMNode): variable_pool = self.graph_runtime_state.variable_pool # extract variables - variable = variable_pool.get(node_data.query_variable_selector) if node_data.query_variable_selector else None + variable = variable_pool.get( + node_data.query_variable_selector) if node_data.query_variable_selector else None query = variable.value if variable else None variables = {"query": query} # fetch model config - model_instance, model_config = self._fetch_model_config(node_data.model) + model_instance, model_config = self._fetch_model_config( + node_data.model) # fetch memory memory = self._fetch_memory( node_data_memory=node_data.memory, @@ -56,7 +58,8 @@ class QuestionClassifierNode(LLMNode): ) # fetch instruction node_data.instruction = node_data.instruction or "" - node_data.instruction = variable_pool.convert_template(node_data.instruction).text + node_data.instruction = variable_pool.convert_template( + node_data.instruction).text files = ( self._fetch_files( @@ -178,12 +181,15 @@ class QuestionClassifierNode(LLMNode): variable_mapping = {"query": node_data.query_variable_selector} variable_selectors = [] if node_data.instruction: - variable_template_parser = VariableTemplateParser(template=node_data.instruction) - variable_selectors.extend(variable_template_parser.extract_variable_selectors()) + variable_template_parser = VariableTemplateParser( + template=node_data.instruction) + variable_selectors.extend( + variable_template_parser.extract_variable_selectors()) for variable_selector in variable_selectors: variable_mapping[variable_selector.variable] = variable_selector.value_selector - variable_mapping = {node_id + "." + key: value for key, value in variable_mapping.items()} + variable_mapping = {node_id + "." + key: value for key, + value in variable_mapping.items()} return variable_mapping @@ -204,7 +210,8 @@ class QuestionClassifierNode(LLMNode): context: Optional[str], ) -> int: prompt_transform = AdvancedPromptTransform(with_variable_tmpl=True) - prompt_template = self._get_prompt_template(node_data, query, None, 2000) + prompt_template = self._get_prompt_template( + node_data, query, None, 2000) prompt_messages = prompt_transform.get_prompt( prompt_template=prompt_template, inputs={}, @@ -217,13 +224,15 @@ class QuestionClassifierNode(LLMNode): ) rest_tokens = 2000 - model_context_tokens = model_config.model_schema.model_properties.get(ModelPropertyKey.CONTEXT_SIZE) + model_context_tokens = model_config.model_schema.model_properties.get( + ModelPropertyKey.CONTEXT_SIZE) if model_context_tokens: model_instance = ModelInstance( provider_model_bundle=model_config.provider_model_bundle, model=model_config.model ) - curr_message_tokens = model_instance.get_llm_num_tokens(prompt_messages) + curr_message_tokens = model_instance.get_llm_num_tokens( + prompt_messages) max_tokens = 0 for parameter_rule in model_config.model_schema.parameter_rules: @@ -264,7 +273,8 @@ class QuestionClassifierNode(LLMNode): prompt_messages: list[LLMNodeChatModelMessage] = [] if model_mode == ModelMode.CHAT: system_prompt_messages = LLMNodeChatModelMessage( - role=PromptMessageRole.SYSTEM, text=QUESTION_CLASSIFIER_SYSTEM_PROMPT.format(histories=memory_str) + role=PromptMessageRole.SYSTEM, text=QUESTION_CLASSIFIER_SYSTEM_PROMPT.format( + histories=memory_str) ) prompt_messages.append(system_prompt_messages) user_prompt_message_1 = LLMNodeChatModelMessage( @@ -305,4 +315,5 @@ class QuestionClassifierNode(LLMNode): ) else: - raise InvalidModelTypeError(f"Model mode {model_mode} not support.") + raise InvalidModelTypeError( + f"Model mode {model_mode} not support.") diff --git a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py index 58b910e17b..285384ee6e 100644 --- a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py +++ b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py @@ -68,7 +68,8 @@ def test_executor_with_json_body_and_object_variable(): system_variables={}, user_inputs={}, ) - variable_pool.add(["pre_node_id", "object"], {"name": "John Doe", "age": 30, "email": "john@example.com"}) + variable_pool.add(["pre_node_id", "object"], { + "name": "John Doe", "age": 30, "email": "john@example.com"}) # Prepare the node data node_data = HttpRequestNodeData( @@ -123,7 +124,8 @@ def test_executor_with_json_body_and_nested_object_variable(): system_variables={}, user_inputs={}, ) - variable_pool.add(["pre_node_id", "object"], {"name": "John Doe", "age": 30, "email": "john@example.com"}) + variable_pool.add(["pre_node_id", "object"], { + "name": "John Doe", "age": 30, "email": "john@example.com"}) # Prepare the node data node_data = HttpRequestNodeData( diff --git a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py index 97bacada74..1375d835d3 100644 --- a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py @@ -18,6 +18,14 @@ from models.enums import UserFrom from models.workflow import WorkflowNodeExecutionStatus, WorkflowType +def test_plain_text_to_dict(): + assert _plain_text_to_dict("aa\n cc:") == {"aa": "", "cc": ""} + assert _plain_text_to_dict("aa:bb\n cc:dd") == {"aa": "bb", "cc": "dd"} + assert _plain_text_to_dict("aa:bb\n cc:dd\n") == {"aa": "bb", "cc": "dd"} + assert _plain_text_to_dict("aa:bb\n\n cc : dd\n\n") == { + "aa": "bb", "cc": "dd"} + + def test_http_request_node_binary_file(monkeypatch): data = HttpRequestNodeData( title="test", @@ -183,7 +191,8 @@ def test_http_request_node_form_with_file(monkeypatch): def attr_checker(*args, **kwargs): assert kwargs["data"] == {"name": "test"} - assert kwargs["files"] == {"file": (None, b"test", "application/octet-stream")} + assert kwargs["files"] == { + "file": (None, b"test", "application/octet-stream")} return httpx.Response(200, content=b"") monkeypatch.setattr( diff --git a/docker/.env.example b/docker/.env.example index f3866a05e9..f85a3d94ee 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -513,7 +513,7 @@ TENCENT_VECTOR_DB_SHARD=1 TENCENT_VECTOR_DB_REPLICAS=2 # ElasticSearch configuration, only available when VECTOR_STORE is `elasticsearch` -ELASTICSEARCH_HOST=elasticsearch +ELASTICSEARCH_HOST=0.0.0.0 ELASTICSEARCH_PORT=9200 ELASTICSEARCH_USERNAME=elastic ELASTICSEARCH_PASSWORD=elastic diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index b1885edf33..0e85452f21 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -451,7 +451,7 @@ services: milvus-standalone: container_name: milvus-standalone - image: milvusdb/milvus:v2.3.1 + image: milvusdb/milvus:v2.5.0-beta profiles: - milvus command: [ 'milvus', 'run', 'standalone' ] @@ -535,20 +535,28 @@ services: container_name: elasticsearch profiles: - elasticsearch + - elasticsearch-ja restart: always volumes: + - ./elasticsearch/docker-entrypoint.sh:/docker-entrypoint-mount.sh - dify_es01_data:/usr/share/elasticsearch/data environment: ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD:-elastic} + VECTOR_STORE: ${VECTOR_STORE:-} cluster.name: dify-es-cluster node.name: dify-es0 discovery.type: single-node - xpack.license.self_generated.type: trial + xpack.license.self_generated.type: basic xpack.security.enabled: 'true' xpack.security.enrollment.enabled: 'false' xpack.security.http.ssl.enabled: 'false' ports: - ${ELASTICSEARCH_PORT:-9200}:9200 + deploy: + resources: + limits: + memory: 2g + entrypoint: [ 'sh', '-c', "sh /docker-entrypoint-mount.sh" ] healthcheck: test: [ 'CMD', 'curl', '-s', 'http://localhost:9200/_cluster/health?pretty' ] interval: 30s diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 20c8117bd1..68d5097e49 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -474,6 +474,8 @@ services: environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} APP_API_URL: ${APP_API_URL:-} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-} + MARKETPLACE_URL: ${MARKETPLACE_URL:-} SENTRY_DSN: ${WEB_SENTRY_DSN:-} NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0} TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000} diff --git a/sdks/nodejs-client/babel.config.json b/sdks/nodejs-client/babel.config.json deleted file mode 100644 index 0639bf7643..0000000000 --- a/sdks/nodejs-client/babel.config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "presets": [ - "@babel/preset-env" - ] -} \ No newline at end of file diff --git a/web/.env.example b/web/.env.example index 2decef02fa..b568bcfcc3 100644 --- a/web/.env.example +++ b/web/.env.example @@ -10,6 +10,10 @@ NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api # console or api domain. # example: http://udify.app/api NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api +# The APIFREX for MARKETPLACE +NEXT_PUBLIC_MARKETPLACE_API_PREFIX=http://localhost:5002/api +# The URL for MARKETPLACE +NEXT_PUBLIC_MARKETPLACE_URL_PREFIX= # SENTRY NEXT_PUBLIC_SENTRY_DSN= @@ -26,5 +30,7 @@ NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS=60000 # CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP NEXT_PUBLIC_CSP_WHITELIST= +# Github Access Token, used for invoking Github API +NEXT_PUBLIC_GITHUB_ACCESS_TOKEN= # The maximum number of top-k value for RAG. NEXT_PUBLIC_TOP_K_MAX_VALUE=10 diff --git a/web/.eslintignore b/web/.eslintignore deleted file mode 100644 index 8a8bc38d80..0000000000 --- a/web/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -/**/node_modules/* -node_modules/ - -dist/ -build/ -out/ -.next/ \ No newline at end of file diff --git a/web/.eslintrc.json b/web/.eslintrc.json deleted file mode 100644 index 18b6bc6016..0000000000 --- a/web/.eslintrc.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "extends": [ - "next", - "@antfu", - "plugin:storybook/recommended" - ], - "rules": { - "@typescript-eslint/consistent-type-definitions": [ - "error", - "type" - ], - "@typescript-eslint/no-var-requires": "off", - "no-console": "off", - "indent": "off", - "@typescript-eslint/indent": [ - "error", - 2, - { - "SwitchCase": 1, - "flatTernaryExpressions": false, - "ignoredNodes": [ - "PropertyDefinition[decorators]", - "TSUnionType", - "FunctionExpression[params]:has(Identifier[decorators])" - ] - } - ], - "react-hooks/exhaustive-deps": "warn", - "react/display-name": "warn" - } -} diff --git a/web/.gitignore b/web/.gitignore index cb8fbe77ac..048c5f6485 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -44,12 +44,11 @@ package-lock.json .pnp.cjs .pnp.loader.mjs .yarn/ -.yarnrc.yml - -# pmpm -pnpm-lock.yaml .favorites.json + +# storybook +/storybook-static *storybook.log # mise diff --git a/web/.husky/pre-commit b/web/.husky/pre-commit index d9290e1853..cca8abe27a 100755 --- a/web/.husky/pre-commit +++ b/web/.husky/pre-commit @@ -1,6 +1,3 @@ -#!/usr/bin/env bash -. "$(dirname -- "$0")/_/husky.sh" - # get the list of modified files files=$(git diff --cached --name-only) @@ -50,7 +47,7 @@ fi if $web_modified; then echo "Running ESLint on web module" cd ./web || exit 1 - npx lint-staged + lint-staged echo "Running unit tests check" modified_files=$(git diff --cached --name-only -- utils | grep -v '\.spec\.ts$' || true) @@ -63,7 +60,7 @@ if $web_modified; then # check if the test file exists if [ -f "../$test_file" ]; then echo "Detected changes in $file, running corresponding unit tests..." - npm run test "../$test_file" + pnpm run test "../$test_file" if [ $? -ne 0 ]; then echo "Unit tests failed. Please fix the errors before committing." diff --git a/web/.storybook/main.ts b/web/.storybook/main.ts index 74e95821de..fecf774e98 100644 --- a/web/.storybook/main.ts +++ b/web/.storybook/main.ts @@ -1,19 +1,19 @@ import type { StorybookConfig } from '@storybook/nextjs' const config: StorybookConfig = { - // stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - stories: ['../app/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - '@storybook/addon-onboarding', - '@storybook/addon-links', - '@storybook/addon-essentials', - '@chromatic-com/storybook', - '@storybook/addon-interactions', - ], - framework: { - name: '@storybook/nextjs', - options: {}, - }, - staticDirs: ['../public'], + // stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + stories: ['../app/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/nextjs', + options: {}, + }, + staticDirs: ['../public'], } export default config diff --git a/web/.storybook/preview.tsx b/web/.storybook/preview.tsx index 49cd24e974..55328602f9 100644 --- a/web/.storybook/preview.tsx +++ b/web/.storybook/preview.tsx @@ -1,6 +1,6 @@ import React from 'react' import type { Preview } from '@storybook/react' -import { withThemeByDataAttribute } from '@storybook/addon-themes'; +import { withThemeByDataAttribute } from '@storybook/addon-themes' import I18nServer from '../app/components/i18n-server' import '../app/styles/globals.css' @@ -8,30 +8,30 @@ import '../app/styles/markdown.scss' import './storybook.css' export const decorators = [ - withThemeByDataAttribute({ - themes: { - light: 'light', - dark: 'dark', - }, - defaultTheme: 'light', - attributeName: 'data-theme', - }), - Story => { - return - - - } - ]; + withThemeByDataAttribute({ + themes: { + light: 'light', + dark: 'dark', + }, + defaultTheme: 'light', + attributeName: 'data-theme', + }), + (Story) => { + return + + + }, +] const preview: Preview = { parameters: { - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/i, - }, - }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, }, + }, } export default preview diff --git a/web/.vscode/settings.example.json b/web/.vscode/settings.example.json index a2dfe7c669..ce5c9d6b01 100644 --- a/web/.vscode/settings.example.json +++ b/web/.vscode/settings.example.json @@ -21,5 +21,6 @@ "editor.defaultFormatter": "vscode.json-language-features" }, "typescript.tsdk": "node_modules/typescript/lib", - "typescript.enablePromptUseWorkspaceTsdk": true + "typescript.enablePromptUseWorkspaceTsdk": true, + "npm.packageManager": "pnpm" } diff --git a/web/Dockerfile b/web/Dockerfile index 6118adbca4..387075b8ac 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -6,6 +6,9 @@ LABEL maintainer="takatost@gmail.com" # RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories RUN apk add --no-cache tzdata +RUN npm install -g pnpm@9.12.2 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" # install packages @@ -14,12 +17,12 @@ FROM base AS packages WORKDIR /app/web COPY package.json . -COPY yarn.lock . +COPY pnpm-lock.yaml . # if you located in China, you can use taobao registry to speed up -# RUN yarn install --frozen-lockfile --registry https://registry.npmmirror.com/ +# RUN pnpm install --frozen-lockfile --registry https://registry.npmmirror.com/ -RUN yarn install --frozen-lockfile +RUN pnpm install --frozen-lockfile # build resources FROM base AS builder @@ -27,7 +30,8 @@ WORKDIR /app/web COPY --from=packages /app/web/ . COPY . . -RUN yarn build +ENV NODE_OPTIONS="--max-old-space-size=4096" +RUN pnpm build # production stage @@ -38,6 +42,8 @@ ENV EDITION=SELF_HOSTED ENV DEPLOY_ENV=PRODUCTION ENV CONSOLE_API_URL=http://127.0.0.1:5001 ENV APP_API_URL=http://127.0.0.1:5001 +ENV MARKETPLACE_API_URL=http://127.0.0.1:5001 +ENV MARKETPLACE_URL=http://127.0.0.1:5001 ENV PORT=3000 ENV NEXT_TELEMETRY_DISABLED=1 @@ -57,8 +63,7 @@ COPY docker/entrypoint.sh ./entrypoint.sh # global runtime packages -RUN yarn global add pm2 \ - && yarn cache clean \ +RUN pnpm add -g pm2 \ && mkdir /.pm2 \ && chown -R 1001:0 /.pm2 /app/web \ && chmod -R g=u /.pm2 /app/web diff --git a/web/README.md b/web/README.md index ce5239e57f..ddba8ed28a 100644 --- a/web/README.md +++ b/web/README.md @@ -6,14 +6,12 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next ### Run by source code -To start the web frontend service, you will need [Node.js v18.x (LTS)](https://nodejs.org/en) and [NPM version 8.x.x](https://www.npmjs.com/) or [Yarn](https://yarnpkg.com/). +To start the web frontend service, you will need [Node.js v18.x (LTS)](https://nodejs.org/en) and [pnpm version 9.12.2](https://pnpm.io). First, install the dependencies: ```bash -npm install -# or -yarn install --frozen-lockfile +pnpm install ``` Then, configure the environment variables. Create a file named `.env.local` in the current directory and copy the contents from `.env.example`. Modify the values of these environment variables according to your requirements: @@ -43,9 +41,7 @@ NEXT_PUBLIC_SENTRY_DSN= Finally, run the development server: ```bash -npm run dev -# or -yarn dev +pnpm run dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. @@ -59,19 +55,19 @@ You can start editing the file under folder `app`. The page auto-updates as you First, build the app for production: ```bash -npm run build +pnpm run build ``` Then, start the server: ```bash -npm run start +pnpm run start ``` If you want to customize the host and port: ```bash -npm run start --port=3001 --host=0.0.0.0 +pnpm run start --port=3001 --host=0.0.0.0 ``` ## Storybook @@ -81,7 +77,7 @@ This project uses [Storybook](https://storybook.js.org/) for UI component develo To start the storybook server, run: ```bash -yarn storybook +pnpm storybook ``` Open [http://localhost:6006](http://localhost:6006) with your browser to see the result. @@ -99,7 +95,7 @@ You can create a test file with a suffix of `.spec` beside the file that to be t Run test: ```bash -npm run test +pnpm run test ``` If you are not familiar with writing tests, here is some code to refer to: diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/annotations/page.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/annotations/page.tsx index 0af2e945f3..7beb1d76bb 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/annotations/page.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/annotations/page.tsx @@ -2,7 +2,7 @@ import React from 'react' import Main from '@/app/components/app/log-annotation' import { PageType } from '@/app/components/base/features/new-feature-panel/annotation-reply/type' -export type IProps = { +export interface IProps { params: { appId: string } } diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/develop/page.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/develop/page.tsx index 4101120703..a4ee3922d9 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/develop/page.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/develop/page.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { type Locale } from '@/i18n' +import type { Locale } from '@/i18n' import DevelopMain from '@/app/components/develop' export type IDevelopProps = { diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/chartView.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/chartView.tsx index bb1e4fd95b..00f1190045 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/chartView.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/chartView.tsx @@ -46,7 +46,7 @@ export default function ChartView({ appId }: IChartViewProps) { return (
-
+
{t('appOverview.analysis.title')} ({ value: k, name: t(`appLog.filter.period.${v.name}`) }))} diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/page.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/page.tsx index 137c2c36ee..47dd36eb81 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/page.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/page.tsx @@ -12,7 +12,7 @@ const Overview = async ({ params: { appId }, }: IDevelopProps) => { return ( -
+
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx index 977e3f057c..ca6fa3a904 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx @@ -1,20 +1,18 @@ 'use client' import type { FC } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react' -import { useTranslation } from 'react-i18next' +import { + RiEqualizer2Line, +} from '@remixicon/react' import type { PopupProps } from './config-popup' import ConfigPopup from './config-popup' import cn from '@/utils/classnames' -import Button from '@/app/components/base/button' -import { Settings04 } from '@/app/components/base/icons/src/vender/line/general' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' -const I18N_PREFIX = 'app.tracing' - type Props = { readOnly: boolean className?: string @@ -28,7 +26,6 @@ const ConfigBtn: FC = ({ controlShowPopup, ...popupProps }) => { - const { t } = useTranslation() const [open, doSetOpen] = useState(false) const openRef = useRef(open) const setOpen = useCallback((v: boolean) => { @@ -50,21 +47,6 @@ const ConfigBtn: FC = ({ if (popupProps.readOnly && !hasConfigured) return null - const triggerContent = hasConfigured - ? ( -
- -
- ) - : ( - - ) - return ( = ({ placement='bottom-end' offset={{ mainAxis: 12, - crossAxis: hasConfigured ? 8 : 0, + crossAxis: hasConfigured ? 8 : 49, }} > - {triggerContent} +
+ +
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx index 8e3d8f9ec6..571b4fd3a6 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx @@ -11,6 +11,8 @@ import ProviderConfigModal from './provider-config-modal' import Indicator from '@/app/components/header/indicator' import Switch from '@/app/components/base/switch' import Tooltip from '@/app/components/base/tooltip' +import Divider from '@/app/components/base/divider' +import cn from '@/utils/classnames' const I18N_PREFIX = 'app.tracing' @@ -77,7 +79,6 @@ const ConfigPopup: FC = ({ className='ml-3' defaultValue={enabled} onChange={onStatusChange} - size='l' disabled={providerAllNotConfigured} /> ) @@ -106,15 +107,15 @@ const ConfigPopup: FC = ({ ) return ( -
+
-
{t(`${I18N_PREFIX}.tracing`)}
+
{t(`${I18N_PREFIX}.tracing`)}
-
+
{t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)}
{!readOnly && ( @@ -130,19 +131,18 @@ const ConfigPopup: FC = ({ : switchContent} )} -
-
+
{t(`${I18N_PREFIX}.tracingDescription`)}
-
-
+ +
{(providerAllConfigured || providerAllNotConfigured) ? ( <> -
{t(`${I18N_PREFIX}.configProviderTitle.${providerAllConfigured ? 'configured' : 'notConfigured'}`)}
+
{t(`${I18N_PREFIX}.configProviderTitle.${providerAllConfigured ? 'configured' : 'notConfigured'}`)}
{langSmithPanel} {langfusePanel} @@ -151,11 +151,11 @@ const ConfigPopup: FC = ({ ) : ( <> -
{t(`${I18N_PREFIX}.configProviderTitle.configured`)}
+
{t(`${I18N_PREFIX}.configProviderTitle.configured`)}
{langSmithConfig ? langSmithPanel : langfusePanel}
-
{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`)}
+
{t(`${I18N_PREFIX}.configProviderTitle.moreProvider`)}
{!langSmithConfig ? langSmithPanel : langfusePanel}
diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/field.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/field.tsx index 87c84948be..84c48a6dde 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/field.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/field.tsx @@ -26,7 +26,7 @@ const Field: FC = ({ return (
-
{label}
+
{label}
{isRequired && *}
+
{t('common.appMenus.overview')}
) @@ -135,43 +139,68 @@ const Panel: FC = () => { return (
- <div className='flex items-center p-2 rounded-xl border-[0.5px] border-gray-200 shadow-xs cursor-pointer hover:bg-gray-100' onClick={showPopup}> - {!inUseTracingProvider - ? <> - <TracingIcon size='md' className='mr-2' /> - <div className='leading-5 text-sm font-semibold text-gray-700'>{t(`${I18N_PREFIX}.title`)}</div> - </> - : <InUseProviderIcon className='ml-1 h-4' />} - - {hasConfiguredTracing && ( - <div className='ml-4 mr-1 flex items-center'> - <Indicator color={enabled ? 'green' : 'gray'} /> - <div className='ml-1.5 text-xs font-semibold text-gray-500 uppercase'> - {t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)} + <div + className={cn( + 'flex items-center p-2 rounded-xl bg-background-default-dodge border-t border-l-[0.5px] border-effects-highlight shadow-xs cursor-pointer hover:bg-background-default-lighter hover:border-effects-highlight-lightmode-off', + controlShowPopup && 'bg-background-default-lighter border-effects-highlight-lightmode-off', + )} + onClick={showPopup} + > + {!inUseTracingProvider && ( + <> + <TracingIcon size='md' /> + <div className='mx-2 system-sm-semibold text-text-secondary'>{t(`${I18N_PREFIX}.title`)}</div> + <div className='flex items-center' onClick={e => e.stopPropagation()}> + <ConfigButton + appId={appId} + readOnly={readOnly} + hasConfigured={false} + enabled={enabled} + onStatusChange={handleTracingEnabledChange} + chosenProvider={inUseTracingProvider} + onChooseProvider={handleChooseProvider} + langSmithConfig={langSmithConfig} + langFuseConfig={langFuseConfig} + onConfigUpdated={handleTracingConfigUpdated} + onConfigRemoved={handleTracingConfigRemoved} + controlShowPopup={controlShowPopup} + /> </div> - </div> + <Divider type='vertical' className='h-3.5' /> + <div className='p-1 rounded-md'> + <RiArrowDownDoubleLine className='w-4 h-4 text-text-tertiary' /> + </div> + </> )} - {hasConfiguredTracing && ( - <div className='ml-2 w-px h-3.5 bg-gray-200'></div> + <> + <div className='ml-4 mr-1 flex items-center'> + <Indicator color={enabled ? 'green' : 'gray'} /> + <div className='ml-1.5 system-xs-semibold-uppercase text-text-tertiary'> + {t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)} + </div> + </div> + <InUseProviderIcon className='ml-1 h-4' /> + <Divider type='vertical' className='h-3.5' /> + <div className='flex items-center' onClick={e => e.stopPropagation()}> + <ConfigButton + appId={appId} + readOnly={readOnly} + hasConfigured + className='ml-2' + enabled={enabled} + onStatusChange={handleTracingEnabledChange} + chosenProvider={inUseTracingProvider} + onChooseProvider={handleChooseProvider} + langSmithConfig={langSmithConfig} + langFuseConfig={langFuseConfig} + onConfigUpdated={handleTracingConfigUpdated} + onConfigRemoved={handleTracingConfigRemoved} + controlShowPopup={controlShowPopup} + /> + </div> + </> )} - <div className='flex items-center' onClick={e => e.stopPropagation()}> - <ConfigButton - appId={appId} - readOnly={readOnly} - hasConfigured - className='ml-2' - enabled={enabled} - onStatusChange={handleTracingEnabledChange} - chosenProvider={inUseTracingProvider} - onChooseProvider={handleChooseProvider} - langSmithConfig={langSmithConfig} - langFuseConfig={langFuseConfig} - onConfigUpdated={handleTracingConfigUpdated} - onConfigRemoved={handleTracingConfigRemoved} - controlShowPopup={controlShowPopup} - /> - </div> </div> </div> ) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx index e7ecd2f4ce..5de6ef4a44 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx @@ -17,6 +17,7 @@ import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/gene import Confirm from '@/app/components/base/confirm' import { addTracingConfig, removeTracingConfig, updateTracingConfig } from '@/service/apps' import Toast from '@/app/components/base/toast' +import Divider from '@/app/components/base/divider' type Props = { appId: string @@ -152,11 +153,11 @@ const ProviderConfigModal: FC<Props> = ({ ? ( <PortalToFollowElem open> <PortalToFollowElemContent className='w-full h-full z-[60]'> - <div className='fixed inset-0 flex items-center justify-center bg-black/[.25]'> - <div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-white shadow-xl rounded-2xl overflow-y-auto'> + <div className='fixed inset-0 flex items-center justify-center bg-background-overlay'> + <div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-components-panel-bg shadow-xl rounded-2xl overflow-y-auto'> <div className='px-8 pt-8'> <div className='flex justify-between items-center mb-4'> - <div className='text-xl font-semibold text-gray-900'>{t(`${I18N_PREFIX}.title`)}{t(`app.tracing.${type}.title`)}</div> + <div className='title-2xl-semibold text-text-primary'>{t(`${I18N_PREFIX}.title`)}{t(`app.tracing.${type}.title`)}</div> </div> <div className='space-y-4'> @@ -230,16 +231,16 @@ const ProviderConfigModal: FC<Props> = ({ {isEdit && ( <> <Button - className='h-9 text-sm font-medium text-gray-700' + className='h-9 text-sm font-medium text-text-secondary' onClick={showRemoveConfirm} > <span className='text-[#D92D20]'>{t('common.operation.remove')}</span> </Button> - <div className='mx-3 w-px h-[18px] bg-gray-200'></div> + <Divider className='mx-3 h-[18px]'/> </> )} <Button - className='mr-2 h-9 text-sm font-medium text-gray-700' + className='mr-2 h-9 text-sm font-medium text-text-secondary' onClick={onCancel} > {t('common.operation.cancel')} @@ -256,9 +257,9 @@ const ProviderConfigModal: FC<Props> = ({ </div> </div> - <div className='border-t-[0.5px] border-t-black/5'> - <div className='flex justify-center items-center py-3 bg-gray-50 text-xs text-gray-500'> - <Lock01 className='mr-1 w-3 h-3 text-gray-500' /> + <div className='border-t-[0.5px] border-divider-regular'> + <div className='flex justify-center items-center py-3 bg-background-section-burn text-xs text-text-tertiary'> + <Lock01 className='mr-1 w-3 h-3 text-text-tertiary' /> {t('common.modelProvider.encrypted.front')} <a className='text-primary-600 mx-1' diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx index 6e5046ecf8..9c2dd6be11 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx @@ -1,11 +1,13 @@ 'use client' import type { FC } from 'react' import React, { useCallback } from 'react' +import { + RiEqualizer2Line, +} from '@remixicon/react' import { useTranslation } from 'react-i18next' import { TracingProvider } from './type' import cn from '@/utils/classnames' import { LangfuseIconBig, LangsmithIconBig } from '@/app/components/base/icons/src/public/tracing' -import { Settings04 } from '@/app/components/base/icons/src/vender/line/general' import { Eye as View } from '@/app/components/base/icons/src/vender/solid/general' const I18N_PREFIX = 'app.tracing' @@ -61,34 +63,37 @@ const ProviderPanel: FC<Props> = ({ }, [hasConfigured, isChosen, onChoose, readOnly]) return ( <div - className={cn(isChosen ? 'border-primary-400' : 'border-transparent', !isChosen && hasConfigured && !readOnly && 'cursor-pointer', 'px-4 py-3 rounded-xl border-[1.5px] bg-gray-100')} + className={cn( + 'px-4 py-3 rounded-xl border-[1.5px] bg-background-section-burn', + isChosen ? 'bg-background-section border-components-option-card-option-selected-border' : 'border-transparent', + !isChosen && hasConfigured && !readOnly && 'cursor-pointer', + )} onClick={handleChosen} > <div className={'flex justify-between items-center space-x-1'}> <div className='flex items-center'> <Icon className='h-6' /> - {isChosen && <div className='ml-1 flex items-center h-4 px-1 rounded-[4px] border border-primary-500 leading-4 text-xs font-medium text-primary-500 uppercase '>{t(`${I18N_PREFIX}.inUse`)}</div>} + {isChosen && <div className='ml-1 flex items-center h-4 px-1 rounded-[4px] border border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary'>{t(`${I18N_PREFIX}.inUse`)}</div>} </div> {!readOnly && ( <div className={'flex justify-between items-center space-x-1'}> {hasConfigured && ( - <div className='flex px-2 items-center h-6 bg-white rounded-md border-[0.5px] border-gray-200 shadow-xs cursor-pointer text-gray-700 space-x-1' onClick={viewBtnClick} > + <div className='flex px-2 items-center h-6 bg-components-button-secondary-bg rounded-md border-[0.5px] border-components-button-secondary-border shadow-xs cursor-pointer text-text-secondary space-x-1' onClick={viewBtnClick} > <View className='w-3 h-3'/> <div className='text-xs font-medium'>{t(`${I18N_PREFIX}.view`)}</div> </div> )} <div - className='flex px-2 items-center h-6 bg-white rounded-md border-[0.5px] border-gray-200 shadow-xs cursor-pointer text-gray-700 space-x-1' + className='flex px-2 items-center h-6 bg-components-button-secondary-bg rounded-md border-[0.5px] border-components-button-secondary-border shadow-xs cursor-pointer text-text-secondary space-x-1' onClick={handleConfigBtnClick} > - <Settings04 className='w-3 h-3' /> + <RiEqualizer2Line className='w-3 h-3' /> <div className='text-xs font-medium'>{t(`${I18N_PREFIX}.config`)}</div> </div> </div> )} - </div> - <div className='mt-2 leading-4 text-xs font-normal text-gray-500'> + <div className='mt-2 system-xs-regular text-text-tertiary'> {t(`${I18N_PREFIX}.${type}.description`)} </div> </div> diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx deleted file mode 100644 index 934eb681b9..0000000000 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx +++ /dev/null @@ -1,45 +0,0 @@ -'use client' -import { ChevronDoubleDownIcon } from '@heroicons/react/20/solid' -import type { FC } from 'react' -import { useTranslation } from 'react-i18next' -import React, { useCallback } from 'react' -import Tooltip from '@/app/components/base/tooltip' - -const I18N_PREFIX = 'app.tracing' - -type Props = { - isFold: boolean - onFoldChange: (isFold: boolean) => void -} - -const ToggleFoldBtn: FC<Props> = ({ - isFold, - onFoldChange, -}) => { - const { t } = useTranslation() - - const handleFoldChange = useCallback((e: React.MouseEvent<HTMLDivElement>) => { - e.stopPropagation() - onFoldChange(!isFold) - }, [isFold, onFoldChange]) - return ( - // text-[0px] to hide spacing between tooltip elements - <div className='shrink-0 cursor-pointer text-[0px]' onClick={handleFoldChange}> - <Tooltip - popupContent={t(`${I18N_PREFIX}.${isFold ? 'expand' : 'collapse'}`)} - > - {isFold && ( - <div className='p-1 rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5'> - <ChevronDoubleDownIcon className='w-4 h-4' /> - </div> - )} - {!isFold && ( - <div className='p-2 rounded-lg text-gray-500 border-[0.5px] border-gray-200 hover:text-gray-800 hover:bg-black/5'> - <ChevronDoubleDownIcon className='w-4 h-4 transform rotate-180' /> - </div> - )} - </Tooltip> - </div> - ) -} -export default React.memo(ToggleFoldBtn) diff --git a/web/app/(commonLayout)/datasets/Container.tsx b/web/app/(commonLayout)/datasets/Container.tsx index a0edb1cd61..6e598ab585 100644 --- a/web/app/(commonLayout)/datasets/Container.tsx +++ b/web/app/(commonLayout)/datasets/Container.tsx @@ -26,7 +26,7 @@ import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import { useStore as useTagStore } from '@/app/components/base/tag-management/store' import { useAppContext } from '@/context/app-context' import { useExternalApiPanel } from '@/context/external-api-panel-context' -// eslint-disable-next-line import/order + import { useQuery } from '@tanstack/react-query' import Input from '@/app/components/base/input' diff --git a/web/app/(commonLayout)/plugins/page.tsx b/web/app/(commonLayout)/plugins/page.tsx new file mode 100644 index 0000000000..a3066311b2 --- /dev/null +++ b/web/app/(commonLayout)/plugins/page.tsx @@ -0,0 +1,20 @@ +import PluginPage from '@/app/components/plugins/plugin-page' +import PluginsPanel from '@/app/components/plugins/plugin-page/plugins-panel' +import Marketplace from '@/app/components/plugins/marketplace' +import { getLocaleOnServer } from '@/i18n/server' + +const PluginList = async () => { + const locale = await getLocaleOnServer() + return ( + <PluginPage + plugins={<PluginsPanel />} + marketplace={<Marketplace locale={locale} pluginTypeSwitchClassName='top-[60px]' searchBoxAutoAnimate={false} />} + /> + ) +} + +export const metadata = { + title: 'Plugins - Dify', +} + +export default PluginList diff --git a/web/app/account/avatar.tsx b/web/app/account/avatar.tsx index 8fdecc07bf..298fa65d52 100644 --- a/web/app/account/avatar.tsx +++ b/web/app/account/avatar.tsx @@ -8,7 +8,7 @@ import { logout } from '@/service/common' import { useAppContext } from '@/context/app-context' import { LogOut01 } from '@/app/components/base/icons/src/vender/line/general' -export type IAppSelector = { +export interface IAppSelector { isMobile: boolean } diff --git a/web/app/components/app-sidebar/basic.tsx b/web/app/components/app-sidebar/basic.tsx index 51fc10721e..20777c7b6a 100644 --- a/web/app/components/app-sidebar/basic.tsx +++ b/web/app/components/app-sidebar/basic.tsx @@ -60,18 +60,18 @@ export default function AppBasic({ icon, icon_background, name, isExternal, type return ( <div className="flex items-start p-1"> {icon && icon_background && iconType === 'app' && ( - <div className='flex-shrink-0 mr-3'> + <div className='shrink-0 mr-3'> <AppIcon icon={icon} background={icon_background} /> </div> )} {iconType !== 'app' - && <div className='flex-shrink-0 mr-3'> + && <div className='shrink-0 mr-3'> {ICON_MAP[iconType]} </div> } {mode === 'expand' && <div className="group"> - <div className={`flex flex-row items-center text-sm font-semibold text-gray-700 group-hover:text-gray-900 break-all ${textStyle?.main ?? ''}`}> + <div className={`flex flex-row items-center text-sm font-semibold text-text-secondary group-hover:text-text-primary break-all ${textStyle?.main ?? ''}`}> {name} {hoverTip && <Tooltip @@ -86,7 +86,7 @@ export default function AppBasic({ icon, icon_background, name, isExternal, type /> } </div> - <div className={`text-xs font-normal text-gray-500 group-hover:text-gray-700 break-all ${textStyle?.extra ?? ''}`}>{type}</div> + <div className={`text-xs font-normal text-text-tertiary group-hover:text-text-secondary break-all ${textStyle?.extra ?? ''}`}>{type}</div> <div className='text-text-tertiary system-2xs-medium-uppercase'>{isExternal ? t('dataset.externalTag') : ''}</div> </div>} </div> diff --git a/web/app/components/app/annotation/filter.tsx b/web/app/components/app/annotation/filter.tsx index d741f6de12..2f1cde22e4 100644 --- a/web/app/components/app/annotation/filter.tsx +++ b/web/app/components/app/annotation/filter.tsx @@ -6,11 +6,11 @@ import useSWR from 'swr' import Input from '@/app/components/base/input' import { fetchAnnotationsCount } from '@/service/log' -export type QueryParam = { +export interface QueryParam { keyword?: string } -type IFilterProps = { +interface IFilterProps { appId: string queryParams: QueryParam setQueryParams: (v: QueryParam) => void diff --git a/web/app/components/app/annotation/list.tsx b/web/app/components/app/annotation/list.tsx index 39a495085e..8944c04851 100644 --- a/web/app/components/app/annotation/list.tsx +++ b/web/app/components/app/annotation/list.tsx @@ -9,7 +9,7 @@ import ActionButton from '@/app/components/base/action-button' import useTimestamp from '@/hooks/use-timestamp' import cn from '@/utils/classnames' -type Props = { +interface Props { list: AnnotationItem[] onRemove: (id: string) => void onView: (item: AnnotationItem) => void diff --git a/web/app/components/app/configuration/base/feature-panel/index.tsx b/web/app/components/app/configuration/base/feature-panel/index.tsx index 9c4adbdd2d..dc5fe87ca3 100644 --- a/web/app/components/app/configuration/base/feature-panel/index.tsx +++ b/web/app/components/app/configuration/base/feature-panel/index.tsx @@ -23,7 +23,7 @@ const FeaturePanel: FC<IFeaturePanelProps> = ({ children, }) => { return ( - <div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] bg-background-section-burn pb-3', noBodySpacing && '!pb-0', className)}> + <div className={cn('rounded-xl border-t-[0.5px] border-l-[0.5px] bg-background-section-burn pb-3', noBodySpacing && 'pb-0', className)}> {/* Header */} <div className={cn('px-3 pt-2', hasHeaderBottomBorder && 'border-b border-divider-subtle')}> <div className='flex justify-between items-center h-8'> diff --git a/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx b/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx index 199f9598a4..4604e43514 100644 --- a/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx +++ b/web/app/components/app/configuration/config-prompt/conversation-history/history-panel.tsx @@ -9,7 +9,7 @@ import { MessageClockCircle } from '@/app/components/base/icons/src/vender/solid import I18n from '@/context/i18n' import { LanguagesSupported } from '@/i18n/language' -type Props = { +interface Props { showWarning: boolean onShowEditModal: () => void } diff --git a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx index cf65e3522d..1987013698 100644 --- a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx +++ b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx @@ -9,7 +9,7 @@ import ConfirmAddVar from './confirm-add-var' import s from './style.module.css' import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap' import cn from '@/utils/classnames' -import { type PromptVariable } from '@/models/debug' +import type { PromptVariable } from '@/models/debug' import Tooltip from '@/app/components/base/tooltip' import type { CompletionParams } from '@/types/app' import { AppType } from '@/types/app' diff --git a/web/app/components/app/configuration/config-var/config-modal/field.tsx b/web/app/components/app/configuration/config-var/config-modal/field.tsx index 5052f988d7..2c8c788e5e 100644 --- a/web/app/components/app/configuration/config-var/config-modal/field.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/field.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react' import React from 'react' import cn from '@/utils/classnames' -type Props = { +interface Props { className?: string title: string children: JSX.Element diff --git a/web/app/components/app/configuration/config-var/config-modal/index.tsx b/web/app/components/app/configuration/config-var/config-modal/index.tsx index 85e241a203..0b18cd323e 100644 --- a/web/app/components/app/configuration/config-var/config-modal/index.tsx +++ b/web/app/components/app/configuration/config-var/config-modal/index.tsx @@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config' const TEXT_MAX_LENGTH = 256 -export type IConfigModalProps = { +export interface IConfigModalProps { isCreate?: boolean payload?: InputVar isShow: boolean diff --git a/web/app/components/app/configuration/config-var/config-string/index.tsx b/web/app/components/app/configuration/config-var/config-string/index.tsx index 719ad8ee13..ef3b3d8d4a 100644 --- a/web/app/components/app/configuration/config-var/config-string/index.tsx +++ b/web/app/components/app/configuration/config-var/config-string/index.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react' import React, { useEffect } from 'react' import Input from '@/app/components/base/input' -export type IConfigStringProps = { +export interface IConfigStringProps { value: number | undefined maxLength: number modelId: string @@ -28,7 +28,7 @@ const ConfigString: FC<IConfigStringProps> = ({ min={1} value={value || ''} onChange={(e) => { - let value = parseInt(e.target.value, 10) + let value = Number.parseInt(e.target.value, 10) if (value > maxLength) value = maxLength diff --git a/web/app/components/app/configuration/config-var/index.tsx b/web/app/components/app/configuration/config-var/index.tsx index 67bc37385e..99150899ea 100644 --- a/web/app/components/app/configuration/config-var/index.tsx +++ b/web/app/components/app/configuration/config-var/index.tsx @@ -3,7 +3,6 @@ import type { FC } from 'react' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import { useBoolean } from 'ahooks' -import type { Timeout } from 'ahooks/lib/useRequest/src/types' import { useContext } from 'use-context-selector' import produce from 'immer' import { @@ -34,7 +33,7 @@ import { InputVarType } from '@/app/components/workflow/types' export const ADD_EXTERNAL_DATA_TOOL = 'ADD_EXTERNAL_DATA_TOOL' -type ExternalDataToolParams = { +interface ExternalDataToolParams { key: string type: string index: number @@ -44,13 +43,13 @@ type ExternalDataToolParams = { icon_background?: string } -export type IConfigVarProps = { +export interface IConfigVarProps { promptVariables: PromptVariable[] readonly?: boolean onPromptVariablesChange?: (promptVariables: PromptVariable[]) => void } -let conflictTimer: Timeout +let conflictTimer: number const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVariablesChange }) => { const { t } = useTranslation() @@ -107,7 +106,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar onPromptVariablesChange?.(newPromptVariables) } const updatePromptKey = (index: number, newKey: string) => { - clearTimeout(conflictTimer) + window.clearTimeout(conflictTimer) const { isValid, errorKey, errorMessageKey } = checkKeys([newKey], true) if (!isValid) { Toast.notify({ @@ -127,7 +126,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar return item }) - conflictTimer = setTimeout(() => { + conflictTimer = window.setTimeout(() => { const isKeyExists = promptVariables.some(item => item.key?.trim() === newKey.trim()) if (isKeyExists) { Toast.notify({ diff --git a/web/app/components/app/configuration/config-var/select-type-item/index.tsx b/web/app/components/app/configuration/config-var/select-type-item/index.tsx index b71486b4eb..cf91b89cb1 100644 --- a/web/app/components/app/configuration/config-var/select-type-item/index.tsx +++ b/web/app/components/app/configuration/config-var/select-type-item/index.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next' import cn from '@/utils/classnames' import type { InputVarType } from '@/app/components/workflow/types' import InputVarTypeIcon from '@/app/components/workflow/nodes/_base/components/input-var-type-icon' -export type ISelectTypeItemProps = { +export interface ISelectTypeItemProps { type: InputVarType selected: boolean onClick: () => void diff --git a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx index 52e5d5d906..9beb50eeba 100644 --- a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx +++ b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx @@ -1,21 +1,25 @@ 'use client' import type { FC } from 'react' -import React, { useState } from 'react' +import React, { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' +import copy from 'copy-to-clipboard' import produce from 'immer' import { RiDeleteBinLine, + RiEqualizer2Line, RiHammerFill, + RiInformation2Line, } from '@remixicon/react' import { useFormattingChangedDispatcher } from '../../../debug/hooks' import SettingBuiltInTool from './setting-built-in-tool' -import cn from '@/utils/classnames' import Panel from '@/app/components/app/configuration/base/feature-panel' -import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general' import OperationBtn from '@/app/components/app/configuration/base/operation-btn' import AppIcon from '@/app/components/base/app-icon' +import Button from '@/app/components/base/button' +import Indicator from '@/app/components/header/indicator' import Switch from '@/app/components/base/switch' +import Toast from '@/app/components/base/toast' import ConfigContext from '@/context/debug-configuration' import type { AgentTool } from '@/types/app' import { type Collection, CollectionType } from '@/app/components/tools/types' @@ -23,7 +27,12 @@ import { MAX_TOOLS_NUM } from '@/config' import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' import Tooltip from '@/app/components/base/tooltip' import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other' -import AddToolModal from '@/app/components/tools/add-tool-modal' +// import AddToolModal from '@/app/components/tools/add-tool-modal' +import ConfigCredential from '@/app/components/tools/setting/build-in/config-credentials' +import { updateBuiltInToolCredential } from '@/service/tools' +import cn from '@/utils/classnames' +import ToolPicker from '@/app/components/workflow/block-selector/tool-picker' +import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types' type AgentToolWithMoreInfo = AgentTool & { icon: any; collection?: Collection } | null const AgentTools: FC = () => { @@ -33,9 +42,19 @@ const AgentTools: FC = () => { const formattingChangedDispatcher = useFormattingChangedDispatcher() const [currentTool, setCurrentTool] = useState<AgentToolWithMoreInfo>(null) + const currentCollection = useMemo(() => { + if (!currentTool) return null + const collection = collectionList.find(collection => collection.id.split('/').pop() === currentTool?.provider_id.split('/').pop() && collection.type === currentTool?.provider_type) + return collection + }, [currentTool, collectionList]) const [isShowSettingTool, setIsShowSettingTool] = useState(false) + const [isShowSettingAuth, setShowSettingAuth] = useState(false) const tools = (modelConfig?.agentConfig?.tools as AgentTool[] || []).map((item) => { - const collection = collectionList.find(collection => collection.id === item.provider_id && collection.type === item.provider_type) + const collection = collectionList.find( + collection => + collection.id.split('/').pop() === item.provider_id.split('/').pop() + && collection.type === item.provider_type, + ) const icon = collection?.icon return { ...item, @@ -55,10 +74,39 @@ const AgentTools: FC = () => { formattingChangedDispatcher() } + const handleToolAuthSetting = (value: any) => { + const newModelConfig = produce(modelConfig, (draft) => { + const tool = (draft.agentConfig.tools).find((item: any) => item.provider_id === value?.collection?.id && item.tool_name === value?.tool_name) + if (tool) + (tool as AgentTool).notAuthor = false + }) + setModelConfig(newModelConfig) + setIsShowSettingTool(false) + formattingChangedDispatcher() + } + + const [isDeleting, setIsDeleting] = useState<number>(-1) + + const handleSelectTool = (tool: ToolDefaultValue) => { + const newModelConfig = produce(modelConfig, (draft) => { + draft.agentConfig.tools.push({ + provider_id: tool.provider_id, + provider_type: tool.provider_type as CollectionType, + provider_name: tool.provider_name, + tool_name: tool.tool_name, + tool_label: tool.tool_label, + tool_parameters: tool.params, + notAuthor: !tool.is_team_authorization, + enabled: true, + }) + }) + setModelConfig(newModelConfig) + } + return ( <> <Panel - className="mt-2" + className={cn('mt-2', tools.length === 0 && 'pb-2')} noBodySpacing={tools.length === 0} headerIcon={ <RiHammerFill className='w-4 h-4 text-primary-500' /> @@ -81,7 +129,14 @@ const AgentTools: FC = () => { {tools.length < MAX_TOOLS_NUM && ( <> <div className='ml-3 mr-1 h-3.5 w-px bg-gray-200'></div> - <OperationBtn type="add" onClick={() => setIsShowChooseTool(true)} /> + <ToolPicker + trigger={<OperationBtn type="add" />} + isShow={isShowChooseTool} + onShowChange={setIsShowChooseTool} + disabled={false} + supportAddCustomTool + onSelect={handleSelectTool} + /> </> )} </div> @@ -90,72 +145,77 @@ const AgentTools: FC = () => { <div className='grid gap-1 grid-cols-1 2xl:grid-cols-2 items-center flex-wrap justify-between'> {tools.map((item: AgentTool & { icon: any; collection?: Collection }, index) => ( <div key={index} - className={cn((item.isDeleted || item.notAuthor) ? 'bg-white/50' : 'bg-white', (item.enabled && !item.isDeleted && !item.notAuthor) && 'shadow-xs', index > 1 && 'mt-1', 'group relative flex justify-between items-center last-of-type:mb-0 pl-2.5 py-2 pr-3 w-full rounded-lg border-[0.5px] border-gray-200 ')} + className={cn( + 'group relative flex justify-between items-center last-of-type:mb-0 p-1.5 pr-2 w-full bg-components-panel-on-panel-item-bg rounded-lg border-[0.5px] border-components-panel-border-subtle shadow-xs hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm cursor', + isDeleting === index && 'hover:bg-state-destructive-hover border-state-destructive-border', + )} > <div className='grow w-0 flex items-center'> - {(item.isDeleted || item.notAuthor) - ? ( - <DefaultToolIcon className='w-6 h-6' /> - ) - : ( - typeof item.icon === 'string' - ? ( - <div - className='w-6 h-6 bg-cover bg-center rounded-md' - style={{ - backgroundImage: `url(${item.icon})`, - }} - ></div> - ) - : ( - <AppIcon - className='rounded-md' - size='tiny' - icon={item.icon?.content} - background={item.icon?.background} - /> - ))} + {item.isDeleted && <DefaultToolIcon className='w-5 h-5' />} + {!item.isDeleted && ( + <div className={cn((item.notAuthor || !item.enabled) && 'opacity-50')}> + {typeof item.icon === 'string' && <div className='w-5 h-5 bg-cover bg-center rounded-md' style={{ backgroundImage: `url(${item.icon})` }} />} + {typeof item.icon !== 'string' && <AppIcon className='rounded-md' size='xs' icon={item.icon?.content} background={item.icon?.background} />} + </div> + )} <div - className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800 truncate')} + className={cn( + 'grow w-0 ml-1.5 flex items-center system-xs-regular truncate', + (item.isDeleted || item.notAuthor || !item.enabled) ? 'opacity-50' : '', + )} > - <span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span> - <Tooltip - popupContent={t('tools.toolNameUsageTip')} - > - <span className='text-gray-500'>{item.tool_name}</span> - </Tooltip> + <span className='text-text-secondary system-xs-medium pr-1.5'>{item.provider_type === CollectionType.builtIn ? item.provider_name.split('/').pop() : item.tool_label}</span> + <span className='text-text-tertiary'>{item.tool_name}</span> + {!item.isDeleted && ( + <Tooltip + needsDelay + popupContent={ + <div className='w-[180px]'> + <div className='mb-1.5 text-text-secondary'>{item.tool_name}</div> + <div className='mb-1.5 text-text-tertiary'>{t('tools.toolNameUsageTip')}</div> + <div className='text-text-accent cursor-pointer' onClick={() => copy(item.tool_name)}>{t('tools.copyToolName')}</div> + </div> + } + > + <div className='w-4 h-4'> + <div className='hidden group-hover:inline-block ml-0.5'> + <RiInformation2Line className='w-4 h-4 text-text-tertiary' /> + </div> + </div> + </Tooltip> + )} </div> </div> <div className='shrink-0 ml-1 flex items-center'> - {(item.isDeleted || item.notAuthor) - ? ( - <div className='flex items-center'> - <Tooltip - popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)} - needsDelay - > - <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { - if (item.notAuthor) - setIsShowChooseTool(true) - }}> - <AlertTriangle className='w-4 h-4 text-[#F79009]' /> - </div> - </Tooltip> - - <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { + {item.isDeleted && ( + <div className='flex items-center mr-2'> + <Tooltip + popupContent={t('tools.toolRemoved')} + needsDelay + > + <div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer'> + <AlertTriangle className='w-4 h-4 text-[#F79009]' /> + </div> + </Tooltip> + <div + className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive' + onClick={() => { const newModelConfig = produce(modelConfig, (draft) => { draft.agentConfig.tools.splice(index, 1) }) setModelConfig(newModelConfig) formattingChangedDispatcher() - }}> - <RiDeleteBinLine className='w-4 h-4 text-gray-500' /> - </div> - <div className='ml-2 mr-3 w-px h-3.5 bg-gray-200'></div> + }} + onMouseOver={() => setIsDeleting(index)} + onMouseLeave={() => setIsDeleting(-1)} + > + <RiDeleteBinLine className='w-4 h-4' /> </div> - ) - : ( - <div className='hidden group-hover:flex items-center'> + </div> + )} + {!item.isDeleted && ( + <div className='hidden group-hover:flex items-center gap-1 mr-2'> + {!item.notAuthor && ( <Tooltip popupContent={t('tools.setBuiltInTools.infoAndSetting')} needsDelay @@ -164,55 +224,81 @@ const AgentTools: FC = () => { setCurrentTool(item) setIsShowSettingTool(true) }}> - <InfoCircle className='w-4 h-4 text-gray-500' /> + <RiEqualizer2Line className='w-4 h-4 text-text-tertiary' /> </div> </Tooltip> - - <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => { + )} + <div + className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive' + onClick={() => { const newModelConfig = produce(modelConfig, (draft) => { draft.agentConfig.tools.splice(index, 1) }) setModelConfig(newModelConfig) formattingChangedDispatcher() - }}> - <RiDeleteBinLine className='w-4 h-4 text-gray-500' /> - </div> - <div className='ml-2 mr-3 w-px h-3.5 bg-gray-200'></div> + }} + onMouseOver={() => setIsDeleting(index)} + onMouseLeave={() => setIsDeleting(-1)} + > + <RiDeleteBinLine className='w-4 h-4' /> </div> + </div> + )} + <div className={cn(item.isDeleted && 'opacity-50')}> + {!item.notAuthor && ( + <Switch + defaultValue={item.isDeleted ? false : item.enabled} + disabled={item.isDeleted} + size='md' + onChange={(enabled) => { + const newModelConfig = produce(modelConfig, (draft) => { + (draft.agentConfig.tools[index] as any).enabled = enabled + }) + setModelConfig(newModelConfig) + formattingChangedDispatcher() + }} /> + )} + {item.notAuthor && ( + <Button variant='secondary' size='small' onClick={() => { + setCurrentTool(item) + setShowSettingAuth(true) + }}> + {t('tools.notAuthorized')} + <Indicator className='ml-2' color='orange' /> + </Button> )} - <div className={cn((item.isDeleted || item.notAuthor) && 'opacity-50')}> - <Switch - defaultValue={(item.isDeleted || item.notAuthor) ? false : item.enabled} - disabled={(item.isDeleted || item.notAuthor)} - size='md' - onChange={(enabled) => { - const newModelConfig = produce(modelConfig, (draft) => { - (draft.agentConfig.tools[index] as any).enabled = enabled - }) - setModelConfig(newModelConfig) - formattingChangedDispatcher() - }} /> </div> </div> </div> ))} </div > </Panel > - {isShowChooseTool && ( - <AddToolModal onHide={() => setIsShowChooseTool(false)} /> + {isShowSettingTool && ( + <SettingBuiltInTool + toolName={currentTool?.tool_name as string} + setting={currentTool?.tool_parameters as any} + collection={currentTool?.collection as Collection} + isBuiltIn={currentTool?.collection?.type === CollectionType.builtIn} + isModel={currentTool?.collection?.type === CollectionType.model} + onSave={handleToolSettingChange} + onHide={() => setIsShowSettingTool(false)} + /> + )} + {isShowSettingAuth && ( + <ConfigCredential + collection={currentCollection as any} + onCancel={() => setShowSettingAuth(false)} + onSaved={async (value) => { + await updateBuiltInToolCredential((currentCollection as any).name, value) + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + handleToolAuthSetting(currentTool as any) + setShowSettingAuth(false) + }} + /> )} - { - isShowSettingTool && ( - <SettingBuiltInTool - toolName={currentTool?.tool_name as string} - setting={currentTool?.tool_parameters as any} - collection={currentTool?.collection as Collection} - isBuiltIn={currentTool?.collection?.type === CollectionType.builtIn} - isModel={currentTool?.collection?.type === CollectionType.model} - onSave={handleToolSettingChange} - onHide={() => setIsShowSettingTool(false)} - />) - } </> ) } diff --git a/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx b/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx index 69e18e3136..e4fae3fbc1 100644 --- a/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx +++ b/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx @@ -3,21 +3,30 @@ import type { FC } from 'react' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' -import cn from '@/utils/classnames' -import Drawer from '@/app/components/base/drawer-plus' +import { + RiArrowLeftLine, + RiCloseLine, +} from '@remixicon/react' +import Drawer from '@/app/components/base/drawer' +import Loading from '@/app/components/base/loading' +import ActionButton from '@/app/components/base/action-button' +import Icon from '@/app/components/plugins/card/base/card-icon' +import OrgInfo from '@/app/components/plugins/card/base/org-info' +import Description from '@/app/components/plugins/card/base/description' +import TabSlider from '@/app/components/base/tab-slider-plain' + +import Button from '@/app/components/base/button' import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' import type { Collection, Tool } from '@/app/components/tools/types' import { CollectionType } from '@/app/components/tools/types' import { fetchBuiltInToolList, fetchCustomToolList, fetchModelToolList, fetchWorkflowToolList } from '@/service/tools' import I18n from '@/context/i18n' -import Button from '@/app/components/base/button' -import Loading from '@/app/components/base/loading' -import { DiagonalDividingLine } from '@/app/components/base/icons/src/public/common' import { getLanguage } from '@/i18n/language' -import AppIcon from '@/app/components/base/app-icon' +import cn from '@/utils/classnames' type Props = { + showBackButton?: boolean collection: Collection isBuiltIn?: boolean isModel?: boolean @@ -29,6 +38,7 @@ type Props = { } const SettingBuiltInTool: FC<Props> = ({ + showBackButton = false, collection, isBuiltIn = true, isModel = true, @@ -96,39 +106,38 @@ const SettingBuiltInTool: FC<Props> = ({ return valid })() - const infoUI = ( - <div className='pt-2'> - <div className='leading-5 text-sm font-medium text-gray-900'> - {t('tools.setBuiltInTools.toolDescription')} - </div> - <div className='mt-1 leading-[18px] text-xs font-normal text-gray-600'> - {currTool?.description[language]} - </div> + const getType = (type: string) => { + if (type === 'number-input') + return t('tools.setBuiltInTools.number') + if (type === 'text-input') + return t('tools.setBuiltInTools.string') + if (type === 'file') + return t('tools.setBuiltInTools.file') + return type + } + const infoUI = ( + <div className=''> {infoSchemas.length > 0 && ( - <div className='mt-6'> - <div className='flex items-center mb-4 leading-[18px] text-xs font-semibold text-gray-500 uppercase'> - <div className='mr-3'>{t('tools.setBuiltInTools.parameters')}</div> - <div className='grow w-0 h-px bg-[#f3f4f6]'></div> - </div> - <div className='space-y-4'> - {infoSchemas.map((item: any, index) => ( - <div key={index}> - <div className='flex items-center space-x-2 leading-[18px]'> - <div className='text-[13px] font-semibold text-gray-900'>{item.label[language]}</div> - <div className='text-xs font-medium text-gray-500'>{item.type === 'number-input' ? t('tools.setBuiltInTools.number') : t('tools.setBuiltInTools.string')}</div> - {item.required && ( - <div className='text-xs font-medium text-[#EC4A0A]'>{t('tools.setBuiltInTools.required')}</div> - )} + <div className='py-2 space-y-1'> + {infoSchemas.map((item: any, index) => ( + <div key={index} className='py-1'> + <div className='flex items-center gap-2'> + <div className='text-text-secondary code-sm-semibold'>{item.label[language]}</div> + <div className='text-text-tertiary system-xs-regular'> + {getType(item.type)} </div> - {item.human_description && ( - <div className='mt-1 leading-[18px] text-xs font-normal text-gray-600'> - {item.human_description?.[language]} - </div> + {item.required && ( + <div className='text-text-warning-secondary system-xs-medium'>{t('tools.setBuiltInTools.required')}</div> )} </div> - ))} - </div> + {item.human_description && ( + <div className='mt-0.5 text-text-tertiary system-xs-regular'> + {item.human_description?.[language]} + </div> + )} + </div> + ))} </div> )} </div> @@ -149,75 +158,82 @@ const SettingBuiltInTool: FC<Props> = ({ return ( <Drawer - isShow - onHide={onHide} - title={( - <div className='flex items-center'> - {typeof collection.icon === 'string' - ? ( - <div - className='w-6 h-6 bg-cover bg-center rounded-md flex-shrink-0' - style={{ - backgroundImage: `url(${collection.icon})`, - }} - ></div> - ) - : ( - <AppIcon - className='rounded-md' - size='tiny' - icon={(collection.icon as any)?.content} - background={(collection.icon as any)?.background} - /> - )} - - <div className='ml-2 leading-6 text-base font-semibold text-gray-900'>{currTool?.label[language]}</div> - {(hasSetting && !readonly) && (<> - <DiagonalDividingLine className='mx-4' /> - <div className='flex space-x-6'> - <div - className={cn(isInfoActive ? 'text-gray-900 font-semibold' : 'font-normal text-gray-600 cursor-pointer', 'relative text-base')} - onClick={() => setCurrType('info')} - > - {t('tools.setBuiltInTools.info')} - {isInfoActive && <div className='absolute left-0 bottom-[-16px] w-full h-0.5 bg-primary-600'></div>} + isOpen + clickOutsideNotOpen={false} + onClose={onHide} + footer={null} + mask={false} + positionCenter={false} + panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')} + > + <> + {isLoading && <Loading type='app' />} + {!isLoading && ( + <> + {/* header */} + <div className='relative p-4 pb-3 border-b border-divider-subtle'> + <div className='absolute top-3 right-3'> + <ActionButton onClick={onHide}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> </div> - <div className={cn(!isInfoActive ? 'text-gray-900 font-semibold' : 'font-normal text-gray-600 cursor-pointer', 'relative text-base ')} - onClick={() => setCurrType('setting')} - > - {t('tools.setBuiltInTools.setting')} - {!isInfoActive && <div className='absolute left-0 bottom-[-16px] w-full h-0.5 bg-primary-600'></div>} - </div> - </div> - </>)} - </div> - )} - panelClassName='mt-[65px] !w-[405px]' - maxWidthClassName='!max-w-[405px]' - height='calc(100vh - 65px)' - headerClassName='!border-b-black/5' - body={ - <div className='h-full pt-3'> - {isLoading - ? <div className='flex h-full items-center'> - <Loading type='app' /> - </div> - : (<div className='flex flex-col h-full'> - <div className='grow h-0 overflow-y-auto px-6'> - {isInfoActive ? infoUI : settingUI} - </div> - {!readonly && !isInfoActive && ( - <div className='mt-2 shrink-0 flex justify-end py-4 px-6 space-x-2 rounded-b-[10px] bg-gray-50 border-t border-black/5'> - <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium !text-gray-700' onClick={onHide}>{t('common.operation.cancel')}</Button> - <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button> + {showBackButton && ( + <div + className='mb-2 flex items-center gap-1 text-text-accent-secondary system-xs-semibold-uppercase cursor-pointer' + onClick={onHide} + > + <RiArrowLeftLine className='w-4 h-4' /> + BACK </div> )} - </div>)} - </div> - } - isShowMask={false} - clickOutsideNotOpen={false} - /> + <div className='flex items-center gap-1'> + <Icon size='tiny' className='w-6 h-6' src={collection.icon} /> + <OrgInfo + packageNameClassName='w-auto' + orgName={collection.author} + packageName={collection.name.split('/').pop() || ''} + /> + </div> + <div className='mt-1 text-text-primary system-md-semibold'>{currTool?.label[language]}</div> + {!!currTool?.description[language] && ( + <Description className='mt-3' text={currTool.description[language]} descriptionLineRows={2}></Description> + )} + </div> + {/* form */} + <div className='h-full'> + <div className='flex flex-col h-full'> + {(hasSetting && !readonly) ? ( + <TabSlider + className='shrink-0 mt-1 px-4' + itemClassName='py-3' + noBorderBottom + value={currType} + onChange={(value) => { + setCurrType(value) + }} + options={[ + { value: 'info', text: t('tools.setBuiltInTools.parameters')! }, + { value: 'setting', text: t('tools.setBuiltInTools.setting')! }, + ]} + /> + ) : ( + <div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>{t('tools.setBuiltInTools.parameters')}</div> + )} + <div className='grow h-0 overflow-y-auto px-4'> + {isInfoActive ? infoUI : settingUI} + </div> + {!readonly && !isInfoActive && ( + <div className='mt-2 shrink-0 flex justify-end py-4 px-6 space-x-2 rounded-b-[10px] bg-components-panel-bg border-t border-divider-regular'> + <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium !text-gray-700' onClick={onHide}>{t('common.operation.cancel')}</Button> + <Button className='flex items-center h-8 !px-3 !text-[13px] font-medium' variant='primary' disabled={!isValid} onClick={() => onSave?.(addDefaultValue(tempSetting, formSchemas))}>{t('common.operation.save')}</Button> + </div> + )} + </div> + </div> + </> + )} + </> + </Drawer> ) } export default React.memo(SettingBuiltInTool) diff --git a/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx b/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx index 0a20f4b376..549421401c 100644 --- a/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx +++ b/web/app/components/app/configuration/config/automatic/get-automatic-res.tsx @@ -38,7 +38,7 @@ import ModelName from '@/app/components/header/account-setting/model-provider-pa import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' -export type IGetAutomaticResProps = { +export interface IGetAutomaticResProps { mode: AppType model: Model isShow: boolean diff --git a/web/app/components/app/configuration/config/index.tsx b/web/app/components/app/configuration/config/index.tsx index 39fdd502ef..dd4a076dde 100644 --- a/web/app/components/app/configuration/config/index.tsx +++ b/web/app/components/app/configuration/config/index.tsx @@ -12,7 +12,7 @@ import AgentTools from './agent/agent-tools' import ConfigContext from '@/context/debug-configuration' import ConfigPrompt from '@/app/components/app/configuration/config-prompt' import ConfigVar from '@/app/components/app/configuration/config-var' -import { type ModelConfig, type PromptVariable } from '@/models/debug' +import type { ModelConfig, PromptVariable } from '@/models/debug' import type { AppType } from '@/types/app' import { ModelModeType } from '@/types/app' diff --git a/web/app/components/app/configuration/dataset-config/params-config/index.tsx b/web/app/components/app/configuration/dataset-config/params-config/index.tsx index acd1955943..a236eaaf24 100644 --- a/web/app/components/app/configuration/dataset-config/params-config/index.tsx +++ b/web/app/components/app/configuration/dataset-config/params-config/index.tsx @@ -140,11 +140,11 @@ const ParamsConfig = ({ /> <div className='mt-6 flex justify-end'> - <Button className='mr-2 flex-shrink-0' onClick={() => { + <Button className='mr-2 shrink-0' onClick={() => { setTempDataSetConfigs(datasetConfigs) setRerankSettingModalOpen(false) }}>{t('common.operation.cancel')}</Button> - <Button variant='primary' className='flex-shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button> + <Button variant='primary' className='shrink-0' onClick={handleSave} >{t('common.operation.save')}</Button> </div> </Modal> ) diff --git a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx index 506406cfe0..fac47d2b42 100644 --- a/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx +++ b/web/app/components/app/configuration/dataset-config/settings-modal/index.tsx @@ -33,7 +33,7 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro import { fetchMembers } from '@/service/common' import type { Member } from '@/models/common' -type SettingsModalProps = { +interface SettingsModalProps { currentDataset: DataSet onCancel: () => void onSave: (newDataset: DataSet) => void diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx index 1144c323d1..e8ec11c19a 100644 --- a/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx +++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/chat-item.tsx @@ -31,7 +31,7 @@ import { useFeatures } from '@/app/components/base/features/hooks' import type { InputForm } from '@/app/components/base/chat/chat/type' import { getLastAnswer } from '@/app/components/base/chat/utils' -type ChatItemProps = { +interface ChatItemProps { modelAndParameter: ModelAndParameter } const ChatItem: FC<ChatItemProps> = ({ diff --git a/web/app/components/app/configuration/debug/debug-with-multiple-model/text-generation-item.tsx b/web/app/components/app/configuration/debug/debug-with-multiple-model/text-generation-item.tsx index 57c8f83f3f..cab6bf4313 100644 --- a/web/app/components/app/configuration/debug/debug-with-multiple-model/text-generation-item.tsx +++ b/web/app/components/app/configuration/debug/debug-with-multiple-model/text-generation-item.tsx @@ -15,7 +15,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter' import { useProviderContext } from '@/context/provider-context' import { useFeatures } from '@/app/components/base/features/hooks' -type TextGenerationItemProps = { +interface TextGenerationItemProps { modelAndParameter: ModelAndParameter } const TextGenerationItem: FC<TextGenerationItemProps> = ({ diff --git a/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx b/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx index 2cbfe91f16..da754b81e5 100644 --- a/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx +++ b/web/app/components/app/configuration/debug/debug-with-single-model/index.tsx @@ -27,10 +27,10 @@ import { useFeatures } from '@/app/components/base/features/hooks' import { getLastAnswer } from '@/app/components/base/chat/utils' import type { InputForm } from '@/app/components/base/chat/chat/type' -type DebugWithSingleModelProps = { +interface DebugWithSingleModelProps { checkCanSend?: () => boolean } -export type DebugWithSingleModelRefType = { +export interface DebugWithSingleModelRefType { handleRestart: () => void } const DebugWithSingleModel = forwardRef<DebugWithSingleModelRefType, DebugWithSingleModelProps>(({ diff --git a/web/app/components/app/configuration/debug/index.tsx b/web/app/components/app/configuration/debug/index.tsx index 480bd782ae..99632eb0d3 100644 --- a/web/app/components/app/configuration/debug/index.tsx +++ b/web/app/components/app/configuration/debug/index.tsx @@ -48,7 +48,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal' import { useStore as useAppStore } from '@/app/components/app/store' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' -type IDebug = { +interface IDebug { isAPIKeySet: boolean onSetting: () => void inputs: Inputs diff --git a/web/app/components/app/configuration/features/chat-group/opening-statement/index.tsx b/web/app/components/app/configuration/features/chat-group/opening-statement/index.tsx index 6d16660e81..f5fb96da08 100644 --- a/web/app/components/app/configuration/features/chat-group/opening-statement/index.tsx +++ b/web/app/components/app/configuration/features/chat-group/opening-statement/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable multiline-ternary */ 'use client' import type { FC } from 'react' import React, { useEffect, useRef, useState } from 'react' diff --git a/web/app/components/app/configuration/index.tsx b/web/app/components/app/configuration/index.tsx index b4289a105a..35e485985f 100644 --- a/web/app/components/app/configuration/index.tsx +++ b/web/app/components/app/configuration/index.tsx @@ -59,7 +59,7 @@ import { useTextGenerationCurrentProviderAndModelAndModelList, } from '@/app/components/header/account-setting/model-provider-page/hooks' import { fetchCollectionList } from '@/service/tools' -import { type Collection } from '@/app/components/tools/types' +import type { Collection } from '@/app/components/tools/types' import { useStore as useAppStore } from '@/app/components/app/store' import { getMultipleRetrievalConfig, @@ -71,6 +71,8 @@ import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import { SupportUploadFileTypes } from '@/app/components/workflow/types' import NewFeaturePanel from '@/app/components/base/features/new-feature-panel' import { fetchFileUploadConfig } from '@/service/common' +import { correctProvider } from '@/utils' +import PluginDependency from '@/app/components/workflow/plugin-dependency' type PublishConfig = { modelConfig: ModelConfig @@ -156,7 +158,7 @@ const Configuration: FC = () => { const setCompletionParams = (value: FormValue) => { const params = { ...value } - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define if ((!params.stop || params.stop.length === 0) && (modeModeTypeRef.current === ModelModeType.completion)) { params.stop = getTempStop() setTempStop([]) @@ -165,7 +167,7 @@ const Configuration: FC = () => { } const [modelConfig, doSetModelConfig] = useState<ModelConfig>({ - provider: 'openai', + provider: 'langgenius/openai/openai', model_id: 'gpt-3.5-turbo', mode: ModelModeType.unset, configs: { @@ -188,7 +190,7 @@ const Configuration: FC = () => { const isAgent = mode === 'agent-chat' - const isOpenAI = modelConfig.provider === 'openai' + const isOpenAI = modelConfig.provider === 'langgenius/openai/openai' const [collectionList, setCollectionList] = useState<Collection[]>([]) useEffect(() => { @@ -361,7 +363,7 @@ const Configuration: FC = () => { const [canReturnToSimpleMode, setCanReturnToSimpleMode] = useState(true) const setPromptMode = async (mode: PromptMode) => { if (mode === PromptMode.advanced) { - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define await migrateToDefaultPrompt() setCanReturnToSimpleMode(true) } @@ -547,8 +549,19 @@ const Configuration: FC = () => { if (modelConfig.retriever_resource) setCitationConfig(modelConfig.retriever_resource) - if (modelConfig.annotation_reply) - setAnnotationConfig(modelConfig.annotation_reply, true) + if (modelConfig.annotation_reply) { + let annotationConfig = modelConfig.annotation_reply + if (modelConfig.annotation_reply.enabled) { + annotationConfig = { + ...modelConfig.annotation_reply, + embedding_model: { + ...modelConfig.annotation_reply.embedding_model, + embedding_provider_name: correctProvider(modelConfig.annotation_reply.embedding_model.embedding_provider_name), + }, + } + } + setAnnotationConfig(annotationConfig, true) + } if (modelConfig.sensitive_word_avoidance) setModerationConfig(modelConfig.sensitive_word_avoidance) @@ -558,7 +571,7 @@ const Configuration: FC = () => { const config = { modelConfig: { - provider: model.provider, + provider: correctProvider(model.provider), model_id: model.name, mode: model.mode, configs: { @@ -600,7 +613,6 @@ const Configuration: FC = () => { annotation_reply: modelConfig.annotation_reply, external_data_tools: modelConfig.external_data_tools, dataSets: datasets || [], - // eslint-disable-next-line multiline-ternary agentConfig: res.mode === 'agent-chat' ? { max_iteration: DEFAULT_AGENT_SETTING.max_iteration, ...modelConfig.agent_mode, @@ -611,8 +623,12 @@ const Configuration: FC = () => { }).map((tool: any) => { return { ...tool, - isDeleted: res.deleted_tools?.includes(tool.tool_name), + isDeleted: res.deleted_tools?.some((deletedTool: any) => deletedTool.id === tool.id && deletedTool.tool_name === tool.tool_name), notAuthor: collectionList.find(c => tool.provider_id === c.id)?.is_team_authorization === false, + ...(tool.provider_type === 'builtin' ? { + provider_id: correctProvider(tool.provider_name), + provider_name: correctProvider(tool.provider_name), + } : {}), } }), } : DEFAULT_AGENT_SETTING, @@ -633,6 +649,12 @@ const Configuration: FC = () => { retrieval_model: RETRIEVE_TYPE.multiWay, ...modelConfig.dataset_configs, ...retrievalConfig, + ...(retrievalConfig.reranking_model ? { + reranking_model: { + ...retrievalConfig.reranking_model, + reranking_provider_name: correctProvider(modelConfig.dataset_configs.reranking_model.reranking_provider_name), + }, + } : {}), }) setHasFetchedDetail(true) }) @@ -1020,6 +1042,7 @@ const Configuration: FC = () => { onAutoAddPromptVariable={handleAddPromptVariable} /> )} + <PluginDependency /> </> </FeaturesProvider> </ConfigContext.Provider> diff --git a/web/app/components/app/configuration/prompt-value-panel/index.tsx b/web/app/components/app/configuration/prompt-value-panel/index.tsx index a4aadc9576..39ffeaf0d0 100644 --- a/web/app/components/app/configuration/prompt-value-panel/index.tsx +++ b/web/app/components/app/configuration/prompt-value-panel/index.tsx @@ -23,7 +23,7 @@ import { DEFAULT_VALUE_MAX_LEN } from '@/config' import { useStore as useAppStore } from '@/app/components/app/store' import cn from '@/utils/classnames' -export type IPromptValuePanelProps = { +export interface IPromptValuePanelProps { appType: AppType onSend?: () => void inputs: Inputs diff --git a/web/app/components/app/configuration/toolbox/annotation/config-param.tsx b/web/app/components/app/configuration/toolbox/annotation/config-param.tsx deleted file mode 100644 index e418a76c34..0000000000 --- a/web/app/components/app/configuration/toolbox/annotation/config-param.tsx +++ /dev/null @@ -1,124 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import { usePathname, useRouter } from 'next/navigation' -import ConfigParamModal from './config-param-modal' -import Panel from '@/app/components/app/configuration/base/feature-panel' -import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' -import Tooltip from '@/app/components/base/tooltip' -import { LinkExternal02, Settings04 } from '@/app/components/base/icons/src/vender/line/general' -import ConfigContext from '@/context/debug-configuration' -import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' -import { fetchAnnotationConfig, updateAnnotationScore } from '@/service/annotation' -import type { AnnotationReplyConfig as AnnotationReplyConfigType } from '@/models/debug' - -type Props = { - onEmbeddingChange: (embeddingModel: EmbeddingModelConfig) => void - onScoreChange: (score: number, embeddingModel?: EmbeddingModelConfig) => void -} - -export const Item: FC<{ title: string; tooltip: string; children: JSX.Element }> = ({ - title, - tooltip, - children, -}) => { - return ( - <div> - <div className='flex items-center space-x-1'> - <div>{title}</div> - <Tooltip - popupContent={ - <div className='max-w-[200px] leading-[18px] text-[13px] font-medium text-gray-800'>{tooltip}</div> - } - /> - </div> - <div>{children}</div> - </div> - ) -} - -const AnnotationReplyConfig: FC<Props> = ({ - onEmbeddingChange, - onScoreChange, -}) => { - const { t } = useTranslation() - const router = useRouter() - const pathname = usePathname() - const matched = pathname.match(/\/app\/([^/]+)/) - const appId = (matched?.length && matched[1]) ? matched[1] : '' - const { - annotationConfig, - } = useContext(ConfigContext) - - const [isShowEdit, setIsShowEdit] = React.useState(false) - - return ( - <> - <Panel - className="mt-4" - headerIcon={ - <MessageFast className='w-4 h-4 text-[#444CE7]' /> - } - title={t('appDebug.feature.annotation.title')} - headerRight={ - <div className='flex items-center'> - <div - className='flex items-center rounded-md h-7 px-3 space-x-1 text-gray-700 cursor-pointer hover:bg-gray-200' - onClick={() => { setIsShowEdit(true) }} - > - <Settings04 className="w-[14px] h-[14px]" /> - <div className='text-xs font-medium'> - - {t('common.operation.params')} - </div> - </div> - <div - className='ml-1 flex items-center h-7 px-3 space-x-1 leading-[18px] text-xs font-medium text-gray-700 rounded-md cursor-pointer hover:bg-gray-200' - onClick={() => { - router.push(`/app/${appId}/annotations`) - }}> - <div>{t('appDebug.feature.annotation.cacheManagement')}</div> - <LinkExternal02 className='w-3.5 h-3.5' /> - </div> - </div> - } - noBodySpacing - /> - {isShowEdit && ( - <ConfigParamModal - appId={appId} - isShow - onHide={() => { - setIsShowEdit(false) - }} - onSave={async (embeddingModel, score) => { - const annotationConfig = await fetchAnnotationConfig(appId) as AnnotationReplyConfigType - let isEmbeddingModelChanged = false - if ( - embeddingModel.embedding_model_name !== annotationConfig.embedding_model.embedding_model_name - || embeddingModel.embedding_provider_name !== annotationConfig.embedding_model.embedding_provider_name - ) { - await onEmbeddingChange(embeddingModel) - isEmbeddingModelChanged = true - } - - if (score !== annotationConfig.score_threshold) { - await updateAnnotationScore(appId, annotationConfig.id, score) - if (isEmbeddingModelChanged) - onScoreChange(score, embeddingModel) - - else - onScoreChange(score) - } - - setIsShowEdit(false) - }} - annotationConfig={annotationConfig} - /> - )} - </> - ) -} -export default React.memo(AnnotationReplyConfig) diff --git a/web/app/components/app/configuration/toolbox/index.tsx b/web/app/components/app/configuration/toolbox/index.tsx deleted file mode 100644 index 00ea301a42..0000000000 --- a/web/app/components/app/configuration/toolbox/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -'use client' - -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import GroupName from '../base/group-name' -import Moderation from './moderation' -import Annotation from './annotation/config-param' -import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type' - -export type ToolboxProps = { - showModerationSettings: boolean - showAnnotation: boolean - onEmbeddingChange: (embeddingModel: EmbeddingModelConfig) => void - onScoreChange: (score: number, embeddingModel?: EmbeddingModelConfig) => void -} - -const Toolbox: FC<ToolboxProps> = ({ - showModerationSettings, - showAnnotation, - onEmbeddingChange, - onScoreChange, -}) => { - const { t } = useTranslation() - - return ( - <div className='mt-7'> - <GroupName name={t('appDebug.feature.toolbox.title')} /> - { - showModerationSettings && ( - <Moderation /> - ) - } - { - showAnnotation && ( - <Annotation - onEmbeddingChange={onEmbeddingChange} - onScoreChange={onScoreChange} - /> - ) - } - </div> - ) -} -export default React.memo(Toolbox) diff --git a/web/app/components/app/configuration/tools/external-data-tool-modal.tsx b/web/app/components/app/configuration/tools/external-data-tool-modal.tsx index eefdd4514c..e1fe73ee32 100644 --- a/web/app/components/app/configuration/tools/external-data-tool-modal.tsx +++ b/web/app/components/app/configuration/tools/external-data-tool-modal.tsx @@ -21,13 +21,13 @@ import { useToastContext } from '@/app/components/base/toast' import AppIcon from '@/app/components/base/app-icon' const systemTypes = ['api'] -type ExternalDataToolModalProps = { +interface ExternalDataToolModalProps { data: ExternalDataTool onCancel: () => void onSave: (externalDataTool: ExternalDataTool) => void onValidateBeforeSave?: (externalDataTool: ExternalDataTool) => boolean } -type Provider = { +interface Provider { key: string name: string form_schema?: CodeBasedExtensionItem['form_schema'] diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index ce06b113bc..26e175eb56 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -25,6 +25,7 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { getRedirection } from '@/utils/app-redirection' import cn from '@/utils/classnames' +import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' type CreateFromDSLModalProps = { show: boolean @@ -50,6 +51,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS const [showErrorModal, setShowErrorModal] = useState(false) const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>() const [importId, setImportId] = useState<string>() + const { handleCheckPluginDependencies } = usePluginDependencies() const readFile = (file: File) => { const reader = new FileReader() @@ -114,6 +116,8 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('app.newApp.appCreateDSLWarning'), }) localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + if (app_id) + await handleCheckPluginDependencies(app_id) getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push) } else if (status === DSLImportStatus.PENDING) { @@ -132,6 +136,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) } } + // eslint-disable-next-line unused-imports/no-unused-vars catch (e) { notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) } @@ -158,6 +163,8 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS type: 'success', message: t('app.newApp.appCreated'), }) + if (app_id) + await handleCheckPluginDependencies(app_id) localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') getRedirection(isCurrentWorkspaceEditor, { id: app_id }, push) } @@ -165,6 +172,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) } } + // eslint-disable-next-line unused-imports/no-unused-vars catch (e) { notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) } @@ -268,7 +276,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS > <div className='flex pb-4 flex-col items-start gap-2 self-stretch'> <div className='text-text-primary title-2xl-semi-bold'>{t('app.newApp.appCreateDSLErrorTitle')}</div> - <div className='flex flex-grow flex-col text-text-secondary system-md-regular'> + <div className='flex grow flex-col text-text-secondary system-md-regular'> <div>{t('app.newApp.appCreateDSLErrorPart1')}</div> <div>{t('app.newApp.appCreateDSLErrorPart2')}</div> <br /> diff --git a/web/app/components/app/duplicate-modal/index.tsx b/web/app/components/app/duplicate-modal/index.tsx index bcad1c24f2..25a5cbf6c1 100644 --- a/web/app/components/app/duplicate-modal/index.tsx +++ b/web/app/components/app/duplicate-modal/index.tsx @@ -13,7 +13,7 @@ import { useProviderContext } from '@/context/provider-context' import AppsFull from '@/app/components/billing/apps-full-in-dialog' import type { AppIconType } from '@/types/app' -export type DuplicateAppModalProps = { +export interface DuplicateAppModalProps { appName: string icon_type: AppIconType | null icon: string diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 383aeb1492..2862eebfa7 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -79,6 +79,9 @@ const HandThumbIconWithCount: FC<{ count: number; iconType: 'up' | 'down' }> = ( } const statusTdRender = (statusCount: StatusCount) => { + if (!statusCount) + return null + if (statusCount.partial_success + statusCount.failed === 0) { return ( <div className='inline-flex items-center gap-1 system-xs-semibold-uppercase'> diff --git a/web/app/components/app/overview/apikey-info-panel/index.tsx b/web/app/components/app/overview/apikey-info-panel/index.tsx index 661a88e823..2ca098a313 100644 --- a/web/app/components/app/overview/apikey-info-panel/index.tsx +++ b/web/app/components/app/overview/apikey-info-panel/index.tsx @@ -27,8 +27,8 @@ const APIKeyInfoPanel: FC = () => { return null return ( - <div className={cn('bg-[#EFF4FF] border-[#D1E0FF]', 'mb-6 relative rounded-2xl shadow-md border p-8 ')}> - <div className={cn('text-[24px] text-gray-800 font-semibold', isCloud ? 'flex items-center h-8 space-x-1' : 'leading-8 mb-6')}> + <div className={cn('bg-components-panel-bg border-components-panel-border', 'mb-6 relative rounded-2xl shadow-md border p-8 ')}> + <div className={cn('text-[24px] text-text-primary font-semibold', isCloud ? 'flex items-center h-8 space-x-1' : 'leading-8 mb-6')}> {isCloud && <em-emoji id={'😀'} />} {isCloud ? ( @@ -42,11 +42,11 @@ const APIKeyInfoPanel: FC = () => { )} </div> {isCloud && ( - <div className='mt-1 text-sm text-gray-600 font-normal'>{t(`appOverview.apiKeyInfo.cloud.${'trial'}.description`)}</div> + <div className='mt-1 text-sm text-text-tertiary font-normal'>{t(`appOverview.apiKeyInfo.cloud.${'trial'}.description`)}</div> )} <Button variant='primary' - className='space-x-2' + className='mt-2 space-x-2' onClick={() => setShowAccountSettingModal({ payload: 'provider' })} > <div className='text-sm font-medium'>{t('appOverview.apiKeyInfo.setAPIBtn')}</div> @@ -65,7 +65,7 @@ const APIKeyInfoPanel: FC = () => { <div onClick={() => setIsShow(false)} className='absolute right-4 top-4 flex items-center justify-center w-8 h-8 cursor-pointer '> - <RiCloseLine className='w-4 h-4 text-gray-500' /> + <RiCloseLine className='w-4 h-4 text-text-tertiary' /> </div> </div> ) diff --git a/web/app/components/app/overview/apikey-info-panel/progress/index.tsx b/web/app/components/app/overview/apikey-info-panel/progress/index.tsx deleted file mode 100644 index 3a4accbb43..0000000000 --- a/web/app/components/app/overview/apikey-info-panel/progress/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import s from './style.module.css' -import cn from '@/utils/classnames' - -export type IProgressProps = { - className?: string - value: number // percent -} - -const Progress: FC<IProgressProps> = ({ - className, - value, -}) => { - const exhausted = value === 100 - return ( - <div className={cn(className, 'relative grow h-2 flex bg-gray-200 rounded-md overflow-hidden')}> - <div - className={cn(s.bar, exhausted && s['bar-error'], 'absolute top-0 left-0 right-0 bottom-0')} - style={{ width: `${value}%` }} - /> - {Array(10).fill(0).map((i, k) => ( - <div key={k} className={s['bar-item']} /> - ))} - </div> - ) -} -export default React.memo(Progress) diff --git a/web/app/components/app/overview/apikey-info-panel/progress/style.module.css b/web/app/components/app/overview/apikey-info-panel/progress/style.module.css deleted file mode 100644 index 94c3ef45cf..0000000000 --- a/web/app/components/app/overview/apikey-info-panel/progress/style.module.css +++ /dev/null @@ -1,16 +0,0 @@ -.bar { - background: linear-gradient(90deg, rgba(41, 112, 255, 0.9) 0%, rgba(21, 94, 239, 0.9) 100%); -} - -.bar-error { - background: linear-gradient(90deg, rgba(240, 68, 56, 0.72) 0%, rgba(217, 45, 32, 0.9) 100%); -} - -.bar-item { - width: 10%; - border-right: 1px solid rgba(255, 255, 255, 0.5); -} - -.bar-item:last-of-type { - border-right: 0; -} \ No newline at end of file diff --git a/web/app/components/app/overview/appCard.tsx b/web/app/components/app/overview/appCard.tsx index f9f5c1fbff..99e847f8b6 100644 --- a/web/app/components/app/overview/appCard.tsx +++ b/web/app/components/app/overview/appCard.tsx @@ -1,6 +1,9 @@ 'use client' import type { HTMLProps } from 'react' import React, { useMemo, useState } from 'react' +import { + RiLoopLeftLine, +} from '@remixicon/react' import { Cog8ToothIcon, DocumentTextIcon, @@ -16,24 +19,25 @@ import style from './style.module.css' import type { ConfigParams } from './settings' import Tooltip from '@/app/components/base/tooltip' import AppBasic from '@/app/components/app-sidebar/basic' -import { asyncRunSafe, randomString } from '@/utils' +import { asyncRunSafe } from '@/utils' import Button from '@/app/components/base/button' import Tag from '@/app/components/base/tag' import Switch from '@/app/components/base/switch' import Divider from '@/app/components/base/divider' import CopyFeedback from '@/app/components/base/copy-feedback' +import ActionButton from '@/app/components/base/action-button' import Confirm from '@/app/components/base/confirm' import ShareQRCode from '@/app/components/base/qrcode' import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button' import type { AppDetailResponse } from '@/models/app' import { useAppContext } from '@/context/app-context' import type { AppSSO } from '@/types/app' +import cn from '@/utils/classnames' export type IAppCardProps = { className?: string appInfo: AppDetailResponse & Partial<AppSSO> cardType?: 'api' | 'webapp' - customBgColor?: string onChangeStatus: (val: boolean) => Promise<void> onSaveSiteConfig?: (params: ConfigParams) => Promise<void> onGenerateCode?: () => Promise<void> @@ -46,7 +50,6 @@ const EmbedIcon = ({ className = '' }: HTMLProps<HTMLDivElement>) => { function AppCard({ appInfo, cardType = 'webapp', - customBgColor, onChangeStatus, onSaveSiteConfig, onGenerateCode, @@ -92,10 +95,6 @@ function AppCard({ const appUrl = `${app_base_url}/${appMode}/${access_token}` const apiUrl = appInfo?.api_base_url - let bgColor = 'bg-primary-50 bg-opacity-40' - if (cardType === 'api') - bgColor = 'bg-purple-50' - const genClickFuncByName = (opName: string) => { switch (opName) { case t('appOverview.overview.appInfo.preview'): @@ -133,11 +132,8 @@ function AppCard({ } return ( - <div - className={ - `shadow-xs border-[0.5px] rounded-lg border-gray-200 ${className ?? ''}`} - > - <div className={`px-6 py-5 ${customBgColor ?? bgColor} rounded-lg`}> + <div className={cn('rounded-xl border-effects-highlight border-t border-l-[0.5px] bg-background-default', className)}> + <div className={cn('px-6 py-5')}> <div className="mb-2.5 flex flex-row items-start justify-between"> <AppBasic iconType={cardType} @@ -161,23 +157,20 @@ function AppCard({ </div> <div className="flex flex-col justify-center py-2"> <div className="py-1"> - <div className="pb-1 text-xs text-gray-500"> + <div className="pb-1 text-xs text-text-tertiary"> {isApp ? t('appOverview.overview.appInfo.accessibleAddress') : t('appOverview.overview.apiInfo.accessibleAddress')} </div> - <div className="w-full h-9 pl-2 pr-0.5 py-0.5 bg-black bg-opacity-2 rounded-lg border border-black border-opacity-5 justify-start items-center inline-flex"> + <div className="w-full h-9 px-2 py-0.5 bg-components-input-bg-normal rounded-lg justify-start items-center inline-flex"> <div className="h-4 px-2 justify-start items-start gap-2 flex flex-1 min-w-0"> - <div className="text-gray-700 text-xs font-medium text-ellipsis overflow-hidden whitespace-nowrap"> + <div className="text-text-secondary system-xs-medium truncate"> {isApp ? appUrl : apiUrl} </div> </div> - <Divider type="vertical" className="!h-3.5 shrink-0 !mx-0.5" /> - {isApp && <ShareQRCode content={isApp ? appUrl : apiUrl} selectorId={randomString(8)} className={'hover:bg-gray-200'} />} - <CopyFeedback - content={isApp ? appUrl : apiUrl} - className={'hover:bg-gray-200'} - /> + <Divider type="vertical" className="!h-3.5 shrink-0" /> + {isApp && <ShareQRCode content={isApp ? appUrl : apiUrl} />} + <CopyFeedback content={isApp ? appUrl : apiUrl}/> {/* button copy link/ button regenerate */} {showConfirmDelete && ( <Confirm @@ -196,22 +189,16 @@ function AppCard({ <Tooltip popupContent={t('appOverview.overview.appInfo.regenerate') || ''} > - <div - className="w-8 h-8 ml-0.5 cursor-pointer hover:bg-gray-200 rounded-lg" - onClick={() => setShowConfirmDelete(true)} - > - <div - className={ - `w-full h-full ${style.refreshIcon} ${genLoading ? style.generateLogo : ''}`} - ></div> - </div> + <ActionButton onClick={() => setShowConfirmDelete(true)}> + <RiLoopLeftLine className={cn('w-4 h-4', genLoading && 'animate-spin')} /> + </ActionButton> </Tooltip> )} </div> </div> </div> <div className={'pt-2 flex flex-row items-center flex-wrap gap-y-2'}> - {!isApp && <SecretKeyButton className='flex-shrink-0 !h-8 bg-white mr-2' textCls='!text-gray-700 font-medium' iconCls='stroke-[1.2px]' appId={appInfo.id} />} + {!isApp && <SecretKeyButton className='shrink-0 !h-8 mr-2' textCls='!text-text-secondary font-medium' iconCls='stroke-[1.2px]' appId={appInfo.id} />} {OPERATIONS_MAP[cardType].map((op) => { const disabled = op.opName === t('appOverview.overview.appInfo.settings.entry') diff --git a/web/app/components/app/overview/appChart.tsx b/web/app/components/app/overview/appChart.tsx index e0788bcda3..6ae6253812 100644 --- a/web/app/components/app/overview/appChart.tsx +++ b/web/app/components/app/overview/appChart.tsx @@ -216,8 +216,8 @@ const Chart: React.FC<IChartProps> = ({ return `<div style='color:#6B7280;font-size:12px'>${params.name}</div> <div style='font-size:14px;color:#1F2A37'>${valueFormatter((params.data as any)[yField])} ${!CHART_TYPE_CONFIG[chartType].showTokens - ? '' - : `<span style='font-size:12px'> + ? '' + : `<span style='font-size:12px'> <span style='margin-left:4px;color:#6B7280'>(</span> <span style='color:#FF8A4C'>~$${get(params.data, 'total_price', 0)}</span> <span style='color:#6B7280'>)</span> @@ -231,7 +231,7 @@ const Chart: React.FC<IChartProps> = ({ const sumData = isAvg ? (sum(yData) / yData.length) : sum(yData) return ( - <div className={`flex flex-col w-full px-6 py-4 border-[0.5px] rounded-lg border-gray-200 shadow-xs ${className ?? ''}`}> + <div className={`flex flex-col w-full px-6 py-4 rounded-xl bg-components-chart-bg shadow-xs ${className ?? ''}`}> <div className='mb-3'> <Basic name={title} type={timePeriod} hoverTip={explanation} /> </div> @@ -242,11 +242,11 @@ const Chart: React.FC<IChartProps> = ({ type={!CHART_TYPE_CONFIG[chartType].showTokens ? '' : <span>{t('appOverview.analysis.tokenUsage.consumed')} Tokens<span className='text-sm'> - <span className='ml-1 text-gray-500'>(</span> - <span className='text-orange-400'>~{sum(statistics.map(item => parseFloat(get(item, 'total_price', '0')))).toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4 })}</span> - <span className='text-gray-500'>)</span> + <span className='ml-1 text-text-tertiary'>(</span> + <span className='text-orange-400'>~{sum(statistics.map(item => Number.parseFloat(get(item, 'total_price', '0')))).toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 4 })}</span> + <span className='text-text-tertiary'>)</span> </span></span>} - textStyle={{ main: `!text-3xl !font-normal ${sumData === 0 ? '!text-gray-300' : ''}` }} /> + textStyle={{ main: `!text-3xl !font-normal ${sumData === 0 ? '!text-text-quaternary' : ''}` }} /> </div> <ReactECharts option={options} style={{ height: 160 }} /> </div> diff --git a/web/app/components/app/overview/customize/index.tsx b/web/app/components/app/overview/customize/index.tsx index d53aa00a6f..2925ba41ee 100644 --- a/web/app/components/app/overview/customize/index.tsx +++ b/web/app/components/app/overview/customize/index.tsx @@ -21,7 +21,7 @@ type IShareLinkProps = { } const StepNum: FC<{ children: React.ReactNode }> = ({ children }) => - <div className='h-7 w-7 flex justify-center items-center flex-shrink-0 mr-3 text-primary-600 bg-primary-50 rounded-2xl'> + <div className='h-7 w-7 flex justify-center items-center shrink-0 mr-3 text-text-accent bg-util-colors-blue-blue-50 rounded-2xl'> {children} </div> @@ -54,27 +54,27 @@ const CustomizeModal: FC<IShareLinkProps> = ({ className='!max-w-2xl w-[640px]' closable={true} > - <div className='w-full mt-4 px-6 py-5 border-gray-200 rounded-lg border-[0.5px]'> - <Tag bordered={true} hideBg={true} className='text-primary-600 border-primary-600 uppercase'>{t(`${prefixCustomize}.way`)} 1</Tag> - <p className='my-2 text-base font-medium text-gray-800'>{t(`${prefixCustomize}.way1.name`)}</p> + <div className='w-full mt-4 px-6 py-5 border-components-panel-border rounded-lg border-[0.5px]'> + <Tag bordered={true} hideBg={true} className='text-text-accent-secondary border-text-accent-secondary uppercase'>{t(`${prefixCustomize}.way`)} 1</Tag> + <p className='my-2 system-sm-medium text-text-secondary'>{t(`${prefixCustomize}.way1.name`)}</p> <div className='flex py-4'> <StepNum>1</StepNum> <div className='flex flex-col'> - <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step1`)}</div> - <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step1Tip`)}</div> + <div className='text-text-primary'>{t(`${prefixCustomize}.way1.step1`)}</div> + <div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step1Tip`)}</div> <a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target='_blank' rel='noopener noreferrer'> - <Button><GithubIcon className='text-gray-800 mr-2' />{t(`${prefixCustomize}.way1.step1Operation`)}</Button> + <Button><GithubIcon className='text-text-secondary mr-2' />{t(`${prefixCustomize}.way1.step1Operation`)}</Button> </a> </div> </div> <div className='flex pt-4'> <StepNum>2</StepNum> <div className='flex flex-col'> - <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step3`)}</div> - <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div> + <div className='text-text-primary'>{t(`${prefixCustomize}.way1.step3`)}</div> + <div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step2Tip`)}</div> <a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target='_blank' rel='noopener noreferrer'> <Button> - <div className='mr-1.5 border-solid border-t-0 border-r-[7px] border-l-[7px] border-b-[12px] border-r-transparent border-b-black border-l-transparent border-t-transparent'></div> + <div className='mr-1.5 border-solid border-t-0 border-r-[7px] border-l-[7px] border-b-[12px] border-r-transparent border-text-primary border-l-transparent border-t-transparent'></div> <span>{t(`${prefixCustomize}.way1.step2Operation`)}</span> </Button> </a> @@ -83,9 +83,9 @@ const CustomizeModal: FC<IShareLinkProps> = ({ <div className='flex py-4'> <StepNum>3</StepNum> <div className='flex flex-col w-full overflow-hidden'> - <div className='text-gray-900'>{t(`${prefixCustomize}.way1.step3`)}</div> - <div className='text-gray-500 text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step3Tip`)}</div> - <pre className='overflow-x-scroll box-border py-3 px-4 bg-gray-100 text-xs font-medium rounded-lg select-text'> + <div className='text-text-primary'>{t(`${prefixCustomize}.way1.step3`)}</div> + <div className='text-text-tertiary text-xs mt-1 mb-2'>{t(`${prefixCustomize}.way1.step3Tip`)}</div> + <pre className='overflow-x-scroll box-border py-3 px-4 bg-background-section text-xs font-medium rounded-lg select-text text-text-secondary border-[0.5px] border-components-panel-border'> NEXT_PUBLIC_APP_ID={`'${appId}'`} <br /> NEXT_PUBLIC_APP_KEY={'\'<Web API Key From Dify>\''} <br /> NEXT_PUBLIC_API_URL={`'${api_base_url}'`} @@ -94,9 +94,9 @@ const CustomizeModal: FC<IShareLinkProps> = ({ </div> </div> - <div className='w-full mt-4 px-6 py-5 border-gray-200 rounded-lg border-[0.5px]'> - <Tag bordered={true} hideBg={true} className='text-primary-600 border-primary-600 uppercase'>{t(`${prefixCustomize}.way`)} 2</Tag> - <p className='mt-2 text-base font-medium text-gray-800'>{t(`${prefixCustomize}.way2.name`)}</p> + <div className='w-full mt-4 px-6 py-5 border-components-panel-border rounded-lg border-[0.5px]'> + <Tag bordered={true} hideBg={true} className='text-text-accent-secondary border-text-accent-secondary uppercase'>{t(`${prefixCustomize}.way`)} 2</Tag> + <p className='my-2 system-sm-medium text-text-secondary'>{t(`${prefixCustomize}.way2.name`)}</p> <Button className='mt-2' onClick={() => @@ -109,8 +109,8 @@ const CustomizeModal: FC<IShareLinkProps> = ({ ) } > - <span className='text-sm text-gray-800'>{t(`${prefixCustomize}.way2.operation`)}</span> - <ArrowTopRightOnSquareIcon className='w-4 h-4 ml-1 text-gray-800 shrink-0' /> + <span className='text-sm text-text-secondary'>{t(`${prefixCustomize}.way2.operation`)}</span> + <ArrowTopRightOnSquareIcon className='w-4 h-4 ml-1 text-text-secondary shrink-0' /> </Button> </div> </Modal> diff --git a/web/app/components/app/overview/embedded/index.tsx b/web/app/components/app/overview/embedded/index.tsx index b71a3c3fdf..06b06e28a8 100644 --- a/web/app/components/app/overview/embedded/index.tsx +++ b/web/app/components/app/overview/embedded/index.tsx @@ -1,15 +1,19 @@ import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' +import { + RiClipboardFill, + RiClipboardLine, +} from '@remixicon/react' import copy from 'copy-to-clipboard' import style from './style.module.css' -import cn from '@/utils/classnames' import Modal from '@/app/components/base/modal' -import copyStyle from '@/app/components/base/copy-btn/style.module.css' import Tooltip from '@/app/components/base/tooltip' import { useAppContext } from '@/context/app-context' import { IS_CE_EDITION } from '@/config' import type { SiteInfo } from '@/models/share' import { useThemeContext } from '@/app/components/base/chat/embedded-chatbot/theme/theme-context' +import ActionButton from '@/app/components/base/action-button' +import cn from '@/utils/classnames' type Props = { siteInfo?: SiteInfo @@ -35,12 +39,12 @@ const OPTION_MAP = { `<script> window.difyChatbotConfig = { token: '${token}'${isTestEnv - ? `, + ? `, isDev: true` - : ''}${IS_CE_EDITION - ? `, + : ''}${IS_CE_EDITION + ? `, baseUrl: '${url}'` - : ''} + : ''} } </script> <script @@ -119,7 +123,7 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam wrapperClassName={className} closable={true} > - <div className="mb-4 mt-8 text-gray-900 text-[14px] font-medium leading-tight"> + <div className="mb-4 mt-8 text-text-primary system-sm-medium"> {t(`${prefixEmbedded}.explanation`)} </div> <div className="flex flex-wrap items-center justify-between gap-y-2"> @@ -143,30 +147,37 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam {option === 'chromePlugin' && ( <div className="w-full mt-6"> <div className={cn('gap-2 py-3 justify-center items-center inline-flex w-full rounded-lg', - 'bg-primary-600 hover:bg-primary-600/75 hover:shadow-md cursor-pointer text-white hover:shadow-sm flex-shrink-0')}> + 'bg-primary-600 hover:bg-primary-600/75 cursor-pointer text-white hover:shadow-sm flex-shrink-0')}> <div className={`w-4 h-4 relative ${style.pluginInstallIcon}`}></div> <div className="text-white text-sm font-medium font-['Inter'] leading-tight" onClick={navigateToChromeUrl}>{t(`${prefixEmbedded}.chromePlugin`)}</div> </div> </div> )} - <div className={cn('w-full bg-gray-100 rounded-lg flex-col justify-start items-start inline-flex', + <div className={cn('w-full bg-background-section border-[0.5px] border-components-panel-border rounded-lg flex-col justify-start items-start inline-flex', 'mt-6')}> - <div className="inline-flex items-center self-stretch justify-start gap-2 py-1 pl-3 pr-1 border border-black rounded-tl-lg rounded-tr-lg bg-gray-50 border-opacity-5"> - <div className="grow shrink basis-0 text-slate-700 text-[13px] font-medium leading-none"> + <div className="inline-flex items-center self-stretch justify-start gap-2 py-1 pl-3 pr-1 rounded-t-lg bg-background-section-burn"> + <div className="grow shrink-0 text-text-secondary system-sm-medium"> {t(`${prefixEmbedded}.${option}`)} </div> - <div className="flex items-center justify-center gap-1 p-2 rounded-lg"> - <Tooltip - popupContent={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''} - > - <div className="w-8 h-8 rounded-lg cursor-pointer hover:bg-gray-100"> - <div onClick={onClickCopy} className={`w-full h-full ${copyStyle.copyIcon} ${isCopied[option] ? copyStyle.copied : ''}`}></div> + <Tooltip + popupContent={ + (isCopied[option] + ? t(`${prefixEmbedded}.copied`) + : t(`${prefixEmbedded}.copy`)) || '' + } + > + <ActionButton> + <div + onClick={onClickCopy} + > + {isCopied[option] && <RiClipboardFill className='w-4 h-4' />} + {!isCopied[option] && <RiClipboardLine className='w-4 h-4' />} </div> - </Tooltip> - </div> + </ActionButton> + </Tooltip> </div> <div className="flex items-start justify-start w-full gap-2 p-3 overflow-x-auto"> - <div className="grow shrink basis-0 text-slate-700 text-[13px] leading-tight font-mono"> + <div className="grow shrink basis-0 text-text-secondary text-[13px] leading-tight font-mono"> <pre className='select-text'>{OPTION_MAP[option].getContent(appBaseUrl, accessToken, themeBuilder.theme?.primaryColor ?? '#1C64F2', isTestEnv)}</pre> </div> </div> diff --git a/web/app/components/app/overview/settings/index.tsx b/web/app/components/app/overview/settings/index.tsx index e7cc4148ef..7e80c83312 100644 --- a/web/app/components/app/overview/settings/index.tsx +++ b/web/app/components/app/overview/settings/index.tsx @@ -5,7 +5,6 @@ import { ChevronRightIcon } from '@heroicons/react/20/solid' import Link from 'next/link' import { Trans, useTranslation } from 'react-i18next' import { useContextSelector } from 'use-context-selector' -import s from './style.module.css' import Modal from '@/app/components/base/modal' import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' @@ -21,6 +20,8 @@ import Tooltip from '@/app/components/base/tooltip' import AppContext, { useAppContext } from '@/context/app-context' import type { AppIconSelection } from '@/app/components/base/app-icon-picker' import AppIconPicker from '@/app/components/base/app-icon-picker' +import Divider from '@/app/components/base/divider' +import cn from '@/utils/classnames' export type ISettingsModalProps = { isChat: boolean @@ -195,9 +196,9 @@ const SettingsModal: FC<ISettingsModalProps> = ({ title={t(`${prefixSettings}.title`)} isShow={isShow} onClose={onHide} - className={`${s.settingsModal}`} + className='max-w-[520px]' > - <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.webName`)}</div> + <div className={cn('mt-6 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.webName`)}</div> <div className='flex mt-2'> <AppIcon size='large' onClick={() => { setShowAppIconPicker(true) }} @@ -214,8 +215,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({ placeholder={t('app.appNamePlaceholder') || ''} /> </div> - <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.webDesc`)}</div> - <p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.webDescTip`)}</p> + <div className={cn('mt-6 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.webDesc`)}</div> + <p className={cn('mt-1 body-xs-regular text-text-tertiary')}>{t(`${prefixSettings}.webDescTip`)}</p> <Textarea className='mt-2' value={inputInfo.desc} @@ -225,36 +226,36 @@ const SettingsModal: FC<ISettingsModalProps> = ({ {isChatBot && ( <div className='w-full mt-4'> <div className='flex justify-between items-center'> - <div className={`font-medium ${s.settingTitle} text-gray-900 `}>{t('app.answerIcon.title')}</div> + <div className={cn('system-sm-semibold text-text-secondary')}>{t('app.answerIcon.title')}</div> <Switch defaultValue={inputInfo.use_icon_as_answer_icon} onChange={v => setInputInfo({ ...inputInfo, use_icon_as_answer_icon: v })} /> </div> - <p className='body-xs-regular text-gray-500'>{t('app.answerIcon.description')}</p> + <p className='body-xs-regular text-text-tertiary'>{t('app.answerIcon.description')}</p> </div> )} - <div className={`mt-6 mb-2 font-medium ${s.settingTitle} text-gray-900 `}>{t(`${prefixSettings}.language`)}</div> + <div className={cn('mt-6 mb-2 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.language`)}</div> <SimpleSelect items={languages.filter(item => item.supported)} defaultValue={language} onSelect={item => setLanguage(item.value as Language)} /> <div className='w-full mt-8'> - <p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.workflow.title`)}</p> + <p className='system-xs-medium text-text-tertiary'>{t(`${prefixSettings}.workflow.title`)}</p> <div className='flex justify-between items-center'> - <div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.workflow.subTitle`)}</div> + <div className='font-medium system-sm-semibold grow text-text-primary'>{t(`${prefixSettings}.workflow.subTitle`)}</div> <Switch disabled={!(appInfo.mode === 'workflow' || appInfo.mode === 'advanced-chat')} defaultValue={inputInfo.show_workflow_steps} onChange={v => setInputInfo({ ...inputInfo, show_workflow_steps: v })} /> </div> - <p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.workflow.showDesc`)}</p> + <p className='body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.workflow.showDesc`)}</p> </div> - {isChat && <> <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.chatColorTheme`)}</div> - <p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.chatColorThemeDesc`)}</p> + {isChat && <> <div className={cn('mt-8 system-sm-semibold text-text-secondary')}>{t(`${prefixSettings}.chatColorTheme`)}</div> + <p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.chatColorThemeDesc`)}</p> <Input className='mt-2 h-10' value={inputInfo.chatColorTheme ?? ''} @@ -262,14 +263,14 @@ const SettingsModal: FC<ISettingsModalProps> = ({ placeholder='E.g #A020F0' /> <div className="mt-1 flex justify-between items-center"> - <p className={`ml-2 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.chatColorThemeInverted`)}</p> + <p className='ml-2 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.chatColorThemeInverted`)}</p> <Switch defaultValue={inputInfo.chatColorThemeInverted} onChange={v => setInputInfo({ ...inputInfo, chatColorThemeInverted: v })}></Switch> </div> </>} {systemFeatures.enable_web_sso_switch_component && <div className='w-full mt-8'> - <p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p> + <p className='system-xs-medium text-text-tertiary'>{t(`${prefixSettings}.sso.label`)}</p> <div className='flex justify-between items-center'> - <div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div> + <div className='system-sm-semibold grow text-text-secondary'>{t(`${prefixSettings}.sso.title`)}</div> <Tooltip disabled={systemFeatures.sso_enforced_for_web} popupContent={ @@ -280,31 +281,31 @@ const SettingsModal: FC<ISettingsModalProps> = ({ <Switch disabled={!systemFeatures.sso_enforced_for_web || !isCurrentWorkspaceEditor} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch> </Tooltip> </div> - <p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p> + <p className='body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.sso.description`)}</p> </div>} {!isShowMore && <div className='w-full cursor-pointer mt-8' onClick={() => setIsShowMore(true)}> <div className='flex justify-between'> - <div className={`font-medium ${s.settingTitle} flex-grow text-gray-900`}>{t(`${prefixSettings}.more.entry`)}</div> - <div className='flex-shrink-0 w-4 h-4 text-gray-500'> + <div className='system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.entry`)}</div> + <div className='shrink-0 w-4 h-4 text-text-tertiary'> <ChevronRightIcon /> </div> </div> - <p className={`mt-1 ${s.policy} text-gray-500`}>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p> + <p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.more.copyright`)} & {t(`${prefixSettings}.more.privacyPolicy`)}</p> </div>} {isShowMore && <> - <hr className='w-full mt-6' /> - <div className={`mt-6 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.copyright`)}</div> + <Divider className='my-6' /> + <div className='system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.copyright`)}</div> <Input className='mt-2 h-10' value={inputInfo.copyright} onChange={onChange('copyright')} placeholder={t(`${prefixSettings}.more.copyRightPlaceholder`) as string} /> - <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.privacyPolicy`)}</div> - <p className={`mt-1 ${s.settingsTip} text-gray-500`}> + <div className='mt-8 system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.privacyPolicy`)}</div> + <p className='mt-1 body-xs-regular text-text-tertiary'> <Trans i18nKey={`${prefixSettings}.more.privacyPolicyTip`} - components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer' className='text-primary-600' /> }} + components={{ privacyPolicyLink: <Link href={'https://docs.dify.ai/user-agreement/privacy-policy'} target='_blank' rel='noopener noreferrer' className='text-text-accent' /> }} /> </p> <Input @@ -313,8 +314,8 @@ const SettingsModal: FC<ISettingsModalProps> = ({ onChange={onChange('privacyPolicy')} placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`) as string} /> - <div className={`mt-8 font-medium ${s.settingTitle} text-gray-900`}>{t(`${prefixSettings}.more.customDisclaimer`)}</div> - <p className={`mt-1 ${s.settingsTip} text-gray-500`}>{t(`${prefixSettings}.more.customDisclaimerTip`)}</p> + <div className='mt-8 system-sm-semibold text-text-secondary'>{t(`${prefixSettings}.more.customDisclaimer`)}</div> + <p className='mt-1 body-xs-regular text-text-tertiary'>{t(`${prefixSettings}.more.customDisclaimerTip`)}</p> <Input className='mt-2 h-10' value={inputInfo.customDisclaimer} diff --git a/web/app/components/app/overview/settings/style.module.css b/web/app/components/app/overview/settings/style.module.css deleted file mode 100644 index 4a3e5a483d..0000000000 --- a/web/app/components/app/overview/settings/style.module.css +++ /dev/null @@ -1,18 +0,0 @@ -.settingsModal { - max-width: 32.5rem !important; -} - -.settingTitle { - line-height: 21px; - font-size: 0.875rem; -} - -.settingsTip { - line-height: 1.125rem; - font-size: 0.75rem; -} - -.policy { - font-size: 0.75rem; - line-height: 1.125rem; -} \ No newline at end of file diff --git a/web/app/components/app/store.ts b/web/app/components/app/store.ts index 5f02f92f0d..3764895ac9 100644 --- a/web/app/components/app/store.ts +++ b/web/app/components/app/store.ts @@ -2,7 +2,7 @@ import { create } from 'zustand' import type { App, AppSSO } from '@/types/app' import type { IChatItem } from '@/app/components/base/chat/chat/type' -type State = { +interface State { appDetail?: App & Partial<AppSSO> appSidebarExpand: string currentLogItem?: IChatItem @@ -13,7 +13,7 @@ type State = { showAppConfigureFeaturesModal: boolean } -type Action = { +interface Action { setAppDetail: (appDetail?: App & Partial<AppSSO>) => void setAppSiderbarExpand: (state: string) => void setCurrentLogItem: (item?: IChatItem) => void diff --git a/web/app/components/app/switch-app-modal/index.tsx b/web/app/components/app/switch-app-modal/index.tsx index 5b45095251..e1fe809e10 100644 --- a/web/app/components/app/switch-app-modal/index.tsx +++ b/web/app/components/app/switch-app-modal/index.tsx @@ -25,7 +25,7 @@ import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/aler import AppIcon from '@/app/components/base/app-icon' import { useStore as useAppStore } from '@/app/components/app/store' -type SwitchAppModalProps = { +interface SwitchAppModalProps { show: boolean appDetail: App onSuccess?: () => void diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index ac868e6ee3..a8084af128 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -33,7 +33,7 @@ import { useChatContext } from '@/app/components/base/chat/chat/context' const MAX_DEPTH = 3 -export type IGenerationItemProps = { +export interface IGenerationItemProps { isWorkflow?: boolean workflowProcessData?: WorkflowProcess className?: string diff --git a/web/app/components/app/workflow-log/detail.tsx b/web/app/components/app/workflow-log/detail.tsx index 2ee9f83c54..f5cf7c3a3b 100644 --- a/web/app/components/app/workflow-log/detail.tsx +++ b/web/app/components/app/workflow-log/detail.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next' import { RiCloseLine } from '@remixicon/react' import Run from '@/app/components/workflow/run' -type ILogDetail = { +interface ILogDetail { runID: string onClose: () => void } diff --git a/web/app/components/app/workflow-log/filter.tsx b/web/app/components/app/workflow-log/filter.tsx index 466e9b8fda..d25f938719 100644 --- a/web/app/components/app/workflow-log/filter.tsx +++ b/web/app/components/app/workflow-log/filter.tsx @@ -6,7 +6,7 @@ import type { QueryParam } from './index' import Chip from '@/app/components/base/chip' import Input from '@/app/components/base/input' -type IFilterProps = { +interface IFilterProps { queryParams: QueryParam setQueryParams: (v: QueryParam) => void } diff --git a/web/app/components/base/action-button/index.css b/web/app/components/base/action-button/index.css index 96fbb14c6c..13f333b11d 100644 --- a/web/app/components/base/action-button/index.css +++ b/web/app/components/base/action-button/index.css @@ -2,9 +2,7 @@ @layer components { .action-btn { - @apply inline-flex justify-center items-center cursor-pointer text-text-tertiary - hover:text-text-secondary - hover:bg-state-base-hover + @apply inline-flex justify-center items-center cursor-pointer text-text-tertiary hover:text-text-secondary hover:bg-state-base-hover } .action-btn-disabled { @@ -29,21 +27,15 @@ } .action-btn.action-btn-active { - @apply - text-text-accent - bg-state-accent-active - hover:bg-state-accent-active-alt + @apply text-text-accent bg-state-accent-active hover:bg-state-accent-active-alt } .action-btn.action-btn-disabled { - @apply - text-text-disabled + @apply text-text-disabled } .action-btn.action-btn-destructive { - @apply - text-text-destructive - bg-state-destructive-hover + @apply text-text-destructive bg-state-destructive-hover } } \ No newline at end of file diff --git a/web/app/components/base/action-button/index.tsx b/web/app/components/base/action-button/index.tsx index 9e4552a2b7..845edfbd6d 100644 --- a/web/app/components/base/action-button/index.tsx +++ b/web/app/components/base/action-button/index.tsx @@ -28,7 +28,7 @@ const actionButtonVariants = cva( ) export type ActionButtonProps = { - size?: 'xs' | 'm' | 'l' | 'xl' + size?: 'xs' | 's' | 'm' | 'l' | 'xl' state?: ActionButtonState styleCss?: CSSProperties } & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof actionButtonVariants> diff --git a/web/app/components/base/app-icon/style.module.css b/web/app/components/base/app-icon/style.module.css new file mode 100644 index 0000000000..151bc6d3fc --- /dev/null +++ b/web/app/components/base/app-icon/style.module.css @@ -0,0 +1,23 @@ +.appIcon { + @apply flex items-center justify-center relative w-9 h-9 text-lg rounded-lg grow-0 shrink-0; +} + +.appIcon.large { + @apply w-10 h-10; +} + +.appIcon.small { + @apply w-8 h-8; +} + +.appIcon.tiny { + @apply w-6 h-6 text-base; +} + +.appIcon.xs { + @apply w-5 h-5 text-base; +} + +.appIcon.rounded { + @apply rounded-full; +} \ No newline at end of file diff --git a/web/app/components/base/audio-btn/audio.player.manager.ts b/web/app/components/base/audio-btn/audio.player.manager.ts index 17d92f8dc2..9b3349754f 100644 --- a/web/app/components/base/audio-btn/audio.player.manager.ts +++ b/web/app/components/base/audio-btn/audio.player.manager.ts @@ -1,6 +1,6 @@ import AudioPlayer from '@/app/components/base/audio-btn/audio' declare global { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + // eslint-disable-next-line ts/consistent-type-definitions interface AudioPlayerManager { instance: AudioPlayerManager } @@ -12,6 +12,7 @@ export class AudioPlayerManager { private audioPlayers: AudioPlayer | null = null private msgId: string | undefined + // eslint-disable-next-line private constructor() { } diff --git a/web/app/components/base/audio-btn/audio.ts b/web/app/components/base/audio-btn/audio.ts index baf675d0be..d7fae02f82 100644 --- a/web/app/components/base/audio-btn/audio.ts +++ b/web/app/components/base/audio-btn/audio.ts @@ -2,7 +2,7 @@ import Toast from '@/app/components/base/toast' import { textToAudioStream } from '@/service/share' declare global { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + // eslint-disable-next-line ts/consistent-type-definitions interface Window { ManagedMediaSource: any } diff --git a/web/app/components/base/audio-btn/index.tsx b/web/app/components/base/audio-btn/index.tsx index 593411ed4d..40a7b96666 100644 --- a/web/app/components/base/audio-btn/index.tsx +++ b/web/app/components/base/audio-btn/index.tsx @@ -7,7 +7,7 @@ import Tooltip from '@/app/components/base/tooltip' import Loading from '@/app/components/base/loading' import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager' -type AudioBtnProps = { +interface AudioBtnProps { id?: string voice?: string value?: string diff --git a/web/app/components/base/audio-gallery/AudioPlayer.module.css b/web/app/components/base/audio-gallery/AudioPlayer.module.css index 6c070e107c..c5dd277fd6 100644 --- a/web/app/components/base/audio-gallery/AudioPlayer.module.css +++ b/web/app/components/base/audio-gallery/AudioPlayer.module.css @@ -2,15 +2,15 @@ display: flex; flex-direction: row; align-items: center; - background-color: #ffffff; + background-color: var(--color-components-chat-input-audio-bg-alt); border-radius: 10px; padding: 8px; min-width: 240px; max-width: 420px; max-height: 40px; backdrop-filter: blur(5px); - border: 1px solid rgba(16, 24, 40, 0.08); - box-shadow: 0 1px 2px rgba(9, 9, 11, 0.05); + border: 1px solid var(--color-components-panel-border-subtle); + box-shadow: 0 1px 2px var(--color-shadow-shadow-3); gap: 8px; } @@ -19,8 +19,8 @@ width: 16px; height: 16px; border-radius: 50%; - background-color: #296DFF; - color: white; + background-color: var(--color-components-button-primary-bg); + color: var(--color-components-chat-input-audio-bg-alt); border: none; cursor: pointer; align-items: center; @@ -30,16 +30,15 @@ } .playButton:hover { - background-color: #3367d6; + background-color: var(--color-components-button-primary-bg-hover); } .playButton:disabled { - background-color: #bdbdbf; + background-color: var(--color-components-button-primary-bg-disabled); } .audioControls { flex-grow: 1; - } .progressBarContainer { @@ -76,8 +75,8 @@ .timeDisplay { /* position: absolute; */ - color: #296DFF; - border-radius: 2px; + color: var(--color-text-accent-secondary); + font-size: 12px; order: 0; height: 100%; width: 50px; @@ -97,7 +96,6 @@ } */ .duration { - background-color: rgba(255, 255, 255, 0.8); padding: 2px 4px; border-radius: 10px; } @@ -114,6 +112,6 @@ } .playButton svg path, -.playButton svg rect{ - fill:currentColor; -} +.playButton svg rect { + fill: currentColor; +} \ No newline at end of file diff --git a/web/app/components/base/audio-gallery/AudioPlayer.tsx b/web/app/components/base/audio-gallery/AudioPlayer.tsx index c482981e8a..95d4c69c83 100644 --- a/web/app/components/base/audio-gallery/AudioPlayer.tsx +++ b/web/app/components/base/audio-gallery/AudioPlayer.tsx @@ -55,7 +55,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src }) => { audio.load() // Delayed generation of waveform data - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define const timer = setTimeout(() => generateWaveformData(src), 1000) return () => { diff --git a/web/app/components/base/badge.tsx b/web/app/components/base/badge.tsx index 787b005a8f..fe034ad2f4 100644 --- a/web/app/components/base/badge.tsx +++ b/web/app/components/base/badge.tsx @@ -1,11 +1,13 @@ +import type { ReactNode } from 'react' import { memo } from 'react' import cn from '@/utils/classnames' type BadgeProps = { className?: string - text?: string - children?: React.ReactNode + text?: ReactNode + children?: ReactNode uppercase?: boolean + hasRedCornerMark?: boolean } const Badge = ({ @@ -13,15 +15,20 @@ const Badge = ({ text, children, uppercase = true, + hasRedCornerMark, }: BadgeProps) => { return ( <div className={cn( - 'inline-flex items-center px-[5px] h-5 rounded-[5px] border border-divider-deep leading-3 text-text-tertiary', + 'relative inline-flex items-center px-[5px] h-5 rounded-[5px] border border-divider-deep leading-3 text-text-tertiary', uppercase ? 'system-2xs-medium-uppercase' : 'system-xs-medium', className, )} > + {hasRedCornerMark && ( + <div className='absolute top-[-2px] right-[-2px] w-1.5 h-1.5 border border-components-badge-status-light-error-border-inner bg-components-badge-status-light-error-bg rounded-[2px] shadow-sm'> + </div> + )} {children || text} </div> ) diff --git a/web/app/components/base/badge/index.css b/web/app/components/base/badge/index.css new file mode 100644 index 0000000000..99db573c9c --- /dev/null +++ b/web/app/components/base/badge/index.css @@ -0,0 +1,28 @@ +@tailwind components; + +@layer components { + .badge { + @apply inline-flex justify-center items-center text-text-tertiary border border-divider-deep + } + + .badge-l { + @apply rounded-md gap-1 min-w-6 + } + + /* m is for the regular button */ + .badge-m { + @apply rounded-md gap-[3px] min-w-5 + } + + .badge-s { + @apply rounded-[5px] gap-0.5 min-w-[18px] + } + + .badge.badge-warning { + @apply text-text-warning border border-text-warning + } + + .badge.badge-accent { + @apply text-text-accent-secondary border border-text-accent-secondary + } +} \ No newline at end of file diff --git a/web/app/components/base/badge/index.tsx b/web/app/components/base/badge/index.tsx new file mode 100644 index 0000000000..88ba026e14 --- /dev/null +++ b/web/app/components/base/badge/index.tsx @@ -0,0 +1,81 @@ +import type { CSSProperties, ReactNode } from 'react' +import React from 'react' +import { type VariantProps, cva } from 'class-variance-authority' +import classNames from '@/utils/classnames' +import './index.css' + +enum BadgeState { + Warning = 'warning', + Accent = 'accent', + Default = '', +} + +const BadgeVariants = cva( + 'badge', + { + variants: { + size: { + s: 'badge-s', + m: 'badge-m', + l: 'badge-l', + }, + }, + defaultVariants: { + size: 'm', + }, + }, +) + +type BadgeProps = { + size?: 's' | 'm' | 'l' + iconOnly?: boolean + uppercase?: boolean + state?: BadgeState + styleCss?: CSSProperties + children?: ReactNode +} & React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof BadgeVariants> + +function getBadgeState(state: BadgeState) { + switch (state) { + case BadgeState.Warning: + return 'badge-warning' + case BadgeState.Accent: + return 'badge-accent' + default: + return '' + } +} + +const Badge: React.FC<BadgeProps> = ({ + className, + size, + state = BadgeState.Default, + iconOnly = false, + uppercase = false, + styleCss, + children, + ...props +}) => { + return ( + <div + className={classNames( + BadgeVariants({ size, className }), + getBadgeState(state), + size === 's' + ? (iconOnly ? 'p-[3px]' : 'px-[5px] py-[3px]') + : size === 'l' + ? (iconOnly ? 'p-1.5' : 'px-2 py-1') + : (iconOnly ? 'p-1' : 'px-[5px] py-[2px]'), + uppercase ? 'system-2xs-medium-uppercase' : 'system-2xs-medium', + )} + style={styleCss} + {...props} + > + {children} + </div> + ) +} +Badge.displayName = 'Badge' + +export default Badge +export { Badge, BadgeState, BadgeVariants } diff --git a/web/app/components/base/button/add-button.tsx b/web/app/components/base/button/add-button.tsx index ab0e247d5f..0b06a493ad 100644 --- a/web/app/components/base/button/add-button.tsx +++ b/web/app/components/base/button/add-button.tsx @@ -4,7 +4,7 @@ import React from 'react' import { RiAddLine } from '@remixicon/react' import cn from '@/utils/classnames' -type Props = { +interface Props { className?: string onClick: () => void } diff --git a/web/app/components/base/chat/__tests__/utils.spec.ts b/web/app/components/base/chat/__tests__/utils.spec.ts index 0bff8a77a1..990e59d5ee 100644 --- a/web/app/components/base/chat/__tests__/utils.spec.ts +++ b/web/app/components/base/chat/__tests__/utils.spec.ts @@ -263,7 +263,7 @@ describe('build chat item tree and get thread messages', () => { expect(tree7).toMatchSnapshot() }) - const partialMessages2 = (partialMessages as ChatItemInTree[]) + const partialMessages2 = partialMessages as ChatItemInTree[] const tree8 = buildChatItemTree(partialMessages2) it('should work with partial messages 2', () => { expect(tree8).toMatchSnapshot() diff --git a/web/app/components/base/chat/chat-with-history/config-panel/form-input.tsx b/web/app/components/base/chat/chat-with-history/config-panel/form-input.tsx index 9be0ff319b..2e6df72bfb 100644 --- a/web/app/components/base/chat/chat-with-history/config-panel/form-input.tsx +++ b/web/app/components/base/chat/chat-with-history/config-panel/form-input.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import { memo } from 'react' import Textarea from '@/app/components/base/textarea' -type InputProps = { +interface InputProps { form: any value: string onChange: (variable: string, value: string) => void diff --git a/web/app/components/base/chat/chat-with-history/context.tsx b/web/app/components/base/chat/chat-with-history/context.tsx index 060c178993..1000c4899a 100644 --- a/web/app/components/base/chat/chat-with-history/context.tsx +++ b/web/app/components/base/chat/chat-with-history/context.tsx @@ -16,7 +16,7 @@ import type { ConversationItem, } from '@/models/share' -export type ChatWithHistoryContextValue = { +export interface ChatWithHistoryContextValue { appInfoError?: any appInfoLoading?: boolean appMeta?: AppMeta diff --git a/web/app/components/base/chat/chat-with-history/index.tsx b/web/app/components/base/chat/chat-with-history/index.tsx index 16524406d4..886bd0e7ef 100644 --- a/web/app/components/base/chat/chat-with-history/index.tsx +++ b/web/app/components/base/chat/chat-with-history/index.tsx @@ -20,7 +20,7 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { checkOrSetAccessToken } from '@/app/components/share/utils' import AppUnavailable from '@/app/components/base/app-unavailable' -type ChatWithHistoryProps = { +interface ChatWithHistoryProps { className?: string } const ChatWithHistory: FC<ChatWithHistoryProps> = ({ @@ -99,7 +99,7 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({ ) } -export type ChatWithHistoryWrapProps = { +export interface ChatWithHistoryWrapProps { installedAppInfo?: InstalledApp className?: string } diff --git a/web/app/components/base/chat/chat/answer/agent-content.tsx b/web/app/components/base/chat/chat/answer/agent-content.tsx index 6f03c938f1..5e71cf6526 100644 --- a/web/app/components/base/chat/chat/answer/agent-content.tsx +++ b/web/app/components/base/chat/chat/answer/agent-content.tsx @@ -8,7 +8,7 @@ import Thought from '@/app/components/base/chat/chat/thought' import { FileList } from '@/app/components/base/file-uploader' import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' -type AgentContentProps = { +interface AgentContentProps { item: ChatItem responding?: boolean } diff --git a/web/app/components/base/chat/chat/answer/basic-content.tsx b/web/app/components/base/chat/chat/answer/basic-content.tsx index 6c8a44cf52..943262cf0c 100644 --- a/web/app/components/base/chat/chat/answer/basic-content.tsx +++ b/web/app/components/base/chat/chat/answer/basic-content.tsx @@ -4,7 +4,7 @@ import type { ChatItem } from '../../types' import { Markdown } from '@/app/components/base/markdown' import cn from '@/utils/classnames' -type BasicContentProps = { +interface BasicContentProps { item: ChatItem } const BasicContent: FC<BasicContentProps> = ({ diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index c6d14ddead..c90a346979 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -23,7 +23,7 @@ import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows import cn from '@/utils/classnames' import { FileList } from '@/app/components/base/file-uploader' -type AnswerProps = { +interface AnswerProps { item: ChatItem question: string index: number diff --git a/web/app/components/base/chat/chat/answer/operation.tsx b/web/app/components/base/chat/chat/answer/operation.tsx index dcd3df6482..9886b755b5 100644 --- a/web/app/components/base/chat/chat/answer/operation.tsx +++ b/web/app/components/base/chat/chat/answer/operation.tsx @@ -21,7 +21,7 @@ import { import Tooltip from '@/app/components/base/tooltip' import Log from '@/app/components/base/chat/chat/log' -type OperationProps = { +interface OperationProps { item: ChatItem question: string index: number diff --git a/web/app/components/base/chat/chat/answer/workflow-process.tsx b/web/app/components/base/chat/chat/answer/workflow-process.tsx index bb9abdb6fc..c7e17d10d3 100644 --- a/web/app/components/base/chat/chat/answer/workflow-process.tsx +++ b/web/app/components/base/chat/chat/answer/workflow-process.tsx @@ -1,5 +1,4 @@ import { - useCallback, useEffect, useMemo, useState, @@ -15,7 +14,6 @@ import TracingPanel from '@/app/components/workflow/run/tracing-panel' import cn from '@/utils/classnames' import { CheckCircle } from '@/app/components/base/icons/src/vender/solid/general' import { WorkflowRunningStatus } from '@/app/components/workflow/types' -import { useStore as useAppStore } from '@/app/components/app/store' type WorkflowProcessProps = { data: WorkflowProcess @@ -26,7 +24,6 @@ type WorkflowProcessProps = { } const WorkflowProcessItem = ({ data, - item, expand = false, hideInfo = false, hideProcessDetail = false, @@ -54,22 +51,6 @@ const WorkflowProcessItem = ({ setCollapse(!expand) }, [expand]) - const setCurrentLogItem = useAppStore(s => s.setCurrentLogItem) - const setShowMessageLogModal = useAppStore(s => s.setShowMessageLogModal) - const setCurrentLogModalActiveTab = useAppStore(s => s.setCurrentLogModalActiveTab) - - const showIterationDetail = useCallback(() => { - setCurrentLogItem(item) - setCurrentLogModalActiveTab('TRACING') - setShowMessageLogModal(true) - }, [item, setCurrentLogItem, setCurrentLogModalActiveTab, setShowMessageLogModal]) - - const showRetryDetail = useCallback(() => { - setCurrentLogItem(item) - setCurrentLogModalActiveTab('TRACING') - setShowMessageLogModal(true) - }, [item, setCurrentLogItem, setCurrentLogModalActiveTab, setShowMessageLogModal]) - return ( <div className={cn( @@ -110,8 +91,6 @@ const WorkflowProcessItem = ({ { <TracingPanel list={data.tracing} - onShowIterationDetail={showIterationDetail} - onShowRetryDetail={showRetryDetail} hideNodeInfo={hideInfo} hideNodeProcessDetail={hideProcessDetail} /> diff --git a/web/app/components/base/chat/chat/hooks.ts b/web/app/components/base/chat/chat/hooks.ts index fa923ca009..869a51396c 100644 --- a/web/app/components/base/chat/chat/hooks.ts +++ b/web/app/components/base/chat/chat/hooks.ts @@ -33,7 +33,7 @@ import { } from '@/app/components/base/file-uploader/utils' type GetAbortController = (abortController: AbortController) => void -type SendCallback = { +interface SendCallback { onGetConversationMessages?: (conversationId: string, getAbortController: GetAbortController) => Promise<any> onGetSuggestedQuestions?: (responseItemId: string, getAbortController: GetAbortController) => Promise<any> onConversationComplete?: (conversationId: string) => void diff --git a/web/app/components/base/chat/chat/index.tsx b/web/app/components/base/chat/chat/index.tsx index e6de01252d..ad7a708d23 100644 --- a/web/app/components/base/chat/chat/index.tsx +++ b/web/app/components/base/chat/chat/index.tsx @@ -35,7 +35,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal' import { useStore as useAppStore } from '@/app/components/app/store' import type { AppData } from '@/models/share' -export type ChatProps = { +export interface ChatProps { appData?: AppData chatList: ChatItem[] config?: ChatConfig diff --git a/web/app/components/base/chat/chat/question.tsx b/web/app/components/base/chat/chat/question.tsx index 7052c1fb5e..3df5aa215c 100644 --- a/web/app/components/base/chat/chat/question.tsx +++ b/web/app/components/base/chat/chat/question.tsx @@ -12,7 +12,7 @@ import { User } from '@/app/components/base/icons/src/public/avatar' import { Markdown } from '@/app/components/base/markdown' import { FileList } from '@/app/components/base/file-uploader' -type QuestionProps = { +interface QuestionProps { item: ChatItem questionIcon?: ReactNode theme: Theme | null | undefined diff --git a/web/app/components/base/chat/chat/thought/index.tsx b/web/app/components/base/chat/chat/thought/index.tsx index 409f83dfaa..dbadd3465e 100644 --- a/web/app/components/base/chat/chat/thought/index.tsx +++ b/web/app/components/base/chat/chat/thought/index.tsx @@ -4,7 +4,7 @@ import React from 'react' import type { ThoughtItem, ToolInfoInThought } from '../type' import ToolDetail from '@/app/components/base/chat/chat/answer/tool-detail' -export type IThoughtProps = { +export interface IThoughtProps { thought: ThoughtItem isFinished: boolean } diff --git a/web/app/components/base/chat/chat/type.ts b/web/app/components/base/chat/chat/type.ts index 7f22ba05b7..bd61ae6e97 100644 --- a/web/app/components/base/chat/chat/type.ts +++ b/web/app/components/base/chat/chat/type.ts @@ -4,13 +4,13 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types' import type { InputVarType } from '@/app/components/workflow/types' import type { FileResponse } from '@/types/workflow' -export type MessageMore = { +export interface MessageMore { time: string tokens: number latency: number | string } -export type FeedbackType = { +export interface FeedbackType { rating: MessageRating content?: string | null } @@ -26,7 +26,7 @@ export type SubmitAnnotationFunc = ( export type DisplayScene = 'web' | 'console' -export type ToolInfoInThought = { +export interface ToolInfoInThought { name: string label: string input: string @@ -34,7 +34,7 @@ export type ToolInfoInThought = { isFinished: boolean } -export type ThoughtItem = { +export interface ThoughtItem { id: string tool: string // plugin or dataset. May has multi. thought: string @@ -47,7 +47,7 @@ export type ThoughtItem = { message_files?: FileEntity[] } -export type CitationItem = { +export interface CitationItem { content: string data_source_type: string dataset_name: string @@ -62,7 +62,7 @@ export type CitationItem = { word_count: number } -export type IChatItem = { +export interface IChatItem { id: string content: string citation?: CitationItem[] @@ -104,7 +104,7 @@ export type IChatItem = { nextSibling?: string } -export type Metadata = { +export interface Metadata { retriever_resources?: CitationItem[] annotation_reply: { id: string @@ -115,20 +115,20 @@ export type Metadata = { } } -export type MessageEnd = { +export interface MessageEnd { id: string metadata: Metadata files?: FileResponse[] } -export type MessageReplace = { +export interface MessageReplace { id: string task_id: string answer: string conversation_id: string } -export type AnnotationReply = { +export interface AnnotationReply { id: string task_id: string answer: string @@ -137,7 +137,7 @@ export type AnnotationReply = { annotation_author_name: string } -export type InputForm = { +export interface InputForm { type: InputVarType label: string variable: any diff --git a/web/app/components/base/chat/embedded-chatbot/config-panel/form-input.tsx b/web/app/components/base/chat/embedded-chatbot/config-panel/form-input.tsx index 9be0ff319b..2e6df72bfb 100644 --- a/web/app/components/base/chat/embedded-chatbot/config-panel/form-input.tsx +++ b/web/app/components/base/chat/embedded-chatbot/config-panel/form-input.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import { memo } from 'react' import Textarea from '@/app/components/base/textarea' -type InputProps = { +interface InputProps { form: any value: string onChange: (variable: string, value: string) => void diff --git a/web/app/components/base/chat/embedded-chatbot/context.tsx b/web/app/components/base/chat/embedded-chatbot/context.tsx index f48247a691..546f9c7c70 100644 --- a/web/app/components/base/chat/embedded-chatbot/context.tsx +++ b/web/app/components/base/chat/embedded-chatbot/context.tsx @@ -15,7 +15,7 @@ import type { ConversationItem, } from '@/models/share' -export type EmbeddedChatbotContextValue = { +export interface EmbeddedChatbotContextValue { appInfoError?: any appInfoLoading?: boolean appMeta?: AppMeta diff --git a/web/app/components/base/chat/types.ts b/web/app/components/base/chat/types.ts index 8d9dacdcd7..442cba85e2 100644 --- a/web/app/components/base/chat/types.ts +++ b/web/app/components/base/chat/types.ts @@ -14,32 +14,32 @@ export type { PromptVariable, } from '@/models/debug' -export type UserInputForm = { +export interface UserInputForm { default: string label: string required: boolean variable: string } -export type UserInputFormTextInput = { +export interface UserInputFormTextInput { 'text-input': UserInputForm & { max_length: number } } -export type UserInputFormSelect = { - 'select': UserInputForm & { +export interface UserInputFormSelect { + select: UserInputForm & { options: string[] } } -export type UserInputFormParagraph = { - 'paragraph': UserInputForm +export interface UserInputFormParagraph { + paragraph: UserInputForm } export type VisionConfig = VisionSettings -export type EnableType = { +export interface EnableType { enabled: boolean } @@ -50,7 +50,7 @@ export type ChatConfig = Omit<ModelConfig, 'model'> & { supportCitationHitInfo?: boolean } -export type WorkflowProcess = { +export interface WorkflowProcess { status: WorkflowRunningStatus tracing: NodeTracing[] expand?: boolean // for UI @@ -73,10 +73,10 @@ export type OnSend = (message: string, files?: FileEntity[], last_answer?: ChatI export type OnRegenerate = (chatItem: ChatItem) => void -export type Callback = { +export interface Callback { onSuccess: () => void } -export type Feedback = { +export interface Feedback { rating: 'like' | 'dislike' | null } diff --git a/web/app/components/base/copy-btn/index.tsx b/web/app/components/base/copy-btn/index.tsx index 2acb5d8e76..5159a96040 100644 --- a/web/app/components/base/copy-btn/index.tsx +++ b/web/app/components/base/copy-btn/index.tsx @@ -1,6 +1,7 @@ 'use client' import { useState } from 'react' import { t } from 'i18next' +import { debounce } from 'lodash-es' import copy from 'copy-to-clipboard' import s from './style.module.css' import Tooltip from '@/app/components/base/tooltip' @@ -18,24 +19,32 @@ const CopyBtn = ({ }: ICopyBtnProps) => { const [isCopied, setIsCopied] = useState(false) + const onClickCopy = debounce(() => { + copy(value) + setIsCopied(true) + }, 100) + + const onMouseLeave = debounce(() => { + setIsCopied(false) + }, 100) + return ( <div className={`${className}`}> <Tooltip popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))} + asChild={false} > <div - className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'} + onMouseLeave={onMouseLeave} + className={'box-border p-0.5 flex items-center justify-center rounded-md bg-components-button-secondary-bg cursor-pointer'} style={!isPlain ? { boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)', } : {}} - onClick={() => { - copy(value) - setIsCopied(true) - }} + onClick={onClickCopy} > - <div className={`w-6 h-6 rounded-md hover:bg-gray-50 ${s.copyIcon} ${isCopied ? s.copied : ''}`}></div> + <div className={`w-6 h-6 rounded-md hover:bg-components-button-secondary-bg-hover ${s.copyIcon} ${isCopied ? s.copied : ''}`}></div> </div> </Tooltip> </div> diff --git a/web/app/components/base/copy-feedback/index.tsx b/web/app/components/base/copy-feedback/index.tsx index ead1eb1d18..bc1cca5205 100644 --- a/web/app/components/base/copy-feedback/index.tsx +++ b/web/app/components/base/copy-feedback/index.tsx @@ -1,10 +1,15 @@ 'use client' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' +import { + RiClipboardFill, + RiClipboardLine, +} from '@remixicon/react' import { debounce } from 'lodash-es' import copy from 'copy-to-clipboard' import copyStyle from './style.module.css' import Tooltip from '@/app/components/base/tooltip' +import ActionButton from '@/app/components/base/action-button' type Props = { content: string @@ -13,7 +18,7 @@ type Props = { const prefixEmbedded = 'appOverview.overview.appInfo.embedded' -const CopyFeedback = ({ content, className }: Props) => { +const CopyFeedback = ({ content }: Props) => { const { t } = useTranslation() const [isCopied, setIsCopied] = useState<boolean>(false) @@ -34,19 +39,15 @@ const CopyFeedback = ({ content, className }: Props) => { : t(`${prefixEmbedded}.copy`)) || '' } > - <div - className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${ - className ?? '' - }`} - > + <ActionButton> <div onClick={onClickCopy} onMouseLeave={onMouseLeave} - className={`w-full h-full ${copyStyle.copyIcon} ${ - isCopied ? copyStyle.copied : '' - }`} - ></div> - </div> + > + {isCopied && <RiClipboardFill className='w-4 h-4' />} + {!isCopied && <RiClipboardLine className='w-4 h-4' />} + </div> + </ActionButton> </Tooltip> ) } diff --git a/web/app/components/base/drawer/index.tsx b/web/app/components/base/drawer/index.tsx index c1057b9f1f..e34dc7697a 100644 --- a/web/app/components/base/drawer/index.tsx +++ b/web/app/components/base/drawer/index.tsx @@ -51,18 +51,18 @@ export default function Drawer({ <Dialog.Overlay className={cn('z-40 fixed inset-0', mask && 'bg-black bg-opacity-30')} /> - <div className={cn('relative z-50 flex flex-col justify-between bg-background-body w-full max-w-sm p-6 overflow-hidden text-left align-middle shadow-xl', panelClassname)}> + <div className={cn('relative z-50 flex flex-col justify-between bg-components-panel-bg w-full max-w-sm p-6 overflow-hidden text-left align-middle shadow-xl', panelClassname)}> <> {title && <Dialog.Title as="h3" - className="text-lg font-medium leading-6 text-gray-900" + className="text-lg font-medium leading-6 text-text-primary" > {title} </Dialog.Title>} {showClose && <Dialog.Title className="flex items-center mb-4" as="div"> - <XMarkIcon className='w-4 h-4 text-gray-500' onClick={onClose} /> + <XMarkIcon className='w-4 h-4 text-text-tertiary' onClick={onClose} /> </Dialog.Title>} - {description && <Dialog.Description className='text-gray-500 text-xs font-normal mt-2'>{description}</Dialog.Description>} + {description && <Dialog.Description className='text-text-tertiary text-xs font-normal mt-2'>{description}</Dialog.Description>} {children} </> {footer || (footer === null diff --git a/web/app/components/base/dropdown/index.tsx b/web/app/components/base/dropdown/index.tsx index 9af2421669..eb2519bbde 100644 --- a/web/app/components/base/dropdown/index.tsx +++ b/web/app/components/base/dropdown/index.tsx @@ -48,16 +48,16 @@ const Dropdown: FC<DropdownProps> = ({ <div className={` flex items-center justify-center w-6 h-6 cursor-pointer rounded-md - ${open && 'bg-black/5'} + ${open && 'bg-divider-regular'} `} > - <RiMoreFill className='w-4 h-4 text-gray-500' /> + <RiMoreFill className='w-4 h-4 text-text-tertiary' /> </div> ) } </PortalToFollowElemTrigger> <PortalToFollowElemContent className={popupClassName}> - <div className='rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg text-sm text-gray-700'> + <div className='rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg text-sm text-text-secondary'> { !!items.length && ( <div className='p-1'> @@ -65,7 +65,7 @@ const Dropdown: FC<DropdownProps> = ({ items.map(item => ( <div key={item.value} - className='flex items-center px-3 h-8 rounded-lg cursor-pointer hover:bg-gray-100' + className='flex items-center px-3 h-8 rounded-lg cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover' onClick={() => handleSelect(item)} > {item.text} @@ -77,7 +77,7 @@ const Dropdown: FC<DropdownProps> = ({ } { (!!items.length && !!secondItems?.length) && ( - <div className='h-[1px] bg-gray-100' /> + <div className='h-[1px] bg-divider-regular' /> ) } { @@ -87,7 +87,7 @@ const Dropdown: FC<DropdownProps> = ({ secondItems.map(item => ( <div key={item.value} - className='flex items-center px-3 h-8 rounded-lg cursor-pointer hover:bg-gray-100' + className='flex items-center px-3 h-8 rounded-lg cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover' onClick={() => handleSelect(item)} > {item.text} diff --git a/web/app/components/base/emoji-picker/Inner.tsx b/web/app/components/base/emoji-picker/Inner.tsx index 5db223e3f4..e3347d4c67 100644 --- a/web/app/components/base/emoji-picker/Inner.tsx +++ b/web/app/components/base/emoji-picker/Inner.tsx @@ -7,13 +7,15 @@ import { init } from 'emoji-mart' import { MagnifyingGlassIcon, } from '@heroicons/react/24/outline' -import cn from '@/utils/classnames' +import Input from '@/app/components/base/input' import Divider from '@/app/components/base/divider' import { searchEmoji } from '@/utils/emoji' +import cn from '@/utils/classnames' declare global { + // eslint-disable-next-line ts/no-namespace namespace JSX { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + // eslint-disable-next-line ts/consistent-type-definitions interface IntrinsicElements { 'em-emoji': React.DetailedHTMLProps< React.HTMLAttributes<HTMLElement>, HTMLElement > } @@ -71,12 +73,12 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ <div className='flex flex-col items-center w-full px-3 pb-2'> <div className="relative w-full"> <div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> - <MagnifyingGlassIcon className="w-5 h-5 text-gray-400" aria-hidden="true" /> + <MagnifyingGlassIcon className="w-5 h-5 text-text-quaternary" aria-hidden="true" /> </div> - <input + <Input + className="pl-10" type="search" id="search" - className='block w-full h-10 px-3 pl-10 text-sm font-normal bg-gray-100 rounded-lg' placeholder="Search emojis..." onChange={async (e: ChangeEvent<HTMLInputElement>) => { if (e.target.value === '') { @@ -91,12 +93,12 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ /> </div> </div> - <Divider className='m-0 mb-3' /> + <Divider className='my-3' /> <div className="w-full max-h-[200px] overflow-x-hidden overflow-y-auto px-3"> {isSearching && <> <div key={'category-search'} className='flex flex-col'> - <p className='font-medium uppercase text-xs text-[#101828] mb-1'>Search</p> + <p className='system-xs-medium-uppercase text-text-primary mb-1'>Search</p> <div className='w-full h-full grid grid-cols-8 gap-1'> {searchedEmojis.map((emoji: string, index: number) => { return <div @@ -106,7 +108,7 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ setSelectedEmoji(emoji) }} > - <div className='cursor-pointer w-8 h-8 p-1 flex items-center justify-center rounded-lg hover:ring-1 ring-offset-1 ring-gray-300'> + <div className='cursor-pointer w-8 h-8 p-1 flex items-center justify-center rounded-lg hover:ring-1 ring-offset-1 ring-components-input-border-hover'> <em-emoji id={emoji} /> </div> </div> @@ -117,7 +119,7 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ {categories.map((category, index: number) => { return <div key={`category-${index}`} className='flex flex-col'> - <p className='font-medium uppercase text-xs text-[#101828] mb-1'>{category.id}</p> + <p className='system-xs-medium-uppercase text-text-primary mb-1'>{category.id}</p> <div className='w-full h-full grid grid-cols-8 gap-1'> {category.emojis.map((emoji, index: number) => { return <div @@ -127,7 +129,7 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ setSelectedEmoji(emoji) }} > - <div className='cursor-pointer w-8 h-8 p-1 flex items-center justify-center rounded-lg hover:ring-1 ring-offset-1 ring-gray-300'> + <div className='cursor-pointer w-8 h-8 p-1 flex items-center justify-center rounded-lg hover:ring-1 ring-offset-1 ring-components-input-border-hover'> <em-emoji id={emoji} /> </div> </div> @@ -140,7 +142,7 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ {/* Color Select */} <div className={cn('p-3 pb-0', selectedEmoji === '' ? 'opacity-25' : '')}> - <p className='font-medium uppercase text-xs text-[#101828] mb-2'>Choose Style</p> + <p className='system-xs-medium-uppercase text-text-primary mb-2'>Choose Style</p> <div className='w-full h-full grid grid-cols-8 gap-1'> {backgroundColors.map((color) => { return <div @@ -150,7 +152,7 @@ const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({ 'cursor-pointer', 'hover:ring-1 ring-offset-1', 'inline-flex w-10 h-10 rounded-lg items-center justify-center', - color === selectedBackground ? 'ring-1 ring-gray-300' : '', + color === selectedBackground ? 'ring-1 ring-components-input-border-hover' : '', )} onClick={() => { setSelectedBackground(color) diff --git a/web/app/components/base/emoji-picker/index.tsx b/web/app/components/base/emoji-picker/index.tsx index 3add14879a..16b07eddaf 100644 --- a/web/app/components/base/emoji-picker/index.tsx +++ b/web/app/components/base/emoji-picker/index.tsx @@ -2,7 +2,6 @@ import type { FC } from 'react' import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import s from './style.module.css' import EmojiPickerInner from './Inner' import cn from '@/utils/classnames' import Divider from '@/app/components/base/divider' @@ -37,12 +36,12 @@ const EmojiPicker: FC<IEmojiPickerProps> = ({ isShow closable={false} wrapperClassName={className} - className={cn(s.container, '!w-[362px] !p-0')} + className={cn('flex flex-col max-h-[552px] border-[0.5px] border-divider-subtle rounded-xl shadow-xl p-0')} > <EmojiPickerInner className="pt-3" onSelect={handleSelectEmoji} /> - <Divider className='m-0' /> + <Divider className='mb-0 mt-3' /> <div className='w-full flex items-center justify-center p-3 gap-2'> <Button className='w-full' onClick={() => { onClose && onClose() diff --git a/web/app/components/base/emoji-picker/style.module.css b/web/app/components/base/emoji-picker/style.module.css deleted file mode 100644 index 5facb3560a..0000000000 --- a/web/app/components/base/emoji-picker/style.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.container { - display: flex; - flex-direction: column; - align-items: flex-start; - width: 362px; - max-height: 552px; - - border: 0.5px solid #EAECF0; - box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03); - border-radius: 12px; - background: #fff; -} diff --git a/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx b/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx index e9e1a79e6f..c77d22dc01 100644 --- a/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx +++ b/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx @@ -60,7 +60,7 @@ const ModerationSettingModal: FC<ModerationSettingModalProps> = ({ '/code-based-extension?module=moderation', fetchCodeBasedExtensionList, ) - const openaiProvider = modelProviders?.data.find(item => item.provider === 'openai') + const openaiProvider = modelProviders?.data.find(item => item.provider === 'langgenius/openai/openai') const systemOpenaiProviderEnabled = openaiProvider?.system_configuration.enabled const systemOpenaiProviderQuota = systemOpenaiProviderEnabled ? openaiProvider?.system_configuration.quota_configurations.find(item => item.quota_type === openaiProvider.system_configuration.current_quota_type) : undefined const systemOpenaiProviderCanUse = systemOpenaiProviderQuota?.is_valid diff --git a/web/app/components/base/features/store.ts b/web/app/components/base/features/store.ts index 2b8c3f7073..49ce0f4338 100644 --- a/web/app/components/base/features/store.ts +++ b/web/app/components/base/features/store.ts @@ -2,16 +2,16 @@ import { createStore } from 'zustand' import type { Features } from './types' import { Resolution, TransferMethod } from '@/types/app' -export type FeaturesModal = { +export interface FeaturesModal { showFeaturesModal: boolean setShowFeaturesModal: (showFeaturesModal: boolean) => void } -export type FeaturesState = { +export interface FeaturesState { features: Features } -export type FeaturesAction = { +export interface FeaturesAction { setFeatures: (features: Features) => void } diff --git a/web/app/components/base/features/types.ts b/web/app/components/base/features/types.ts index 83f876383d..c948e538d7 100644 --- a/web/app/components/base/features/types.ts +++ b/web/app/components/base/features/types.ts @@ -1,7 +1,7 @@ import type { Resolution, TransferMethod, TtsAutoPlay } from '@/types/app' import type { FileUploadConfigResponse } from '@/models/common' -export type EnabledOrDisabled = { +export interface EnabledOrDisabled { enabled?: boolean } @@ -42,7 +42,7 @@ export type FileUpload = { fileUploadConfig?: FileUploadConfigResponse } & EnabledOrDisabled -export type AnnotationReplyConfig = { +export interface AnnotationReplyConfig { enabled: boolean id?: string score_threshold?: number @@ -64,7 +64,7 @@ export enum FeatureEnum { annotationReply = 'annotationReply', } -export type Features = { +export interface Features { [FeatureEnum.moreLikeThis]?: MoreLikeThis [FeatureEnum.opening]?: OpeningStatement [FeatureEnum.suggested]?: SuggestedQuestionsAfterAnswer diff --git a/web/app/components/base/file-uploader/file-from-link-or-local/index.tsx b/web/app/components/base/file-uploader/file-from-link-or-local/index.tsx index 1ff2bdd174..8ae8bb0538 100644 --- a/web/app/components/base/file-uploader/file-from-link-or-local/index.tsx +++ b/web/app/components/base/file-uploader/file-from-link-or-local/index.tsx @@ -59,7 +59,7 @@ const FileFromLinkOrLocal = ({ <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)} asChild> {trigger(open)} </PortalToFollowElemTrigger> - <PortalToFollowElemContent className='z-10'> + <PortalToFollowElemContent className='z-[1001]'> <div className='p-3 w-[280px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl shadow-lg'> { showFromLink && ( diff --git a/web/app/components/base/grid-mask/index.tsx b/web/app/components/base/grid-mask/index.tsx index 876eb7f1de..0bf6625a83 100644 --- a/web/app/components/base/grid-mask/index.tsx +++ b/web/app/components/base/grid-mask/index.tsx @@ -36,8 +36,8 @@ const GridMask: FC<GridMaskProps> = ({ const drawRecord = useCallback(() => { const canvas = canvasRef.current! const ctx = ctxRef.current! - const rowNumber = parseInt(`${canvas.width / 24}`) - const colNumber = parseInt(`${canvas.height / 24}`) + const rowNumber = Number.parseInt(`${canvas.width / 24}`) + const colNumber = Number.parseInt(`${canvas.height / 24}`) ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.beginPath() @@ -82,9 +82,9 @@ const GridMask: FC<GridMaskProps> = ({ }, []) return ( - <div className={`relative bg-white ${wrapperClassName}`}> + <div className={`relative bg-components-panel-bg ${wrapperClassName}`}> <canvas ref={canvasRef} className={`absolute inset-0 w-full h-full ${canvasClassName}`} /> - <div className={`absolute w-full h-full z-[1] bg-gradient-to-b from-white/80 to-white rounded-lg ${gradientClassName}`} /> + <div className={`absolute w-full h-full z-[1] bg-gradient-to-b from-background-body to-background-gradient-mask-transparent rounded-lg ${gradientClassName}`} /> <div className='relative z-[2]'>{children}</div> </div> ) diff --git a/web/app/components/base/icons/IconBase.tsx b/web/app/components/base/icons/IconBase.tsx index 994cd98bcd..4de39e293c 100644 --- a/web/app/components/base/icons/IconBase.tsx +++ b/web/app/components/base/icons/IconBase.tsx @@ -28,4 +28,6 @@ const IconBase = forwardRef<React.MutableRefObject<HTMLOrSVGElement>, IconBasePr }) }) +IconBase.displayName = 'IconBase' + export default IconBase diff --git a/web/app/components/base/icons/assets/public/common/highlight.svg b/web/app/components/base/icons/assets/public/common/highlight.svg new file mode 100644 index 0000000000..f4b809040b --- /dev/null +++ b/web/app/components/base/icons/assets/public/common/highlight.svg @@ -0,0 +1,9 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="46" height="24" viewBox="0 0 46 24" fill="none"> + <path opacity="0.5" d="M-6.5 8C-6.5 3.58172 -2.91828 0 1.5 0H45.5L33.0248 24H1.49999C-2.91829 24 -6.5 20.4183 -6.5 16V8Z" fill="url(#paint0_linear_6333_42118)"/> + <defs> + <linearGradient id="paint0_linear_6333_42118" x1="1.81679" y1="5.47784e-07" x2="101.257" y2="30.3866" gradientUnits="userSpaceOnUse"> + <stop stop-color="white" stop-opacity="0.12"/> + <stop offset="1" stop-color="white" stop-opacity="0.3"/> + </linearGradient> + </defs> +</svg> \ No newline at end of file diff --git a/web/app/components/base/icons/assets/public/common/sparkles-soft.svg b/web/app/components/base/icons/assets/public/common/sparkles-soft.svg new file mode 100644 index 0000000000..37f3072df7 --- /dev/null +++ b/web/app/components/base/icons/assets/public/common/sparkles-soft.svg @@ -0,0 +1,6 @@ +<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="sparkles-soft"> +<path id="Vector" opacity="0.5" d="M10.9963 1.36798C10.9839 1.25339 10.8909 1.16677 10.7802 1.16666C10.6695 1.16654 10.5763 1.25295 10.5636 1.36752C10.5045 1.90085 10.3525 2.26673 10.1143 2.5149C9.87599 2.76307 9.52476 2.92145 9.01275 2.98296C8.90277 2.99618 8.81983 3.09324 8.81995 3.20856C8.82006 3.32388 8.90322 3.42076 9.0132 3.43373C9.51653 3.49312 9.87583 3.65148 10.1201 3.90135C10.3631 4.14986 10.518 4.51523 10.563 5.04321C10.573 5.16035 10.6673 5.25012 10.7802 5.24999C10.8931 5.24986 10.9872 5.15987 10.9969 5.0427C11.0401 4.52364 11.1949 4.15004 11.4394 3.89528C11.684 3.64052 12.0426 3.47926 12.5409 3.43433C12.6534 3.42419 12.7398 3.32619 12.7399 3.20858C12.7401 3.09097 12.6539 2.99277 12.5414 2.98236C12.0346 2.93546 11.6838 2.77407 11.4452 2.52098C11.2054 2.2665 11.0533 1.89229 10.9963 1.36798Z" fill="#F5F8FF"/> +<path id="Vector_2" d="M7.13646 2.85102C7.10442 2.55638 6.8653 2.33365 6.5806 2.33334C6.29595 2.33304 6.05633 2.55526 6.02374 2.84984C5.87186 4.22127 5.48089 5.1621 4.86827 5.80025C4.25565 6.43838 3.35245 6.84566 2.03587 7.00386C1.75307 7.03781 1.53975 7.28742 1.54004 7.58393C1.54033 7.88049 1.75415 8.12958 2.03701 8.16294C3.33132 8.31566 4.25509 8.72289 4.88328 9.36543C5.50807 10.0045 5.90647 10.9439 6.02222 12.3016C6.04793 12.6029 6.29035 12.8337 6.58066 12.8333C6.87102 12.833 7.11294 12.6016 7.13797 12.3003C7.24885 10.9656 7.64695 10.0049 8.27583 9.34979C8.90477 8.69471 9.82698 8.28002 11.1083 8.16452C11.3976 8.13844 11.6197 7.88644 11.62 7.58399C11.6204 7.28159 11.3988 7.02906 11.1096 7.00229C9.8062 6.88171 8.90432 6.46673 8.29084 5.81589C7.674 5.16152 7.28306 4.19926 7.13646 2.85102Z" fill="#F5F8FF"/> +</g> +</svg> diff --git a/web/app/components/base/icons/assets/vender/other/anthropic-text.svg b/web/app/components/base/icons/assets/vender/other/anthropic-text.svg new file mode 100644 index 0000000000..cace17da73 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/other/anthropic-text.svg @@ -0,0 +1,78 @@ +<svg width="90" height="20" viewBox="0 0 90 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_8587_60274)"> +<mask id="mask0_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M89.375 4.99805H0V14.998H89.375V4.99805Z" fill="white"/> +</mask> +<g mask="url(#mask0_8587_60274)"> +<mask id="mask1_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99609H89.375V14.9961H0V4.99609Z" fill="white"/> +</mask> +<g mask="url(#mask1_8587_60274)"> +<mask id="mask2_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99414H89.375V14.9941H0V4.99414Z" fill="white"/> +</mask> +<g mask="url(#mask2_8587_60274)"> +<mask id="mask3_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask3_8587_60274)"> +<path d="M18.1273 11.9244L13.7773 5.15625H11.4297V14.825H13.4321V8.05688L17.7821 14.825H20.1297V5.15625H18.1273V11.9244Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask4_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask4_8587_60274)"> +<path d="M21.7969 7.02094H25.0423V14.825H27.1139V7.02094H30.3594V5.15625H21.7969V7.02094Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask5_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask5_8587_60274)"> +<path d="M38.6442 9.00994H34.0871V5.15625H32.0156V14.825H34.0871V10.8746H38.6442V14.825H40.7156V5.15625H38.6442V9.00994Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask6_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask6_8587_60274)"> +<path d="M45.3376 7.02094H47.893C48.9152 7.02094 49.4539 7.39387 49.4539 8.09831C49.4539 8.80275 48.9152 9.17569 47.893 9.17569H45.3376V7.02094ZM51.5259 8.09831C51.5259 6.27506 50.186 5.15625 47.9897 5.15625H43.2656V14.825H45.3376V11.0404H47.6443L49.7164 14.825H52.0094L49.715 10.7521C50.8666 10.3094 51.5259 9.37721 51.5259 8.09831Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask7_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask7_8587_60274)"> +<path d="M57.8732 13.0565C56.2438 13.0565 55.2496 11.8963 55.2496 10.004C55.2496 8.08416 56.2438 6.92394 57.8732 6.92394C59.4887 6.92394 60.4691 8.08416 60.4691 10.004C60.4691 11.8963 59.4887 13.0565 57.8732 13.0565ZM57.8732 4.99023C55.0839 4.99023 53.1094 7.06206 53.1094 10.004C53.1094 12.9184 55.0839 14.9902 57.8732 14.9902C60.6486 14.9902 62.6094 12.9184 62.6094 10.004C62.6094 7.06206 60.6486 4.99023 57.8732 4.99023Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask8_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask8_8587_60274)"> +<path d="M69.1794 9.45194H66.6233V7.02094H69.1794C70.2019 7.02094 70.7407 7.43532 70.7407 8.23644C70.7407 9.03756 70.2019 9.45194 69.1794 9.45194ZM69.2762 5.15625H64.5508V14.825H66.6233V11.3166H69.2762C71.473 11.3166 72.8133 10.1564 72.8133 8.23644C72.8133 6.3165 71.473 5.15625 69.2762 5.15625Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask9_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask9_8587_60274)"> +<path d="M86.8413 11.5786C86.4823 12.5179 85.7642 13.0565 84.7837 13.0565C83.1542 13.0565 82.16 11.8963 82.16 10.004C82.16 8.08416 83.1542 6.92394 84.7837 6.92394C85.7642 6.92394 86.4823 7.46261 86.8413 8.40183H89.0369C88.4984 6.33002 86.8827 4.99023 84.7837 4.99023C81.9942 4.99023 80.0195 7.06206 80.0195 10.004C80.0195 12.9184 81.9942 14.9902 84.7837 14.9902C86.8965 14.9902 88.5122 13.6366 89.0508 11.5786H86.8413Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask10_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask10_8587_60274)"> +<path d="M73.6484 5.15625L77.5033 14.825H79.6172L75.7624 5.15625H73.6484Z" fill="black" fill-opacity="0.92"/> +</g> +<mask id="mask11_8587_60274" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="4" width="90" height="11"> +<path d="M0 4.99219H89.375V14.9922H0V4.99219Z" fill="white"/> +</mask> +<g mask="url(#mask11_8587_60274)"> +<path d="M3.64038 10.9989L4.95938 7.60106L6.27838 10.9989H3.64038ZM3.85422 5.15625L0 14.825H2.15505L2.9433 12.7946H6.97558L7.76371 14.825H9.91875L6.06453 5.15625H3.85422Z" fill="black" fill-opacity="0.92"/> +</g> +</g> +</g> +</g> +</g> +<defs> +<clipPath id="clip0_8587_60274"> +<rect width="89.375" height="10" fill="white" transform="translate(0 5)"/> +</clipPath> +</defs> +</svg> diff --git a/web/app/components/base/icons/assets/vender/other/group.svg b/web/app/components/base/icons/assets/vender/other/group.svg new file mode 100644 index 0000000000..90f1e6b89e --- /dev/null +++ b/web/app/components/base/icons/assets/vender/other/group.svg @@ -0,0 +1,8 @@ +<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Group"> +<path id="Vector" d="M5.6475 8.0115L0.333496 5.05884V11.3335C0.333491 11.4524 0.365258 11.569 0.425506 11.6715C0.485754 11.7739 0.572294 11.8584 0.676163 11.9162L6.3335 15.0588V9.17684C6.33344 8.93907 6.26981 8.70565 6.14919 8.50075C6.02857 8.29586 5.85536 8.12694 5.6475 8.0115Z" fill="#354052"/> +<path id="Vector_2" d="M7.66699 9.17684V15.0588L13.3243 11.9162C13.4282 11.8584 13.5147 11.7739 13.575 11.6715C13.6352 11.569 13.667 11.4524 13.667 11.3335V5.05884L8.35299 8.0115C8.14513 8.12694 7.97192 8.29586 7.8513 8.50075C7.73068 8.70565 7.66705 8.93907 7.66699 9.17684Z" fill="#676F83"/> +<path id="Vector_3" d="M10.1913 2.34351C9.804 3.33351 8.588 4.00017 7 4.00017C5.412 4.00017 4.196 3.33351 3.80867 2.34351L1 3.90417L6.35267 6.87817C6.5507 6.98815 6.77348 7.04586 7 7.04586C7.22652 7.04586 7.4493 6.98815 7.64733 6.87817L13 3.90417L10.1913 2.34351Z" fill="#676F83"/> +<path id="Vector_4" d="M7 2.66675C8.10457 2.66675 9 2.21903 9 1.66675C9 1.11446 8.10457 0.666748 7 0.666748C5.89543 0.666748 5 1.11446 5 1.66675C5 2.21903 5.89543 2.66675 7 2.66675Z" fill="#354052"/> +</g> +</svg> diff --git a/web/app/components/base/icons/assets/vender/other/openai.svg b/web/app/components/base/icons/assets/vender/other/openai.svg new file mode 100644 index 0000000000..5a9a93bc2e --- /dev/null +++ b/web/app/components/base/icons/assets/vender/other/openai.svg @@ -0,0 +1,9 @@ +<svg width="80" height="22" viewBox="0 0 80 22" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M25.1152 10.5767C25.1152 14.1738 27.4253 16.6818 30.6264 16.6818C33.8274 16.6818 36.1375 14.1738 36.1375 10.5767C36.1375 6.97961 33.8274 4.47156 30.6264 4.47156C27.4253 4.47156 25.1152 6.97961 25.1152 10.5767ZM34.0254 10.5767C34.0254 13.1507 32.6229 14.8173 30.6264 14.8173C28.6298 14.8173 27.2273 13.1507 27.2273 10.5767C27.2273 8.00263 28.6298 6.3361 30.6264 6.3361C32.6229 6.3361 34.0254 8.00263 34.0254 10.5767Z" fill="black"/> +<path d="M42.0868 16.6819C44.5124 16.6819 45.8984 14.6358 45.8984 12.1773C45.8984 9.71871 44.5124 7.67267 42.0868 7.67267C40.9648 7.67267 40.1398 8.11818 39.5953 8.76169V7.83767H37.6152V19.4704H39.5953V15.5928C40.1398 16.2364 40.9648 16.6819 42.0868 16.6819ZM39.5458 11.9298C39.5458 10.2962 40.4698 9.40521 41.6908 9.40521C43.1264 9.40521 43.9019 10.5272 43.9019 12.1773C43.9019 13.8273 43.1264 14.9493 41.6908 14.9493C40.4698 14.9493 39.5458 14.0418 39.5458 12.4413V11.9298Z" fill="black"/> +<path d="M51.2545 16.6819C52.987 16.6819 54.3565 15.7743 54.967 14.2563L53.2675 13.6128C53.0035 14.5038 52.228 14.9988 51.2545 14.9988C49.9839 14.9988 49.0929 14.0913 48.9444 12.6063H55.0165V11.9463C55.0165 9.57021 53.68 7.67267 51.172 7.67267C48.6639 7.67267 47.0469 9.63621 47.0469 12.1773C47.0469 14.8503 48.7794 16.6819 51.2545 16.6819ZM51.1555 9.3392C52.4095 9.3392 53.0035 10.1642 53.02 11.1212H49.0434C49.3404 9.94972 50.1324 9.3392 51.1555 9.3392Z" fill="black"/> +<path d="M56.5039 16.5004H58.484V11.4182C58.484 10.1807 59.3915 9.52071 60.2825 9.52071C61.3715 9.52071 61.8005 10.2962 61.8005 11.3687V16.5004H63.7806V10.7912C63.7806 8.9267 62.6915 7.67267 60.8765 7.67267C59.7545 7.67267 58.979 8.18418 58.484 8.76169V7.83767H56.5039V16.5004Z" fill="black"/> +<path d="M69.5799 4.65308L65.0918 16.5003H67.1873L68.1939 13.7943H73.309L74.332 16.5003H76.4605L71.9724 4.65308H69.5799ZM70.7349 6.99613L72.616 11.9462H68.8869L70.7349 6.99613Z" fill="black"/> +<path d="M79.8581 4.6875H77.7461V16.5348H79.8581V4.6875Z" fill="black"/> +<path d="M20.2769 9.00436C20.776 7.50627 20.6041 5.86517 19.8059 4.50251C18.6055 2.41247 16.1924 1.3372 13.8356 1.84321C12.7871 0.662057 11.2808 -0.00964523 9.70154 -2.00271e-05C7.29248 -0.00552014 5.155 1.54551 4.41386 3.83769C2.86626 4.15463 1.53042 5.12334 0.748717 6.49631C-0.460621 8.58085 -0.184928 11.2085 1.43073 12.9961C0.931596 14.4942 1.10348 16.1353 1.90168 17.4979C3.10208 19.588 5.51526 20.6632 7.87206 20.1572C8.91983 21.3384 10.4269 22.0101 12.0061 21.9998C14.4165 22.006 16.5547 20.4535 17.2958 18.1593C18.8434 17.8424 20.1793 16.8737 20.961 15.5007C22.1689 13.4161 21.8925 10.7905 20.2776 9.00298L20.2769 9.00436ZM12.0075 20.5622C11.0429 20.5635 10.1085 20.226 9.36809 19.6079C9.40178 19.59 9.46022 19.5577 9.49803 19.5343L13.8789 17.0043C14.103 16.8771 14.2405 16.6385 14.2391 16.3807V10.2048L16.0906 11.2738C16.1105 11.2835 16.1236 11.3027 16.1264 11.3247V16.4391C16.1236 18.7134 14.2818 20.5574 12.0075 20.5622ZM3.14952 16.7788C2.6662 15.9441 2.49225 14.9658 2.65795 14.0163C2.69026 14.0356 2.74732 14.0707 2.78789 14.094L7.16873 16.6241C7.3908 16.754 7.6658 16.754 7.88856 16.6241L13.2367 13.5358V15.6739C13.2381 15.6959 13.2278 15.7173 13.2106 15.731L8.78233 18.2879C6.80985 19.4236 4.29079 18.7485 3.15021 16.7788H3.14952ZM1.99656 7.21613C2.47782 6.38012 3.23752 5.74073 4.14229 5.40866C4.14229 5.44647 4.14023 5.51316 4.14023 5.55991V10.6207C4.13885 10.8778 4.27636 11.1164 4.4998 11.2436L9.84798 14.3312L7.9965 15.4003C7.97794 15.4127 7.95456 15.4147 7.93393 15.4058L3.50496 12.8469C1.53661 11.707 0.86147 9.18861 1.99587 7.21682L1.99656 7.21613ZM17.2085 10.7561L11.8603 7.66783L13.7118 6.59943C13.7304 6.58706 13.7537 6.585 13.7744 6.59393L18.2033 9.1508C20.1751 10.29 20.851 12.8125 19.7118 14.7843C19.2298 15.6189 18.4708 16.2583 17.5667 16.5911V11.379C17.5688 11.1219 17.432 10.884 17.2092 10.7561H17.2085ZM19.0511 7.98271C19.0187 7.96278 18.9617 7.9284 18.9211 7.90502L14.5403 5.37497C14.3182 5.24503 14.0432 5.24503 13.8204 5.37497L8.47226 8.46329V6.32512C8.47088 6.30311 8.4812 6.2818 8.49838 6.26805L12.9267 3.71325C14.8991 2.57541 17.4209 3.25261 18.5581 5.22578C19.0387 6.05905 19.2126 7.03463 19.0497 7.98271H19.0511ZM7.46574 11.7936L5.61357 10.7245C5.59363 10.7149 5.58057 10.6956 5.57782 10.6736V5.55922C5.5792 3.28218 7.42655 1.43689 9.7036 1.43826C10.6668 1.43826 11.5991 1.77652 12.3395 2.39253C12.3058 2.41041 12.2481 2.44272 12.2096 2.46609L7.82874 4.99615C7.60461 5.12334 7.46711 5.36122 7.46849 5.61904L7.46574 11.7922V11.7936ZM8.47157 9.62519L10.8538 8.24947L13.236 9.6245V12.3752L10.8538 13.7503L8.47157 12.3752V9.62519Z" fill="black"/> +</svg> diff --git a/web/app/components/base/icons/assets/vender/plugin/box-sparkle-fill.svg b/web/app/components/base/icons/assets/vender/plugin/box-sparkle-fill.svg new file mode 100644 index 0000000000..3ec651fd94 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/plugin/box-sparkle-fill.svg @@ -0,0 +1,9 @@ +<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Icon"> +<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M11.3891 2.41987C11.6635 2.58871 11.749 2.94802 11.5802 3.22239L10.3324 5.25H11.0833C11.4055 5.25 11.6667 5.51117 11.6667 5.83334V11.6667C11.6667 12.311 11.1444 12.8333 10.5 12.8333H3.50001C2.85568 12.8333 2.33334 12.311 2.33334 11.6667V5.83334C2.33334 5.51117 2.59451 5.25 2.91668 5.25H8.96252L10.5865 2.61094C10.7554 2.33657 11.1147 2.25102 11.3891 2.41987ZM5.83334 7.58334C5.51118 7.58334 5.25001 7.84449 5.25001 8.16667C5.25001 8.48884 5.51118 8.75 5.83334 8.75H8.16668C8.48885 8.75 8.75001 8.48884 8.75001 8.16667C8.75001 7.84449 8.48885 7.58334 8.16668 7.58334H5.83334Z" fill="#676F83"/> +<g id="Vector_2" opacity="0.5"> +<path d="M6.91257 1.79347C6.96898 1.76525 7.01477 1.71948 7.043 1.66303L7.32195 1.10508C7.42946 0.890105 7.73623 0.890105 7.84374 1.10508L8.12269 1.66303C8.15093 1.71948 8.19672 1.76525 8.25313 1.79347L8.81108 2.07245C9.0261 2.17994 9.0261 2.48672 8.81108 2.5942L8.25313 2.87318C8.19672 2.9014 8.15093 2.94717 8.12269 3.00362L7.84374 3.56158C7.73623 3.77655 7.42946 3.77655 7.32195 3.56158L7.043 3.00362C7.01477 2.94717 6.96898 2.9014 6.91257 2.87318L6.35461 2.5942C6.13965 2.48672 6.13965 2.17994 6.35461 2.07245L6.91257 1.79347Z" fill="#676F83"/> +<path d="M3.80145 2.7657C3.85789 2.73748 3.90366 2.69171 3.93189 2.63526L4.11364 2.27174C4.22113 2.05677 4.5279 2.05677 4.63539 2.27174L4.81715 2.63526C4.84537 2.6917 4.89114 2.73748 4.94759 2.7657L5.3111 2.94745C5.52607 3.05494 5.52607 3.36172 5.3111 3.4692L4.94759 3.65096C4.89114 3.67919 4.84537 3.72495 4.81715 3.7814L4.63539 4.14491C4.5279 4.35988 4.22113 4.35988 4.11364 4.14491L3.93189 3.7814C3.90366 3.72495 3.85789 3.67919 3.80145 3.65096L3.43793 3.4692C3.22296 3.36172 3.22296 3.05494 3.43793 2.94745L3.80145 2.7657Z" fill="#676F83"/> +</g> +</g> +</svg> diff --git a/web/app/components/base/icons/assets/vender/plugin/left-corner.svg b/web/app/components/base/icons/assets/vender/plugin/left-corner.svg new file mode 100644 index 0000000000..9b360e4be7 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/plugin/left-corner.svg @@ -0,0 +1,3 @@ +<svg width="13" height="20" viewBox="0 0 13 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path id="Shape" d="M0 0H13V20C9.98017 20 7.26458 18.1615 6.14305 15.3576L0 0Z" fill="#F9FAFB"/> +</svg> diff --git a/web/app/components/base/icons/assets/vender/solid/files/file-zip.svg b/web/app/components/base/icons/assets/vender/solid/files/file-zip.svg new file mode 100644 index 0000000000..213606ae49 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/solid/files/file-zip.svg @@ -0,0 +1,6 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Icon"> +<path id="Vector" d="M3.99999 1.33325H7.99999V5.33325C7.99999 6.06963 8.59692 6.66659 9.33332 6.66659H13.3333V13.3333C13.3333 14.0697 12.7364 14.6666 12 14.6666H6.66666V13.3333H7.99999V11.9999H6.66666V10.6666H7.99999V9.33325H6.66666V7.99992H5.33332V9.33325H6.66666V10.6666H5.33332V11.9999H6.66666V13.3333H5.33332V14.6666H3.99999C3.26361 14.6666 2.66666 14.0697 2.66666 13.3333V2.66659C2.66666 1.93021 3.26361 1.33325 3.99999 1.33325Z" fill="#676F83"/> +<path id="Vector_2" opacity="0.5" d="M12.9428 4.99993C13.0415 5.09868 13.1232 5.21133 13.1859 5.33327H9.33334V1.48071C9.45528 1.54338 9.56794 1.62504 9.66668 1.72379L12.9428 4.99993Z" fill="#676F83"/> +</g> +</svg> diff --git a/web/app/components/base/icons/assets/vender/solid/general/github.svg b/web/app/components/base/icons/assets/vender/solid/general/github.svg new file mode 100644 index 0000000000..c7b203ddb2 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/solid/general/github.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Icon"> +<path id="Vector" d="M8 1C4.1325 1 1 4.1325 1 8C1 11.0975 3.00375 13.7137 5.78625 14.6413C6.13625 14.7025 6.2675 14.4925 6.2675 14.3088C6.2675 14.1425 6.25875 13.5913 6.25875 13.005C4.5 13.3288 4.045 12.5763 3.905 12.1825C3.82625 11.9812 3.485 11.36 3.1875 11.1937C2.9425 11.0625 2.5925 10.7387 3.17875 10.73C3.73 10.7212 4.12375 11.2375 4.255 11.4475C4.885 12.5062 5.89125 12.2088 6.29375 12.025C6.355 11.57 6.53875 11.2638 6.74 11.0887C5.1825 10.9137 3.555 10.31 3.555 7.6325C3.555 6.87125 3.82625 6.24125 4.2725 5.75125C4.2025 5.57625 3.9575 4.85875 4.3425 3.89625C4.3425 3.89625 4.92875 3.7125 6.2675 4.61375C6.8275 4.45625 7.4225 4.3775 8.0175 4.3775C8.6125 4.3775 9.2075 4.45625 9.7675 4.61375C11.1063 3.70375 11.6925 3.89625 11.6925 3.89625C12.0775 4.85875 11.8325 5.57625 11.7625 5.75125C12.2087 6.24125 12.48 6.8625 12.48 7.6325C12.48 10.3187 10.8438 10.9137 9.28625 11.0887C9.54 11.3075 9.75875 11.7275 9.75875 12.3837C9.75875 13.32 9.75 14.0725 9.75 14.3088C9.75 14.4925 9.88125 14.7113 10.2312 14.6413C11.6209 14.1721 12.8284 13.279 13.6839 12.0877C14.5393 10.8963 14.9996 9.46668 15 8C15 4.1325 11.8675 1 8 1Z" fill="#676F83"/> +</g> +</svg> diff --git a/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/audio-support-icon.svg b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/audio-support-icon.svg new file mode 100644 index 0000000000..cad145c65f --- /dev/null +++ b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/audio-support-icon.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"> + <path d="M10.3567 3.56405L10.2334 3.84689C10.1432 4.05396 9.8568 4.05396 9.76655 3.84689L9.6433 3.56405C9.42355 3.05973 9.02775 2.6582 8.53385 2.43854L8.154 2.26961C7.94865 2.17826 7.94865 1.8794 8.154 1.78806L8.5126 1.62857C9.0192 1.40325 9.4221 0.986865 9.63805 0.465414L9.76465 0.159767C9.8529 -0.0532556 10.1471 -0.0532556 10.2353 0.159767L10.3619 0.465414C10.5779 0.986865 10.9808 1.40325 11.4874 1.62857L11.846 1.78806C12.0514 1.8794 12.0514 2.17826 11.846 2.26961L11.4662 2.43854C10.9723 2.6582 10.5764 3.05973 10.3567 3.56405ZM4.25 3H3.25V9H4.25V3ZM2 5H1V7H2V5ZM6.5 1H5.5V11H6.5V1ZM8.75 4H7.75V9H8.75V4ZM11 5H10V7H11V5Z" fill="#676F83"/> +</svg> \ No newline at end of file diff --git a/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/document-support-icon.svg b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/document-support-icon.svg new file mode 100644 index 0000000000..d7c09789fb --- /dev/null +++ b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/document-support-icon.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"> + <path d="M10.5 4V10.4966C10.5 10.7751 10.2776 11 10.0033 11H1.9967C1.72248 11 1.5 10.778 1.5 10.5041V1.4959C1.5 1.22766 1.72435 1 2.00111 1H7.4984L10.5 4ZM9.5 4.5H7V2H2.5V10H9.5V4.5ZM4 3.5H5.5V4.5H4V3.5ZM4 5.5H8V6.5H4V5.5ZM4 7.5H8V8.5H4V7.5Z" fill="#676F83"/> +</svg> \ No newline at end of file diff --git a/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/video-support-icon.svg b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/video-support-icon.svg new file mode 100644 index 0000000000..f87aa023b6 --- /dev/null +++ b/web/app/components/base/icons/assets/vender/solid/mediaAndDevices/video-support-icon.svg @@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"> + <path d="M10.2334 4.3469L10.3567 4.06406C10.5764 3.55974 10.9723 3.15821 11.4662 2.93854L11.846 2.76961C12.0514 2.67827 12.0514 2.37941 11.846 2.28806L11.4874 2.12857C10.9808 1.90326 10.5779 1.48687 10.3619 0.965415L10.2353 0.659765C10.1471 0.446745 9.8529 0.446745 9.76465 0.659765L9.63805 0.965415C9.4221 1.48687 9.0192 1.90326 8.5126 2.12857L8.154 2.28806C7.94865 2.37941 7.94865 2.67827 8.154 2.76961L8.53385 2.93854C9.02775 3.15821 9.42355 3.55974 9.6433 4.06406L9.76655 4.3469C9.8568 4.55396 10.1432 4.55396 10.2334 4.3469ZM1.4959 1.5H7V2.5H4V9.5H8V4.5H9V5.5H10H11V10.0033C11 10.2776 10.7723 10.5 10.5041 10.5H1.4959C1.22203 10.5 1 10.2775 1 10.0033V1.9967C1 1.72238 1.22766 1.5 1.4959 1.5ZM2 2.5V3.5H3V2.5H2ZM2 4.5V5.5H3V4.5H2ZM2 6.5V7.5H3V6.5H2ZM9 6.5V7.5H10V6.5H9ZM2 8.5V9.5H3V8.5H2ZM9 8.5V9.5H10V8.5H9Z" fill="#676F83"/> +</svg> \ No newline at end of file diff --git a/web/app/components/base/icons/assets/vender/workflow/agent.svg b/web/app/components/base/icons/assets/vender/workflow/agent.svg new file mode 100644 index 0000000000..f30c0b455f --- /dev/null +++ b/web/app/components/base/icons/assets/vender/workflow/agent.svg @@ -0,0 +1,8 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="agent"> +<g id="Vector"> +<path d="M14.7401 5.80454C14.5765 4.77996 14.1638 3.79808 13.5306 2.97273C12.8973 2.14738 12.0648 1.48568 11.1185 1.06589C10.1722 0.646098 9.12632 0.461106 8.08751 0.546487C7.05582 0.624753 6.04548 0.966277 5.17744 1.53548C4.3094 2.09758 3.58366 2.88024 3.09272 3.79808C2.59466 4.70881 2.33852 5.7405 2.33852 6.7793V7.22756L1.25703 9.3692C1.04357 9.80322 1.22145 10.3368 1.65547 10.5574L2.3314 10.8989V12.3006C2.3314 12.82 2.53063 13.3038 2.90061 13.6738C3.2706 14.0367 3.75442 14.243 4.27382 14.243H6.01702V14.7624C6.01702 15.1538 6.3372 15.4739 6.72853 15.4739C7.11986 15.4739 7.44004 15.1538 7.44004 14.7624V13.7094C7.44004 13.2185 7.04159 12.82 6.55065 12.82H4.27382C4.13864 12.82 4.00345 12.7631 3.91095 12.6706C3.81846 12.5781 3.76154 12.4429 3.76154 12.3077V10.5716C3.76154 10.2301 3.56943 9.92417 3.2706 9.77476L2.77254 9.52573L3.66904 7.73984C3.72596 7.61889 3.76154 7.4837 3.76154 7.34851V6.77219C3.76154 5.96818 3.96076 5.17129 4.34498 4.4669C4.72919 3.76251 5.28417 3.15772 5.9601 2.7237C6.63603 2.28968 7.41158 2.02643 8.20847 1.96239C9.00536 1.89835 9.81648 2.04066 10.5493 2.36795C11.2822 2.69524 11.9225 3.20042 12.4135 3.84077C12.8973 4.47402 13.2246 5.23533 13.3456 6.02511C13.4665 6.81488 13.3954 7.63312 13.125 8.38731C12.8617 9.12017 12.4206 9.78187 11.8585 10.3084C11.6735 10.4792 11.5668 10.7139 11.5668 10.9701V14.7624C11.5668 15.1538 11.887 15.4739 12.2783 15.4739C12.6696 15.4739 12.9898 15.1538 12.9898 14.7624V11.1978C13.6515 10.5432 14.1567 9.73918 14.4697 8.87114C14.8184 7.89637 14.918 6.83623 14.7615 5.81165L14.7401 5.80454Z" fill="white"/> +<path d="M10.8055 7.99599C10.8909 7.83234 10.962 7.66158 11.0189 7.4837H11.6522C12.0435 7.4837 12.3637 7.16352 12.3637 6.77219C12.3637 6.38086 12.0435 6.06068 11.6522 6.06068H11.0189C10.9691 5.8828 10.898 5.71204 10.8055 5.54839L11.2537 5.10014C11.5312 4.82266 11.5312 4.3744 11.2537 4.09692C10.9762 3.81943 10.528 3.81943 10.2505 4.09692L9.80225 4.54517C9.6386 4.45267 9.46784 4.38863 9.28996 4.33171V3.69847C9.28996 3.30714 8.96978 2.98696 8.57845 2.98696C8.18712 2.98696 7.86694 3.30714 7.86694 3.69847V4.33171C7.68907 4.38152 7.5183 4.45267 7.35466 4.54517L6.90641 4.09692C6.62892 3.81943 6.18067 3.81943 5.90318 4.09692C5.62569 4.3744 5.62569 4.82266 5.90318 5.10014L6.35143 5.54839C6.26605 5.71204 6.1949 5.8828 6.13798 6.06068H5.50473C5.1134 6.06068 4.79323 6.38086 4.79323 6.77219C4.79323 7.16352 5.1134 7.4837 5.50473 7.4837H6.13798C6.18778 7.66158 6.25893 7.83234 6.35143 7.99599L5.90318 8.44424C5.62569 8.72172 5.62569 9.16997 5.90318 9.44746C6.04548 9.58976 6.22336 9.6538 6.40835 9.6538C6.59334 9.6538 6.77122 9.58265 6.91352 9.44746L7.36177 8.99921C7.52542 9.08459 7.69618 9.15574 7.87406 9.21267V9.84591C7.87406 10.2372 8.19424 10.5574 8.58557 10.5574C8.9769 10.5574 9.29708 10.2372 9.29708 9.84591V9.21267C9.47496 9.16286 9.64572 9.09171 9.80936 8.99921L10.2576 9.44746C10.3999 9.58976 10.5778 9.6538 10.7628 9.6538C10.9478 9.6538 11.1257 9.58265 11.268 9.44746C11.5454 9.16997 11.5454 8.72172 11.268 8.44424L10.8197 7.99599H10.8055ZM7.44004 6.77219C7.44004 6.14606 7.94521 5.64089 8.57134 5.64089C9.19747 5.64089 9.70264 6.14606 9.70264 6.77219C9.70264 7.39832 9.19747 7.90349 8.57134 7.90349C7.94521 7.90349 7.44004 7.39832 7.44004 6.77219Z" fill="white"/> +</g> +</g> +</svg> diff --git a/web/app/components/base/icons/script.js b/web/app/components/base/icons/script.mjs similarity index 94% rename from web/app/components/base/icons/script.js rename to web/app/components/base/icons/script.mjs index 0ff6a2a483..1952a15251 100644 --- a/web/app/components/base/icons/script.js +++ b/web/app/components/base/icons/script.mjs @@ -1,8 +1,9 @@ -const path = require('node:path') -const { open, readdir, access, mkdir, writeFile, appendFile, rm } = require('node:fs/promises') -const { parseXml } = require('@rgrove/parse-xml') -const camelCase = require('lodash/camelCase') -const template = require('lodash/template') +import path from 'node:path' +import { access, appendFile, mkdir, open, readdir, rm, writeFile } from 'node:fs/promises' +import { parseXml } from '@rgrove/parse-xml' +import { camelCase, template } from 'lodash-es' + +const __dirname = path.dirname(new URL(import.meta.url).pathname) const generateDir = async (currentPath) => { try { diff --git a/web/app/components/base/icons/src/image/llm/BaichuanTextCn.tsx b/web/app/components/base/icons/src/image/llm/BaichuanTextCn.tsx index 5206d02622..85280607a7 100644 --- a/web/app/components/base/icons/src/image/llm/BaichuanTextCn.tsx +++ b/web/app/components/base/icons/src/image/llm/BaichuanTextCn.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './BaichuanTextCn.module.css' import cn from '@/utils/classnames' +import s from './BaichuanTextCn.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/Minimax.tsx b/web/app/components/base/icons/src/image/llm/Minimax.tsx index 7b75ff6f61..ea8c87a188 100644 --- a/web/app/components/base/icons/src/image/llm/Minimax.tsx +++ b/web/app/components/base/icons/src/image/llm/Minimax.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './Minimax.module.css' import cn from '@/utils/classnames' +import s from './Minimax.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/MinimaxText.tsx b/web/app/components/base/icons/src/image/llm/MinimaxText.tsx index 490a977517..b6dfba4f70 100644 --- a/web/app/components/base/icons/src/image/llm/MinimaxText.tsx +++ b/web/app/components/base/icons/src/image/llm/MinimaxText.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './MinimaxText.module.css' import cn from '@/utils/classnames' +import s from './MinimaxText.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/Tongyi.tsx b/web/app/components/base/icons/src/image/llm/Tongyi.tsx index 543b4ce63d..2fc2c8b000 100644 --- a/web/app/components/base/icons/src/image/llm/Tongyi.tsx +++ b/web/app/components/base/icons/src/image/llm/Tongyi.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './Tongyi.module.css' import cn from '@/utils/classnames' +import s from './Tongyi.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/TongyiText.tsx b/web/app/components/base/icons/src/image/llm/TongyiText.tsx index 16e3920780..ca8cd5793b 100644 --- a/web/app/components/base/icons/src/image/llm/TongyiText.tsx +++ b/web/app/components/base/icons/src/image/llm/TongyiText.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './TongyiText.module.css' import cn from '@/utils/classnames' +import s from './TongyiText.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/TongyiTextCn.tsx b/web/app/components/base/icons/src/image/llm/TongyiTextCn.tsx index c14d323c60..605a254b57 100644 --- a/web/app/components/base/icons/src/image/llm/TongyiTextCn.tsx +++ b/web/app/components/base/icons/src/image/llm/TongyiTextCn.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './TongyiTextCn.module.css' import cn from '@/utils/classnames' +import s from './TongyiTextCn.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/Wxyy.tsx b/web/app/components/base/icons/src/image/llm/Wxyy.tsx index 312e325043..c73ddffa1c 100644 --- a/web/app/components/base/icons/src/image/llm/Wxyy.tsx +++ b/web/app/components/base/icons/src/image/llm/Wxyy.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './Wxyy.module.css' import cn from '@/utils/classnames' +import s from './Wxyy.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/WxyyText.tsx b/web/app/components/base/icons/src/image/llm/WxyyText.tsx index fd618e8d34..1ba8335fd2 100644 --- a/web/app/components/base/icons/src/image/llm/WxyyText.tsx +++ b/web/app/components/base/icons/src/image/llm/WxyyText.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './WxyyText.module.css' import cn from '@/utils/classnames' +import s from './WxyyText.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/image/llm/WxyyTextCn.tsx b/web/app/components/base/icons/src/image/llm/WxyyTextCn.tsx index 01acc26241..02616573e5 100644 --- a/web/app/components/base/icons/src/image/llm/WxyyTextCn.tsx +++ b/web/app/components/base/icons/src/image/llm/WxyyTextCn.tsx @@ -2,8 +2,8 @@ // DON NOT EDIT IT MANUALLY import * as React from 'react' -import s from './WxyyTextCn.module.css' import cn from '@/utils/classnames' +import s from './WxyyTextCn.module.css' const Icon = React.forwardRef<HTMLSpanElement, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>>(( { className, ...restProps }, diff --git a/web/app/components/base/icons/src/public/common/Highlight.json b/web/app/components/base/icons/src/public/common/Highlight.json new file mode 100644 index 0000000000..d18386eb01 --- /dev/null +++ b/web/app/components/base/icons/src/public/common/Highlight.json @@ -0,0 +1,67 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "xmlns": "http://www.w3.org/2000/svg", + "width": "46", + "height": "24", + "viewBox": "0 0 46 24", + "fill": "none" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "opacity": "0.5", + "d": "M-6.5 8C-6.5 3.58172 -2.91828 0 1.5 0H45.5L33.0248 24H1.49999C-2.91829 24 -6.5 20.4183 -6.5 16V8Z", + "fill": "url(#paint0_linear_6333_42118)" + }, + "children": [] + }, + { + "type": "element", + "name": "defs", + "attributes": {}, + "children": [ + { + "type": "element", + "name": "linearGradient", + "attributes": { + "id": "paint0_linear_6333_42118", + "x1": "1.81679", + "y1": "5.47784e-07", + "x2": "101.257", + "y2": "30.3866", + "gradientUnits": "userSpaceOnUse" + }, + "children": [ + { + "type": "element", + "name": "stop", + "attributes": { + "stop-color": "white", + "stop-opacity": "0.12" + }, + "children": [] + }, + { + "type": "element", + "name": "stop", + "attributes": { + "offset": "1", + "stop-color": "white", + "stop-opacity": "0.3" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "Highlight" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/public/common/Highlight.tsx b/web/app/components/base/icons/src/public/common/Highlight.tsx new file mode 100644 index 0000000000..379f38f78e --- /dev/null +++ b/web/app/components/base/icons/src/public/common/Highlight.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Highlight.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'Highlight' + +export default Icon diff --git a/web/app/components/base/icons/src/public/common/SparklesSoft.json b/web/app/components/base/icons/src/public/common/SparklesSoft.json new file mode 100644 index 0000000000..e22cec82a3 --- /dev/null +++ b/web/app/components/base/icons/src/public/common/SparklesSoft.json @@ -0,0 +1,47 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "14", + "height": "14", + "viewBox": "0 0 14 14", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "sparkles-soft" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "opacity": "0.5", + "d": "M10.9963 1.36798C10.9839 1.25339 10.8909 1.16677 10.7802 1.16666C10.6695 1.16654 10.5763 1.25295 10.5636 1.36752C10.5045 1.90085 10.3525 2.26673 10.1143 2.5149C9.87599 2.76307 9.52476 2.92145 9.01275 2.98296C8.90277 2.99618 8.81983 3.09324 8.81995 3.20856C8.82006 3.32388 8.90322 3.42076 9.0132 3.43373C9.51653 3.49312 9.87583 3.65148 10.1201 3.90135C10.3631 4.14986 10.518 4.51523 10.563 5.04321C10.573 5.16035 10.6673 5.25012 10.7802 5.24999C10.8931 5.24986 10.9872 5.15987 10.9969 5.0427C11.0401 4.52364 11.1949 4.15004 11.4394 3.89528C11.684 3.64052 12.0426 3.47926 12.5409 3.43433C12.6534 3.42419 12.7398 3.32619 12.7399 3.20858C12.7401 3.09097 12.6539 2.99277 12.5414 2.98236C12.0346 2.93546 11.6838 2.77407 11.4452 2.52098C11.2054 2.2665 11.0533 1.89229 10.9963 1.36798Z", + "fill": "#F5F8FF" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_2", + "d": "M7.13646 2.85102C7.10442 2.55638 6.8653 2.33365 6.5806 2.33334C6.29595 2.33304 6.05633 2.55526 6.02374 2.84984C5.87186 4.22127 5.48089 5.1621 4.86827 5.80025C4.25565 6.43838 3.35245 6.84566 2.03587 7.00386C1.75307 7.03781 1.53975 7.28742 1.54004 7.58393C1.54033 7.88049 1.75415 8.12958 2.03701 8.16294C3.33132 8.31566 4.25509 8.72289 4.88328 9.36543C5.50807 10.0045 5.90647 10.9439 6.02222 12.3016C6.04793 12.6029 6.29035 12.8337 6.58066 12.8333C6.87102 12.833 7.11294 12.6016 7.13797 12.3003C7.24885 10.9656 7.64695 10.0049 8.27583 9.34979C8.90477 8.69471 9.82698 8.28002 11.1083 8.16452C11.3976 8.13844 11.6197 7.88644 11.62 7.58399C11.6204 7.28159 11.3988 7.02906 11.1096 7.00229C9.8062 6.88171 8.90432 6.46673 8.29084 5.81589C7.674 5.16152 7.28306 4.19926 7.13646 2.85102Z", + "fill": "#F5F8FF" + }, + "children": [] + } + ] + } + ] + }, + "name": "SparklesSoft" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/public/common/SparklesSoft.tsx b/web/app/components/base/icons/src/public/common/SparklesSoft.tsx new file mode 100644 index 0000000000..dd422c400f --- /dev/null +++ b/web/app/components/base/icons/src/public/common/SparklesSoft.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './SparklesSoft.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'SparklesSoft' + +export default Icon diff --git a/web/app/components/base/icons/src/public/common/index.ts b/web/app/components/base/icons/src/public/common/index.ts index e581cff751..788d275f92 100644 --- a/web/app/components/base/icons/src/public/common/index.ts +++ b/web/app/components/base/icons/src/public/common/index.ts @@ -2,9 +2,11 @@ export { default as D } from './D' export { default as DiagonalDividingLine } from './DiagonalDividingLine' export { default as Dify } from './Dify' export { default as Github } from './Github' +export { default as Highlight } from './Highlight' export { default as Line3 } from './Line3' export { default as Lock } from './Lock' export { default as MessageChatSquare } from './MessageChatSquare' export { default as MultiPathRetrieval } from './MultiPathRetrieval' export { default as NTo1Retrieval } from './NTo1Retrieval' export { default as Notion } from './Notion' +export { default as SparklesSoft } from './SparklesSoft' diff --git a/web/app/components/base/icons/src/vender/other/AnthropicText.json b/web/app/components/base/icons/src/vender/other/AnthropicText.json new file mode 100644 index 0000000000..a65ef47747 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/AnthropicText.json @@ -0,0 +1,539 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "90", + "height": "20", + "viewBox": "0 0 90 20", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "clip-path": "url(#clip0_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask0_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M89.375 4.99805H0V14.998H89.375V4.99805Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask0_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask1_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99609H89.375V14.9961H0V4.99609Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask1_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask2_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99414H89.375V14.9941H0V4.99414Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask2_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask3_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask3_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M18.1273 11.9244L13.7773 5.15625H11.4297V14.825H13.4321V8.05688L17.7821 14.825H20.1297V5.15625H18.1273V11.9244Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask4_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask4_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M21.7969 7.02094H25.0423V14.825H27.1139V7.02094H30.3594V5.15625H21.7969V7.02094Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask5_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask5_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M38.6442 9.00994H34.0871V5.15625H32.0156V14.825H34.0871V10.8746H38.6442V14.825H40.7156V5.15625H38.6442V9.00994Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask6_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask6_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M45.3376 7.02094H47.893C48.9152 7.02094 49.4539 7.39387 49.4539 8.09831C49.4539 8.80275 48.9152 9.17569 47.893 9.17569H45.3376V7.02094ZM51.5259 8.09831C51.5259 6.27506 50.186 5.15625 47.9897 5.15625H43.2656V14.825H45.3376V11.0404H47.6443L49.7164 14.825H52.0094L49.715 10.7521C50.8666 10.3094 51.5259 9.37721 51.5259 8.09831Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask7_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask7_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M57.8732 13.0565C56.2438 13.0565 55.2496 11.8963 55.2496 10.004C55.2496 8.08416 56.2438 6.92394 57.8732 6.92394C59.4887 6.92394 60.4691 8.08416 60.4691 10.004C60.4691 11.8963 59.4887 13.0565 57.8732 13.0565ZM57.8732 4.99023C55.0839 4.99023 53.1094 7.06206 53.1094 10.004C53.1094 12.9184 55.0839 14.9902 57.8732 14.9902C60.6486 14.9902 62.6094 12.9184 62.6094 10.004C62.6094 7.06206 60.6486 4.99023 57.8732 4.99023Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask8_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask8_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M69.1794 9.45194H66.6233V7.02094H69.1794C70.2019 7.02094 70.7407 7.43532 70.7407 8.23644C70.7407 9.03756 70.2019 9.45194 69.1794 9.45194ZM69.2762 5.15625H64.5508V14.825H66.6233V11.3166H69.2762C71.473 11.3166 72.8133 10.1564 72.8133 8.23644C72.8133 6.3165 71.473 5.15625 69.2762 5.15625Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask9_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask9_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M86.8413 11.5786C86.4823 12.5179 85.7642 13.0565 84.7837 13.0565C83.1542 13.0565 82.16 11.8963 82.16 10.004C82.16 8.08416 83.1542 6.92394 84.7837 6.92394C85.7642 6.92394 86.4823 7.46261 86.8413 8.40183H89.0369C88.4984 6.33002 86.8827 4.99023 84.7837 4.99023C81.9942 4.99023 80.0195 7.06206 80.0195 10.004C80.0195 12.9184 81.9942 14.9902 84.7837 14.9902C86.8965 14.9902 88.5122 13.6366 89.0508 11.5786H86.8413Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask10_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask10_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M73.6484 5.15625L77.5033 14.825H79.6172L75.7624 5.15625H73.6484Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask11_8587_60274", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "4", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M0 4.99219H89.375V14.9922H0V4.99219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask11_8587_60274)" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M3.64038 10.9989L4.95938 7.60106L6.27838 10.9989H3.64038ZM3.85422 5.15625L0 14.825H2.15505L2.9433 12.7946H6.97558L7.76371 14.825H9.91875L6.06453 5.15625H3.85422Z", + "fill": "currentColor", + "fill-opacity": "0.92" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "defs", + "attributes": {}, + "children": [ + { + "type": "element", + "name": "clipPath", + "attributes": { + "id": "clip0_8587_60274" + }, + "children": [ + { + "type": "element", + "name": "rect", + "attributes": { + "width": "89.375", + "height": "10", + "fill": "white", + "transform": "translate(0 5)" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "AnthropicText" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/other/AnthropicText.tsx b/web/app/components/base/icons/src/vender/other/AnthropicText.tsx new file mode 100644 index 0000000000..868cfe5f27 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/AnthropicText.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './AnthropicText.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'AnthropicText' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/other/Group.json b/web/app/components/base/icons/src/vender/other/Group.json new file mode 100644 index 0000000000..078febbc80 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/Group.json @@ -0,0 +1,66 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "14", + "height": "16", + "viewBox": "0 0 14 16", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M5.6475 8.0115L0.333496 5.05884V11.3335C0.333491 11.4524 0.365258 11.569 0.425506 11.6715C0.485754 11.7739 0.572294 11.8584 0.676163 11.9162L6.3335 15.0588V9.17684C6.33344 8.93907 6.26981 8.70565 6.14919 8.50075C6.02857 8.29586 5.85536 8.12694 5.6475 8.0115Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_2", + "d": "M7.66699 9.17684V15.0588L13.3243 11.9162C13.4282 11.8584 13.5147 11.7739 13.575 11.6715C13.6352 11.569 13.667 11.4524 13.667 11.3335V5.05884L8.35299 8.0115C8.14513 8.12694 7.97192 8.29586 7.8513 8.50075C7.73068 8.70565 7.66705 8.93907 7.66699 9.17684Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_3", + "d": "M10.1913 2.34351C9.804 3.33351 8.588 4.00017 7 4.00017C5.412 4.00017 4.196 3.33351 3.80867 2.34351L1 3.90417L6.35267 6.87817C6.5507 6.98815 6.77348 7.04586 7 7.04586C7.22652 7.04586 7.4493 6.98815 7.64733 6.87817L13 3.90417L10.1913 2.34351Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_4", + "d": "M7 2.66675C8.10457 2.66675 9 2.21903 9 1.66675C9 1.11446 8.10457 0.666748 7 0.666748C5.89543 0.666748 5 1.11446 5 1.66675C5 2.21903 5.89543 2.66675 7 2.66675Z", + "fill": "currentColor" + }, + "children": [] + } + ] + } + ] + }, + "name": "Group" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/other/Group.tsx b/web/app/components/base/icons/src/vender/other/Group.tsx new file mode 100644 index 0000000000..ba9d130f80 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/Group.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Group.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'Group' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/other/Openai.json b/web/app/components/base/icons/src/vender/other/Openai.json new file mode 100644 index 0000000000..236f66fcf2 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/Openai.json @@ -0,0 +1,80 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "80", + "height": "22", + "viewBox": "0 0 80 22", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M25.1152 10.5767C25.1152 14.1738 27.4253 16.6818 30.6264 16.6818C33.8274 16.6818 36.1375 14.1738 36.1375 10.5767C36.1375 6.97961 33.8274 4.47156 30.6264 4.47156C27.4253 4.47156 25.1152 6.97961 25.1152 10.5767ZM34.0254 10.5767C34.0254 13.1507 32.6229 14.8173 30.6264 14.8173C28.6298 14.8173 27.2273 13.1507 27.2273 10.5767C27.2273 8.00263 28.6298 6.3361 30.6264 6.3361C32.6229 6.3361 34.0254 8.00263 34.0254 10.5767Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M42.0868 16.6819C44.5124 16.6819 45.8984 14.6358 45.8984 12.1773C45.8984 9.71871 44.5124 7.67267 42.0868 7.67267C40.9648 7.67267 40.1398 8.11818 39.5953 8.76169V7.83767H37.6152V19.4704H39.5953V15.5928C40.1398 16.2364 40.9648 16.6819 42.0868 16.6819ZM39.5458 11.9298C39.5458 10.2962 40.4698 9.40521 41.6908 9.40521C43.1264 9.40521 43.9019 10.5272 43.9019 12.1773C43.9019 13.8273 43.1264 14.9493 41.6908 14.9493C40.4698 14.9493 39.5458 14.0418 39.5458 12.4413V11.9298Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M51.2545 16.6819C52.987 16.6819 54.3565 15.7743 54.967 14.2563L53.2675 13.6128C53.0035 14.5038 52.228 14.9988 51.2545 14.9988C49.9839 14.9988 49.0929 14.0913 48.9444 12.6063H55.0165V11.9463C55.0165 9.57021 53.68 7.67267 51.172 7.67267C48.6639 7.67267 47.0469 9.63621 47.0469 12.1773C47.0469 14.8503 48.7794 16.6819 51.2545 16.6819ZM51.1555 9.3392C52.4095 9.3392 53.0035 10.1642 53.02 11.1212H49.0434C49.3404 9.94972 50.1324 9.3392 51.1555 9.3392Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M56.5039 16.5004H58.484V11.4182C58.484 10.1807 59.3915 9.52071 60.2825 9.52071C61.3715 9.52071 61.8005 10.2962 61.8005 11.3687V16.5004H63.7806V10.7912C63.7806 8.9267 62.6915 7.67267 60.8765 7.67267C59.7545 7.67267 58.979 8.18418 58.484 8.76169V7.83767H56.5039V16.5004Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M69.5799 4.65308L65.0918 16.5003H67.1873L68.1939 13.7943H73.309L74.332 16.5003H76.4605L71.9724 4.65308H69.5799ZM70.7349 6.99613L72.616 11.9462H68.8869L70.7349 6.99613Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M79.8581 4.6875H77.7461V16.5348H79.8581V4.6875Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M20.2769 9.00436C20.776 7.50627 20.6041 5.86517 19.8059 4.50251C18.6055 2.41247 16.1924 1.3372 13.8356 1.84321C12.7871 0.662057 11.2808 -0.00964523 9.70154 -2.00271e-05C7.29248 -0.00552014 5.155 1.54551 4.41386 3.83769C2.86626 4.15463 1.53042 5.12334 0.748717 6.49631C-0.460621 8.58085 -0.184928 11.2085 1.43073 12.9961C0.931596 14.4942 1.10348 16.1353 1.90168 17.4979C3.10208 19.588 5.51526 20.6632 7.87206 20.1572C8.91983 21.3384 10.4269 22.0101 12.0061 21.9998C14.4165 22.006 16.5547 20.4535 17.2958 18.1593C18.8434 17.8424 20.1793 16.8737 20.961 15.5007C22.1689 13.4161 21.8925 10.7905 20.2776 9.00298L20.2769 9.00436ZM12.0075 20.5622C11.0429 20.5635 10.1085 20.226 9.36809 19.6079C9.40178 19.59 9.46022 19.5577 9.49803 19.5343L13.8789 17.0043C14.103 16.8771 14.2405 16.6385 14.2391 16.3807V10.2048L16.0906 11.2738C16.1105 11.2835 16.1236 11.3027 16.1264 11.3247V16.4391C16.1236 18.7134 14.2818 20.5574 12.0075 20.5622ZM3.14952 16.7788C2.6662 15.9441 2.49225 14.9658 2.65795 14.0163C2.69026 14.0356 2.74732 14.0707 2.78789 14.094L7.16873 16.6241C7.3908 16.754 7.6658 16.754 7.88856 16.6241L13.2367 13.5358V15.6739C13.2381 15.6959 13.2278 15.7173 13.2106 15.731L8.78233 18.2879C6.80985 19.4236 4.29079 18.7485 3.15021 16.7788H3.14952ZM1.99656 7.21613C2.47782 6.38012 3.23752 5.74073 4.14229 5.40866C4.14229 5.44647 4.14023 5.51316 4.14023 5.55991V10.6207C4.13885 10.8778 4.27636 11.1164 4.4998 11.2436L9.84798 14.3312L7.9965 15.4003C7.97794 15.4127 7.95456 15.4147 7.93393 15.4058L3.50496 12.8469C1.53661 11.707 0.86147 9.18861 1.99587 7.21682L1.99656 7.21613ZM17.2085 10.7561L11.8603 7.66783L13.7118 6.59943C13.7304 6.58706 13.7537 6.585 13.7744 6.59393L18.2033 9.1508C20.1751 10.29 20.851 12.8125 19.7118 14.7843C19.2298 15.6189 18.4708 16.2583 17.5667 16.5911V11.379C17.5688 11.1219 17.432 10.884 17.2092 10.7561H17.2085ZM19.0511 7.98271C19.0187 7.96278 18.9617 7.9284 18.9211 7.90502L14.5403 5.37497C14.3182 5.24503 14.0432 5.24503 13.8204 5.37497L8.47226 8.46329V6.32512C8.47088 6.30311 8.4812 6.2818 8.49838 6.26805L12.9267 3.71325C14.8991 2.57541 17.4209 3.25261 18.5581 5.22578C19.0387 6.05905 19.2126 7.03463 19.0497 7.98271H19.0511ZM7.46574 11.7936L5.61357 10.7245C5.59363 10.7149 5.58057 10.6956 5.57782 10.6736V5.55922C5.5792 3.28218 7.42655 1.43689 9.7036 1.43826C10.6668 1.43826 11.5991 1.77652 12.3395 2.39253C12.3058 2.41041 12.2481 2.44272 12.2096 2.46609L7.82874 4.99615C7.60461 5.12334 7.46711 5.36122 7.46849 5.61904L7.46574 11.7922V11.7936ZM8.47157 9.62519L10.8538 8.24947L13.236 9.6245V12.3752L10.8538 13.7503L8.47157 12.3752V9.62519Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + "name": "Openai" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/other/Openai.tsx b/web/app/components/base/icons/src/vender/other/Openai.tsx new file mode 100644 index 0000000000..cf8d21a449 --- /dev/null +++ b/web/app/components/base/icons/src/vender/other/Openai.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Openai.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'Openai' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/other/index.ts b/web/app/components/base/icons/src/vender/other/index.ts index 1982dcfa3a..8ddf5e7a86 100644 --- a/web/app/components/base/icons/src/vender/other/index.ts +++ b/web/app/components/base/icons/src/vender/other/index.ts @@ -1,2 +1,5 @@ +export { default as AnthropicText } from './AnthropicText' export { default as Generator } from './Generator' +export { default as Group } from './Group' +export { default as Openai } from './Openai' export { default as ReplayLine } from './ReplayLine' diff --git a/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.json b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.json new file mode 100644 index 0000000000..3733f98afd --- /dev/null +++ b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.json @@ -0,0 +1,66 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "14", + "height": "14", + "viewBox": "0 0 14 14", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Icon" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "fill-rule": "evenodd", + "clip-rule": "evenodd", + "d": "M11.3891 2.41987C11.6635 2.58871 11.749 2.94802 11.5802 3.22239L10.3324 5.25H11.0833C11.4055 5.25 11.6667 5.51117 11.6667 5.83334V11.6667C11.6667 12.311 11.1444 12.8333 10.5 12.8333H3.50001C2.85568 12.8333 2.33334 12.311 2.33334 11.6667V5.83334C2.33334 5.51117 2.59451 5.25 2.91668 5.25H8.96252L10.5865 2.61094C10.7554 2.33657 11.1147 2.25102 11.3891 2.41987ZM5.83334 7.58334C5.51118 7.58334 5.25001 7.84449 5.25001 8.16667C5.25001 8.48884 5.51118 8.75 5.83334 8.75H8.16668C8.48885 8.75 8.75001 8.48884 8.75001 8.16667C8.75001 7.84449 8.48885 7.58334 8.16668 7.58334H5.83334Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Vector_2", + "opacity": "0.5" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M6.91257 1.79347C6.96898 1.76525 7.01477 1.71948 7.043 1.66303L7.32195 1.10508C7.42946 0.890105 7.73623 0.890105 7.84374 1.10508L8.12269 1.66303C8.15093 1.71948 8.19672 1.76525 8.25313 1.79347L8.81108 2.07245C9.0261 2.17994 9.0261 2.48672 8.81108 2.5942L8.25313 2.87318C8.19672 2.9014 8.15093 2.94717 8.12269 3.00362L7.84374 3.56158C7.73623 3.77655 7.42946 3.77655 7.32195 3.56158L7.043 3.00362C7.01477 2.94717 6.96898 2.9014 6.91257 2.87318L6.35461 2.5942C6.13965 2.48672 6.13965 2.17994 6.35461 2.07245L6.91257 1.79347Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M3.80145 2.7657C3.85789 2.73748 3.90366 2.69171 3.93189 2.63526L4.11364 2.27174C4.22113 2.05677 4.5279 2.05677 4.63539 2.27174L4.81715 2.63526C4.84537 2.6917 4.89114 2.73748 4.94759 2.7657L5.3111 2.94745C5.52607 3.05494 5.52607 3.36172 5.3111 3.4692L4.94759 3.65096C4.89114 3.67919 4.84537 3.72495 4.81715 3.7814L4.63539 4.14491C4.5279 4.35988 4.22113 4.35988 4.11364 4.14491L3.93189 3.7814C3.90366 3.72495 3.85789 3.67919 3.80145 3.65096L3.43793 3.4692C3.22296 3.36172 3.22296 3.05494 3.43793 2.94745L3.80145 2.7657Z", + "fill": "currentColor" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "BoxSparkleFill" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx new file mode 100644 index 0000000000..5b60827fe9 --- /dev/null +++ b/web/app/components/base/icons/src/vender/plugin/BoxSparkleFill.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './BoxSparkleFill.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'BoxSparkleFill' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/plugin/LeftCorner.json b/web/app/components/base/icons/src/vender/plugin/LeftCorner.json new file mode 100644 index 0000000000..d4cd0cd0ec --- /dev/null +++ b/web/app/components/base/icons/src/vender/plugin/LeftCorner.json @@ -0,0 +1,27 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "13", + "height": "20", + "viewBox": "0 0 13 20", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Shape", + "d": "M0 0H13V20C9.98017 20 7.26458 18.1615 6.14305 15.3576L0 0Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + "name": "LeftCorner" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx b/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx new file mode 100644 index 0000000000..dd215b9bf7 --- /dev/null +++ b/web/app/components/base/icons/src/vender/plugin/LeftCorner.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './LeftCorner.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'LeftCorner' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/plugin/index.ts b/web/app/components/base/icons/src/vender/plugin/index.ts new file mode 100644 index 0000000000..943c764116 --- /dev/null +++ b/web/app/components/base/icons/src/vender/plugin/index.ts @@ -0,0 +1,2 @@ +export { default as BoxSparkleFill } from './BoxSparkleFill' +export { default as LeftCorner } from './LeftCorner' diff --git a/web/app/components/base/icons/src/vender/solid/files/FileZip.json b/web/app/components/base/icons/src/vender/solid/files/FileZip.json new file mode 100644 index 0000000000..11fe823916 --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/files/FileZip.json @@ -0,0 +1,47 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "16", + "height": "16", + "viewBox": "0 0 16 16", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Icon" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M3.99999 1.33325H7.99999V5.33325C7.99999 6.06963 8.59692 6.66659 9.33332 6.66659H13.3333V13.3333C13.3333 14.0697 12.7364 14.6666 12 14.6666H6.66666V13.3333H7.99999V11.9999H6.66666V10.6666H7.99999V9.33325H6.66666V7.99992H5.33332V9.33325H6.66666V10.6666H5.33332V11.9999H6.66666V13.3333H5.33332V14.6666H3.99999C3.26361 14.6666 2.66666 14.0697 2.66666 13.3333V2.66659C2.66666 1.93021 3.26361 1.33325 3.99999 1.33325Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_2", + "opacity": "0.5", + "d": "M12.9428 4.99993C13.0415 5.09868 13.1232 5.21133 13.1859 5.33327H9.33334V1.48071C9.45528 1.54338 9.56794 1.62504 9.66668 1.72379L12.9428 4.99993Z", + "fill": "currentColor" + }, + "children": [] + } + ] + } + ] + }, + "name": "FileZip" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx b/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx new file mode 100644 index 0000000000..675fa0ac98 --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/files/FileZip.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './FileZip.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'FileZip' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/solid/files/index.ts b/web/app/components/base/icons/src/vender/solid/files/index.ts index 31feeb5309..fa93cd68dc 100644 --- a/web/app/components/base/icons/src/vender/solid/files/index.ts +++ b/web/app/components/base/icons/src/vender/solid/files/index.ts @@ -1,3 +1,4 @@ export { default as File05 } from './File05' export { default as FileSearch02 } from './FileSearch02' +export { default as FileZip } from './FileZip' export { default as Folder } from './Folder' diff --git a/web/app/components/base/icons/src/vender/solid/general/Github.json b/web/app/components/base/icons/src/vender/solid/general/Github.json new file mode 100644 index 0000000000..46e694215b --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/general/Github.json @@ -0,0 +1,36 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "16", + "height": "16", + "viewBox": "0 0 16 16", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Icon" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M8 1C4.1325 1 1 4.1325 1 8C1 11.0975 3.00375 13.7137 5.78625 14.6413C6.13625 14.7025 6.2675 14.4925 6.2675 14.3088C6.2675 14.1425 6.25875 13.5913 6.25875 13.005C4.5 13.3288 4.045 12.5763 3.905 12.1825C3.82625 11.9812 3.485 11.36 3.1875 11.1937C2.9425 11.0625 2.5925 10.7387 3.17875 10.73C3.73 10.7212 4.12375 11.2375 4.255 11.4475C4.885 12.5062 5.89125 12.2088 6.29375 12.025C6.355 11.57 6.53875 11.2638 6.74 11.0887C5.1825 10.9137 3.555 10.31 3.555 7.6325C3.555 6.87125 3.82625 6.24125 4.2725 5.75125C4.2025 5.57625 3.9575 4.85875 4.3425 3.89625C4.3425 3.89625 4.92875 3.7125 6.2675 4.61375C6.8275 4.45625 7.4225 4.3775 8.0175 4.3775C8.6125 4.3775 9.2075 4.45625 9.7675 4.61375C11.1063 3.70375 11.6925 3.89625 11.6925 3.89625C12.0775 4.85875 11.8325 5.57625 11.7625 5.75125C12.2087 6.24125 12.48 6.8625 12.48 7.6325C12.48 10.3187 10.8438 10.9137 9.28625 11.0887C9.54 11.3075 9.75875 11.7275 9.75875 12.3837C9.75875 13.32 9.75 14.0725 9.75 14.3088C9.75 14.4925 9.88125 14.7113 10.2312 14.6413C11.6209 14.1721 12.8284 13.279 13.6839 12.0877C14.5393 10.8963 14.9996 9.46668 15 8C15 4.1325 11.8675 1 8 1Z", + "fill": "currentColor" + }, + "children": [] + } + ] + } + ] + }, + "name": "Github" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/solid/general/Github.tsx b/web/app/components/base/icons/src/vender/solid/general/Github.tsx new file mode 100644 index 0000000000..416743fc71 --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/general/Github.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Github.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'Github' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/solid/general/index.ts b/web/app/components/base/icons/src/vender/solid/general/index.ts index 9d2492e287..52647905ab 100644 --- a/web/app/components/base/icons/src/vender/solid/general/index.ts +++ b/web/app/components/base/icons/src/vender/solid/general/index.ts @@ -5,6 +5,7 @@ export { default as Download02 } from './Download02' export { default as Edit03 } from './Edit03' export { default as Edit04 } from './Edit04' export { default as Eye } from './Eye' +export { default as Github } from './Github' export { default as MessageClockCircle } from './MessageClockCircle' export { default as PlusCircle } from './PlusCircle' export { default as QuestionTriangle } from './QuestionTriangle' diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.json b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.json new file mode 100644 index 0000000000..cd3006b76d --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.json @@ -0,0 +1,26 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "xmlns": "http://www.w3.org/2000/svg", + "width": "12", + "height": "12", + "viewBox": "0 0 12 12", + "fill": "none" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M10.3567 3.56405L10.2334 3.84689C10.1432 4.05396 9.8568 4.05396 9.76655 3.84689L9.6433 3.56405C9.42355 3.05973 9.02775 2.6582 8.53385 2.43854L8.154 2.26961C7.94865 2.17826 7.94865 1.8794 8.154 1.78806L8.5126 1.62857C9.0192 1.40325 9.4221 0.986865 9.63805 0.465414L9.76465 0.159767C9.8529 -0.0532556 10.1471 -0.0532556 10.2353 0.159767L10.3619 0.465414C10.5779 0.986865 10.9808 1.40325 11.4874 1.62857L11.846 1.78806C12.0514 1.8794 12.0514 2.17826 11.846 2.26961L11.4662 2.43854C10.9723 2.6582 10.5764 3.05973 10.3567 3.56405ZM4.25 3H3.25V9H4.25V3ZM2 5H1V7H2V5ZM6.5 1H5.5V11H6.5V1ZM8.75 4H7.75V9H8.75V4ZM11 5H10V7H11V5Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + "name": "AudioSupportIcon" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx new file mode 100644 index 0000000000..c9477fc07f --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/AudioSupportIcon.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './AudioSupportIcon.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'AudioSupportIcon' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.json b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.json new file mode 100644 index 0000000000..49cb6a521c --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.json @@ -0,0 +1,26 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "xmlns": "http://www.w3.org/2000/svg", + "width": "12", + "height": "12", + "viewBox": "0 0 12 12", + "fill": "none" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M10.5 4V10.4966C10.5 10.7751 10.2776 11 10.0033 11H1.9967C1.72248 11 1.5 10.778 1.5 10.5041V1.4959C1.5 1.22766 1.72435 1 2.00111 1H7.4984L10.5 4ZM9.5 4.5H7V2H2.5V10H9.5V4.5ZM4 3.5H5.5V4.5H4V3.5ZM4 5.5H8V6.5H4V5.5ZM4 7.5H8V8.5H4V7.5Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + "name": "DocumentSupportIcon" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx new file mode 100644 index 0000000000..d848c5a156 --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/DocumentSupportIcon.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './DocumentSupportIcon.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'DocumentSupportIcon' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.json b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.json new file mode 100644 index 0000000000..4bc6881a5d --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.json @@ -0,0 +1,26 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "xmlns": "http://www.w3.org/2000/svg", + "width": "12", + "height": "12", + "viewBox": "0 0 12 12", + "fill": "none" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M10.2334 4.3469L10.3567 4.06406C10.5764 3.55974 10.9723 3.15821 11.4662 2.93854L11.846 2.76961C12.0514 2.67827 12.0514 2.37941 11.846 2.28806L11.4874 2.12857C10.9808 1.90326 10.5779 1.48687 10.3619 0.965415L10.2353 0.659765C10.1471 0.446745 9.8529 0.446745 9.76465 0.659765L9.63805 0.965415C9.4221 1.48687 9.0192 1.90326 8.5126 2.12857L8.154 2.28806C7.94865 2.37941 7.94865 2.67827 8.154 2.76961L8.53385 2.93854C9.02775 3.15821 9.42355 3.55974 9.6433 4.06406L9.76655 4.3469C9.8568 4.55396 10.1432 4.55396 10.2334 4.3469ZM1.4959 1.5H7V2.5H4V9.5H8V4.5H9V5.5H10H11V10.0033C11 10.2776 10.7723 10.5 10.5041 10.5H1.4959C1.22203 10.5 1 10.2775 1 10.0033V1.9967C1 1.72238 1.22766 1.5 1.4959 1.5ZM2 2.5V3.5H3V2.5H2ZM2 4.5V5.5H3V4.5H2ZM2 6.5V7.5H3V6.5H2ZM9 6.5V7.5H10V6.5H9ZM2 8.5V9.5H3V8.5H2ZM9 8.5V9.5H10V8.5H9Z", + "fill": "currentColor" + }, + "children": [] + } + ] + }, + "name": "VideoSupportIcon" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx new file mode 100644 index 0000000000..6406af0746 --- /dev/null +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/VideoSupportIcon.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './VideoSupportIcon.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'VideoSupportIcon' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/index.ts b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/index.ts index ab43a47ea1..7c313fecfb 100644 --- a/web/app/components/base/icons/src/vender/solid/mediaAndDevices/index.ts +++ b/web/app/components/base/icons/src/vender/solid/mediaAndDevices/index.ts @@ -1,3 +1,5 @@ +export { default as AudioSupportIcon } from './AudioSupportIcon' +export { default as DocumentSupportIcon } from './DocumentSupportIcon' export { default as MagicBox } from './MagicBox' export { default as MagicEyes } from './MagicEyes' export { default as MagicWand } from './MagicWand' @@ -7,3 +9,4 @@ export { default as Robot } from './Robot' export { default as Sliders02 } from './Sliders02' export { default as Speaker } from './Speaker' export { default as StopCircle } from './StopCircle' +export { default as VideoSupportIcon } from './VideoSupportIcon' diff --git a/web/app/components/base/icons/src/vender/workflow/Agent.json b/web/app/components/base/icons/src/vender/workflow/Agent.json new file mode 100644 index 0000000000..e7ed19369b --- /dev/null +++ b/web/app/components/base/icons/src/vender/workflow/Agent.json @@ -0,0 +1,53 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "16", + "height": "16", + "viewBox": "0 0 16 16", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "agent" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Vector" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "d": "M14.7401 5.80454C14.5765 4.77996 14.1638 3.79808 13.5306 2.97273C12.8973 2.14738 12.0648 1.48568 11.1185 1.06589C10.1722 0.646098 9.12632 0.461106 8.08751 0.546487C7.05582 0.624753 6.04548 0.966277 5.17744 1.53548C4.3094 2.09758 3.58366 2.88024 3.09272 3.79808C2.59466 4.70881 2.33852 5.7405 2.33852 6.7793V7.22756L1.25703 9.3692C1.04357 9.80322 1.22145 10.3368 1.65547 10.5574L2.3314 10.8989V12.3006C2.3314 12.82 2.53063 13.3038 2.90061 13.6738C3.2706 14.0367 3.75442 14.243 4.27382 14.243H6.01702V14.7624C6.01702 15.1538 6.3372 15.4739 6.72853 15.4739C7.11986 15.4739 7.44004 15.1538 7.44004 14.7624V13.7094C7.44004 13.2185 7.04159 12.82 6.55065 12.82H4.27382C4.13864 12.82 4.00345 12.7631 3.91095 12.6706C3.81846 12.5781 3.76154 12.4429 3.76154 12.3077V10.5716C3.76154 10.2301 3.56943 9.92417 3.2706 9.77476L2.77254 9.52573L3.66904 7.73984C3.72596 7.61889 3.76154 7.4837 3.76154 7.34851V6.77219C3.76154 5.96818 3.96076 5.17129 4.34498 4.4669C4.72919 3.76251 5.28417 3.15772 5.9601 2.7237C6.63603 2.28968 7.41158 2.02643 8.20847 1.96239C9.00536 1.89835 9.81648 2.04066 10.5493 2.36795C11.2822 2.69524 11.9225 3.20042 12.4135 3.84077C12.8973 4.47402 13.2246 5.23533 13.3456 6.02511C13.4665 6.81488 13.3954 7.63312 13.125 8.38731C12.8617 9.12017 12.4206 9.78187 11.8585 10.3084C11.6735 10.4792 11.5668 10.7139 11.5668 10.9701V14.7624C11.5668 15.1538 11.887 15.4739 12.2783 15.4739C12.6696 15.4739 12.9898 15.1538 12.9898 14.7624V11.1978C13.6515 10.5432 14.1567 9.73918 14.4697 8.87114C14.8184 7.89637 14.918 6.83623 14.7615 5.81165L14.7401 5.80454Z", + "fill": "currentColor" + }, + "children": [] + }, + { + "type": "element", + "name": "path", + "attributes": { + "d": "M10.8055 7.99599C10.8909 7.83234 10.962 7.66158 11.0189 7.4837H11.6522C12.0435 7.4837 12.3637 7.16352 12.3637 6.77219C12.3637 6.38086 12.0435 6.06068 11.6522 6.06068H11.0189C10.9691 5.8828 10.898 5.71204 10.8055 5.54839L11.2537 5.10014C11.5312 4.82266 11.5312 4.3744 11.2537 4.09692C10.9762 3.81943 10.528 3.81943 10.2505 4.09692L9.80225 4.54517C9.6386 4.45267 9.46784 4.38863 9.28996 4.33171V3.69847C9.28996 3.30714 8.96978 2.98696 8.57845 2.98696C8.18712 2.98696 7.86694 3.30714 7.86694 3.69847V4.33171C7.68907 4.38152 7.5183 4.45267 7.35466 4.54517L6.90641 4.09692C6.62892 3.81943 6.18067 3.81943 5.90318 4.09692C5.62569 4.3744 5.62569 4.82266 5.90318 5.10014L6.35143 5.54839C6.26605 5.71204 6.1949 5.8828 6.13798 6.06068H5.50473C5.1134 6.06068 4.79323 6.38086 4.79323 6.77219C4.79323 7.16352 5.1134 7.4837 5.50473 7.4837H6.13798C6.18778 7.66158 6.25893 7.83234 6.35143 7.99599L5.90318 8.44424C5.62569 8.72172 5.62569 9.16997 5.90318 9.44746C6.04548 9.58976 6.22336 9.6538 6.40835 9.6538C6.59334 9.6538 6.77122 9.58265 6.91352 9.44746L7.36177 8.99921C7.52542 9.08459 7.69618 9.15574 7.87406 9.21267V9.84591C7.87406 10.2372 8.19424 10.5574 8.58557 10.5574C8.9769 10.5574 9.29708 10.2372 9.29708 9.84591V9.21267C9.47496 9.16286 9.64572 9.09171 9.80936 8.99921L10.2576 9.44746C10.3999 9.58976 10.5778 9.6538 10.7628 9.6538C10.9478 9.6538 11.1257 9.58265 11.268 9.44746C11.5454 9.16997 11.5454 8.72172 11.268 8.44424L10.8197 7.99599H10.8055ZM7.44004 6.77219C7.44004 6.14606 7.94521 5.64089 8.57134 5.64089C9.19747 5.64089 9.70264 6.14606 9.70264 6.77219C9.70264 7.39832 9.19747 7.90349 8.57134 7.90349C7.94521 7.90349 7.44004 7.39832 7.44004 6.77219Z", + "fill": "currentColor" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "Agent" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/workflow/Agent.tsx b/web/app/components/base/icons/src/vender/workflow/Agent.tsx new file mode 100644 index 0000000000..e4337d4dbd --- /dev/null +++ b/web/app/components/base/icons/src/vender/workflow/Agent.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './Agent.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'Agent' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/workflow/index.ts b/web/app/components/base/icons/src/vender/workflow/index.ts index b2cc7968bb..11ce55b130 100644 --- a/web/app/components/base/icons/src/vender/workflow/index.ts +++ b/web/app/components/base/icons/src/vender/workflow/index.ts @@ -1,3 +1,4 @@ +export { default as Agent } from './Agent' export { default as Answer } from './Answer' export { default as Assigner } from './Assigner' export { default as Code } from './Code' diff --git a/web/app/components/base/image-uploader/image-preview.tsx b/web/app/components/base/image-uploader/image-preview.tsx index 748e6ba8da..1a11c91275 100644 --- a/web/app/components/base/image-uploader/image-preview.tsx +++ b/web/app/components/base/image-uploader/image-preview.tsx @@ -7,7 +7,7 @@ import { useHotkeys } from 'react-hotkeys-hook' import Tooltip from '@/app/components/base/tooltip' import Toast from '@/app/components/base/toast' -type ImagePreviewProps = { +interface ImagePreviewProps { url: string title: string onCancel: () => void @@ -99,7 +99,7 @@ const ImagePreview: FC<ImagePreviewProps> = ({ for (let offset = 0; offset < byteCharacters.length; offset += 512) { const slice = byteCharacters.slice(offset, offset + 512) - const byteNumbers = new Array(slice.length) + const byteNumbers = Array.from({ length: slice.length }) for (let i = 0; i < slice.length; i++) byteNumbers[i] = slice.charCodeAt(i) diff --git a/web/app/components/base/install-button/index.tsx b/web/app/components/base/install-button/index.tsx new file mode 100644 index 0000000000..848183780c --- /dev/null +++ b/web/app/components/base/install-button/index.tsx @@ -0,0 +1,27 @@ +import Button from '../button' +import { RiInstallLine, RiLoader2Line } from '@remixicon/react' + +type InstallButtonProps = { + loading: boolean + onInstall: (e: React.MouseEvent) => void + t: any +} + +const InstallButton = ({ loading, onInstall, t }: InstallButtonProps) => { + return ( + <Button size='small' className='z-[100]' onClick={onInstall}> + <div className={`flex px-[3px] justify-center items-center gap-1 + ${loading ? 'text-components-button-secondary-text-disabled' : 'text-components-button-secondary-text'} + system-xs-medium`} + > + {loading ? t('workflow.nodes.agent.pluginInstaller.installing') : t('workflow.nodes.agent.pluginInstaller.install')} + </div> + {loading + ? <RiLoader2Line className='w-3.5 h-3.5 text-text-quaternary animate-spin' /> + : <RiInstallLine className='w-3.5 h-3.5 text-text-secondary' /> + } + </Button> + ) +} + +export default InstallButton diff --git a/web/app/components/base/list-empty/index.tsx b/web/app/components/base/list-empty/index.tsx index e925878bc1..c295ffbaec 100644 --- a/web/app/components/base/list-empty/index.tsx +++ b/web/app/components/base/list-empty/index.tsx @@ -1,3 +1,4 @@ +import type { ReactNode } from 'react' import React from 'react' import { Variable02 } from '../icons/src/vender/solid/development' import VerticalLine from './vertical-line' @@ -5,19 +6,21 @@ import HorizontalLine from './horizontal-line' type ListEmptyProps = { title?: string - description?: React.ReactNode + description?: ReactNode + icon?: ReactNode } const ListEmpty = ({ title, description, + icon, }: ListEmptyProps) => { return ( <div className='flex w-[320px] p-4 flex-col items-start gap-2 rounded-[10px] bg-workflow-process-bg'> <div className='flex w-10 h-10 justify-center items-center gap-2 rounded-[10px]'> <div className='flex relative p-1 justify-center items-center gap-2 grow self-stretch rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg shadow-lg'> - <Variable02 className='w-5 h-5 shrink-0 text-text-accent' /> + {icon || <Variable02 className='w-5 h-5 shrink-0 text-text-accent' />} <VerticalLine className='absolute -right-[1px] top-1/2 -translate-y-1/4'/> <VerticalLine className='absolute -left-[1px] top-1/2 -translate-y-1/4'/> <HorizontalLine className='absolute top-0 left-3/4 -translate-x-1/4 -translate-y-1/2'/> diff --git a/web/app/components/base/logo/logo-site.tsx b/web/app/components/base/logo/logo-site.tsx index a399ff3301..4b0e026afd 100644 --- a/web/app/components/base/logo/logo-site.tsx +++ b/web/app/components/base/logo/logo-site.tsx @@ -1,7 +1,6 @@ 'use client' import type { FC } from 'react' import classNames from '@/utils/classnames' -import { useSelector } from '@/context/app-context' type LogoSiteProps = { className?: string @@ -10,17 +9,10 @@ type LogoSiteProps = { const LogoSite: FC<LogoSiteProps> = ({ className, }) => { - const { theme } = useSelector((s) => { - return { - theme: s.theme, - } - }) - - const src = theme === 'light' ? '/logo/logo-site.png' : `/logo/logo-site-${theme}.png` return ( <img - src={src} - className={classNames('block w-auto h-10', className)} + src={'/logo/logo.png'} + className={classNames('block w-[22.651px] h-[24.5px]', className)} alt='logo' /> ) diff --git a/web/app/components/base/markdown.tsx b/web/app/components/base/markdown.tsx index b77dee9a61..abb9a546ca 100644 --- a/web/app/components/base/markdown.tsx +++ b/web/app/components/base/markdown.tsx @@ -1,3 +1,4 @@ +import type { Components } from 'react-markdown' import ReactMarkdown from 'react-markdown' import ReactEcharts from 'echarts-for-react' import 'katex/dist/katex.min.css' @@ -8,8 +9,7 @@ import RemarkGfm from 'remark-gfm' import RehypeRaw from 'rehype-raw' import SyntaxHighlighter from 'react-syntax-highlighter' import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs' -import { Component, memo, useMemo, useRef, useState } from 'react' -import type { CodeComponent } from 'react-markdown/lib/ast-to-react' +import { Component, createContext, memo, useContext, useEffect, useMemo, useRef, useState } from 'react' import cn from '@/utils/classnames' import CopyBtn from '@/app/components/base/copy-btn' import SVGBtn from '@/app/components/base/svg' @@ -21,6 +21,7 @@ import AudioGallery from '@/app/components/base/audio-gallery' import SVGRenderer from '@/app/components/base/svg-gallery' import MarkdownButton from '@/app/components/base/markdown-blocks/button' import MarkdownForm from '@/app/components/base/markdown-blocks/form' +import type { ElementContentMap } from 'hast' // Available language https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD const capitalizationLanguageNameMap: Record<string, string> = { @@ -55,7 +56,7 @@ const getCorrectCapitalizationLanguageName = (language: string) => { return language.charAt(0).toUpperCase() + language.substring(1) } -const preprocessLaTeX = (content: string) => { +const preprocessLaTeX = (content?: string) => { if (typeof content !== 'string') return content return content.replace(/\\\[(.*?)\\\]/g, (_, equation) => `$$${equation}$$`) @@ -76,6 +77,20 @@ export function PreCode(props: { children: any }) { ) } +const PreContext = createContext({ + // if children not in PreContext, just leave inline true + inline: true, +}) + +const PreBlock: Components['pre'] = (props) => { + const { ...rest } = props + return <PreContext.Provider value={{ + inline: false, + }}> + <pre {...rest} /> + </PreContext.Provider> +} + // **Add code block // Avoid error #185 (Maximum update depth exceeded. // This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. @@ -89,7 +104,8 @@ export function PreCode(props: { children: any }) { // visit https://reactjs.org/docs/error-decoder.html?invariant=185 for the full message // or use the non-minified dev environment for full errors and additional helpful warnings. -const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props }) => { +const CodeBlock: Components['code'] = memo(({ className, children, ...props }) => { + const { inline } = useContext(PreContext) const [isSVG, setIsSVG] = useState(true) const match = /language-(\w+)/.exec(className || '') const language = match?.[1] @@ -128,7 +144,7 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props } else { return ( <SyntaxHighlighter - {...props} + {...props as any} style={atelierHeathLight} customStyle={{ paddingLeft: 12, @@ -169,23 +185,23 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props } </div> ) }) -CodeBlock.displayName = 'CodeBlock' +// CodeBlock.displayName = 'CodeBlock' -const VideoBlock: CodeComponent = memo(({ node }) => { - const srcs = node.children.filter(child => 'properties' in child).map(child => (child as any).properties.src) +const VideoBlock: Components['video'] = memo(({ node }) => { + const srcs = node!.children.filter(child => 'properties' in child).map(child => (child as any).properties.src) if (srcs.length === 0) return null return <VideoGallery key={srcs.join()} srcs={srcs} /> }) -VideoBlock.displayName = 'VideoBlock' +// VideoBlock.displayName = 'VideoBlock' -const AudioBlock: CodeComponent = memo(({ node }) => { - const srcs = node.children.filter(child => 'properties' in child).map(child => (child as any).properties.src) +const AudioBlock: Components['audio'] = memo(({ node }) => { + const srcs = node!.children.filter(child => 'properties' in child).map(child => (child as any).properties.src) if (srcs.length === 0) return null return <AudioGallery key={srcs.join()} srcs={srcs} /> }) -AudioBlock.displayName = 'AudioBlock' +// AudioBlock.displayName = 'AudioBlock' const ScriptBlock = memo(({ node }: any) => { const scriptContent = node.children[0]?.value || '' @@ -193,34 +209,32 @@ const ScriptBlock = memo(({ node }: any) => { }) ScriptBlock.displayName = 'ScriptBlock' -const Paragraph = (paragraph: any) => { - const { node }: any = paragraph - const children_node = node.children - if (children_node && children_node[0] && 'tagName' in children_node[0] && children_node[0].tagName === 'img') { - return ( - <> - <ImageGallery srcs={[children_node[0].properties.src]} /> - <p>{paragraph.children.slice(1)}</p> - </> - ) - } - return <p>{paragraph.children}</p> +const Paragraph: Components['p'] = ({ node, children }) => { + const children_node = node!.children + if (children_node && children_node[0] && 'tagName' in children_node[0] && children_node[0].tagName === 'img') + return <ImageGallery srcs={[children_node?.[0]?.properties?.src as string]} /> + return <p>{children}</p> } -const Img = ({ src }: any) => { - return (<ImageGallery srcs={[src]} />) +const Img: Components['img'] = ({ src }) => { + return (<ImageGallery srcs={[src!]} />) } -const Link = ({ node, ...props }: any) => { - if (node.properties?.href && node.properties.href?.toString().startsWith('abbr')) { +const Link: Components['a'] = ({ node, ...props }) => { + if (node!.properties?.href && node!.properties.href?.toString().startsWith('abbr')) { // eslint-disable-next-line react-hooks/rules-of-hooks const { onSend } = useChatContext() - const hidden_text = decodeURIComponent(node.properties.href.toString().split('abbr:')[1]) - - return <abbr className="underline decoration-dashed !decoration-primary-700 cursor-pointer" onClick={() => onSend?.(hidden_text)} title={node.children[0]?.value}>{node.children[0]?.value}</abbr> + const hidden_text = decodeURIComponent(node!.properties.href.toString().split('abbr:')[1]) + const title = (node!.children[0] as ElementContentMap['text'])?.value + return <abbr className="underline decoration-dashed !decoration-primary-700 cursor-pointer" onClick={() => onSend?.(hidden_text)} title={title}>{title}</abbr> } else { - return <a {...props} target="_blank" className="underline decoration-dashed !decoration-primary-700 cursor-pointer">{node.children[0] ? node.children[0]?.value : 'Download'}</a> + const firstChild = node?.children?.[0] as ElementContentMap['text'] | undefined + return <a {...props} target="_blank" className="underline decoration-dashed !decoration-primary-700 cursor-pointer">{ + firstChild + ? firstChild.value + : 'Download' + }</a> } } @@ -249,6 +263,7 @@ export function Markdown(props: { content: string; className?: string }) { ]} disallowedElements={['iframe', 'head', 'html', 'meta', 'link', 'style', 'body']} components={{ + pre: PreBlock, code: CodeBlock, img: Img, video: VideoBlock, @@ -259,7 +274,6 @@ export function Markdown(props: { content: string; className?: string }) { form: MarkdownForm, script: ScriptBlock, }} - linkTarget='_blank' > {/* Markdown detect has problem. */} {latexContent} @@ -284,11 +298,11 @@ export default class ErrorBoundary extends Component { } render() { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line ts/ban-ts-comment // @ts-expect-error if (this.state.hasError) return <div>Oops! An error occurred. This could be due to an ECharts runtime error or invalid SVG content. <br />(see the browser console for more information)</div> - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line ts/ban-ts-comment // @ts-expect-error return this.props.children } diff --git a/web/app/components/base/mermaid/index.tsx b/web/app/components/base/mermaid/index.tsx index bcc30ca939..af5c010ac2 100644 --- a/web/app/components/base/mermaid/index.tsx +++ b/web/app/components/base/mermaid/index.tsx @@ -33,7 +33,7 @@ const Flowchart = React.forwardRef((props: { const prevPrimitiveCode = usePrevious(props.PrimitiveCode) const [isLoading, setIsLoading] = useState(true) - const timeRef = useRef<NodeJS.Timeout>() + const timeRef = useRef<number>() const [errMsg, setErrMsg] = useState('') const [imagePreviewUrl, setImagePreviewUrl] = useState('') @@ -75,15 +75,15 @@ const Flowchart = React.forwardRef((props: { useEffect(() => { if (timeRef.current) - clearTimeout(timeRef.current) + window.clearTimeout(timeRef.current) - timeRef.current = setTimeout(() => { + timeRef.current = window.setTimeout(() => { renderFlowchart(props.PrimitiveCode) }, 300) }, [props.PrimitiveCode]) return ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line ts/ban-ts-comment // @ts-expect-error <div ref={ref}> <div className="msh-segmented msh-segmented-sm css-23bs09 css-var-r1"> @@ -136,4 +136,6 @@ const Flowchart = React.forwardRef((props: { ) }) +Flowchart.displayName = 'Flowchart' + export default Flowchart diff --git a/web/app/components/base/message-log-modal/index.tsx b/web/app/components/base/message-log-modal/index.tsx index 7bbd3f311d..13667f1dc7 100644 --- a/web/app/components/base/message-log-modal/index.tsx +++ b/web/app/components/base/message-log-modal/index.tsx @@ -7,7 +7,7 @@ import cn from '@/utils/classnames' import type { IChatItem } from '@/app/components/base/chat/chat/type' import Run from '@/app/components/workflow/run' -type MessageLogModalProps = { +interface MessageLogModalProps { currentLogItem?: IChatItem defaultTab?: string width: number diff --git a/web/app/components/base/modal/index.tsx b/web/app/components/base/modal/index.tsx index 26cde5fce3..a659ccaac7 100644 --- a/web/app/components/base/modal/index.tsx +++ b/web/app/components/base/modal/index.tsx @@ -29,7 +29,7 @@ export default function Modal({ }: IModal) { return ( <Transition appear show={isShow} as={Fragment}> - <Dialog as="div" className={classNames('relative z-50', wrapperClassName)} onClose={onClose}> + <Dialog as="div" className={classNames('relative z-[60]', wrapperClassName)} onClose={onClose}> <Transition.Child as={Fragment} enter="ease-out duration-300" diff --git a/web/app/components/base/pagination/hook.ts b/web/app/components/base/pagination/hook.ts index 6501d6f457..32a2af8013 100644 --- a/web/app/components/base/pagination/hook.ts +++ b/web/app/components/base/pagination/hook.ts @@ -10,7 +10,7 @@ const usePagination = ({ edgePageCount, middlePagesSiblingCount, }: IPaginationProps): IUsePagination => { - const pages = Array(totalPages) + const pages = new Array(totalPages) .fill(0) .map((_, i) => i + 1) diff --git a/web/app/components/base/pagination/index.tsx b/web/app/components/base/pagination/index.tsx index c0cc9f86ec..ec67040c01 100644 --- a/web/app/components/base/pagination/index.tsx +++ b/web/app/components/base/pagination/index.tsx @@ -33,20 +33,20 @@ const CustomizedPagination: FC<Props> = ({ const [showPerPageTip, setShowPerPageTip] = React.useState(false) const { run: handlePaging } = useDebounceFn((value: string) => { - if (parseInt(value) > totalPages) { + if (Number.parseInt(value) > totalPages) { setInputValue(totalPages) onChange(totalPages - 1) setShowInput(false) return } - if (parseInt(value) < 1) { + if (Number.parseInt(value) < 1) { setInputValue(1) onChange(0) setShowInput(false) return } - onChange(parseInt(value) - 1) - setInputValue(parseInt(value)) + onChange(Number.parseInt(value) - 1) + setInputValue(Number.parseInt(value)) setShowInput(false) }, { wait: 500 }) @@ -54,9 +54,9 @@ const CustomizedPagination: FC<Props> = ({ const value = e.target.value if (!value) return setInputValue('') - if (isNaN(parseInt(value))) + if (isNaN(Number.parseInt(value))) return setInputValue('') - setInputValue(parseInt(value)) + setInputValue(Number.parseInt(value)) handlePaging(value) } diff --git a/web/app/components/base/popover/index.tsx b/web/app/components/base/popover/index.tsx index 8fd9906a2b..f510c21642 100644 --- a/web/app/components/base/popover/index.tsx +++ b/web/app/components/base/popover/index.tsx @@ -33,15 +33,15 @@ export default function CustomPopover({ disabled = false, }: IPopover) { const buttonRef = useRef<HTMLButtonElement>(null) - const timeOutRef = useRef<NodeJS.Timeout | null>(null) + const timeOutRef = useRef<number | null>(null) const onMouseEnter = (isOpen: boolean) => { - timeOutRef.current && clearTimeout(timeOutRef.current) + timeOutRef.current && window.clearTimeout(timeOutRef.current) !isOpen && buttonRef.current?.click() } const onMouseLeave = (isOpen: boolean) => { - timeOutRef.current = setTimeout(() => { + timeOutRef.current = window.setTimeout(() => { isOpen && buttonRef.current?.click() }, timeoutDuration) } diff --git a/web/app/components/base/portal-to-follow-elem/index.tsx b/web/app/components/base/portal-to-follow-elem/index.tsx index 4a380e6abd..3d24c6ee99 100644 --- a/web/app/components/base/portal-to-follow-elem/index.tsx +++ b/web/app/components/base/portal-to-follow-elem/index.tsx @@ -106,7 +106,7 @@ export function PortalToFollowElem({ } export const PortalToFollowElemTrigger = React.forwardRef< -HTMLElement, + HTMLElement, React.HTMLProps<HTMLElement> & { asChild?: boolean } >(({ children, asChild = false, ...props }, propRef) => { const context = usePortalToFollowElemContext() @@ -141,8 +141,8 @@ React.HTMLProps<HTMLElement> & { asChild?: boolean } PortalToFollowElemTrigger.displayName = 'PortalToFollowElemTrigger' export const PortalToFollowElemContent = React.forwardRef< -HTMLDivElement, -React.HTMLProps<HTMLDivElement> + HTMLDivElement, + React.HTMLProps<HTMLDivElement> >(({ style, ...props }, propRef) => { const context = usePortalToFollowElemContext() const ref = useMergeRefs([context.refs.setFloating, propRef]) diff --git a/web/app/components/base/premium-badge/index.css b/web/app/components/base/premium-badge/index.css new file mode 100644 index 0000000000..be8f9e6ae6 --- /dev/null +++ b/web/app/components/base/premium-badge/index.css @@ -0,0 +1,48 @@ +@tailwind components; + +@layer components { + .premium-badge { + @apply inline-flex justify-center items-center rounded-full border box-border border-[rgba(255,255,255,0.8)] text-white + } + + /* m is for the regular button */ + .premium-badge-m { + @apply border shadow-lg !p-1 h-6 w-auto + } + + .premium-badge-s { + @apply border-[0.5px] shadow-xs !px-1 !py-[3px] h-[18px] w-auto + } + + .premium-badge-blue { + @apply bg-gradient-to-r from-[#5289ffe6] to-[#155aefe6] bg-util-colors-blue-blue-200 + } + + .premium-badge-indigo { + @apply bg-gradient-to-r from-[#8098f9e6] to-[#444ce7e6] bg-util-colors-indigo-indigo-200 + } + + .premium-badge-gray { + @apply bg-gradient-to-r from-[#98a2b2e6] to-[#676f83e6] bg-util-colors-gray-gray-200 + } + + .premium-badge-orange { + @apply bg-gradient-to-r from-[#ff692ee6] to-[#e04f16e6] bg-util-colors-orange-orange-200 + } + + .premium-badge-blue.allowHover:hover { + @apply bg-gradient-to-r from-[#296dffe6] to-[#004aebe6] bg-util-colors-blue-blue-300 cursor-pointer + } + + .premium-badge-indigo.allowHover:hover { + @apply bg-gradient-to-r from-[#6172f3e6] to-[#2d31a6e6] bg-util-colors-indigo-indigo-300 cursor-pointer + } + + .premium-badge-gray.allowHover:hover { + @apply bg-gradient-to-r from-[#676f83e6] to-[#354052e6] bg-util-colors-gray-gray-300 cursor-pointer + } + + .premium-badge-orange.allowHover:hover { + @apply bg-gradient-to-r from-[#ff4405e6] to-[#b93815e6] bg-util-colors-orange-orange-300 cursor-pointer + } +} \ No newline at end of file diff --git a/web/app/components/base/premium-badge/index.tsx b/web/app/components/base/premium-badge/index.tsx new file mode 100644 index 0000000000..ce260fcf80 --- /dev/null +++ b/web/app/components/base/premium-badge/index.tsx @@ -0,0 +1,78 @@ +import type { CSSProperties, ReactNode } from 'react' +import React from 'react' +import { type VariantProps, cva } from 'class-variance-authority' +import classNames from '@/utils/classnames' +import './index.css' +import { Highlight } from '../icons/src/public/common' + +const PremiumBadgeVariants = cva( + 'premium-badge', + { + variants: { + size: { + s: 'premium-badge-s', + m: 'premium-badge-m', + }, + color: { + blue: 'premium-badge-blue', + indigo: 'premium-badge-indigo', + gray: 'premium-badge-gray', + orange: 'premium-badge-orange', + }, + allowHover: { + true: 'allowHover', + false: '', + }, + }, + defaultVariants: { + size: 'm', + color: 'blue', + allowHover: false, + }, + }, +) + +type PremiumBadgeProps = { + size?: 's' | 'm' + color?: 'blue' | 'indigo' | 'gray' | 'orange' + allowHover?: boolean + styleCss?: CSSProperties + children?: ReactNode +} & React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof PremiumBadgeVariants> + +const PremiumBadge: React.FC<PremiumBadgeProps> = ({ + className, + size, + color, + allowHover, + styleCss, + children, + ...props +}) => { + return ( + <div + className={classNames( + PremiumBadgeVariants({ size, color, allowHover, className }), + 'relative text-nowrap', + )} + style={styleCss} + {...props} + > + {children} + <Highlight + className={classNames( + 'absolute top-0 opacity-50 hover:opacity-80', + size === 's' ? 'h-4.5 w-12' : 'h-6 w-12', + )} + style={{ + right: '50%', + transform: 'translateX(10%)', + }} + /> + </div> + ) +} +PremiumBadge.displayName = 'PremiumBadge' + +export default PremiumBadge +export { PremiumBadge, PremiumBadgeVariants } diff --git a/web/app/components/base/prompt-editor/index.tsx b/web/app/components/base/prompt-editor/index.tsx index 4a718527b8..8e13a7850a 100644 --- a/web/app/components/base/prompt-editor/index.tsx +++ b/web/app/components/base/prompt-editor/index.tsx @@ -61,7 +61,7 @@ import { import { useEventEmitterContextContext } from '@/context/event-emitter' import cn from '@/utils/classnames' -export type PromptEditorProps = { +export interface PromptEditorProps { instanceId?: string compact?: boolean className?: string diff --git a/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx b/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx index a5cb39f383..39e8092b1e 100644 --- a/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx +++ b/web/app/components/base/prompt-editor/plugins/component-picker-block/index.tsx @@ -32,7 +32,7 @@ import type { PickerBlockMenuOption } from './menu' import VarReferenceVars from '@/app/components/workflow/nodes/_base/components/variable/var-reference-vars' import { useEventEmitterContextContext } from '@/context/event-emitter' -type ComponentPickerProps = { +interface ComponentPickerProps { triggerString: string contextBlock?: ContextBlockType queryBlock?: QueryBlockType diff --git a/web/app/components/base/prompt-editor/plugins/custom-text/node.tsx b/web/app/components/base/prompt-editor/plugins/custom-text/node.tsx index 5df4894c6b..49f4a056db 100644 --- a/web/app/components/base/prompt-editor/plugins/custom-text/node.tsx +++ b/web/app/components/base/prompt-editor/plugins/custom-text/node.tsx @@ -1,4 +1,4 @@ -import type { EditorConfig, NodeKey, SerializedTextNode } from 'lexical' +import type { EditorConfig, SerializedTextNode } from 'lexical' import { $createTextNode, TextNode } from 'lexical' export class CustomTextNode extends TextNode { @@ -10,9 +10,9 @@ export class CustomTextNode extends TextNode { return new CustomTextNode(node.__text, node.__key) } - constructor(text: string, key?: NodeKey) { - super(text, key) - } + // constructor(text: string, key?: NodeKey) { + // super(text, key) + // } createDOM(config: EditorConfig) { const dom = super.createDOM(config) diff --git a/web/app/components/base/prompt-editor/plugins/variable-value-block/node.tsx b/web/app/components/base/prompt-editor/plugins/variable-value-block/node.tsx index 163d4bfac4..34487b257c 100644 --- a/web/app/components/base/prompt-editor/plugins/variable-value-block/node.tsx +++ b/web/app/components/base/prompt-editor/plugins/variable-value-block/node.tsx @@ -1,7 +1,6 @@ import type { EditorConfig, LexicalNode, - NodeKey, SerializedTextNode, } from 'lexical' import { @@ -18,9 +17,9 @@ export class VariableValueBlockNode extends TextNode { return new VariableValueBlockNode(node.__text, node.__key) } - constructor(text: string, key?: NodeKey) { - super(text, key) - } + // constructor(text: string, key?: NodeKey) { + // super(text, key) + // } createDOM(config: EditorConfig): HTMLElement { const element = super.createDOM(config) diff --git a/web/app/components/base/prompt-editor/plugins/workflow-variable-block/node.tsx b/web/app/components/base/prompt-editor/plugins/workflow-variable-block/node.tsx index e4154731ba..9fa518218f 100644 --- a/web/app/components/base/prompt-editor/plugins/workflow-variable-block/node.tsx +++ b/web/app/components/base/prompt-editor/plugins/workflow-variable-block/node.tsx @@ -18,7 +18,7 @@ export class WorkflowVariableBlockNode extends DecoratorNode<JSX.Element> { } static clone(node: WorkflowVariableBlockNode): WorkflowVariableBlockNode { - return new WorkflowVariableBlockNode(node.__variables, node.__workflowNodesMap) + return new WorkflowVariableBlockNode(node.__variables, node.__workflowNodesMap, node.__key) } isInline(): boolean { diff --git a/web/app/components/base/qrcode/index.tsx b/web/app/components/base/qrcode/index.tsx index c9323992e9..08569a8c89 100644 --- a/web/app/components/base/qrcode/index.tsx +++ b/web/app/components/base/qrcode/index.tsx @@ -1,19 +1,20 @@ 'use client' import React, { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import QRCode from 'qrcode.react' -import QrcodeStyle from './style.module.css' +import { + RiQrCodeLine, +} from '@remixicon/react' +import { QRCodeCanvas as QRCode } from 'qrcode.react' +import ActionButton from '@/app/components/base/action-button' import Tooltip from '@/app/components/base/tooltip' type Props = { content: string - selectorId: string - className?: string } const prefixEmbedded = 'appOverview.overview.appInfo.qrcode.title' -const ShareQRCode = ({ content, selectorId, className }: Props) => { +const ShareQRCode = ({ content }: Props) => { const { t } = useTranslation() const [isShow, setIsShow] = useState<boolean>(false) const qrCodeRef = useRef<HTMLDivElement>(null) @@ -53,22 +54,21 @@ const ShareQRCode = ({ content, selectorId, className }: Props) => { <Tooltip popupContent={t(`${prefixEmbedded}`) || ''} > - <div - className={`w-8 h-8 cursor-pointer rounded-lg ${className ?? ''}`} - onClick={toggleQRCode} - > - <div className={`w-full h-full ${QrcodeStyle.QrcodeIcon} ${isShow ? QrcodeStyle.show : ''}`} /> + <div className='relative w-6 h-6' onClick={toggleQRCode}> + <ActionButton> + <RiQrCodeLine className='w-4 h-4' /> + </ActionButton> {isShow && ( <div ref={qrCodeRef} - className={QrcodeStyle.qrcodeform} + className='absolute top-8 -right-8 z-10 w-[232px] flex flex-col items-center bg-components-panel-bg shadow-xs rounded-lg p-4' onClick={handlePanelClick} > - <QRCode size={160} value={content} className={QrcodeStyle.qrcodeimage}/> - <div className={QrcodeStyle.text}> - <div className={`text-gray-500 ${QrcodeStyle.scan}`}>{t('appOverview.overview.appInfo.qrcode.scan')}</div> - <div className={`text-gray-500 ${QrcodeStyle.scan}`}>·</div> - <div className={QrcodeStyle.download} onClick={downloadQR}>{t('appOverview.overview.appInfo.qrcode.download')}</div> + <QRCode size={160} value={content} className='mb-2'/> + <div className='flex items-center system-xs-regular'> + <div className='text-text-tertiary'>{t('appOverview.overview.appInfo.qrcode.scan')}</div> + <div className='text-text-tertiary'>·</div> + <div className='text-text-accent-secondary cursor-pointer' onClick={downloadQR}>{t('appOverview.overview.appInfo.qrcode.download')}</div> </div> </div> )} diff --git a/web/app/components/base/qrcode/style.module.css b/web/app/components/base/qrcode/style.module.css deleted file mode 100644 index b0c4441e99..0000000000 --- a/web/app/components/base/qrcode/style.module.css +++ /dev/null @@ -1,61 +0,0 @@ -.QrcodeIcon { - background-image: url(~@/app/components/develop/secret-key/assets/qrcode.svg); - background-position: center; - background-repeat: no-repeat; -} - -.QrcodeIcon:hover { - background-image: url(~@/app/components/develop/secret-key/assets/qrcode-hover.svg); - background-position: center; - background-repeat: no-repeat; -} - -.QrcodeIcon.show { - background-image: url(~@/app/components/develop/secret-key/assets/qrcode-hover.svg); - background-position: center; - background-repeat: no-repeat; -} - -.qrcodeimage { - position: relative; - object-fit: cover; -} -.scan { - margin: 0; - line-height: 1rem; - font-size: 0.75rem; -} -.download { - position: relative; - color: #155eef; - font-size: 0.75rem; - line-height: 1rem; -} -.text { - align-self: stretch; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - white-space: nowrap; - gap: 4px; -} -.qrcodeform { - border: 0.5px solid #eaecf0; - display: flex; - flex-direction: column; - margin: 0 !important; - margin-top: 4px !important; - margin-left: -75px !important; - width: fit-content; - position: relative; - border-radius: 8px; - background-color: #fff; - box-shadow: 0 12px 16px -4px rgba(16, 24, 40, 0.08), - 0 4px 6px -2px rgba(16, 24, 40, 0.03); - overflow: hidden; - align-items: center; - justify-content: center; - padding: 15px; - gap: 8px; -} diff --git a/web/app/components/base/radio/ui.tsx b/web/app/components/base/radio/ui.tsx index 234560a690..772c3de8b1 100644 --- a/web/app/components/base/radio/ui.tsx +++ b/web/app/components/base/radio/ui.tsx @@ -11,7 +11,7 @@ const RadioUI: FC<Props> = ({ isChecked, }) => { return ( - <div className={cn(isChecked ? 'border-[5px] border-[#155eef]' : 'border-[2px] border-gray-200', 'w-4 h-4 rounded-full')}> + <div className={cn(isChecked ? 'border-[5px] border-components-radio-border-checked' : 'border-[2px] border-components-radio-border', 'w-4 h-4 rounded-full')}> </div> ) } diff --git a/web/app/components/base/select/index.tsx b/web/app/components/base/select/index.tsx index 221d70355f..3332a11abd 100644 --- a/web/app/components/base/select/index.tsx +++ b/web/app/components/base/select/index.tsx @@ -3,6 +3,7 @@ import type { FC } from 'react' import React, { Fragment, useEffect, useState } from 'react' import { Combobox, Listbox, Transition } from '@headlessui/react' import { ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/20/solid' +import Badge from '../badge/index' import { RiCheckLine } from '@remixicon/react' import { useTranslation } from 'react-i18next' import classNames from '@/utils/classnames' @@ -244,7 +245,7 @@ const SimpleSelect: FC<ISelectProps> = ({ leaveTo="opacity-0" > - <Listbox.Options className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}> + <Listbox.Options className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}> {items.map((item: Item) => ( <Listbox.Option key={item.value} @@ -290,6 +291,7 @@ type PortalSelectProps = { onSelect: (value: Item) => void items: Item[] placeholder?: string + installedValue?: string | number renderTrigger?: (value?: Item) => JSX.Element | null triggerClassName?: string triggerClassNameFn?: (open: boolean) => string @@ -303,6 +305,7 @@ const PortalSelect: FC<PortalSelectProps> = ({ onSelect, items, placeholder, + installedValue, renderTrigger, triggerClassName, triggerClassNameFn, @@ -314,7 +317,7 @@ const PortalSelect: FC<PortalSelectProps> = ({ const { t } = useTranslation() const [open, setOpen] = useState(false) const localPlaceholder = placeholder || t('common.placeholder.select') - const selectedItem = items.find(item => item.value === value) + const selectedItem = value ? items.find(item => item.value === value) : undefined return ( <PortalToFollowElem @@ -329,33 +332,34 @@ const PortalSelect: FC<PortalSelectProps> = ({ : ( <div className={classNames(` - flex items-center justify-between px-2.5 h-9 rounded-lg border-0 bg-gray-100 text-sm ${readonly ? 'cursor-not-allowed' : 'cursor-pointer'} + group flex items-center justify-between px-2.5 h-9 rounded-lg border-0 bg-components-input-bg-normal hover:bg-state-base-hover-alt text-sm ${readonly ? 'cursor-not-allowed' : 'cursor-pointer'} `, triggerClassName, triggerClassNameFn?.(open))} title={selectedItem?.name} > <span className={` grow truncate - ${!selectedItem?.name && 'text-gray-400'} + ${!selectedItem?.name && 'text-components-input-text-placeholder'} `} > {selectedItem?.name ?? localPlaceholder} </span> - <ChevronDownIcon className='shrink-0 h-4 w-4 text-gray-400' /> + <div className='mx-0.5'>{installedValue && selectedItem && selectedItem.value !== installedValue && <Badge>{installedValue} {'->'} {selectedItem.value} </Badge>}</div> + <ChevronDownIcon className='shrink-0 h-4 w-4 text-text-quaternary group-hover:text-text-secondary' /> </div> )} </PortalToFollowElemTrigger> <PortalToFollowElemContent className={`z-20 ${popupClassName}`}> <div - className={classNames('px-1 py-1 max-h-60 overflow-auto rounded-md bg-white text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm', popupInnerClassName)} + className={classNames('px-1 py-1 max-h-60 overflow-auto rounded-md text-base shadow-lg border-components-panel-border bg-components-panel-bg border-[0.5px] focus:outline-none sm:text-sm', popupInnerClassName)} > {items.map((item: Item) => ( <div key={item.value} className={` - flex items-center justify-between px-2.5 h-9 cursor-pointer rounded-lg hover:bg-gray-100 text-gray-700 - ${item.value === value && 'bg-gray-100'} + flex items-center justify-between px-2.5 h-9 cursor-pointer rounded-lg hover:bg-state-base-hover text-text-secondary + ${item.value === value && 'bg-state-base-hover'} `} title={item.name} onClick={() => { @@ -367,7 +371,10 @@ const PortalSelect: FC<PortalSelectProps> = ({ className='w-0 grow truncate' title={item.name} > - {item.name} + <span className='truncate'>{item.name}</span> + {item.value === installedValue && ( + <Badge uppercase={true} className='shrink-0 ml-1'>INSTALLED</Badge> + )} </span> {!hideChecked && item.value === value && ( <RiCheckLine className='shrink-0 h-4 w-4 text-text-accent' /> diff --git a/web/app/components/base/skeleton/index.tsx b/web/app/components/base/skeleton/index.tsx index a2d4e4da63..41edc26cf9 100644 --- a/web/app/components/base/skeleton/index.tsx +++ b/web/app/components/base/skeleton/index.tsx @@ -24,7 +24,7 @@ export const SkeletonRow: FC<SkeletonProps> = (props) => { export const SkeletonRectangle: FC<SkeletonProps> = (props) => { const { className, children, ...rest } = props return ( - <div className={classNames('h-2 rounded-sm opacity-20 bg-text-tertiary my-1', className)} {...rest}> + <div className={classNames('h-2 rounded-sm opacity-20 bg-text-quaternary my-1', className)} {...rest}> {children} </div> ) diff --git a/web/app/components/base/sort/index.tsx b/web/app/components/base/sort/index.tsx index 36f1fdfdf7..5b30a0edb8 100644 --- a/web/app/components/base/sort/index.tsx +++ b/web/app/components/base/sort/index.tsx @@ -14,7 +14,7 @@ export type Item = { name: string } & Record<string, any> -type Props = { +interface Props { order?: string value: number | string items: Item[] diff --git a/web/app/components/base/tab-slider-plain/index.tsx b/web/app/components/base/tab-slider-plain/index.tsx index a472aba502..194b6ad650 100644 --- a/web/app/components/base/tab-slider-plain/index.tsx +++ b/web/app/components/base/tab-slider-plain/index.tsx @@ -3,12 +3,12 @@ import type { FC } from 'react' import React from 'react' import cn from '@/utils/classnames' -type Option = { +interface Option { value: string text: string | JSX.Element } -type ItemProps = { +interface ItemProps { className?: string isActive: boolean onClick: (v: string) => void @@ -38,7 +38,7 @@ const Item: FC<ItemProps> = ({ ) } -type Props = { +interface Props { className?: string value: string onChange: (v: string) => void diff --git a/web/app/components/base/tab-slider/index.tsx b/web/app/components/base/tab-slider/index.tsx index 03296a9dee..1b4e42e0d7 100644 --- a/web/app/components/base/tab-slider/index.tsx +++ b/web/app/components/base/tab-slider/index.tsx @@ -1,64 +1,85 @@ import type { FC } from 'react' +import { useEffect, useState } from 'react' import cn from '@/utils/classnames' - +import Badge, { BadgeState } from '@/app/components/base/badge/index' +import { useInstalledPluginList } from '@/service/use-plugins' type Option = { value: string text: string } + type TabSliderProps = { className?: string - itemWidth?: number value: string onChange: (v: string) => void options: Option[] } + const TabSlider: FC<TabSliderProps> = ({ className, - itemWidth = 118, value, onChange, options, }) => { - const currentIndex = options.findIndex(option => option.value === value) - const current = options[currentIndex] + const [activeIndex, setActiveIndex] = useState(options.findIndex(option => option.value === value)) + const [sliderStyle, setSliderStyle] = useState({}) + const { data: pluginList } = useInstalledPluginList() + + const updateSliderStyle = (index: number) => { + const tabElement = document.getElementById(`tab-${index}`) + if (tabElement) { + const { offsetLeft, offsetWidth } = tabElement + setSliderStyle({ + transform: `translateX(${offsetLeft}px)`, + width: `${offsetWidth}px`, + }) + } + } + + useEffect(() => { + const newIndex = options.findIndex(option => option.value === value) + setActiveIndex(newIndex) + updateSliderStyle(newIndex) + }, [value, options, pluginList]) return ( - <div className={cn(className, 'relative flex p-0.5 rounded-lg bg-gray-200')}> - { - options.map((option, index) => ( - <div - key={option.value} - className={` - flex justify-center items-center h-7 text-[13px] - font-semibold text-gray-600 rounded-[7px] cursor-pointer - hover:bg-gray-50 - ${index !== options.length - 1 && 'mr-[1px]'} - `} - style={{ - width: itemWidth, - }} - onClick={() => onChange(option.value)} - > - {option.text} - </div> - )) - } - { - current && ( - <div - className={` - absolute flex justify-center items-center h-7 bg-white text-[13px] font-semibold text-primary-600 - border-[0.5px] border-gray-200 rounded-[7px] shadow-xs transition-transform - `} - style={{ - width: itemWidth, - transform: `translateX(${currentIndex * itemWidth + 1}px)`, - }} - > - {current.text} - </div> - ) - } + <div className={cn(className, 'inline-flex p-0.5 rounded-[10px] bg-components-segmented-control-bg-normal relative items-center justify-center')}> + <div + className="absolute top-0.5 bottom-0.5 left-0 right-0 bg-components-panel-bg rounded-[10px] transition-transform duration-300 ease-in-out shadows-shadow-xs" + style={sliderStyle} + /> + {options.map((option, index) => ( + <div + id={`tab-${index}`} + key={option.value} + className={cn( + 'relative flex justify-center items-center px-2.5 py-1.5 gap-1 rounded-[10px] transition-colors duration-300 ease-in-out cursor-pointer z-10', + 'system-md-semibold', + index === activeIndex + ? 'text-text-primary' + : 'text-text-tertiary', + )} + onClick={() => { + if (index !== activeIndex) { + onChange(option.value) + updateSliderStyle(index) + } + }} + > + {option.text} + {/* if no plugin installed, the badge won't show */} + {option.value === 'plugins' + && (pluginList?.plugins.length ?? 0) > 0 + && <Badge + size='s' + uppercase={true} + state={BadgeState.Default} + > + {pluginList?.plugins.length} + </Badge> + } + </div> + ))} </div> ) } diff --git a/web/app/components/base/tag-input/index.tsx b/web/app/components/base/tag-input/index.tsx index ec6c1cee34..e3e5cef732 100644 --- a/web/app/components/base/tag-input/index.tsx +++ b/web/app/components/base/tag-input/index.tsx @@ -7,7 +7,7 @@ import { RiAddLine, RiCloseLine } from '@remixicon/react' import cn from '@/utils/classnames' import { useToastContext } from '@/app/components/base/toast' -type TagInputProps = { +interface TagInputProps { items: string[] onChange: (items: string[]) => void disableRemove?: boolean diff --git a/web/app/components/base/tag-management/filter.tsx b/web/app/components/base/tag-management/filter.tsx index 49a3e7cf4f..00408d3b81 100644 --- a/web/app/components/base/tag-management/filter.tsx +++ b/web/app/components/base/tag-management/filter.tsx @@ -18,7 +18,7 @@ import type { Tag } from '@/app/components/base/tag-management/constant' import { fetchTagList } from '@/service/tag' -type TagFilterProps = { +interface TagFilterProps { type: 'knowledge' | 'app' value: string[] onChange: (v: string[]) => void diff --git a/web/app/components/base/tag-management/index.tsx b/web/app/components/base/tag-management/index.tsx index 9a747910d2..5921d3da31 100644 --- a/web/app/components/base/tag-management/index.tsx +++ b/web/app/components/base/tag-management/index.tsx @@ -30,7 +30,7 @@ const TagManagementModal = ({ show, type }: TagManagementModalProps) => { setTagList(res) } - const [pending, setPending] = useState<Boolean>(false) + const [pending, setPending] = useState<boolean>(false) const [name, setName] = useState<string>('') const createNewTag = async () => { if (!name) diff --git a/web/app/components/base/tag-management/selector.tsx b/web/app/components/base/tag-management/selector.tsx index 68fe7dd2ab..01e9eb162f 100644 --- a/web/app/components/base/tag-management/selector.tsx +++ b/web/app/components/base/tag-management/selector.tsx @@ -16,7 +16,7 @@ import Checkbox from '@/app/components/base/checkbox' import { bindTag, createTag, fetchTagList, unBindTag } from '@/service/tag' import { ToastContext } from '@/app/components/base/toast' -type TagSelectorProps = { +interface TagSelectorProps { targetID: string isPopover?: boolean position?: 'bl' | 'br' @@ -54,7 +54,7 @@ const Panel = (props: PanelProps) => { return tagList.filter(tag => tag.type === type && !value.includes(tag.id) && tag.name.includes(keywords)) }, [type, tagList, value, keywords]) - const [creating, setCreating] = useState<Boolean>(false) + const [creating, setCreating] = useState<boolean>(false) const createNewTag = async () => { if (!keywords) return diff --git a/web/app/components/base/tag-management/tag-item-editor.tsx b/web/app/components/base/tag-management/tag-item-editor.tsx index 3735695302..0605f28cf6 100644 --- a/web/app/components/base/tag-management/tag-item-editor.tsx +++ b/web/app/components/base/tag-management/tag-item-editor.tsx @@ -78,7 +78,7 @@ const TagItemEditor: FC<TagItemEditorProps> = ({ } } const [showRemoveModal, setShowRemoveModal] = useState(false) - const [pending, setPending] = useState<Boolean>(false) + const [pending, setPending] = useState<boolean>(false) const removeTag = async (tagID: string) => { if (pending) return diff --git a/web/app/components/base/text-generation/types.ts b/web/app/components/base/text-generation/types.ts index e4a8b76abb..87a79f4637 100644 --- a/web/app/components/base/text-generation/types.ts +++ b/web/app/components/base/text-generation/types.ts @@ -7,32 +7,32 @@ import type { ExternalDataTool } from '@/models/common' export type { VisionFile } from '@/types/app' export { TransferMethod } from '@/types/app' -export type UserInputForm = { +export interface UserInputForm { default: string label: string required: boolean variable: string } -export type UserInputFormTextInput = { +export interface UserInputFormTextInput { 'text-input': UserInputForm & { max_length: number } } -export type UserInputFormSelect = { - 'select': UserInputForm & { +export interface UserInputFormSelect { + select: UserInputForm & { options: string[] } } -export type UserInputFormParagraph = { - 'paragraph': UserInputForm +export interface UserInputFormParagraph { + paragraph: UserInputForm } export type VisionConfig = VisionSettings -export type EnableType = { +export interface EnableType { enabled: boolean } diff --git a/web/app/components/base/toast/index.tsx b/web/app/components/base/toast/index.tsx index ba7d8af518..65317e05c7 100644 --- a/web/app/components/base/toast/index.tsx +++ b/web/app/components/base/toast/index.tsx @@ -51,10 +51,11 @@ const Toast = ({ 'top-0', 'right-0', )}> - <div className={`absolute inset-0 opacity-40 -z-10 ${(type === 'success' && 'bg-[linear-gradient(92deg,rgba(23,178,106,0.25)_0%,rgba(255,255,255,0.00)_100%)]') - || (type === 'warning' && 'bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)]') - || (type === 'error' && 'bg-[linear-gradient(92deg,rgba(240,68,56,0.25)_0%,rgba(255,255,255,0.00)_100%)]') - || (type === 'info' && 'bg-[linear-gradient(92deg,rgba(11,165,236,0.25)_0%,rgba(255,255,255,0.00)_100%)]') + <div className={`absolute inset-0 opacity-40 ${ + (type === 'success' && 'bg-toast-success-bg') + || (type === 'warning' && 'bg-toast-warning-bg') + || (type === 'error' && 'bg-toast-error-bg') + || (type === 'info' && 'bg-toast-info-bg') }`} /> <div className={`flex ${size === 'md' ? 'gap-1' : 'gap-0.5'}`}> @@ -64,19 +65,18 @@ const Toast = ({ {type === 'warning' && <RiAlertFill className={`${size === 'md' ? 'w-5 h-5' : 'w-4 h-4'} text-text-warning-secondary`} aria-hidden="true" />} {type === 'info' && <RiInformation2Fill className={`${size === 'md' ? 'w-5 h-5' : 'w-4 h-4'} text-text-accent`} aria-hidden="true" />} </div> - <div className={`flex py-1 ${size === 'md' ? 'px-1' : 'px-0.5'} flex-col items-start gap-1 flex-grow z-10`}> - <div className='flex items-center gap-1'> - <div className='text-text-primary system-sm-semibold'>{message}</div> - {customComponent} - </div> + <div className={`flex py-1 ${size === 'md' ? 'px-1' : 'px-0.5'} flex-col items-start gap-1 grow`}> + <div className='text-text-primary system-sm-semibold'>{message}</div> {children && <div className='text-text-secondary system-xs-regular'> {children} </div> } </div> - <ActionButton onClick={close}> - <RiCloseLine className='w-4 h-4 flex-shrink-0 text-text-tertiary' /> - </ActionButton> + {close + && (<ActionButton className='z-[1000]' onClick={close}> + <RiCloseLine className='w-4 h-4 shrink-0 text-text-tertiary' /> + </ActionButton>) + } </div> </div> } diff --git a/web/app/components/base/tooltip/content.tsx b/web/app/components/base/tooltip/content.tsx new file mode 100644 index 0000000000..fe357ccfa6 --- /dev/null +++ b/web/app/components/base/tooltip/content.tsx @@ -0,0 +1,22 @@ +import type { FC, PropsWithChildren, ReactNode } from 'react' + +export type ToolTipContentProps = { + title?: ReactNode + action?: ReactNode +} & PropsWithChildren + +export const ToolTipContent: FC<ToolTipContentProps> = ({ + title, + action, + children, +}) => { + return ( + <div className='w-[180px]'> + {title && ( + <div className='mb-1.5 text-text-secondary font-semibold'>{title}</div> + )} + <div className='mb-1.5 text-text-tertiary'>{children}</div> + {action && <div className='text-text-accent cursor-pointer'>{action}</div>} + </div> + ) +} diff --git a/web/app/components/base/video-gallery/index.tsx b/web/app/components/base/video-gallery/index.tsx index a41dfe8e0a..ae2fab8e6f 100644 --- a/web/app/components/base/video-gallery/index.tsx +++ b/web/app/components/base/video-gallery/index.tsx @@ -6,7 +6,7 @@ type Props = { } const VideoGallery: React.FC<Props> = ({ srcs }) => { - return (<><br/>{srcs.map((src, index) => (<><br/><VideoPlayer key={`video_${index}`} src={src}/></>))}</>) + return (<><br/>{srcs.map((src, index) => (<React.Fragment key={`video_${index}`}><br/><VideoPlayer src={src}/></React.Fragment>))}</>) } export default React.memo(VideoGallery) diff --git a/web/app/components/billing/header-billing-btn/index.tsx b/web/app/components/billing/header-billing-btn/index.tsx index a8415524fd..a5bc310d9b 100644 --- a/web/app/components/billing/header-billing-btn/index.tsx +++ b/web/app/components/billing/header-billing-btn/index.tsx @@ -7,11 +7,13 @@ import cn from '@/utils/classnames' import { useProviderContext } from '@/context/provider-context' type Props = { - onClick: () => void + onClick?: () => void + isDisplayOnly?: boolean } const HeaderBillingBtn: FC<Props> = ({ onClick, + isDisplayOnly = false, }) => { const { plan, enableBilling, isFetchedPlan } = useProviderContext() const { @@ -25,9 +27,9 @@ const HeaderBillingBtn: FC<Props> = ({ })() const classNames = (() => { if (type === Plan.professional) - return 'border-[#E0F2FE] hover:border-[#B9E6FE] bg-[#E0F2FE] text-[#026AA2]' + return `border-[#E0F2FE] ${!isDisplayOnly ? 'hover:border-[#B9E6FE]' : ''} bg-[#E0F2FE] text-[#026AA2]` if (type === Plan.team) - return 'border-[#E0EAFF] hover:border-[#C7D7FE] bg-[#E0EAFF] text-[#3538CD]' + return `border-[#E0EAFF] ${!isDisplayOnly ? 'hover:border-[#C7D7FE]' : ''} bg-[#E0EAFF] text-[#3538CD]` return '' })() @@ -35,10 +37,22 @@ const HeaderBillingBtn: FC<Props> = ({ return null if (type === Plan.sandbox) - return <UpgradeBtn onClick={onClick} isShort /> + return <UpgradeBtn onClick={isDisplayOnly ? undefined : onClick} isShort /> + + const handleClick = () => { + if (!isDisplayOnly && onClick) + onClick() + } return ( - <div onClick={onClick} className={cn(classNames, 'flex items-center h-[22px] px-2 rounded-md border text-xs font-semibold uppercase cursor-pointer')}> + <div + onClick={handleClick} + className={cn( + classNames, + 'flex items-center h-[22px] px-2 rounded-md border text-xs font-semibold uppercase', + isDisplayOnly ? 'cursor-default' : 'cursor-pointer', + )} + > {name} </div> ) diff --git a/web/app/components/billing/upgrade-btn/index.tsx b/web/app/components/billing/upgrade-btn/index.tsx index d7885d7569..f080e6bbc4 100644 --- a/web/app/components/billing/upgrade-btn/index.tsx +++ b/web/app/components/billing/upgrade-btn/index.tsx @@ -2,9 +2,8 @@ import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' -import { GoldCoin } from '../../base/icons/src/vender/solid/FinanceAndECommerce' -import { Sparkles } from '../../base/icons/src/public/billing' -import s from './style.module.css' +import PremiumBadge from '../../base/premium-badge' +import { SparklesSoft } from '@/app/components/base/icons/src/public/common' import cn from '@/utils/classnames' import { useModalContext } from '@/context/modal-context' @@ -36,9 +35,7 @@ const PlainBtn = ({ className, onClick }: { className?: string; onClick: () => v const UpgradeBtn: FC<Props> = ({ className, isPlain = false, - isFull = false, isShort = false, - size = 'md', onClick: _onClick, loc, }) => { @@ -63,22 +60,19 @@ const UpgradeBtn: FC<Props> = ({ return <PlainBtn onClick={onClick} className={className} /> return ( - <div - className={cn( - s.upgradeBtn, - className, - isFull ? 'justify-center' : 'px-3', - size === 'lg' ? 'h-10' : 'h-9', - 'relative flex items-center cursor-pointer border rounded-[20px] border-[#0096EA] text-white', - )} + <PremiumBadge + size="m" + color="blue" + allowHover={true} onClick={onClick} > - <GoldCoin className='mr-1 w-3.5 h-3.5' /> - <div className='text-xs font-normal'>{t(`billing.upgradeBtn.${isShort ? 'encourageShort' : 'encourage'}`)}</div> - <Sparkles - className='absolute -right-1 -top-2 w-4 h-5 bg-cover' - /> - </div> + <SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' /> + <div className='system-xs-medium'> + <span className='p-1'> + {t(`billing.upgradeBtn.${isShort ? 'encourageShort' : 'encourage'}`)} + </span> + </div> + </PremiumBadge> ) } export default React.memo(UpgradeBtn) diff --git a/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx b/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx index 7702a70d3f..bce8f072d1 100644 --- a/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx +++ b/web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx @@ -12,7 +12,7 @@ import Button from '@/app/components/base/button' import { ToastContext } from '@/app/components/base/toast' import { createEmptyDataset } from '@/service/datasets' -type IProps = { +interface IProps { show: boolean onHide: () => void } diff --git a/web/app/components/datasets/create/step-one/index.tsx b/web/app/components/datasets/create/step-one/index.tsx index 2cca003b39..45dda51795 100644 --- a/web/app/components/datasets/create/step-one/index.tsx +++ b/web/app/components/datasets/create/step-one/index.tsx @@ -23,7 +23,7 @@ import classNames from '@/utils/classnames' type IStepOneProps = { datasetId?: string dataSourceType?: DataSourceType - dataSourceTypeDisable: Boolean + dataSourceTypeDisable: boolean hasConnection: boolean onSetting: () => void files: FileItem[] diff --git a/web/app/components/datasets/create/step-two/language-select/index.tsx b/web/app/components/datasets/create/step-two/language-select/index.tsx index 9cbf1a40d1..7730e0539a 100644 --- a/web/app/components/datasets/create/step-two/language-select/index.tsx +++ b/web/app/components/datasets/create/step-two/language-select/index.tsx @@ -6,7 +6,7 @@ import cn from '@/utils/classnames' import Popover from '@/app/components/base/popover' import { languages } from '@/i18n/language' -export type ILanguageSelectProps = { +export interface ILanguageSelectProps { currentLanguage: string onSelect: (language: string) => void disabled?: boolean diff --git a/web/app/components/datasets/create/website/jina-reader/base/checkbox-with-label.tsx b/web/app/components/datasets/create/website/jina-reader/base/checkbox-with-label.tsx index 25d40fe076..609bce3125 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/checkbox-with-label.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/checkbox-with-label.tsx @@ -5,7 +5,7 @@ import cn from '@/utils/classnames' import Checkbox from '@/app/components/base/checkbox' import Tooltip from '@/app/components/base/tooltip' -type Props = { +interface Props { className?: string isChecked: boolean onChange: (isChecked: boolean) => void diff --git a/web/app/components/datasets/create/website/jina-reader/base/error-message.tsx b/web/app/components/datasets/create/website/jina-reader/base/error-message.tsx index aa337ec4bf..4bd23fa293 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/error-message.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/error-message.tsx @@ -4,7 +4,7 @@ import React from 'react' import cn from '@/utils/classnames' import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' -type Props = { +interface Props { className?: string title: string errorMsg?: string diff --git a/web/app/components/datasets/create/website/jina-reader/base/field.tsx b/web/app/components/datasets/create/website/jina-reader/base/field.tsx index 5b5ca90c5d..363a57bdfc 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/field.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/field.tsx @@ -5,7 +5,7 @@ import Input from './input' import cn from '@/utils/classnames' import Tooltip from '@/app/components/base/tooltip' -type Props = { +interface Props { className?: string label: string labelClassName?: string diff --git a/web/app/components/datasets/create/website/jina-reader/base/input.tsx b/web/app/components/datasets/create/website/jina-reader/base/input.tsx index 7d2d2b609f..450ef4f721 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/input.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/input.tsx @@ -2,7 +2,7 @@ import type { FC } from 'react' import React, { useCallback } from 'react' -type Props = { +interface Props { value: string | number onChange: (value: string | number) => void placeholder?: string @@ -20,7 +20,7 @@ const Input: FC<Props> = ({ const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { const value = e.target.value if (isNumber) { - let numberValue = parseInt(value, 10) // integer only + let numberValue = Number.parseInt(value, 10) // integer only if (isNaN(numberValue)) { onChange('') return diff --git a/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx b/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx index 652401a20f..6446948961 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/options-wrap.tsx @@ -8,7 +8,7 @@ import { Settings04 } from '@/app/components/base/icons/src/vender/line/general' import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' const I18N_PREFIX = 'datasetCreation.stepOne.website' -type Props = { +interface Props { className?: string children: React.ReactNode controlFoldOptions?: number diff --git a/web/app/components/datasets/create/website/jina-reader/base/url-input.tsx b/web/app/components/datasets/create/website/jina-reader/base/url-input.tsx index e6b0475874..6ed2b9d799 100644 --- a/web/app/components/datasets/create/website/jina-reader/base/url-input.tsx +++ b/web/app/components/datasets/create/website/jina-reader/base/url-input.tsx @@ -7,7 +7,7 @@ import Button from '@/app/components/base/button' const I18N_PREFIX = 'datasetCreation.stepOne.website' -type Props = { +interface Props { isRunning: boolean onRun: (url: string) => void } diff --git a/web/app/components/datasets/create/website/jina-reader/crawled-result-item.tsx b/web/app/components/datasets/create/website/jina-reader/crawled-result-item.tsx index 5531d3e140..4999aeaea6 100644 --- a/web/app/components/datasets/create/website/jina-reader/crawled-result-item.tsx +++ b/web/app/components/datasets/create/website/jina-reader/crawled-result-item.tsx @@ -6,7 +6,7 @@ import cn from '@/utils/classnames' import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets' import Checkbox from '@/app/components/base/checkbox' -type Props = { +interface Props { payload: CrawlResultItemType isChecked: boolean isPreview: boolean diff --git a/web/app/components/datasets/create/website/jina-reader/crawled-result.tsx b/web/app/components/datasets/create/website/jina-reader/crawled-result.tsx index 2bd51e4d73..1746fe63e3 100644 --- a/web/app/components/datasets/create/website/jina-reader/crawled-result.tsx +++ b/web/app/components/datasets/create/website/jina-reader/crawled-result.tsx @@ -9,7 +9,7 @@ import type { CrawlResultItem } from '@/models/datasets' const I18N_PREFIX = 'datasetCreation.stepOne.website' -type Props = { +interface Props { className?: string list: CrawlResultItem[] checkedList: CrawlResultItem[] diff --git a/web/app/components/datasets/create/website/jina-reader/crawling.tsx b/web/app/components/datasets/create/website/jina-reader/crawling.tsx index ee26e7671a..b84a938d22 100644 --- a/web/app/components/datasets/create/website/jina-reader/crawling.tsx +++ b/web/app/components/datasets/create/website/jina-reader/crawling.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next' import cn from '@/utils/classnames' import { RowStruct } from '@/app/components/base/icons/src/public/other' -type Props = { +interface Props { className?: string crawledNum: number totalNum: number diff --git a/web/app/components/datasets/documents/detail/completed/index.tsx b/web/app/components/datasets/documents/detail/completed/index.tsx index 69cba1d8cd..c833688fbe 100644 --- a/web/app/components/datasets/documents/detail/completed/index.tsx +++ b/web/app/components/datasets/documents/detail/completed/index.tsx @@ -79,7 +79,7 @@ export const useSegmentListContext = (selector: (value: SegmentListContextValue) return useContextSelector(SegmentListContext, selector) } -type ICompletedProps = { +interface ICompletedProps { embeddingAvailable: boolean showNewSegmentModal: boolean onNewSegmentModalChange: (state: boolean) => void diff --git a/web/app/components/datasets/documents/detail/metadata/index.tsx b/web/app/components/datasets/documents/detail/metadata/index.tsx index 4a5560203e..da96b859be 100644 --- a/web/app/components/datasets/documents/detail/metadata/index.tsx +++ b/web/app/components/datasets/documents/detail/metadata/index.tsx @@ -29,7 +29,7 @@ const map2Options = (map: { [key: string]: string }) => { return Object.keys(map).map(key => ({ value: key, name: map[key] })) } -type IFieldInfoProps = { +interface IFieldInfoProps { label: string value?: string valueIcon?: ReactNode @@ -117,7 +117,7 @@ const IconButton: FC<{ ) } -type IMetadataProps = { +interface IMetadataProps { docDetail?: FullDocumentDetail loading: boolean onUpdate: () => void diff --git a/web/app/components/datasets/documents/detail/new-segment-modal.tsx b/web/app/components/datasets/documents/detail/new-segment-modal.tsx new file mode 100644 index 0000000000..4c51779f9c --- /dev/null +++ b/web/app/components/datasets/documents/detail/new-segment-modal.tsx @@ -0,0 +1,156 @@ +import { memo, useState } from 'react' +import type { FC } from 'react' +import { useTranslation } from 'react-i18next' +import { useContext } from 'use-context-selector' +import { useParams } from 'next/navigation' +import { RiCloseLine } from '@remixicon/react' +import Modal from '@/app/components/base/modal' +import Button from '@/app/components/base/button' +import AutoHeightTextarea from '@/app/components/base/auto-height-textarea/common' +import { Hash02 } from '@/app/components/base/icons/src/vender/line/general' +import { ToastContext } from '@/app/components/base/toast' +import type { SegmentUpdater } from '@/models/datasets' +import { addSegment } from '@/service/datasets' +import TagInput from '@/app/components/base/tag-input' + +type NewSegmentModalProps = { + isShow: boolean + onCancel: () => void + docForm: string + onSave: () => void +} + +const NewSegmentModal: FC<NewSegmentModalProps> = ({ + isShow, + onCancel, + docForm, + onSave, +}) => { + const { t } = useTranslation() + const { notify } = useContext(ToastContext) + const [question, setQuestion] = useState('') + const [answer, setAnswer] = useState('') + const { datasetId, documentId } = useParams() + const [keywords, setKeywords] = useState<string[]>([]) + const [loading, setLoading] = useState(false) + + const handleCancel = () => { + setQuestion('') + setAnswer('') + onCancel() + setKeywords([]) + } + + const handleSave = async () => { + const params: SegmentUpdater = { content: '' } + if (docForm === 'qa_model') { + if (!question.trim()) + return notify({ type: 'error', message: t('datasetDocuments.segment.questionEmpty') }) + if (!answer.trim()) + return notify({ type: 'error', message: t('datasetDocuments.segment.answerEmpty') }) + + params.content = question + params.answer = answer + } + else { + if (!question.trim()) + return notify({ type: 'error', message: t('datasetDocuments.segment.contentEmpty') }) + + params.content = question + } + + if (keywords?.length) + params.keywords = keywords + + setLoading(true) + try { + await addSegment({ datasetId, documentId, body: params }) + notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') }) + handleCancel() + onSave() + } + finally { + setLoading(false) + } + } + + const renderContent = () => { + if (docForm === 'qa_model') { + return ( + <> + <div className='mb-1 text-xs font-medium text-gray-500'>QUESTION</div> + <AutoHeightTextarea + outerClassName='mb-4' + className='leading-6 text-md text-gray-800' + value={question} + placeholder={t('datasetDocuments.segment.questionPlaceholder') || ''} + onChange={e => setQuestion(e.target.value)} + autoFocus + /> + <div className='mb-1 text-xs font-medium text-gray-500'>ANSWER</div> + <AutoHeightTextarea + outerClassName='mb-4' + className='leading-6 text-md text-gray-800' + value={answer} + placeholder={t('datasetDocuments.segment.answerPlaceholder') || ''} + onChange={e => setAnswer(e.target.value)} + /> + </> + ) + } + + return ( + <AutoHeightTextarea + className='leading-6 text-md text-gray-800' + value={question} + placeholder={t('datasetDocuments.segment.contentPlaceholder') || ''} + onChange={e => setQuestion(e.target.value)} + autoFocus + /> + ) + } + + return ( + <Modal isShow={isShow} onClose={() => { }} className='pt-8 px-8 pb-6 !max-w-[640px] !rounded-xl'> + <div className={'flex flex-col relative'}> + <div className='absolute right-0 -top-0.5 flex items-center h-6'> + <div className='flex justify-center items-center w-6 h-6 cursor-pointer' onClick={handleCancel}> + <RiCloseLine className='w-4 h-4 text-gray-500' /> + </div> + </div> + <div className='mb-[14px]'> + <span className='inline-flex items-center px-1.5 h-5 border border-gray-200 rounded-md'> + <Hash02 className='mr-0.5 w-3 h-3 text-gray-400' /> + <span className='text-[11px] font-medium text-gray-500 italic'> + { + docForm === 'qa_model' + ? t('datasetDocuments.segment.newQaSegment') + : t('datasetDocuments.segment.newTextSegment') + } + </span> + </span> + </div> + <div className='mb-4 py-1.5 h-[420px] overflow-auto'>{renderContent()}</div> + <div className='text-xs font-medium text-gray-500'>{t('datasetDocuments.segment.keywords')}</div> + <div className='mb-8'> + <TagInput items={keywords} onChange={newKeywords => setKeywords(newKeywords)} /> + </div> + <div className='flex justify-end space-x-2'> + <Button + onClick={handleCancel}> + {t('common.operation.cancel')} + </Button> + <Button + variant='primary' + onClick={handleSave} + disabled={loading} + > + {t('common.operation.save')} + </Button> + </div> + </div> + </Modal> + ) +} + +export default memo(NewSegmentModal) diff --git a/web/app/components/datasets/documents/detail/settings/index.tsx b/web/app/components/datasets/documents/detail/settings/index.tsx index 05c52d4de8..6bd6aaa265 100644 --- a/web/app/components/datasets/documents/detail/settings/index.tsx +++ b/web/app/components/datasets/documents/detail/settings/index.tsx @@ -16,7 +16,7 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro import type { NotionPage } from '@/models/common' import { useDocumentDetail, useInvalidDocumentDetailKey } from '@/service/knowledge/use-document' -type DocumentSettingsProps = { +interface DocumentSettingsProps { datasetId: string documentId: string } diff --git a/web/app/components/datasets/documents/index.tsx b/web/app/components/datasets/documents/index.tsx index c9df2f28e2..bbd1c03214 100644 --- a/web/app/components/datasets/documents/index.tsx +++ b/web/app/components/datasets/documents/index.tsx @@ -73,7 +73,7 @@ const EmptyElement: FC<{ canAdd: boolean; onClick: () => void; type?: 'upload' | </div> } -type IDocumentsProps = { +interface IDocumentsProps { datasetId: string } diff --git a/web/app/components/datasets/documents/rename-modal.tsx b/web/app/components/datasets/documents/rename-modal.tsx index 883897b510..0b73c37207 100644 --- a/web/app/components/datasets/documents/rename-modal.tsx +++ b/web/app/components/datasets/documents/rename-modal.tsx @@ -9,7 +9,7 @@ import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' import { renameDocumentName } from '@/service/datasets' -type Props = { +interface Props { datasetId: string documentId: string name: string diff --git a/web/app/components/datasets/external-api/external-api-modal/Form.tsx b/web/app/components/datasets/external-api/external-api-modal/Form.tsx index ada01493fe..824b5e6c9e 100644 --- a/web/app/components/datasets/external-api/external-api-modal/Form.tsx +++ b/web/app/components/datasets/external-api/external-api-modal/Form.tsx @@ -87,4 +87,6 @@ const Form: FC<FormProps> = React.memo(({ ) }) +Form.displayName = 'Form' + export default Form diff --git a/web/app/components/datasets/hit-testing/textarea.tsx b/web/app/components/datasets/hit-testing/textarea.tsx index fcd72a2f1b..1ae715b528 100644 --- a/web/app/components/datasets/hit-testing/textarea.tsx +++ b/web/app/components/datasets/hit-testing/textarea.tsx @@ -15,7 +15,7 @@ import { asyncRunSafe } from '@/utils' import { RETRIEVE_METHOD, type RetrievalConfig } from '@/types/app' import promptS from '@/app/components/app/configuration/config-prompt/style.module.css' -type TextAreaWithButtonIProps = { +interface TextAreaWithButtonIProps { datasetId: string onUpdateList: () => void setHitResult: (res: HitTestingResponse) => void diff --git a/web/app/components/datasets/rename-modal/index.tsx b/web/app/components/datasets/rename-modal/index.tsx index e93862f63d..22c7f8e988 100644 --- a/web/app/components/datasets/rename-modal/index.tsx +++ b/web/app/components/datasets/rename-modal/index.tsx @@ -14,7 +14,7 @@ import { ToastContext } from '@/app/components/base/toast' import type { DataSet } from '@/models/datasets' import { updateDatasetSetting } from '@/service/datasets' -type RenameDatasetModalProps = { +interface RenameDatasetModalProps { show: boolean dataset: DataSet onSuccess?: () => void diff --git a/web/app/components/datasets/settings/form/index.tsx b/web/app/components/datasets/settings/form/index.tsx index 760954d6cb..b9a2522174 100644 --- a/web/app/components/datasets/settings/form/index.tsx +++ b/web/app/components/datasets/settings/form/index.tsx @@ -19,7 +19,7 @@ import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/d import { updateDatasetSetting } from '@/service/datasets' import { type DataSetListResponse } from '@/models/datasets' import DatasetDetailContext from '@/context/dataset-detail' -import { type RetrievalConfig } from '@/types/app' +import type { RetrievalConfig } from '@/types/app' import { useAppContext } from '@/context/app-context' import { isReRankModelSelected } from '@/app/components/datasets/common/check-rerank-model' import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' diff --git a/web/app/components/datasets/settings/permission-selector/index.tsx b/web/app/components/datasets/settings/permission-selector/index.tsx index f70e41d46f..ace8c4512b 100644 --- a/web/app/components/datasets/settings/permission-selector/index.tsx +++ b/web/app/components/datasets/settings/permission-selector/index.tsx @@ -15,7 +15,7 @@ import { Users01, UsersPlus } from '@/app/components/base/icons/src/vender/solid import type { DatasetPermission } from '@/models/datasets' import { useAppContext } from '@/context/app-context' import type { Member } from '@/models/common' -export type RoleSelectorProps = { +export interface RoleSelectorProps { disabled?: boolean permission?: DatasetPermission value: string[] diff --git a/web/app/components/develop/md.tsx b/web/app/components/develop/md.tsx index 26b4007c87..7cb0dd7dde 100644 --- a/web/app/components/develop/md.tsx +++ b/web/app/components/develop/md.tsx @@ -55,7 +55,7 @@ export const Heading = function H2({ export function Row({ children }: IChildrenProps) { return ( - <div className="grid items-start grid-cols-1 gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2"> + <div className="grid items-start grid-cols-1 gap-x-16 gap-y-10 xl:!max-w-none xl:grid-cols-2"> {children} </div> ) diff --git a/web/app/components/develop/secret-key/input-copy.tsx b/web/app/components/develop/secret-key/input-copy.tsx index d31077919e..cab0d5fc66 100644 --- a/web/app/components/develop/secret-key/input-copy.tsx +++ b/web/app/components/develop/secret-key/input-copy.tsx @@ -33,10 +33,10 @@ const InputCopy = ({ }, [isCopied]) return ( - <div className={`flex rounded-lg bg-gray-50 hover:bg-gray-50 py-2 items-center ${className}`}> - <div className="flex items-center flex-grow h-5"> + <div className={`flex rounded-lg bg-components-input-bg-normal hover:bg-state-base-hover py-2 items-center ${className}`}> + <div className="flex items-center grow h-5"> {children} - <div className='flex-grow bg-gray-50 text-[13px] relative h-full'> + <div className='grow text-[13px] relative h-full'> <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => { copy(value) setIsCopied(true) @@ -49,13 +49,13 @@ const InputCopy = ({ </Tooltip> </div> </div> - <div className="flex-shrink-0 h-4 bg-gray-200 border" /> + <div className="shrink-0 h-4 bg-divider-regular border" /> <Tooltip popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} position='bottom' > - <div className="px-0.5 flex-shrink-0"> - <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => { + <div className="px-0.5 shrink-0"> + <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-state-base-hover cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => { copy(value) setIsCopied(true) }}> diff --git a/web/app/components/develop/secret-key/secret-key-button.tsx b/web/app/components/develop/secret-key/secret-key-button.tsx index dab319bab4..a9f2656392 100644 --- a/web/app/components/develop/secret-key/secret-key-button.tsx +++ b/web/app/components/develop/secret-key/secret-key-button.tsx @@ -23,7 +23,7 @@ const SecretKeyButton = ({ className, appId, iconCls, textCls }: ISecretKeyButto <path d="M9 3.66672C9.35362 3.66672 9.69276 3.80719 9.94281 4.05724C10.1929 4.30729 10.3333 4.64643 10.3333 5.00005M13 5.00005C13.0002 5.62483 12.854 6.24097 12.5732 6.79908C12.2924 7.3572 11.8847 7.84177 11.3829 8.21397C10.8811 8.58617 10.2991 8.83564 9.68347 8.94239C9.06788 9.04915 8.43584 9.01022 7.838 8.82872L6.33333 10.3334H5V11.6667H3.66667V13.0001H1.66667C1.48986 13.0001 1.32029 12.9298 1.19526 12.8048C1.07024 12.6798 1 12.5102 1 12.3334V10.6094C1.00004 10.4326 1.0703 10.263 1.19533 10.1381L5.17133 6.16205C5.00497 5.61206 4.95904 5.03268 5.0367 4.46335C5.11435 3.89402 5.31375 3.3481 5.62133 2.86275C5.92891 2.3774 6.33744 1.96401 6.81913 1.65073C7.30082 1.33745 7.84434 1.13162 8.41272 1.04725C8.9811 0.96289 9.56098 1.00197 10.1129 1.16184C10.6648 1.32171 11.1758 1.59861 11.6111 1.97369C12.0464 2.34878 12.3958 2.81324 12.6354 3.33548C12.8751 3.85771 12.9994 4.42545 13 5.00005Z" stroke="#1F2A37" strokeLinecap="round" strokeLinejoin="round" /> </svg> </div> - <div className={`text-[13px] text-gray-800 ${textCls}`}>{t('appApi.apiKey')}</div> + <div className={`text-[13px] text-text-secondary ${textCls}`}>{t('appApi.apiKey')}</div> </Button> <SecretKeyModal isShow={isVisible} onClose={() => setVisible(false)} appId={appId} /> </> diff --git a/web/app/components/develop/secret-key/secret-key-generate.tsx b/web/app/components/develop/secret-key/secret-key-generate.tsx index 14b862f68a..07cdf11c48 100644 --- a/web/app/components/develop/secret-key/secret-key-generate.tsx +++ b/web/app/components/develop/secret-key/secret-key-generate.tsx @@ -23,14 +23,14 @@ const SecretKeyGenerateModal = ({ const { t } = useTranslation() return ( <Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`px-8 ${className}`}> - <XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} /> - <p className='mt-1 text-[13px] text-gray-500 font-normal leading-5'>{t('appApi.apiKeyModal.generateTips')}</p> + <XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-text-tertiary ${s.close}`} onClick={onClose} /> + <p className='mt-1 text-[13px] text-text-tertiary font-normal leading-5'>{t('appApi.apiKeyModal.generateTips')}</p> <div className='my-4'> <InputCopy className='w-full' value={newKey?.token} /> </div> <div className='flex justify-end my-4'> - <Button className={`flex-shrink-0 ${s.w64}`} onClick={onClose}> - <span className='text-xs font-medium text-gray-800'>{t('appApi.actionMsg.ok')}</span> + <Button className={`shrink-0 ${s.w64}`} onClick={onClose}> + <span className='text-xs font-medium text-text-secondary'>{t('appApi.actionMsg.ok')}</span> </Button> </div> diff --git a/web/app/components/develop/secret-key/secret-key-modal.tsx b/web/app/components/develop/secret-key/secret-key-modal.tsx index dbb5cc37c7..54b833edef 100644 --- a/web/app/components/develop/secret-key/secret-key-modal.tsx +++ b/web/app/components/develop/secret-key/secret-key-modal.tsx @@ -98,37 +98,37 @@ const SecretKeyModal = ({ return ( <Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`${s.customModal} px-8 flex flex-col`}> - <XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} /> - <p className='mt-1 text-[13px] text-gray-500 font-normal leading-5 flex-shrink-0'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p> + <XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-text-tertiary ${s.close}`} onClick={onClose} /> + <p className='mt-1 text-[13px] text-text-tertiary font-normal leading-5 shrink-0'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p> {!apiKeysList && <div className='mt-4'><Loading /></div>} { !!apiKeysList?.data?.length && ( - <div className='flex flex-col flex-grow mt-4 overflow-hidden'> - <div className='flex items-center flex-shrink-0 text-xs font-semibold text-gray-500 border-b border-solid h-9'> - <div className='flex-shrink-0 w-64 px-3'>{t('appApi.apiKeyModal.secretKey')}</div> - <div className='flex-shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.created')}</div> - <div className='flex-shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.lastUsed')}</div> - <div className='flex-grow px-3'></div> + <div className='flex flex-col grow mt-4 overflow-hidden'> + <div className='flex items-center shrink-0 text-xs font-semibold text-text-tertiary border-b border-solid h-9'> + <div className='shrink-0 w-64 px-3'>{t('appApi.apiKeyModal.secretKey')}</div> + <div className='shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.created')}</div> + <div className='shrink-0 px-3 w-[200px]'>{t('appApi.apiKeyModal.lastUsed')}</div> + <div className='grow px-3'></div> </div> - <div className='flex-grow overflow-auto'> + <div className='grow overflow-auto'> {apiKeysList.data.map(api => ( - <div className='flex items-center text-sm font-normal text-gray-700 border-b border-solid h-9' key={api.id}> - <div className='flex-shrink-0 w-64 px-3 font-mono truncate'>{generateToken(api.token)}</div> - <div className='flex-shrink-0 px-3 truncate w-[200px]'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div> - <div className='flex-shrink-0 px-3 truncate w-[200px]'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div> - <div className='flex flex-grow px-3'> + <div className='flex items-center text-sm font-normal text-text-secondary border-b border-solid h-9' key={api.id}> + <div className='shrink-0 w-64 px-3 font-mono truncate'>{generateToken(api.token)}</div> + <div className='shrink-0 px-3 truncate w-[200px]'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div> + <div className='shrink-0 px-3 truncate w-[200px]'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div> + <div className='flex grow px-3'> <Tooltip popupContent={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`} popupClassName='mr-1' > - <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-gray-100 ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => { + <div className={`flex items-center justify-center shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-state-base-hover ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => { // setIsCopied(true) copy(api.token) setCopyValue(api.token) }}></div> </Tooltip> {isCurrentWorkspaceManager - && <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 rounded-lg cursor-pointer ${s.trashIcon}`} onClick={() => { + && <div className={`flex items-center justify-center shrink-0 w-6 h-6 rounded-lg cursor-pointer ${s.trashIcon}`} onClick={() => { setDelKeyId(api.id) setShowConfirmDelete(true) }}> @@ -142,12 +142,12 @@ const SecretKeyModal = ({ ) } <div className='flex'> - <Button className={`flex flex-shrink-0 mt-4 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}> - <PlusIcon className='flex flex-shrink-0 w-4 h-4' /> - <div className='text-xs font-medium text-gray-800'>{t('appApi.apiKeyModal.createNewSecretKey')}</div> + <Button className={`flex shrink-0 mt-4 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}> + <PlusIcon className='flex shrink-0 w-4 h-4 mr-1' /> + <div className='text-xs font-medium text-text-secondary'>{t('appApi.apiKeyModal.createNewSecretKey')}</div> </Button> </div> - <SecretKeyGenerateModal className='flex-shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} /> + <SecretKeyGenerateModal className='shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} /> {showConfirmDelete && ( <Confirm title={`${t('appApi.actionMsg.deleteConfirmTitle')}`} diff --git a/web/app/components/explore/create-app-modal/index.tsx b/web/app/components/explore/create-app-modal/index.tsx index 45baf773f8..152f3b9282 100644 --- a/web/app/components/explore/create-app-modal/index.tsx +++ b/web/app/components/explore/create-app-modal/index.tsx @@ -14,7 +14,7 @@ import { useProviderContext } from '@/context/provider-context' import AppsFull from '@/app/components/billing/apps-full-in-dialog' import type { AppIconType } from '@/types/app' -export type CreateAppModalProps = { +export interface CreateAppModalProps { show: boolean isEditModal?: boolean appName: string diff --git a/web/app/components/header/account-dropdown/index.tsx b/web/app/components/header/account-dropdown/index.tsx index e92b16fd67..88eb2628ea 100644 --- a/web/app/components/header/account-dropdown/index.tsx +++ b/web/app/components/header/account-dropdown/index.tsx @@ -9,7 +9,6 @@ import { Menu, Transition } from '@headlessui/react' import Indicator from '../indicator' import AccountAbout from '../account-about' import { mailToSupport } from '../utils/util' -import WorkplaceSelector from './workplace-selector' import classNames from '@/utils/classnames' import I18n from '@/context/i18n' import Avatar from '@/app/components/base/avatar' @@ -99,10 +98,6 @@ export default function AppSelector({ isMobile }: IAppSelector) { </div> </div> </Menu.Item> - <div className='px-1 py-1'> - <div className='mt-2 px-3 text-xs font-medium text-text-tertiary'>{t('common.userProfile.workspace')}</div> - <WorkplaceSelector /> - </div> <div className="px-1 py-1"> <Menu.Item> {({ active }) => <Link diff --git a/web/app/components/header/account-dropdown/workplace-selector/index.tsx b/web/app/components/header/account-dropdown/workplace-selector/index.tsx index bcc72a7bb3..f8bde33d51 100644 --- a/web/app/components/header/account-dropdown/workplace-selector/index.tsx +++ b/web/app/components/header/account-dropdown/workplace-selector/index.tsx @@ -2,34 +2,21 @@ import { Fragment } from 'react' import { useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' import { Menu, Transition } from '@headlessui/react' -import s from './index.module.css' +import { RiArrowDownSLine } from '@remixicon/react' import cn from '@/utils/classnames' import { switchWorkspace } from '@/service/common' import { useWorkspacesContext } from '@/context/workspace-context' -import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' -import { Check } from '@/app/components/base/icons/src/vender/line/general' +import { useProviderContext } from '@/context/provider-context' import { ToastContext } from '@/app/components/base/toast' -import classNames from '@/utils/classnames' - -const itemClassName = ` - flex items-center px-3 py-2 h-10 cursor-pointer -` -const itemIconClassName = ` - shrink-0 mr-2 flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600 -` -const itemNameClassName = ` - grow mr-2 text-sm text-gray-700 text-left -` -const itemCheckClassName = ` - shrink-0 w-4 h-4 text-primary-600 -` +import PremiumBadge from '@/app/components/base/premium-badge' const WorkplaceSelector = () => { const { t } = useTranslation() + const { plan } = useProviderContext() const { notify } = useContext(ToastContext) const { workspaces } = useWorkspacesContext() const currentWorkspace = workspaces.find(v => v.current) - + const isFreePlan = plan.type === 'sandbox' const handleSwitchWorkspace = async (tenant_id: string) => { try { if (currentWorkspace?.id === tenant_id) @@ -50,13 +37,15 @@ const WorkplaceSelector = () => { <> <Menu.Button className={cn( ` - ${itemClassName} w-full - group hover:bg-state-base-hover cursor-pointer ${open && 'bg-state-base-hover'} rounded-lg + flex items-center p-0.5 gap-1.5 w-full + group hover:bg-state-base-hover cursor-pointer ${open && 'bg-state-base-hover'} rounded-[10px] `, )}> - <div className={itemIconClassName}>{currentWorkspace?.name[0].toLocaleUpperCase()}</div> - <div className={`${itemNameClassName} truncate`}>{currentWorkspace?.name}</div> - <ChevronRight className='shrink-0 w-[14px] h-[14px] text-gray-500' /> + <div className='flex items-center justify-center w-7 h-7 bg-[#EFF4FF] rounded-lg text-xs font-medium text-primary-600'>{currentWorkspace?.name[0].toLocaleUpperCase()}</div> + <div className='flex flex-row'> + <div className={'truncate max-w-[80px] text-text-secondary system-sm-medium'}>{currentWorkspace?.name}</div> + <RiArrowDownSLine className='w-4 h-4 text-text-secondary' /> + </div> </Menu.Button> <Transition as={Fragment} @@ -70,25 +59,29 @@ const WorkplaceSelector = () => { <Menu.Items className={cn( ` - absolute top-[1px] min-w-[200px] max-h-[70vh] overflow-y-scroll z-10 bg-white border-[0.5px] border-gray-200 - divide-y divide-gray-100 origin-top-right rounded-xl focus:outline-none + flex w-[280px] flex-col items-start absolute left-[-15px] mt-1 rounded-xl shadows-shadow-lg `, - s.popup, )} > - <div className="px-1 py-1"> + <div className="flex flex-col p-1 pb-2 items-start self-stretch w-full rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg "> + <div className='flex px-3 pt-1 pb-0.5 items-start self-stretch'> + <span className='flex-1 text-text-tertiary system-xs-medium-uppercase'>{t('common.userProfile.workspace')}</span> + </div> { workspaces.map(workspace => ( - <Menu.Item key={workspace.id}> - {({ active }) => <div className={classNames(itemClassName, - active && 'bg-state-base-hover', - )} key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}> - <div className={itemIconClassName}>{workspace.name[0].toLocaleUpperCase()}</div> - <div className={itemNameClassName}>{workspace.name}</div> - {workspace.current && <Check className={itemCheckClassName} />} - </div>} - - </Menu.Item> + <div className='flex py-1 pl-3 pr-2 items-center gap-2 self-stretch hover:bg-state-base-hover rounded-lg' key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}> + <div className='flex items-center justify-center w-6 h-6 bg-[#EFF4FF] rounded-md text-xs font-medium text-primary-600'>{workspace.name[0].toLocaleUpperCase()}</div> + <div className='line-clamp-1 grow overflow-hidden text-text-secondary text-ellipsis system-md-regular cursor-pointer'>{workspace.name}</div> + { + <PremiumBadge size='s' color='gray' allowHover={false}> + <div className='system-2xs-medium'> + <span className='p-[2px]'> + {plan.type === 'professional' ? 'PRO' : plan.type.toUpperCase()} + </span> + </div> + </PremiumBadge> + } + </div> )) } </div> diff --git a/web/app/components/header/account-setting/index.module.css b/web/app/components/header/account-setting/index.module.css deleted file mode 100644 index bb855e1c86..0000000000 --- a/web/app/components/header/account-setting/index.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.modal { - max-width: 1024px !important; - border-radius: 12px !important; - margin-top: 60px; - margin-bottom: 60px; - padding: 0 !important; - overflow-y: auto; -} \ No newline at end of file diff --git a/web/app/components/header/account-setting/index.tsx b/web/app/components/header/account-setting/index.tsx index 4be7ec6ab7..b3409c226a 100644 --- a/web/app/components/header/account-setting/index.tsx +++ b/web/app/components/header/account-setting/index.tsx @@ -2,8 +2,8 @@ import { useTranslation } from 'react-i18next' import { useEffect, useRef, useState } from 'react' import { - RiBox3Fill, - RiBox3Line, + RiBrain2Fill, + RiBrain2Line, RiCloseLine, RiColorFilterFill, RiColorFilterLine, @@ -17,26 +17,23 @@ import { RiPuzzle2Line, RiTranslate2, } from '@remixicon/react' +import Button from '../../base/button' import MembersPage from './members-page' import LanguagePage from './language-page' import ApiBasedExtensionPage from './api-based-extension-page' import DataSourcePage from './data-source-page' import ModelProviderPage from './model-provider-page' -import s from './index.module.css' import cn from '@/utils/classnames' import BillingPage from '@/app/components/billing/billing-page' import CustomPage from '@/app/components/custom/custom-page' -import Modal from '@/app/components/base/modal' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { useProviderContext } from '@/context/provider-context' import { useAppContext } from '@/context/app-context' +import MenuDialog from '@/app/components/header/account-setting/menu-dialog' +import Input from '@/app/components/base/input' const iconClassName = ` - w-4 h-4 ml-3 mr-2 -` - -const scrolledClassName = ` - border-b shadow-xs bg-white/[.98] + w-5 h-5 mr-2 ` type IAccountSettingProps = { @@ -68,8 +65,8 @@ export default function AccountSetting({ { key: 'provider', name: t('common.settings.provider'), - icon: <RiBox3Line className={iconClassName} />, - activeIcon: <RiBox3Fill className={iconClassName} />, + icon: <RiBrain2Line className={iconClassName} />, + activeIcon: <RiBrain2Fill className={iconClassName} />, }, { key: 'members', @@ -117,7 +114,7 @@ export default function AccountSetting({ }, { key: 'account-group', - name: t('common.settings.accountGroup'), + name: t('common.settings.generalGroup'), items: [ { key: 'language', @@ -144,32 +141,31 @@ export default function AccountSetting({ const activeItem = [...menuItems[0].items, ...menuItems[1].items].find(item => item.key === activeMenu) + const [searchValue, setSearchValue] = useState<string>('') + return ( - <Modal - isShow - onClose={() => { }} - className={s.modal} - wrapperClassName='pt-[60px]' + <MenuDialog + show + onClose={onCancel} > - <div className='flex'> - <div className='w-[44px] sm:w-[200px] px-[1px] py-4 sm:p-4 border border-divider-burn shrink-0 sm:shrink-1 flex flex-col items-center sm:items-start'> - <div className='mb-8 ml-0 sm:ml-2 sm:text-base title-2xl-semi-bold text-text-primary'>{t('common.userProfile.settings')}</div> + <div className='mx-auto max-w-[1048px] h-[100vh] flex'> + <div className='w-[44px] sm:w-[224px] pl-4 pr-6 border-r border-divider-burn flex flex-col'> + <div className='mt-6 mb-8 px-3 py-2 text-text-primary title-2xl-semi-bold'>{t('common.userProfile.settings')}</div> <div className='w-full'> { menuItems.map(menuItem => ( - <div key={menuItem.key} className='mb-4'> + <div key={menuItem.key} className='mb-2'> {!isCurrentWorkspaceDatasetOperator && ( - <div className='px-2 mb-[6px] sm:text-xs system-xs-medium-uppercase text-text-tertiary'>{menuItem.name}</div> + <div className='py-2 pl-3 pb-1 mb-0.5 system-xs-medium-uppercase text-text-tertiary'>{menuItem.name}</div> )} <div> { menuItem.items.map(item => ( <div key={item.key} - className={` - flex items-center h-[37px] mb-[2px] text-sm cursor-pointer rounded-lg - ${activeMenu === item.key ? 'system-sm-semibold text-components-menu-item-text-active bg-state-base-active' : 'system-sm-medium text-components-menu-item-text'} - `} + className={cn( + 'flex items-center mb-0.5 p-1 pl-3 h-[37px] text-sm cursor-pointer rounded-lg', + activeMenu === item.key ? 'bg-state-base-active text-components-menu-item-text-active system-sm-semibold' : 'text-components-menu-item-text system-sm-medium')} title={item.name} onClick={() => setActiveMenu(item.key)} > @@ -184,31 +180,50 @@ export default function AccountSetting({ } </div> </div> - <div ref={scrollRef} className='relative w-[824px] h-[720px] pb-4 overflow-y-auto'> - <div className={cn('sticky top-0 px-6 py-4 flex items-center h-14 mb-4 bg-components-panel-bg title-2xl-semi-bold text-text-primary z-20', scrolled && scrolledClassName)}> - <div className='shrink-0'>{activeItem?.name}</div> - { - activeItem?.description && ( - <div className='shrink-0 ml-2 text-xs text-gray-600'>{activeItem?.description}</div> - ) - } - <div className='grow flex justify-end'> - <div className='z-[10] flex items-center justify-center -mr-4 p-2 cursor-pointer rounded-[10px] hover:bg-components-button-tertiary-bg' onClick={onCancel}> - <RiCloseLine className='w-5 h-5 text-components-button-tertiary-text' /> - </div> - </div> + <div className='relative flex w-[824px]'> + <div className='absolute top-6 -right-11 flex flex-col items-center z-[9999]'> + <Button + variant='tertiary' + size='large' + className='px-2' + onClick={onCancel} + > + <RiCloseLine className='w-5 h-5' /> + </Button> + <div className='mt-1 text-text-tertiary system-2xs-medium-uppercase'>ESC</div> </div> - <div className='px-4 sm:px-8 pt-2'> - {activeMenu === 'members' && <MembersPage />} - {activeMenu === 'billing' && <BillingPage />} - {activeMenu === 'language' && <LanguagePage />} - {activeMenu === 'provider' && <ModelProviderPage />} - {activeMenu === 'data-source' && <DataSourcePage />} - {activeMenu === 'api-based-extension' && <ApiBasedExtensionPage />} - {activeMenu === 'custom' && <CustomPage />} + <div ref={scrollRef} className='w-full pb-4 bg-components-panel-bg overflow-y-auto'> + <div className={cn('sticky top-0 mx-8 pt-[27px] pb-2 mb-[18px] flex items-center bg-components-panel-bg z-20', scrolled && 'border-b border-divider-regular')}> + <div className='shrink-0 text-text-primary title-2xl-semi-bold'>{activeItem?.name}</div> + { + activeItem?.description && ( + <div className='shrink-0 ml-2 text-xs text-text-tertiary'>{activeItem?.description}</div> + ) + } + {activeItem?.key === 'provider' && ( + <div className='grow flex justify-end'> + <Input + showLeftIcon + wrapperClassName='!w-[200px]' + className='!h-8 !text-[13px]' + onChange={e => setSearchValue(e.target.value)} + value={searchValue} + /> + </div> + )} + </div> + <div className='px-4 sm:px-8 pt-2'> + {activeMenu === 'provider' && <ModelProviderPage searchText={searchValue} />} + {activeMenu === 'members' && <MembersPage />} + {activeMenu === 'billing' && <BillingPage />} + {activeMenu === 'data-source' && <DataSourcePage />} + {activeMenu === 'api-based-extension' && <ApiBasedExtensionPage />} + {activeMenu === 'custom' && <CustomPage />} + {activeMenu === 'language' && <LanguagePage />} + </div> </div> </div> </div> - </Modal> + </MenuDialog> ) } diff --git a/web/app/components/header/account-setting/members-page/index.tsx b/web/app/components/header/account-setting/members-page/index.tsx index 808da454d1..92199a7da6 100644 --- a/web/app/components/header/account-setting/members-page/index.tsx +++ b/web/app/components/header/account-setting/members-page/index.tsx @@ -47,7 +47,7 @@ const MembersPage = () => { return ( <> <div className='flex flex-col'> - <div className='flex items-center mb-4 p-3 bg-gray-50 rounded-2xl'> + <div className='flex items-center mb-4 p-3 gap-1 bg-gray-50 rounded-2xl'> <LogoEmbeddedChatHeader className='!w-10 !h-10' /> <div className='grow mx-2'> <div className='text-sm font-medium text-gray-900'>{currentWorkspace?.name}</div> diff --git a/web/app/components/header/account-setting/menu-dialog.tsx b/web/app/components/header/account-setting/menu-dialog.tsx new file mode 100644 index 0000000000..76296b84dd --- /dev/null +++ b/web/app/components/header/account-setting/menu-dialog.tsx @@ -0,0 +1,59 @@ +import { Fragment, useCallback, useEffect } from 'react' +import type { ReactNode } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import cn from '@/utils/classnames' + +type DialogProps = { + className?: string + children: ReactNode + show: boolean + onClose?: () => void +} + +const MenuDialog = ({ + className, + children, + show, + onClose, +}: DialogProps) => { + const close = useCallback(() => onClose?.(), [onClose]) + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') + close() + } + + document.addEventListener('keydown', handleKeyDown) + return () => { + document.removeEventListener('keydown', handleKeyDown) + } + }, [close]) + + return ( + <Transition appear show={show} as={Fragment}> + <Dialog as="div" className="relative z-[60]" onClose={() => {}}> + <div className="fixed inset-0"> + <div className="flex flex-col items-center justify-center min-h-full"> + <Transition.Child + as={Fragment} + enter="ease-out duration-300" + enterFrom="opacity-0 scale-95" + enterTo="opacity-100 scale-100" + leave="ease-in duration-200" + leaveFrom="opacity-100 scale-100" + leaveTo="opacity-0 scale-95" + > + <Dialog.Panel className={cn('grow relative w-full h-full p-0 overflow-hidden text-left align-middle transition-all transform bg-background-sidenav-bg backdrop-blur-md', className)}> + <div className='absolute top-0 right-0 h-full w-1/2 bg-components-panel-bg' /> + {children} + </Dialog.Panel> + </Transition.Child> + </div> + </div> + </Dialog> + </Transition > + ) +} + +export default MenuDialog diff --git a/web/app/components/header/account-setting/model-provider-page/declarations.ts b/web/app/components/header/account-setting/model-provider-page/declarations.ts index 02f178c52f..486a1e44f5 100644 --- a/web/app/components/header/account-setting/model-provider-page/declarations.ts +++ b/web/app/components/header/account-setting/model-provider-page/declarations.ts @@ -15,6 +15,10 @@ export enum FormTypeEnum { boolean = 'boolean', files = 'files', file = 'file', + modelSelector = 'model-selector', + toolSelector = 'tool-selector', + multiToolSelector = 'array[tools]', + appSelector = 'app-selector', } export type FormOption = { @@ -109,9 +113,19 @@ export type CredentialFormSchemaBase = { tooltip?: TypeWithI18N show_on: FormShowOnObject[] url?: string + scope?: string } -export type CredentialFormSchemaTextInput = CredentialFormSchemaBase & { max_length?: number; placeholder?: TypeWithI18N } +export type CredentialFormSchemaTextInput = CredentialFormSchemaBase & { + max_length?: number; + placeholder?: TypeWithI18N, + template?: { + enabled: boolean + }, + auto_generate?: { + type: string + } +} export type CredentialFormSchemaNumberInput = CredentialFormSchemaBase & { min?: number; max?: number; placeholder?: TypeWithI18N } export type CredentialFormSchemaSelect = CredentialFormSchemaBase & { options: FormOption[]; placeholder?: TypeWithI18N } export type CredentialFormSchemaRadio = CredentialFormSchemaBase & { options: FormOption[] } diff --git a/web/app/components/header/account-setting/model-provider-page/hooks.ts b/web/app/components/header/account-setting/model-provider-page/hooks.ts index 54396cc538..231df0e9db 100644 --- a/web/app/components/header/account-setting/model-provider-page/hooks.ts +++ b/web/app/components/header/account-setting/model-provider-page/hooks.ts @@ -11,10 +11,12 @@ import type { DefaultModel, DefaultModelResponse, Model, + ModelProvider, ModelTypeEnum, } from './declarations' import { ConfigurationMethodEnum, + CustomConfigurationStatusEnum, ModelStatusEnum, } from './declarations' import I18n from '@/context/i18n' @@ -26,6 +28,15 @@ import { getPayUrl, } from '@/service/common' import { useProviderContext } from '@/context/provider-context' +import { + useMarketplacePlugins, +} from '@/app/components/plugins/marketplace/hooks' +import type { Plugin } from '@/app/components/plugins/types' +import { PluginType } from '@/app/components/plugins/types' +import { getMarketplacePluginsByCollectionId } from '@/app/components/plugins/marketplace/utils' +import { useModalContextSelector } from '@/context/modal-context' +import { useEventEmitterContextContext } from '@/context/event-emitter' +import { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './provider-added-card' type UseDefaultModelAndModelList = ( defaultModel: DefaultModelResponse | undefined, @@ -233,3 +244,106 @@ export const useUpdateModelProviders = () => { return updateModelProviders } + +export const useMarketplaceAllPlugins = (providers: ModelProvider[], searchText: string) => { + const exclude = useMemo(() => { + return providers.map(provider => provider.provider.replace(/(.+)\/([^/]+)$/, '$1')) + }, [providers]) + const [collectionPlugins, setCollectionPlugins] = useState<Plugin[]>([]) + + const { + plugins, + queryPlugins, + queryPluginsWithDebounced, + isLoading, + } = useMarketplacePlugins() + + const getCollectionPlugins = useCallback(async () => { + const collectionPlugins = await getMarketplacePluginsByCollectionId('__model-settings-pinned-models') + + setCollectionPlugins(collectionPlugins) + }, []) + + useEffect(() => { + getCollectionPlugins() + }, [getCollectionPlugins]) + + useEffect(() => { + if (searchText) { + queryPluginsWithDebounced({ + query: searchText, + category: PluginType.model, + exclude, + type: 'plugin', + }) + } + else { + queryPlugins({ + query: '', + category: PluginType.model, + type: 'plugin', + pageSize: 1000, + exclude, + }) + } + }, [queryPlugins, queryPluginsWithDebounced, searchText, exclude]) + + const allPlugins = useMemo(() => { + const allPlugins = [...collectionPlugins.filter(plugin => !exclude.includes(plugin.plugin_id))] + + if (plugins?.length) { + for (let i = 0; i < plugins.length; i++) { + const plugin = plugins[i] + + if (plugin.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin.plugin_id)) + allPlugins.push(plugin) + } + } + + return allPlugins + }, [plugins, collectionPlugins, exclude]) + + return { + plugins: allPlugins, + isLoading, + } +} + +export const useModelModalHandler = () => { + const setShowModelModal = useModalContextSelector(state => state.setShowModelModal) + const updateModelProviders = useUpdateModelProviders() + const updateModelList = useUpdateModelList() + const { eventEmitter } = useEventEmitterContextContext() + + return ( + provider: ModelProvider, + configurationMethod: ConfigurationMethodEnum, + CustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields, + ) => { + setShowModelModal({ + payload: { + currentProvider: provider, + currentConfigurationMethod: configurationMethod, + currentCustomConfigurationModelFixedFields: CustomConfigurationModelFixedFields, + }, + onSaveCallback: () => { + updateModelProviders() + + provider.supported_model_types.forEach((type) => { + updateModelList(type) + }) + + if (configurationMethod === ConfigurationMethodEnum.customizableModel + && provider.custom_configuration.status === CustomConfigurationStatusEnum.active) { + eventEmitter?.emit({ + type: UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST, + payload: provider.provider, + } as any) + + if (CustomConfigurationModelFixedFields?.__model_type) + updateModelList(CustomConfigurationModelFixedFields.__model_type) + } + }, + }) + } +} diff --git a/web/app/components/header/account-setting/model-provider-page/index.tsx b/web/app/components/header/account-setting/model-provider-page/index.tsx index a8a5a0cf42..f77974abaf 100644 --- a/web/app/components/header/account-setting/model-provider-page/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/index.tsx @@ -1,39 +1,53 @@ -import { useMemo } from 'react' +import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' +import Link from 'next/link' +import { useDebounce } from 'ahooks' +import { + RiAlertFill, + RiArrowDownSLine, + RiArrowRightUpLine, + RiBrainLine, +} from '@remixicon/react' import SystemModelSelector from './system-model-selector' -import ProviderAddedCard, { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './provider-added-card' -import ProviderCard from './provider-card' +import ProviderAddedCard from './provider-added-card' import type { + ConfigurationMethodEnum, CustomConfigurationModelFixedFields, + ModelProvider, } from './declarations' import { - ConfigurationMethodEnum, CustomConfigurationStatusEnum, ModelTypeEnum, } from './declarations' import { useDefaultModel, - useUpdateModelList, - useUpdateModelProviders, + useMarketplaceAllPlugins, + useModelModalHandler, } from './hooks' -import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback' +import Divider from '@/app/components/base/divider' +import Loading from '@/app/components/base/loading' +import ProviderCard from '@/app/components/plugins/provider-card' +import List from '@/app/components/plugins/marketplace/list' import { useProviderContext } from '@/context/provider-context' -import { useModalContextSelector } from '@/context/modal-context' -import { useEventEmitterContextContext } from '@/context/event-emitter' +import type { Plugin } from '@/app/components/plugins/types' +import { MARKETPLACE_URL_PREFIX } from '@/config' +import cn from '@/utils/classnames' +import { getLocaleOnClient } from '@/i18n' -const ModelProviderPage = () => { +type Props = { + searchText: string +} + +const ModelProviderPage = ({ searchText }: Props) => { + const debouncedSearchText = useDebounce(searchText, { wait: 500 }) const { t } = useTranslation() - const { eventEmitter } = useEventEmitterContextContext() - const updateModelProviders = useUpdateModelProviders() - const updateModelList = useUpdateModelList() const { data: textGenerationDefaultModel } = useDefaultModel(ModelTypeEnum.textGeneration) const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding) const { data: rerankDefaultModel } = useDefaultModel(ModelTypeEnum.rerank) const { data: speech2textDefaultModel } = useDefaultModel(ModelTypeEnum.speech2text) const { data: ttsDefaultModel } = useDefaultModel(ModelTypeEnum.tts) const { modelProviders: providers } = useProviderContext() - const setShowModelModal = useModalContextSelector(state => state.setShowModelModal) const defaultModelNotConfigured = !textGenerationDefaultModel && !embeddingsDefaultModel && !speech2textDefaultModel && !rerankDefaultModel && !ttsDefaultModel const [configuredProviders, notConfiguredProviders] = useMemo(() => { const configuredProviders: ModelProvider[] = [] @@ -54,97 +68,125 @@ const ModelProviderPage = () => { return [configuredProviders, notConfiguredProviders] }, [providers]) + const [filteredConfiguredProviders, filteredNotConfiguredProviders] = useMemo(() => { + const filteredConfiguredProviders = configuredProviders.filter( + provider => provider.provider.toLowerCase().includes(debouncedSearchText.toLowerCase()) + || Object.values(provider.label).some(text => text.toLowerCase().includes(debouncedSearchText.toLowerCase())), + ) + const filteredNotConfiguredProviders = notConfiguredProviders.filter( + provider => provider.provider.toLowerCase().includes(debouncedSearchText.toLowerCase()) + || Object.values(provider.label).some(text => text.toLowerCase().includes(debouncedSearchText.toLowerCase())), + ) - const handleOpenModal = ( - provider: ModelProvider, - configurateMethod: ConfigurationMethodEnum, - CustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields, - ) => { - setShowModelModal({ - payload: { - currentProvider: provider, - currentConfigurationMethod: configurateMethod, - currentCustomConfigurationModelFixedFields: CustomConfigurationModelFixedFields, - }, - onSaveCallback: () => { - updateModelProviders() + return [filteredConfiguredProviders, filteredNotConfiguredProviders] + }, [configuredProviders, debouncedSearchText, notConfiguredProviders]) - if (configurateMethod === ConfigurationMethodEnum.predefinedModel) { - provider.supported_model_types.forEach((type) => { - updateModelList(type) - }) - } + const handleOpenModal = useModelModalHandler() + const [collapse, setCollapse] = useState(false) + const locale = getLocaleOnClient() + const { + plugins: allPlugins, + isLoading: isAllPluginsLoading, + } = useMarketplaceAllPlugins(providers, searchText) - if (configurateMethod === ConfigurationMethodEnum.customizableModel && provider.custom_configuration.status === CustomConfigurationStatusEnum.active) { - eventEmitter?.emit({ - type: UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST, - payload: provider.provider, - } as any) + const cardRender = useCallback((plugin: Plugin) => { + if (plugin.type === 'bundle') + return null - if (CustomConfigurationModelFixedFields?.__model_type) - updateModelList(CustomConfigurationModelFixedFields?.__model_type) - } - }, - }) - } + return <ProviderCard key={plugin.plugin_id} payload={plugin} /> + }, []) return ( <div className='relative pt-1 -mt-2'> - <div className={`flex items-center justify-between mb-2 h-8 ${defaultModelNotConfigured && 'px-3 bg-[#FFFAEB] rounded-lg border border-[#FEF0C7]'}`}> - { - defaultModelNotConfigured - ? ( - <div className='flex items-center text-xs font-medium text-gray-700'> - <AlertTriangle className='mr-1 w-3 h-3 text-[#F79009]' /> - {t('common.modelProvider.notConfigured')} - </div> - ) - : <div className='text-sm font-medium text-gray-800'>{t('common.modelProvider.models')}</div> - } - <SystemModelSelector - textGenerationDefaultModel={textGenerationDefaultModel} - embeddingsDefaultModel={embeddingsDefaultModel} - rerankDefaultModel={rerankDefaultModel} - speech2textDefaultModel={speech2textDefaultModel} - ttsDefaultModel={ttsDefaultModel} - /> + <div className={cn('flex items-center mb-2')}> + <div className='grow text-text-primary system-md-semibold'>{t('common.modelProvider.models')}</div> + <div className={cn( + 'shrink-0 relative flex items-center justify-end gap-2 p-px rounded-lg border border-transparent', + defaultModelNotConfigured && 'pl-2 bg-components-panel-bg-blur border-components-panel-border shadow-xs', + )}> + {defaultModelNotConfigured && <div className='absolute top-0 bottom-0 right-0 left-0 opacity-40' style={{ background: 'linear-gradient(92deg, rgba(247, 144, 9, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%)' }} />} + {defaultModelNotConfigured && ( + <div className='flex items-center gap-1 text-text-primary system-xs-medium'> + <RiAlertFill className='w-4 h-4 text-text-warning-secondary' /> + {t('common.modelProvider.notConfigured')} + </div> + )} + <SystemModelSelector + notConfigured={defaultModelNotConfigured} + textGenerationDefaultModel={textGenerationDefaultModel} + embeddingsDefaultModel={embeddingsDefaultModel} + rerankDefaultModel={rerankDefaultModel} + speech2textDefaultModel={speech2textDefaultModel} + ttsDefaultModel={ttsDefaultModel} + /> + </div> </div> - { - !!configuredProviders?.length && ( - <div className='pb-3'> - { - configuredProviders?.map(provider => ( - <ProviderAddedCard - key={provider.provider} - provider={provider} - onOpenModal={(configurateMethod: ConfigurationMethodEnum, currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields) => handleOpenModal(provider, configurateMethod, currentCustomConfigurationModelFixedFields)} - /> - )) - } + {!filteredConfiguredProviders?.length && ( + <div className='mb-2 p-4 rounded-[10px] bg-workflow-process-bg'> + <div className='w-10 h-10 flex items-center justify-center rounded-[10px] border-[0.5px] border-components-card-border bg-components-card-bg shadow-lg backdrop-blur'> + <RiBrainLine className='w-5 h-5 text-text-primary' /> </div> - ) - } - { - !!notConfiguredProviders?.length && ( - <> - <div className='flex items-center mb-2 text-xs font-semibold text-gray-500'> - + {t('common.modelProvider.addMoreModelProvider')} - <span className='grow ml-3 h-[1px] bg-gradient-to-r from-[#f3f4f6]' /> - </div> - <div className='grid grid-cols-3 gap-2'> - { - notConfiguredProviders?.map(provider => ( - <ProviderCard - key={provider.provider} - provider={provider} - onOpenModal={(configurateMethod: ConfigurationMethodEnum) => handleOpenModal(provider, configurateMethod)} - /> - )) - } - </div> - </> - ) - } + <div className='mt-2 text-text-secondary system-sm-medium'>{t('common.modelProvider.emptyProviderTitle')}</div> + <div className='mt-1 text-text-tertiary system-xs-regular'>{t('common.modelProvider.emptyProviderTip')}</div> + </div> + )} + {!!filteredConfiguredProviders?.length && ( + <div className='relative'> + {filteredConfiguredProviders?.map(provider => ( + <ProviderAddedCard + key={provider.provider} + provider={provider} + onOpenModal={(configurationMethod: ConfigurationMethodEnum, currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields) => handleOpenModal(provider, configurationMethod, currentCustomConfigurationModelFixedFields)} + /> + ))} + </div> + )} + {!!filteredNotConfiguredProviders?.length && ( + <> + <div className='flex items-center mb-2 pt-2 text-text-primary system-md-semibold'>{t('common.modelProvider.configureRequired')}</div> + <div className='relative'> + {filteredNotConfiguredProviders?.map(provider => ( + <ProviderAddedCard + notConfigured + key={provider.provider} + provider={provider} + onOpenModal={(configurationMethod: ConfigurationMethodEnum, currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields) => handleOpenModal(provider, configurationMethod, currentCustomConfigurationModelFixedFields)} + /> + ))} + </div> + </> + )} + <div className='mb-2'> + <Divider className='!mt-4 h-px' /> + <div className='flex items-center justify-between'> + <div className='flex items-center gap-1 text-text-primary system-md-semibold cursor-pointer' onClick={() => setCollapse(!collapse)}> + <RiArrowDownSLine className={cn('w-4 h-4', collapse && '-rotate-90')} /> + {t('common.modelProvider.installProvider')} + </div> + <div className='flex items-center mb-2 pt-2'> + <span className='pr-1 text-text-tertiary system-sm-regular'>{t('common.modelProvider.discoverMore')}</span> + <Link target="_blank" href={`${MARKETPLACE_URL_PREFIX}`} className='inline-flex items-center system-sm-medium text-text-accent'> + {t('plugin.marketplace.difyMarketplace')} + <RiArrowRightUpLine className='w-4 h-4' /> + </Link> + </div> + </div> + {!collapse && isAllPluginsLoading && <Loading type='area' />} + { + !isAllPluginsLoading && !collapse && ( + <List + marketplaceCollections={[]} + marketplaceCollectionPluginsMap={{}} + plugins={allPlugins} + showInstallButton + locale={locale} + cardContainerClassName='grid grid-cols-2 gap-2' + cardRender={cardRender} + emptyClassName='h-auto' + /> + ) + } + </div> </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx index a16b101e6a..0576672a4f 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx @@ -4,40 +4,48 @@ import type { ModelProvider, } from '../declarations' import { useLanguage } from '../hooks' -import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes' -import { OpenaiViolet } from '@/app/components/base/icons/src/public/llm' +import { Group } from '@/app/components/base/icons/src/vender/other' +import { OpenaiBlue, OpenaiViolet } from '@/app/components/base/icons/src/public/llm' +import cn from '@/utils/classnames' type ModelIconProps = { provider?: Model | ModelProvider modelName?: string className?: string + isDeprecated?: boolean } const ModelIcon: FC<ModelIconProps> = ({ provider, className, modelName, + isDeprecated = false, }) => { const language = useLanguage() - - if (provider?.provider === 'openai' && (modelName?.startsWith('gpt-4') || modelName?.includes('4o'))) - return <OpenaiViolet className={`w-4 h-4 ${className}`}/> + if (provider?.provider.includes('openai') && modelName?.includes('gpt-4o')) + return <div className='flex items-center justify-center'><OpenaiBlue className={cn('w-5 h-5', className)}/></div> + if (provider?.provider.includes('openai') && modelName?.startsWith('gpt-4')) + return <div className='flex items-center justify-center'><OpenaiViolet className={cn('w-5 h-5', className)}/></div> if (provider?.icon_small) { return ( - <img - alt='model-icon' - src={`${provider.icon_small[language] || provider.icon_small.en_US}`} - className={`w-4 h-4 ${className}`} - /> + <div className={`flex items-center justify-center w-5 h-5 ${isDeprecated ? 'opacity-50' : ''}`}> + <img + alt='model-icon' + src={`${provider.icon_small[language] || provider.icon_small.en_US}`} + className={cn('w-4.5 h-4.5', className)} + /> + </div> ) } return ( - <div className={` - flex items-center justify-center w-6 h-6 rounded border-[0.5px] border-black/5 bg-gray-50 - ${className} - `}> - <CubeOutline className='w-4 h-4 text-gray-400' /> + <div className={cn( + 'flex items-center justify-center rounded-md border-[0.5px] w-5 h-5 border-components-panel-border-subtle bg-background-default-subtle', + className, + )}> + <div className='flex w-5 h-5 items-center justify-center opacity-35'> + <Group className='text-text-tertiary w-3 h-3' /> + </div> </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx index c0a7be68a6..2b8530696a 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react' -import type { FC } from 'react' +import { useCallback, useState } from 'react' +import type { ReactNode } from 'react' import { ValidatingTip } from '../../key-validator/ValidateStatus' import type { CredentialFormSchema, @@ -17,24 +17,41 @@ import cn from '@/utils/classnames' import { SimpleSelect } from '@/app/components/base/select' import Tooltip from '@/app/components/base/tooltip' import Radio from '@/app/components/base/radio' -type FormProps = { +import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector' +import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector' +import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector' +import RadioE from '@/app/components/base/radio/ui' + +type FormProps< + CustomFormSchema extends Omit<CredentialFormSchema, 'type'> & { type: string } = never, +> = { className?: string itemClassName?: string fieldLabelClassName?: string value: FormValue onChange: (val: FormValue) => void - formSchemas: CredentialFormSchema[] + formSchemas: Array<CredentialFormSchema | CustomFormSchema> validating: boolean validatedSuccess?: boolean showOnVariableMap: Record<string, string[]> isEditMode: boolean + isAgentStrategy?: boolean readonly?: boolean inputClassName?: string isShowDefaultValue?: boolean - fieldMoreInfo?: (payload: CredentialFormSchema) => JSX.Element | null + fieldMoreInfo?: (payload: CredentialFormSchema | CustomFormSchema) => ReactNode + customRenderField?: ( + formSchema: CustomFormSchema, + props: Omit<FormProps<CustomFormSchema>, 'override' | 'customRenderField'> + ) => ReactNode + // If return falsy value, this field will fallback to default render + override?: [Array<FormTypeEnum>, (formSchema: CredentialFormSchema, props: Omit<FormProps<CustomFormSchema>, 'override' | 'customRenderField'>) => ReactNode] } -const Form: FC<FormProps> = ({ +function Form< + CustomFormSchema extends Omit<CredentialFormSchema, 'type'> & { type: string } = never, +>({ className, itemClassName, fieldLabelClassName, @@ -45,13 +62,32 @@ const Form: FC<FormProps> = ({ validatedSuccess, showOnVariableMap, isEditMode, + isAgentStrategy = false, readonly, inputClassName, isShowDefaultValue = false, fieldMoreInfo, -}) => { + customRenderField, + override, +}: FormProps<CustomFormSchema>) { const language = useLanguage() const [changeKey, setChangeKey] = useState('') + const filteredProps: Omit<FormProps<CustomFormSchema>, 'override' | 'customRenderField'> = { + className, + itemClassName, + fieldLabelClassName, + value, + onChange, + formSchemas, + validating, + validatedSuccess, + showOnVariableMap, + isEditMode, + readonly, + inputClassName, + isShowDefaultValue, + fieldMoreInfo, + } const handleFormChange = (key: string, val: string | boolean) => { if (isEditMode && (key === '__model_type' || key === '__model_name')) @@ -67,25 +103,37 @@ const Form: FC<FormProps> = ({ onChange({ ...value, [key]: val, ...shouldClearVariable }) } - const renderField = (formSchema: CredentialFormSchema) => { + const handleModelChanged = useCallback((key: string, model: any) => { + const newValue = { + ...value[key], + ...model, + type: FormTypeEnum.modelSelector, + } + onChange({ ...value, [key]: newValue }) + }, [onChange, value]) + + const renderField = (formSchema: CredentialFormSchema | CustomFormSchema) => { const tooltip = formSchema.tooltip const tooltipContent = (tooltip && ( <Tooltip - popupContent={ - <div className='w-[200px]'> - {tooltip[language] || tooltip.en_US} - </div>} + popupContent={<div className='w-[200px]'> + {tooltip[language] || tooltip.en_US} + </div>} triggerClassName='ml-1 w-4 h-4' - asChild={false} - /> + asChild={false} /> )) + if (override) { + const [overrideTypes, overrideRender] = override + if (overrideTypes.includes(formSchema.type as FormTypeEnum)) { + const node = overrideRender(formSchema as CredentialFormSchema, filteredProps) + if (node) + return node + } + } + if (formSchema.type === FormTypeEnum.textInput || formSchema.type === FormTypeEnum.secretInput || formSchema.type === FormTypeEnum.textNumber) { const { - variable, - label, - placeholder, - required, - show_on, + variable, label, placeholder, required, show_on, } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)) @@ -94,13 +142,11 @@ const Form: FC<FormProps> = ({ const disabled = readonly || (isEditMode && (variable === '__model_type' || variable === '__model_name')) return ( <div key={variable} className={cn(itemClassName, 'py-3')}> - <div className={cn(fieldLabelClassName, 'flex items-center py-2 text-sm text-gray-900')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> {label[language] || label.en_US} - { - required && ( - <span className='ml-1 text-red-500'>*</span> - ) - } + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} {tooltipContent} </div> <Input @@ -111,8 +157,7 @@ const Form: FC<FormProps> = ({ placeholder={placeholder?.[language] || placeholder?.en_US} disabled={disabled} type={formSchema.type === FormTypeEnum.textNumber ? 'number' : 'text'} - {...(formSchema.type === FormTypeEnum.textNumber ? { min: (formSchema as CredentialFormSchemaNumberInput).min, max: (formSchema as CredentialFormSchemaNumberInput).max } : {})} - /> + {...(formSchema.type === FormTypeEnum.textNumber ? { min: (formSchema as CredentialFormSchemaNumberInput).min, max: (formSchema as CredentialFormSchemaNumberInput).max } : {})} /> {fieldMoreInfo?.(formSchema)} {validating && changeKey === variable && <ValidatingTip />} </div> @@ -121,11 +166,7 @@ const Form: FC<FormProps> = ({ if (formSchema.type === FormTypeEnum.radio) { const { - options, - variable, - label, - show_on, - required, + options, variable, label, show_on, required, } = formSchema as CredentialFormSchemaRadio if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)) @@ -135,40 +176,34 @@ const Form: FC<FormProps> = ({ return ( <div key={variable} className={cn(itemClassName, 'py-3')}> - <div className={cn(fieldLabelClassName, 'flex items-center py-2 text-sm text-gray-900')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> {label[language] || label.en_US} - { - required && ( - <span className='ml-1 text-red-500'>*</span> - ) - } + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} {tooltipContent} </div> <div className={`grid grid-cols-${options?.length} gap-3`}> - { - options.filter((option) => { - if (option.show_on.length) - return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value) + {options.filter((option) => { + if (option.show_on.length) + return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value) - return true - }).map(option => ( - <div - className={` - flex items-center px-3 py-2 rounded-lg border border-gray-100 bg-gray-25 cursor-pointer - ${value[variable] === option.value && 'bg-white border-[1.5px] border-primary-400 shadow-sm'} + return true + }).map(option => ( + <div + className={` + flex items-center gap-2 px-3 py-2 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg cursor-pointer + ${value[variable] === option.value && 'bg-components-option-card-option-selected-bg border-[1.5px] border-components-option-card-option-selected-border shadow-sm'} ${disabled && '!cursor-not-allowed opacity-60'} `} - onClick={() => handleFormChange(variable, option.value)} - key={`${variable}-${option.value}`} - > - <div className={` - flex justify-center items-center mr-2 w-4 h-4 border border-gray-300 rounded-full - ${value[variable] === option.value && 'border-[5px] border-primary-600'} - `} /> - <div className='text-sm text-gray-900'>{option.label[language] || option.label.en_US}</div> - </div> - )) - } + onClick={() => handleFormChange(variable, option.value)} + key={`${variable}-${option.value}`} + > + <RadioE isChecked={value[variable] === option.value} /> + + <div className='system-sm-regular text-text-secondary'>{option.label[language] || option.label.en_US}</div> + </div> + ))} </div> {fieldMoreInfo?.(formSchema)} {validating && changeKey === variable && <ValidatingTip />} @@ -176,14 +211,9 @@ const Form: FC<FormProps> = ({ ) } - if (formSchema.type === 'select') { + if (formSchema.type === FormTypeEnum.select) { const { - options, - variable, - label, - show_on, - required, - placeholder, + options, variable, label, show_on, required, placeholder, } = formSchema as CredentialFormSchemaSelect if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)) @@ -191,17 +221,16 @@ const Form: FC<FormProps> = ({ return ( <div key={variable} className={cn(itemClassName, 'py-3')}> - <div className={cn(fieldLabelClassName, 'flex items-center py-2 text-sm text-gray-900')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> {label[language] || label.en_US} - { - required && ( - <span className='ml-1 text-red-500'>*</span> - ) - } + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} {tooltipContent} </div> <SimpleSelect + wrapperClassName='h-8' className={cn(inputClassName)} disabled={readonly} defaultValue={(isShowDefaultValue && ((value[variable] as string) === '' || value[variable] === undefined || value[variable] === null)) ? formSchema.default : value[variable]} @@ -212,20 +241,16 @@ const Form: FC<FormProps> = ({ return true }).map(option => ({ value: option.value, name: option.label[language] || option.label.en_US }))} onSelect={item => handleFormChange(variable, item.value as string)} - placeholder={placeholder?.[language] || placeholder?.en_US} - /> + placeholder={placeholder?.[language] || placeholder?.en_US} /> {fieldMoreInfo?.(formSchema)} {validating && changeKey === variable && <ValidatingTip />} </div> ) } - if (formSchema.type === 'boolean') { + if (formSchema.type === FormTypeEnum.boolean) { const { - variable, - label, - show_on, - required, + variable, label, show_on, required, } = formSchema as CredentialFormSchemaRadio if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)) @@ -233,14 +258,12 @@ const Form: FC<FormProps> = ({ return ( <div key={variable} className={cn(itemClassName, 'py-3')}> - <div className='flex items-center justify-between py-2 text-sm text-gray-900'> + <div className='flex items-center justify-between py-2 system-sm-semibold text-text-secondary'> <div className='flex items-center space-x-2'> - <span className={cn(fieldLabelClassName, 'flex items-center py-2 text-sm text-gray-900')}>{label[language] || label.en_US}</span> - { - required && ( - <span className='ml-1 text-red-500'>*</span> - ) - } + <span className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-regular text-text-secondary')}>{label[language] || label.en_US}</span> + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} {tooltipContent} </div> <Radio.Group @@ -256,13 +279,124 @@ const Form: FC<FormProps> = ({ </div> ) } + + if (formSchema.type === FormTypeEnum.modelSelector) { + const { + variable, label, required, scope, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + return ( + <div key={variable} className={cn(itemClassName, 'py-3')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> + {label[language] || label.en_US} + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} + {tooltipContent} + </div> + <ModelParameterModal + popupClassName='!w-[387px]' + isAdvancedMode + isInWorkflow + isAgentStrategy={isAgentStrategy} + value={value[variable]} + setModel={model => handleModelChanged(variable, model)} + readonly={readonly} + scope={scope} /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && <ValidatingTip />} + </div> + ) + } + + if (formSchema.type === FormTypeEnum.toolSelector) { + const { + variable, + label, + required, + scope, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + + return ( + <div key={variable} className={cn(itemClassName, 'py-3')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> + {label[language] || label.en_US} + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} + {tooltipContent} + </div> + <ToolSelector + scope={scope} + disabled={readonly} + value={value[variable]} + onSelect={item => handleFormChange(variable, item as any)} + onDelete={() => handleFormChange(variable, null as any)} + /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && <ValidatingTip />} + </div> + ) + } + + if (formSchema.type === FormTypeEnum.multiToolSelector) { + const { + variable, + label, + tooltip, + required, + scope, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + + return ( + <div key={variable} className={cn(itemClassName, 'py-3')}> + <MultipleToolSelector + disabled={readonly} + scope={scope} + label={label[language] || label.en_US} + required={required} + tooltip={tooltip?.[language] || tooltip?.en_US} + value={value[variable] || []} + onChange={item => handleFormChange(variable, item as any)} + /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && <ValidatingTip />} + </div> + ) + } + + if (formSchema.type === FormTypeEnum.appSelector) { + const { + variable, label, required, scope, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + + return ( + <div key={variable} className={cn(itemClassName, 'py-3')}> + <div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}> + {label[language] || label.en_US} + {required && ( + <span className='ml-1 text-red-500'>*</span> + )} + {tooltipContent} + </div> + <AppSelector + disabled={readonly} + scope={scope} + value={value[variable]} + onSelect={item => handleFormChange(variable, { ...item, type: FormTypeEnum.appSelector } as any)} /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && <ValidatingTip />} + </div> + ) + } + + // @ts-expect-error it work + if (!Object.values(FormTypeEnum).includes(formSchema.type)) + return customRenderField?.(formSchema as CustomFormSchema, filteredProps) } return ( <div className={className}> - { - formSchemas.map(formSchema => renderField(formSchema)) - } + {formSchemas.map(formSchema => renderField(formSchema))} </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx index 86d52619e6..f94b708bf3 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Input.tsx @@ -26,14 +26,14 @@ const Input: FC<InputProps> = ({ max, }) => { const toLimit = (v: string) => { - const minNum = parseFloat(`${min}`) - const maxNum = parseFloat(`${max}`) - if (!isNaN(minNum) && parseFloat(v) < minNum) { + const minNum = Number.parseFloat(`${min}`) + const maxNum = Number.parseFloat(`${max}`) + if (!isNaN(minNum) && Number.parseFloat(v) < minNum) { onChange(`${min}`) return } - if (!isNaN(maxNum) && parseFloat(v) > maxNum) + if (!isNaN(maxNum) && Number.parseFloat(v) > maxNum) onChange(`${max}`) } return ( @@ -41,11 +41,11 @@ const Input: FC<InputProps> = ({ <input tabIndex={0} className={` - block px-3 w-full h-9 bg-gray-100 text-sm rounded-lg border border-transparent + block px-3 w-full h-8 bg-components-input-bg-normal text-sm text-components-input-text-filled rounded-lg border border-transparent appearance-none outline-none caret-primary-600 - hover:border-[rgba(0,0,0,0.08)] hover:bg-gray-50 - focus:bg-white focus:border-gray-300 focus:shadow-xs - placeholder:text-sm placeholder:text-gray-400 + hover:border-components-input-border-hover hover:bg-components-input-bg-hover + focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs + placeholder:text-sm placeholder:text-text-tertiary ${validated && 'pr-[30px]'} ${className} `} diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx index 967bcccdca..c9f8e44c59 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx @@ -35,7 +35,6 @@ import { useLanguage, useProviderCredentialsAndLoadBalancing, } from '../hooks' -import ProviderIcon from '../provider-icon' import { useValidate } from '../../key-validator/hooks' import { ValidatedStatus } from '../../key-validator/declarations' import ModelLoadBalancingConfigs from '../provider-added-card/model-load-balancing-configs' @@ -280,11 +279,10 @@ const ModelModal: FC<ModelModalProps> = ({ <PortalToFollowElem open> <PortalToFollowElemContent className='w-full h-full z-[60]'> <div className='fixed inset-0 flex items-center justify-center bg-black/[.25]'> - <div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-white shadow-xl rounded-2xl overflow-y-auto'> + <div className='mx-2 w-[640px] max-h-[calc(100vh-120px)] bg-components-panel-bg shadow-xl rounded-2xl overflow-y-auto'> <div className='px-8 pt-8'> - <div className='flex justify-between items-center mb-2'> - <div className='text-xl font-semibold text-gray-900'>{renderTitlePrefix()}</div> - <ProviderIcon provider={provider} /> + <div className='flex items-center mb-2'> + <div className='text-xl font-semibold text-text-primary'>{renderTitlePrefix()}</div> </div> <Form @@ -297,7 +295,7 @@ const ModelModal: FC<ModelModalProps> = ({ isEditMode={isEditMode} /> - <div className='mt-1 mb-4 border-t-[0.5px] border-t-gray-100' /> + <div className='mt-1 mb-4 border-t-[0.5px] border-t-divider-regular' /> <ModelLoadBalancingConfigs withSwitch {...{ draftConfig, setDraftConfig, @@ -306,7 +304,7 @@ const ModelModal: FC<ModelModalProps> = ({ configurationMethod: configurateMethod, }} /> - <div className='sticky bottom-0 flex justify-between items-center mt-2 -mx-2 pt-4 px-2 pb-6 flex-wrap gap-y-2 bg-white'> + <div className='sticky bottom-0 flex justify-between items-center mt-2 -mx-2 pt-4 px-2 pb-6 flex-wrap gap-y-2 bg-components-panel-bg'> { (provider.help && (provider.help.title || provider.help.url)) ? ( @@ -326,8 +324,9 @@ const ModelModal: FC<ModelModalProps> = ({ { isEditMode && ( <Button + variant='warning' size='large' - className='mr-2 text-[#D92D20]' + className='mr-2' onClick={() => setShowConfirm(true)} > {t('common.operation.remove')} @@ -357,21 +356,21 @@ const ModelModal: FC<ModelModalProps> = ({ </div> </div> </div> - <div className='border-t-[0.5px] border-t-black/5'> + <div className='border-t-[0.5px] border-t-divider-regular'> { (validatedStatusState.status === ValidatedStatus.Error && validatedStatusState.message) ? ( - <div className='flex px-[10px] py-3 bg-[#FEF3F2] text-xs text-[#D92D20]'> + <div className='flex px-[10px] py-3 bg-background-section-burn text-xs text-[#D92D20]'> <RiErrorWarningFill className='mt-[1px] mr-2 w-[14px] h-[14px]' /> {validatedStatusState.message} </div> ) : ( - <div className='flex justify-center items-center py-3 bg-gray-50 text-xs text-gray-500'> - <Lock01 className='mr-1 w-3 h-3 text-gray-500' /> + <div className='flex justify-center items-center py-3 bg-background-section-burn text-xs text-text-tertiary'> + <Lock01 className='mr-1 w-3 h-3 text-text-tertiary' /> {t('common.modelProvider.encrypted.front')} <a - className='text-primary-600 mx-1' + className='text-text-accent mx-1' target='_blank' rel='noopener noreferrer' href='https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html' > diff --git a/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx index 379a9f41ca..a14a22bb35 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx @@ -37,43 +37,45 @@ const ModelName: FC<ModelNameProps> = ({ if (!modelItem) return null return ( - <div className={cn('flex items-center truncate text-components-input-text-filled system-sm-regular', className)}> + <div className={cn('flex gap-0.5 items-center overflow-hidden text-ellipsis truncate text-components-input-text-filled system-sm-regular', className)}> <div className='truncate' title={modelItem.label[language] || modelItem.label.en_US} > {modelItem.label[language] || modelItem.label.en_US} </div> - { - showModelType && modelItem.model_type && ( - <ModelBadge className={cn('ml-1', modelTypeClassName)}> - {modelTypeFormat(modelItem.model_type)} - </ModelBadge> - ) - } - { - modelItem.model_properties.mode && showMode && ( - <ModelBadge className={cn('ml-1', modeClassName)}> - {(modelItem.model_properties.mode as string).toLocaleUpperCase()} - </ModelBadge> - ) - } - { - showFeatures && modelItem.features?.map(feature => ( - <FeatureIcon - key={feature} - feature={feature} - className={featuresClassName} - /> - )) - } - { - showContextSize && modelItem.model_properties.context_size && ( - <ModelBadge className='ml-1'> - {sizeFormat(modelItem.model_properties.context_size as number)} - </ModelBadge> - ) - } + <div className='flex items-center gap-0.5'> + { + showModelType && modelItem.model_type && ( + <ModelBadge className={modelTypeClassName}> + {modelTypeFormat(modelItem.model_type)} + </ModelBadge> + ) + } + { + modelItem.model_properties.mode && showMode && ( + <ModelBadge className={modeClassName}> + {(modelItem.model_properties.mode as string).toLocaleUpperCase()} + </ModelBadge> + ) + } + { + showFeatures && modelItem.features?.map(feature => ( + <FeatureIcon + key={feature} + feature={feature} + className={featuresClassName} + /> + )) + } + { + showContextSize && modelItem.model_properties.context_size && ( + <ModelBadge> + {sizeFormat(modelItem.model_properties.context_size as number)} + </ModelBadge> + ) + } + </div> {children} </div> ) diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger.tsx new file mode 100644 index 0000000000..c78b4a98c6 --- /dev/null +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger.tsx @@ -0,0 +1,186 @@ +import type { FC } from 'react' +import { useEffect, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import type { + ModelItem, + ModelProvider, +} from '../declarations' +import { + CustomConfigurationStatusEnum, + ModelTypeEnum, +} from '../declarations' +import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types' +import { useInvalidateInstalledPluginList } from '@/service/use-plugins' +import ConfigurationButton from './configuration-button' +import Loading from '@/app/components/base/loading' +import { PluginType } from '@/app/components/plugins/types' +import { + useModelModalHandler, + useUpdateModelList, + useUpdateModelProviders, +} from '../hooks' +import ModelIcon from '../model-icon' +import ModelDisplay from './model-display' +import { InstallPluginButton } from '@/app/components/workflow/nodes/_base/components/install-plugin-button' +import StatusIndicators from './status-indicators' +import cn from '@/utils/classnames' +import { useProviderContext } from '@/context/provider-context' +import { RiEqualizer2Line } from '@remixicon/react' +import { fetchPluginInfoFromMarketPlace } from '@/service/plugins' +import { fetchModelProviderModelList } from '@/service/common' + +export type AgentModelTriggerProps = { + open?: boolean + disabled?: boolean + currentProvider?: ModelProvider + currentModel?: ModelItem + providerName?: string + modelId?: string + hasDeprecated?: boolean + scope?: string +} + +const AgentModelTrigger: FC<AgentModelTriggerProps> = ({ + disabled, + currentProvider, + currentModel, + providerName, + modelId, + hasDeprecated, + scope, +}) => { + const { t } = useTranslation() + const { modelProviders } = useProviderContext() + const updateModelProviders = useUpdateModelProviders() + const updateModelList = useUpdateModelList() + const { modelProvider, needsConfiguration } = useMemo(() => { + const modelProvider = modelProviders.find(item => item.provider === providerName) + const needsConfiguration = modelProvider?.custom_configuration.status === CustomConfigurationStatusEnum.noConfigure && !( + modelProvider.system_configuration.enabled === true + && modelProvider.system_configuration.quota_configurations.find( + item => item.quota_type === modelProvider.system_configuration.current_quota_type, + ) + ) + return { + modelProvider, + needsConfiguration, + } + }, [modelProviders, providerName]) + const [pluginInfo, setPluginInfo] = useState<PluginInfoFromMarketPlace | null>(null) + const [isPluginChecked, setIsPluginChecked] = useState(false) + const [installed, setInstalled] = useState(false) + const [inModelList, setInModelList] = useState(false) + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + const handleOpenModal = useModelModalHandler() + + useEffect(() => { + (async () => { + if (modelId && currentProvider) { + try { + const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${currentProvider?.provider}/models`) + if (modelId && modelsData.data.find(item => item.model === modelId)) + setInModelList(true) + } + catch (error) { + // pass + } + } + if (providerName) { + const parts = providerName.split('/') + const org = parts[0] + const name = parts[1] + try { + const pluginInfo = await fetchPluginInfoFromMarketPlace({ org, name }) + if (pluginInfo.data.plugin.category === PluginType.model) + setPluginInfo(pluginInfo.data.plugin) + } + catch (error) { + // pass + } + } + setIsPluginChecked(true) + })() + }, [providerName, modelId, currentProvider]) + + if (modelId && !isPluginChecked) + return <Loading /> + + return ( + <div + className={cn( + 'relative group flex items-center p-1 gap-[2px] flex-grow rounded-lg bg-components-input-bg-normal cursor-pointer hover:bg-state-base-hover-alt', + )} + > + {modelId ? ( + <> + <ModelIcon + className='p-0.5' + provider={currentProvider || modelProvider} + modelName={currentModel?.model || modelId} + isDeprecated={hasDeprecated} + /> + <ModelDisplay + currentModel={currentModel} + modelId={modelId} + /> + {needsConfiguration && ( + <ConfigurationButton + modelProvider={modelProvider} + handleOpenModal={handleOpenModal} + /> + )} + <StatusIndicators + needsConfiguration={needsConfiguration} + modelProvider={!!modelProvider} + inModelList={inModelList} + disabled={!!disabled} + pluginInfo={pluginInfo} + t={t} + /> + {!installed && !modelProvider && pluginInfo && ( + <InstallPluginButton + onClick={e => e.stopPropagation()} + size={'small'} + uniqueIdentifier={pluginInfo.latest_package_identifier} + onSuccess={() => { + [ + ModelTypeEnum.textGeneration, + ModelTypeEnum.textEmbedding, + ModelTypeEnum.rerank, + ModelTypeEnum.moderation, + ModelTypeEnum.speech2text, + ModelTypeEnum.tts, + ].forEach((type: ModelTypeEnum) => { + if (scope?.includes(type)) + updateModelList(type) + }, + ) + updateModelProviders() + invalidateInstalledPluginList() + setInstalled(true) + }} + /> + )} + {modelProvider && !disabled && !needsConfiguration && ( + <div className="flex pr-1 items-center"> + <RiEqualizer2Line className="w-4 h-4 text-text-tertiary group-hover:text-text-secondary" /> + </div> + )} + </> + ) : ( + <> + <div className="flex p-1 pl-2 items-center gap-1 grow"> + <span className="overflow-hidden text-ellipsis whitespace-nowrap system-sm-regular text-components-input-text-placeholder"> + {t('workflow.nodes.agent.configureModel')} + </span> + </div> + <div className="flex pr-1 items-center"> + <RiEqualizer2Line className="w-4 h-4 text-text-tertiary group-hover:text-text-secondary" /> + </div> + </> + )} + </div> + ) +} + +export default AgentModelTrigger diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/configuration-button.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/configuration-button.tsx new file mode 100644 index 0000000000..0cc0f1be8e --- /dev/null +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/configuration-button.tsx @@ -0,0 +1,32 @@ +import Button from '@/app/components/base/button' +import { ConfigurationMethodEnum } from '../declarations' +import { useTranslation } from 'react-i18next' + +type ConfigurationButtonProps = { + modelProvider: any + handleOpenModal: any +} + +const ConfigurationButton = ({ modelProvider, handleOpenModal }: ConfigurationButtonProps) => { + const { t } = useTranslation() + return ( + <Button + size="small" + className="z-[100]" + onClick={(e) => { + e.stopPropagation() + handleOpenModal(modelProvider, ConfigurationMethodEnum.predefinedModel, undefined) + }} + > + <div className="flex px-[3px] justify-center items-center gap-1"> + {t('workflow.nodes.agent.notAuthorized')} + </div> + <div className="flex w-[14px] h-[14px] justify-center items-center"> + <div className="w-2 h-2 shrink-0 rounded-[3px] border border-components-badge-status-light-warning-border-inner + bg-components-badge-status-light-warning-bg shadow-components-badge-status-light-warning-halo" /> + </div> + </Button> + ) +} + +export default ConfigurationButton diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx index e21aa33d7a..5457b0e677 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/index.tsx @@ -48,6 +48,7 @@ export type ModelParameterModalProps = { renderTrigger?: (v: TriggerProps) => ReactNode readonly?: boolean isInWorkflow?: boolean + scope?: string } const stopParameterRule: ModelParameterRule = { default: [], @@ -68,7 +69,7 @@ const stopParameterRule: ModelParameterRule = { }, } -const PROVIDER_WITH_PRESET_TONE = ['openai', 'azure_openai'] +const PROVIDER_WITH_PRESET_TONE = ['langgenius/openai/openai', 'langgenius/azure_openai/azure_openai'] const ModelParameterModal: FC<ModelParameterModalProps> = ({ popupClassName, portalToFollowElemContentClassName, @@ -84,6 +85,7 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({ renderTrigger, readonly, isInWorkflow, + scope = 'text-generation', }) => { const { t } = useTranslation() const { isAPIKeySet } = useProviderContext() @@ -190,26 +192,22 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({ ) } </PortalToFollowElemTrigger> - <PortalToFollowElemContent className={cn(portalToFollowElemContentClassName, 'z-[60]')}> - <div className={cn(popupClassName, 'w-[496px] rounded-xl border border-gray-100 bg-white shadow-xl')}> - <div className={cn( - 'max-h-[480px] overflow-y-auto', - !isInWorkflow && 'px-10 pt-6 pb-8', - isInWorkflow && 'p-4')}> - <div className='flex items-center justify-between h-8'> - <div className={cn('font-semibold text-gray-900 shrink-0', isInWorkflow && 'text-[13px]')}> + <PortalToFollowElemContent className={cn('z-[60]', portalToFollowElemContentClassName)}> + <div className={cn(popupClassName, 'w-[389px] rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg')}> + <div className={cn('max-h-[420px] p-4 pt-3 overflow-y-auto')}> + <div className='relative'> + <div className={cn('mb-1 h-6 flex items-center text-text-secondary system-sm-semibold')}> {t('common.modelProvider.model').toLocaleUpperCase()} </div> <ModelSelector defaultModel={(provider || modelId) ? { provider, model: modelId } : undefined} modelList={activeTextGenerationModelList} onSelect={handleChangeModel} - triggerClassName='max-w-[295px]' /> </div> { !!parameterRules.length && ( - <div className='my-5 h-[1px] bg-gray-100' /> + <div className='my-3 h-[1px] bg-divider-subtle' /> ) } { @@ -219,8 +217,8 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({ } { !isLoading && !!parameterRules.length && ( - <div className='flex items-center justify-between mb-4'> - <div className={cn('font-semibold text-gray-900', isInWorkflow && 'text-[13px]')}>{t('common.modelProvider.parameters')}</div> + <div className='flex items-center justify-between mb-2'> + <div className={cn('h-6 flex items-center text-text-secondary system-sm-semibold')}>{t('common.modelProvider.parameters')}</div> { PROVIDER_WITH_PRESET_TONE.includes(provider) && ( <PresetsParameter onSelect={handleSelectPresetParameter} /> @@ -237,7 +235,6 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({ ].map(parameter => ( <ParameterItem key={`${modelId}-${parameter.name}`} - className='mb-4' parameterRule={parameter} value={completionParams?.[parameter.name]} onChange={v => handleParamChange(parameter.name, v)} @@ -250,7 +247,7 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({ </div> {!hideDebugWithMultipleModel && ( <div - className='flex items-center justify-between px-6 h-[50px] bg-gray-50 border-t border-t-gray-100 text-xs font-medium text-primary-600 cursor-pointer rounded-b-xl' + className='flex items-center justify-between px-4 h-[50px] bg-components-section-burn border-t border-t-divider-subtle system-sm-regular text-text-accent cursor-pointer rounded-b-xl' onClick={() => onDebugWithMultipleModelChange?.()} > { diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/model-display.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/model-display.tsx new file mode 100644 index 0000000000..6f586c1f6f --- /dev/null +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/model-display.tsx @@ -0,0 +1,25 @@ +import ModelName from '../model-name' + +type ModelDisplayProps = { + currentModel: any + modelId: string +} + +const ModelDisplay = ({ currentModel, modelId }: ModelDisplayProps) => { + return currentModel ? ( + <ModelName + className="flex px-1 py-[3px] items-center gap-1 grow" + modelItem={currentModel} + showMode + showFeatures + /> + ) : ( + <div className="flex py-[3px] px-1 items-center gap-1 grow opacity-50 truncate"> + <div className="text-components-input-text-filled text-ellipsis overflow-hidden system-sm-regular"> + {modelId} + </div> + </div> + ) +} + +export default ModelDisplay diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx index 376a08c120..f43598fc38 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx @@ -17,7 +17,6 @@ type ParameterItemProps = { parameterRule: ModelParameterRule value?: ParameterValue onChange?: (value: ParameterValue) => void - className?: string onSwitch?: (checked: boolean, assignValue: ParameterValue) => void isInWorkflow?: boolean } @@ -25,7 +24,6 @@ const ParameterItem: FC<ParameterItemProps> = ({ parameterRule, value, onChange, - className, onSwitch, isInWorkflow, }) => { @@ -150,7 +148,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ />} <input ref={numberInputRef} - className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900' + className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-components-input-bg-normal text-components-input-text-filled system-sm-regular' type='number' max={parameterRule.max} min={parameterRule.min} @@ -175,7 +173,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ />} <input ref={numberInputRef} - className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900' + className='shrink-0 block ml-4 pl-3 w-16 h-8 appearance-none outline-none rounded-lg bg-components-input-bg-normal text-components-input-text-filled system-sm-regular' type='number' max={parameterRule.max} min={parameterRule.min} @@ -190,12 +188,12 @@ const ParameterItem: FC<ParameterItemProps> = ({ if (parameterRule.type === 'boolean') { return ( <Radio.Group - className='w-[200px] flex items-center' + className='w-[178px] flex items-center' value={renderValue ? 1 : 0} onChange={handleRadioChange} > - <Radio value={1} className='!mr-1 w-[94px]'>True</Radio> - <Radio value={0} className='w-[94px]'>False</Radio> + <Radio value={1} className='w-[83px]'>True</Radio> + <Radio value={0} className='w-[83px]'>False</Radio> </Radio.Group> ) } @@ -203,7 +201,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ if (parameterRule.type === 'string' && !parameterRule.options?.length) { return ( <input - className={cn(isInWorkflow ? 'w-[200px]' : 'w-full', 'ml-4 flex items-center px-3 h-8 appearance-none outline-none rounded-lg bg-gray-100 text-[13px] text-gra-900')} + className={cn(isInWorkflow ? 'w-[178px]' : 'w-full', 'ml-4 flex items-center px-3 h-8 appearance-none outline-none rounded-lg bg-components-input-bg-normal text-components-input-text-filled system-sm-regular')} value={renderValue as string} onChange={handleStringInputChange} /> @@ -213,7 +211,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ if (parameterRule.type === 'text') { return ( <textarea - className='w-full h-20 ml-4 px-1 rounded-lg bg-gray-100 outline-none text-[12px] text-gray-900' + className='w-full h-20 ml-4 px-1 rounded-lg bg-components-input-bg-normal text-components-input-text-filled system-sm-regular' value={renderValue as string} onChange={handleStringInputChange} /> @@ -224,7 +222,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ return ( <SimpleSelect className='!py-0' - wrapperClassName={cn(isInWorkflow ? '!w-[200px]' : 'w-full', 'ml-4 !h-8')} + wrapperClassName={cn('w-full !h-8')} defaultValue={renderValue as string} onSelect={handleSelect} items={parameterRule.options.map(option => ({ value: option, name: option }))} @@ -234,7 +232,7 @@ const ParameterItem: FC<ParameterItemProps> = ({ if (parameterRule.type === 'tag') { return ( - <div className={cn(isInWorkflow ? 'w-[200px]' : 'w-full', 'ml-4')}> + <div className={cn('w-full !h-8')}> <TagInput items={renderValue as string[]} onChange={handleTagChange} @@ -249,11 +247,22 @@ const ParameterItem: FC<ParameterItemProps> = ({ } return ( - <div className={`flex items-center justify-between ${className}`}> - <div> - <div className={cn(isInWorkflow ? 'w-[140px]' : 'w-full', 'ml-4 shrink-0 flex items-center')}> + <div className='flex items-center justify-between mb-2'> + <div className='shrink-0 basis-1/2'> + <div className={cn('shrink-0 w-full flex items-center')}> + { + !parameterRule.required && parameterRule.name !== 'stop' && ( + <div className='mr-2 w-7'> + <Switch + defaultValue={!isNullOrUndefined(value)} + onChange={handleSwitch} + size='md' + /> + </div> + ) + } <div - className='mr-0.5 text-[13px] font-medium text-gray-700 truncate' + className='mr-0.5 system-xs-regular text-text-secondary truncate' title={parameterRule.label[language] || parameterRule.label.en_US} > {parameterRule.label[language] || parameterRule.label.en_US} @@ -262,27 +271,17 @@ const ParameterItem: FC<ParameterItemProps> = ({ parameterRule.help && ( <Tooltip popupContent={( - <div className='w-[200px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div> + <div className='w-[178px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div> )} popupClassName='mr-1' triggerClassName='mr-1 w-4 h-4 shrink-0' /> ) } - { - !parameterRule.required && parameterRule.name !== 'stop' && ( - <Switch - className='mr-1' - defaultValue={!isNullOrUndefined(value)} - onChange={handleSwitch} - size='md' - /> - ) - } </div> { parameterRule.type === 'tag' && ( - <div className={cn(!isInWorkflow && 'w-[200px]', 'text-gray-400 text-xs font-normal')}> + <div className={cn(!isInWorkflow && 'w-[178px]', 'text-text-tertiary system-xs-regular')}> {parameterRule?.tagPlaceholder?.[language]} </div> ) diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/presets-parameter.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/presets-parameter.tsx index de5061ef45..0d9e90853e 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/presets-parameter.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/presets-parameter.tsx @@ -2,12 +2,13 @@ import type { FC } from 'react' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { RiArrowDownSLine } from '@remixicon/react' +import Button from '@/app/components/base/button' import Dropdown from '@/app/components/base/dropdown' -import { SlidersH } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' import { Brush01 } from '@/app/components/base/icons/src/vender/solid/editor' import { Scales02 } from '@/app/components/base/icons/src/vender/solid/FinanceAndECommerce' import { Target04 } from '@/app/components/base/icons/src/vender/solid/general' import { TONE_LIST } from '@/config' +import cn from '@/utils/classnames' type PresetsParameterProps = { onSelect: (toneId: number) => void @@ -18,19 +19,16 @@ const PresetsParameter: FC<PresetsParameterProps> = ({ const { t } = useTranslation() const renderTrigger = useCallback((open: boolean) => { return ( - <div - className={` - flex items-center px-[7px] h-7 rounded-md border-[0.5px] border-gray-200 shadow-xs - text-xs font-medium text-gray-700 cursor-pointer - ${open && 'bg-gray-100'} - `} + <Button + size={'small'} + variant={'secondary'} + className={cn(open && 'bg-state-base-hover')} > - <SlidersH className='mr-[5px] w-3.5 h-3.5 text-gray-500' /> {t('common.modelProvider.loadPresets')} - <RiArrowDownSLine className='ml-0.5 w-3.5 h-3.5 text-gray-500' /> - </div> + <RiArrowDownSLine className='ml-0.5 w-3.5 h-3.5' /> + </Button> ) - }, []) + }, [t]) const getToneIcon = (toneId: number) => { const className = 'mr-2 w-[14px] h-[14px]' const res = ({ diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/status-indicators.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/status-indicators.tsx new file mode 100644 index 0000000000..9f3543a475 --- /dev/null +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/status-indicators.tsx @@ -0,0 +1,99 @@ +import Tooltip from '@/app/components/base/tooltip' +import Link from 'next/link' +import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version' +import { useInstalledPluginList } from '@/service/use-plugins' +import { RiErrorWarningFill } from '@remixicon/react' + +type StatusIndicatorsProps = { + needsConfiguration: boolean + modelProvider: boolean + inModelList: boolean + disabled: boolean + pluginInfo: any + t: any +} + +const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disabled, pluginInfo, t }: StatusIndicatorsProps) => { + const { data: pluginList } = useInstalledPluginList() + const renderTooltipContent = (title: string, description?: string, linkText?: string, linkHref?: string) => { + return ( + <div className='flex w-[240px] max-w-[240px] gap-1 flex-col px-1 py-1.5' onClick={e => e.stopPropagation()}> + <div className='text-text-primary title-xs-semi-bold'>{title}</div> + {description && ( + <div className='min-w-[200px] text-text-secondary body-xs-regular'> + {description} + </div> + )} + {linkText && linkHref && ( + <div className='text-text-accent body-xs-regular cursor-pointer z-[100]'> + <Link + href={linkHref} + onClick={(e) => { + e.stopPropagation() + }} + > + {linkText} + </Link> + </div> + )} + </div> + ) + } + // const installedPluginUniqueIdentifier = pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier + return ( + <> + {/* plugin installed and model is in model list but disabled */} + {/* plugin installed from github/local and model is not in model list */} + {!needsConfiguration && modelProvider && disabled && ( + <> + {inModelList ? ( + <Tooltip + popupContent={t('workflow.nodes.agent.modelSelectorTooltips.deprecated')} + asChild={false} + needsDelay={false} + > + <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> + </Tooltip> + ) : !pluginInfo ? ( + <Tooltip + popupContent={renderTooltipContent( + t('workflow.nodes.agent.modelNotSupport.title'), + t('workflow.nodes.agent.modelNotSupport.desc'), + t('workflow.nodes.agent.linkToPlugin'), + '/plugins', + )} + asChild={false} + needsDelay={true} + > + <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> + </Tooltip> + ) : ( + <SwitchPluginVersion + tooltip={renderTooltipContent( + t('workflow.nodes.agent.modelNotSupport.title'), + t('workflow.nodes.agent.modelNotSupport.descForVersionSwitch'), + )} + uniqueIdentifier={pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier ?? ''} + /> + )} + </> + )} + {!modelProvider && !pluginInfo && ( + <Tooltip + popupContent={renderTooltipContent( + t('workflow.nodes.agent.modelNotInMarketplace.title'), + t('workflow.nodes.agent.modelNotInMarketplace.desc'), + t('workflow.nodes.agent.linkToPlugin'), + '/plugins', + )} + asChild={false} + needsDelay + > + <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> + </Tooltip> + )} + </> + ) +} + +export default StatusIndicators diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx index ba632179d1..2fbc517ec1 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx @@ -46,8 +46,8 @@ const Trigger: FC<TriggerProps> = ({ className={cn( 'relative flex items-center px-2 h-8 rounded-lg cursor-pointer', !isInWorkflow && 'border hover:border-[1.5px]', - !isInWorkflow && (disabled ? 'border-[#F79009] bg-[#FFFAEB]' : 'border-[#444CE7] bg-primary-50'), - isInWorkflow && 'pr-[30px] bg-gray-100 border border-gray-100 hover:border-gray-200', + !isInWorkflow && (disabled ? 'border-[#F79009] bg-components-input-bg-disabled' : 'border-[#444CE7] bg-components-input-bg-normal'), + isInWorkflow && 'pr-[30px] bg-components-input-bg-normal border border-components-input-border-hover hover:border-components-input-border-hover', )} > { @@ -71,18 +71,16 @@ const Trigger: FC<TriggerProps> = ({ { currentModel && ( <ModelName - className='mr-1.5 text-gray-900' + className='mr-1.5 text-text-primary' modelItem={currentModel} showMode - modeClassName={cn(!isInWorkflow ? '!text-[#444CE7] !border-[#A4BCFD]' : '!text-gray-500 !border-black/8')} showFeatures - featuresClassName={cn(!isInWorkflow ? '!text-[#444CE7] !border-[#A4BCFD]' : '!text-gray-500 !border-black/8')} /> ) } { !currentModel && ( - <div className='mr-1 text-[13px] font-medium text-gray-900 truncate'> + <div className='mr-1 text-[13px] font-medium text-text-primary truncate'> {modelId} </div> ) @@ -103,10 +101,10 @@ const Trigger: FC<TriggerProps> = ({ </Tooltip> ) : ( - <SlidersH className={cn(!isInWorkflow ? 'text-indigo-600' : 'text-gray-500', 'shrink-0 w-4 h-4')} /> + <SlidersH className={cn(!isInWorkflow ? 'text-indigo-600' : 'text-text-tertiary', 'shrink-0 w-4 h-4')} /> ) } - {isInWorkflow && (<RiArrowDownSLine className='absolute top-[9px] right-2 w-3.5 h-3.5 text-gray-500' />)} + {isInWorkflow && (<RiArrowDownSLine className='absolute top-[9px] right-2 w-3.5 h-3.5 text-text-tertiary' />)} </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx index f40423d869..069e026b64 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx @@ -4,16 +4,21 @@ import ModelIcon from '../model-icon' import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' import { useProviderContext } from '@/context/provider-context' import Tooltip from '@/app/components/base/tooltip' +import cn from '@/utils/classnames' type ModelTriggerProps = { modelName: string providerName: string className?: string + showWarnIcon?: boolean + contentClassName?: string } const ModelTrigger: FC<ModelTriggerProps> = ({ modelName, providerName, className, + showWarnIcon, + contentClassName, }) => { const { t } = useTranslation() const { modelProviders } = useProviderContext() @@ -21,23 +26,26 @@ const ModelTrigger: FC<ModelTriggerProps> = ({ return ( <div - className={` - group flex items-center px-2 h-8 rounded-lg bg-[#FFFAEB] cursor-pointer - ${className} - `} + className={cn('group flex flex-grow box-content items-center p-[3px] pl-1 h-8 gap-1 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)} > - <ModelIcon - className='shrink-0 mr-1.5' - provider={currentProvider} - modelName={modelName} - /> - <div className='mr-1 text-[13px] font-medium text-gray-800 truncate'> - {modelName} - </div> - <div className='shrink-0 flex items-center justify-center w-4 h-4'> - <Tooltip popupContent={t('common.modelProvider.deprecated')}> - <AlertTriangle className='w-4 h-4 text-[#F79009]' /> - </Tooltip> + <div className={cn('flex items-center w-full', contentClassName)}> + <div className='flex items-center py-[1px] gap-1 min-w-0 flex-1'> + <ModelIcon + className="w-4 h-4" + provider={currentProvider} + modelName={modelName} + /> + <div className='system-sm-regular text-components-input-text-filled truncate'> + {modelName} + </div> + </div> + <div className='shrink-0 flex items-center justify-center'> + {showWarnIcon && ( + <Tooltip popupContent={t('common.modelProvider.deprecated')}> + <AlertTriangle className='w-4 h-4 text-text-warning-secondary' /> + </Tooltip> + )} + </div> </div> </div> ) diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/empty-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/empty-trigger.tsx index 0c6d3efa39..980e4e3784 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/empty-trigger.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/empty-trigger.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react' import { RiArrowDownSLine } from '@remixicon/react' import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes' +import cn from '@/utils/classnames' type ModelTriggerProps = { open: boolean @@ -12,25 +13,24 @@ const ModelTrigger: FC<ModelTriggerProps> = ({ }) => { return ( <div - className={` - flex items-center px-2 h-8 rounded-lg bg-gray-100 hover:bg-gray-200 cursor-pointer - ${className} - ${open && '!bg-gray-200'} - `} + className={cn( + 'flex items-center p-1 gap-0.5 rounded-lg bg-components-input-bg-normal hover:bg-components-input-bg-hover cursor-pointer', open && 'bg-components-input-bg-hover', + className, + )} > <div className='grow flex items-center'> - <div className='mr-1.5 flex items-center justify-center w-4 h-4 rounded-[5px] border border-dashed border-black/5'> - <CubeOutline className='w-3 h-3 text-gray-400' /> + <div className='mr-1.5 flex items-center justify-center w-4 h-4 rounded-[5px] border border-dashed border-divider-regular'> + <CubeOutline className='w-3 h-3 text-text-quaternary' /> </div> <div - className='text-[13px] text-gray-500 truncate' + className='text-[13px] text-text-tertiary truncate' title='Select model' > Select model </div> </div> <div className='shrink-0 flex items-center justify-center w-4 h-4'> - <RiArrowDownSLine className='w-3.5 h-3.5 text-gray-500' /> + <RiArrowDownSLine className='w-3.5 h-3.5 text-text-tertiary' /> </div> </div> ) diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx index 32bd58d318..9c7a9788ef 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx @@ -6,10 +6,13 @@ import { ModelFeatureTextEnum, } from '../declarations' import { + AudioSupportIcon, + DocumentSupportIcon, // MagicBox, MagicEyes, // MagicWand, // Robot, + VideoSupportIcon, } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' import Tooltip from '@/app/components/base/tooltip' @@ -65,7 +68,7 @@ const FeatureIcon: FC<FeatureIconProps> = ({ popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.vision })} > <div className='inline-block cursor-help'> - <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}> + <ModelBadge className={`!px-0 w-[18px] justify-center text-text-tertiary ${className}`}> <MagicEyes className='w-3 h-3' /> </ModelBadge> </div> @@ -73,6 +76,48 @@ const FeatureIcon: FC<FeatureIconProps> = ({ ) } + if (feature === ModelFeatureEnum.document) { + return ( + <Tooltip + popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.document })} + > + <div className='inline-block cursor-help'> + <ModelBadge className={`!px-0 w-[18px] justify-center text-text-tertiary ${className}`}> + <DocumentSupportIcon className='w-3 h-3' /> + </ModelBadge> + </div> + </Tooltip> + ) + } + + if (feature === ModelFeatureEnum.audio) { + return ( + <Tooltip + popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.audio })} + > + <div className='inline-block cursor-help'> + <ModelBadge className={`!px-0 w-[18px] justify-center text-text-tertiary ${className}`}> + <AudioSupportIcon className='w-3 h-3' /> + </ModelBadge> + </div> + </Tooltip> + ) + } + + if (feature === ModelFeatureEnum.video) { + return ( + <Tooltip + popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.video })} + > + <div className='inline-block cursor-help'> + <ModelBadge className={`!px-0 w-[18px] justify-center text-text-tertiary ${className}`}> + <VideoSupportIcon className='w-3 h-3' /> + </ModelBadge> + </div> + </Tooltip> + ) + } + return null } diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx index c6dd76a04f..d28959a509 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/index.tsx @@ -15,6 +15,7 @@ import { PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' +import classNames from '@/utils/classnames' type ModelSelectorProps = { defaultModel?: DefaultModel @@ -23,6 +24,9 @@ type ModelSelectorProps = { popupClassName?: string onSelect?: (model: DefaultModel) => void readonly?: boolean + scopeFeatures?: string[] + deprecatedClassName?: string + showDeprecatedWarnIcon?: boolean } const ModelSelector: FC<ModelSelectorProps> = ({ defaultModel, @@ -31,6 +35,9 @@ const ModelSelector: FC<ModelSelectorProps> = ({ popupClassName, onSelect, readonly, + scopeFeatures = [], + deprecatedClassName, + showDeprecatedWarnIcon = false, }) => { const [open, setOpen] = useState(false) const { @@ -62,7 +69,7 @@ const ModelSelector: FC<ModelSelectorProps> = ({ placement='bottom-start' offset={4} > - <div className='relative'> + <div className={classNames('relative')}> <PortalToFollowElemTrigger onClick={handleToggle} className='block' @@ -84,6 +91,8 @@ const ModelSelector: FC<ModelSelectorProps> = ({ modelName={defaultModel?.model || ''} providerName={defaultModel?.provider || ''} className={triggerClassName} + showWarnIcon={showDeprecatedWarnIcon} + contentClassName={deprecatedClassName} /> ) } @@ -101,6 +110,8 @@ const ModelSelector: FC<ModelSelectorProps> = ({ defaultModel={defaultModel} modelList={modelList} onSelect={handleSelect} + scopeFeatures={scopeFeatures} + onHide={() => setOpen(false)} /> </PortalToFollowElemContent> </div> diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx index 556a2ef66f..009887acd7 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx @@ -13,7 +13,7 @@ import ModelIcon from '../model-icon' import ModelName from '../model-name' import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' import Tooltip from '@/app/components/base/tooltip' -import classNames from '@/utils/classnames' +import cn from '@/utils/classnames' type ModelTriggerProps = { open: boolean @@ -33,42 +33,44 @@ const ModelTrigger: FC<ModelTriggerProps> = ({ return ( <div - className={classNames( - 'group flex items-center px-2 h-8 rounded-lg bg-components-input-bg-normal', + className={cn( + 'group flex items-center p-1 h-8 gap-0.5 rounded-lg bg-components-input-bg-normal', !readonly && 'hover:bg-components-input-bg-hover cursor-pointer', + open && 'bg-components-input-bg-hover', + model.status !== ModelStatusEnum.active && 'bg-components-input-bg-disabled hover:bg-components-input-bg-disabled', className, - open && '!bg-components-input-bg-hover', - model.status !== ModelStatusEnum.active && '!bg-[#FFFAEB]', )} > <ModelIcon - className='shrink-0 mr-1.5' + className='p-0.5' provider={provider} modelName={model.model} /> - <ModelName - className='grow' - modelItem={model} - showMode - showFeatures - /> - {!readonly && ( - <div className='shrink-0 flex items-center justify-center w-4 h-4'> - { - model.status !== ModelStatusEnum.active - ? ( - <Tooltip popupContent={MODEL_STATUS_TEXT[model.status][language]}> - <AlertTriangle className='w-4 h-4 text-[#F79009]' /> - </Tooltip> - ) - : ( - <RiArrowDownSLine - className='w-3.5 h-3.5 text-gray-500' - /> - ) - } - </div> - )} + <div className='flex px-1 py-[3px] items-center gap-1 grow truncate'> + <ModelName + className='grow' + modelItem={model} + showMode + showFeatures + /> + {!readonly && ( + <div className='shrink-0 flex items-center justify-center w-4 h-4'> + { + model.status !== ModelStatusEnum.active + ? ( + <Tooltip popupContent={MODEL_STATUS_TEXT[model.status][language]}> + <AlertTriangle className='w-4 h-4 text-text-warning-secondary' /> + </Tooltip> + ) + : ( + <RiArrowDownSLine + className='w-3.5 h-3.5 text-text-tertiary' + /> + ) + } + </div> + )} + </div> </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx index d62131ac4c..d9cdb26431 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx @@ -1,10 +1,25 @@ import type { FC } from 'react' import { useTranslation } from 'react-i18next' +import { + RiFileTextLine, + RiFilmAiLine, + RiImageCircleAiLine, + RiVoiceAiFill, +} from '@remixicon/react' import type { DefaultModel, Model, ModelItem, } from '../declarations' +import { + ModelFeatureEnum, + ModelFeatureTextEnum, + ModelTypeEnum, +} from '../declarations' +import { + modelTypeFormat, + sizeFormat, +} from '../utils' import { useLanguage, useUpdateModelList, @@ -12,15 +27,16 @@ import { } from '../hooks' import ModelIcon from '../model-icon' import ModelName from '../model-name' +import ModelBadge from '../model-badge' import { ConfigurationMethodEnum, - MODEL_STATUS_TEXT, ModelStatusEnum, } from '../declarations' import { Check } from '@/app/components/base/icons/src/vender/line/general' import { useModalContext } from '@/context/modal-context' import { useProviderContext } from '@/context/provider-context' import Tooltip from '@/app/components/base/tooltip' +import cn from '@/utils/classnames' type PopupItemProps = { defaultModel?: DefaultModel @@ -64,50 +80,104 @@ const PopupItem: FC<PopupItemProps> = ({ return ( <div className='mb-1'> - <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'> + <div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'> {model.label[language] || model.label.en_US} </div> { model.models.map(modelItem => ( <Tooltip key={modelItem.model} - popupContent={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined} position='right' + popupClassName='p-3 !w-[206px] bg-components-panel-bg-blur backdrop-blur-sm border-[0.5px] border-components-panel-border rounded-xl' + popupContent={ + <div className='flex flex-col gap-1'> + <div className='flex flex-col items-start gap-2'> + <ModelIcon + className={cn('shrink-0 w-5 h-5')} + provider={model} + modelName={modelItem.model} + /> + <div className='truncate text-text-primary system-md-medium'>{modelItem.label[language] || modelItem.label.en_US}</div> + </div> + {/* {currentProvider?.description && ( + <div className='text-text-tertiary system-xs-regular'>{currentProvider?.description?.[language] || currentProvider?.description?.en_US}</div> + )} */} + <div className='flex flex-wrap gap-1'> + {modelItem.model_type && ( + <ModelBadge> + {modelTypeFormat(modelItem.model_type)} + </ModelBadge> + )} + {modelItem.model_properties.mode && ( + <ModelBadge> + {(modelItem.model_properties.mode as string).toLocaleUpperCase()} + </ModelBadge> + )} + {modelItem.model_properties.context_size && ( + <ModelBadge> + {sizeFormat(modelItem.model_properties.context_size as number)} + </ModelBadge> + )} + </div> + {modelItem.model_type === ModelTypeEnum.textGeneration && modelItem.features?.some(feature => [ModelFeatureEnum.vision, ModelFeatureEnum.audio, ModelFeatureEnum.video, ModelFeatureEnum.document].includes(feature)) && ( + <div className='pt-2'> + <div className='mb-1 text-text-tertiary system-2xs-medium-uppercase'>{t('common.model.capabilities')}</div> + <div className='flex flex-wrap gap-1'> + {modelItem.features?.includes(ModelFeatureEnum.vision) && ( + <ModelBadge> + <RiImageCircleAiLine className='w-3.5 h-3.5 mr-0.5' /> + <span>{ModelFeatureTextEnum.vision}</span> + </ModelBadge> + )} + {modelItem.features?.includes(ModelFeatureEnum.audio) && ( + <ModelBadge> + <RiVoiceAiFill className='w-3.5 h-3.5 mr-0.5' /> + <span>{ModelFeatureTextEnum.audio}</span> + </ModelBadge> + )} + {modelItem.features?.includes(ModelFeatureEnum.video) && ( + <ModelBadge> + <RiFilmAiLine className='w-3.5 h-3.5 mr-0.5' /> + <span>{ModelFeatureTextEnum.video}</span> + </ModelBadge> + )} + {modelItem.features?.includes(ModelFeatureEnum.document) && ( + <ModelBadge> + <RiFileTextLine className='w-3.5 h-3.5 mr-0.5' /> + <span>{ModelFeatureTextEnum.document}</span> + </ModelBadge> + )} + </div> + </div> + )} + </div> + } > <div key={modelItem.model} - className={` - group relative flex items-center px-3 py-1.5 h-8 rounded-lg - ${modelItem.status === ModelStatusEnum.active ? 'cursor-pointer hover:bg-gray-50' : 'cursor-not-allowed hover:bg-gray-50/60'} - `} + className={cn('group relative flex items-center px-3 py-1.5 h-8 rounded-lg gap-1', modelItem.status === ModelStatusEnum.active ? 'cursor-pointer hover:bg-state-base-hover' : 'cursor-not-allowed hover:bg-state-base-hover-alt')} onClick={() => handleSelect(model.provider, modelItem)} > - <ModelIcon - className={` - shrink-0 mr-2 w-4 h-4 - ${modelItem.status !== ModelStatusEnum.active && 'opacity-60'} - `} - provider={model} - modelName={modelItem.model} - /> - <ModelName - className={` - grow text-sm font-normal text-gray-900 - ${modelItem.status !== ModelStatusEnum.active && 'opacity-60'} - `} - modelItem={modelItem} - showMode - showFeatures - /> + <div className='flex items-center gap-2'> + <ModelIcon + className={cn('shrink-0 w-5 h-5')} + provider={model} + modelName={modelItem.model} + /> + <ModelName + className={cn('text-text-secondary system-sm-medium', modelItem.status !== ModelStatusEnum.active && 'opacity-60')} + modelItem={modelItem} + /> + </div> { defaultModel?.model === modelItem.model && defaultModel.provider === currentProvider.provider && ( - <Check className='shrink-0 w-4 h-4 text-primary-600' /> + <Check className='shrink-0 w-4 h-4 text-text-accent' /> ) } { modelItem.status === ModelStatusEnum.noConfigure && ( <div - className='hidden group-hover:block text-xs font-medium text-primary-600 cursor-pointer' + className='hidden group-hover:block text-xs font-medium text-text-accent cursor-pointer' onClick={handleOpenModelModal} > {t('common.operation.add').toLocaleUpperCase()} diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx index 1e43439d15..8de3cbd720 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx @@ -1,6 +1,8 @@ import type { FC } from 'react' -import { useState } from 'react' +import { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' import { + RiArrowRightUpLine, RiSearchLine, } from '@remixicon/react' import type { @@ -8,51 +10,69 @@ import type { Model, ModelItem, } from '../declarations' +import { ModelFeatureEnum } from '../declarations' import { useLanguage } from '../hooks' import PopupItem from './popup-item' import { XCircle } from '@/app/components/base/icons/src/vender/solid/general' +import { useModalContext } from '@/context/modal-context' type PopupProps = { defaultModel?: DefaultModel modelList: Model[] onSelect: (provider: string, model: ModelItem) => void + scopeFeatures?: string[] + onHide: () => void } const Popup: FC<PopupProps> = ({ defaultModel, modelList, onSelect, + scopeFeatures = [], + onHide, }) => { + const { t } = useTranslation() const language = useLanguage() const [searchText, setSearchText] = useState('') + const { setShowAccountSettingModal } = useModalContext() - const filteredModelList = modelList.map((model) => { - const filteredModels = model.models.filter((modelItem) => { - if (modelItem.label[language] !== undefined) - return modelItem.label[language].toLowerCase().includes(searchText.toLowerCase()) - - return Object.values(modelItem.label).some(label => - label.toLowerCase().includes(searchText.toLowerCase()), - ) - }) - - return { ...model, models: filteredModels } - }).filter(model => model.models.length > 0) + const filteredModelList = useMemo(() => { + return modelList.map((model) => { + const filteredModels = model.models + .filter((modelItem) => { + if (modelItem.label[language] !== undefined) + return modelItem.label[language].toLowerCase().includes(searchText.toLowerCase()) + return Object.values(modelItem.label).some(label => + label.toLowerCase().includes(searchText.toLowerCase()), + ) + }) + .filter((modelItem) => { + if (scopeFeatures.length === 0) + return true + return scopeFeatures.every((feature) => { + if (feature === ModelFeatureEnum.toolCall) + return modelItem.features?.some(featureItem => featureItem === ModelFeatureEnum.toolCall || featureItem === ModelFeatureEnum.multiToolCall) + return modelItem.features?.some(featureItem => featureItem === feature) + }) + }) + return { ...model, models: filteredModels } + }).filter(model => model.models.length > 0) + }, [language, modelList, scopeFeatures, searchText]) return ( - <div className='w-[320px] max-h-[480px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg overflow-y-auto'> - <div className='sticky top-0 pl-3 pt-3 pr-2 pb-1 bg-white z-10'> + <div className='w-[320px] max-h-[480px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg overflow-y-auto'> + <div className='sticky top-0 pl-3 pt-3 pr-2 pb-1 bg-components-panel-bg z-10'> <div className={` flex items-center pl-[9px] pr-[10px] h-8 rounded-lg border - ${searchText ? 'bg-white border-gray-300 shadow-xs' : 'bg-gray-100 border-transparent'} + ${searchText ? 'bg-components-input-bg-active border-components-input-border-active shadow-xs' : 'bg-components-input-bg-normal border-transparent'} `}> <RiSearchLine className={` shrink-0 mr-[7px] w-[14px] h-[14px] - ${searchText ? 'text-gray-500' : 'text-gray-400'} + ${searchText ? 'text-text-tertiary' : 'text-text-quaternary'} `} /> <input - className='block grow h-[18px] text-[13px] appearance-none outline-none bg-transparent' + className='block grow h-[18px] text-[13px] text-text-primary appearance-none outline-none bg-transparent' placeholder='Search model' value={searchText} onChange={e => setSearchText(e.target.value)} @@ -60,7 +80,7 @@ const Popup: FC<PopupProps> = ({ { searchText && ( <XCircle - className='shrink-0 ml-1.5 w-[14px] h-[14px] text-gray-400 cursor-pointer' + className='shrink-0 ml-1.5 w-[14px] h-[14px] text-text-quaternary cursor-pointer' onClick={() => setSearchText('')} /> ) @@ -80,12 +100,19 @@ const Popup: FC<PopupProps> = ({ } { !filteredModelList.length && ( - <div className='px-3 py-1.5 leading-[18px] text-center text-xs text-gray-500 break-all'> + <div className='px-3 py-1.5 leading-[18px] text-center text-xs text-text-tertiary break-all'> {`No model found for “${searchText}”`} </div> ) } </div> + <div className='sticky bottom-0 px-4 py-2 flex items-center border-t border-divider-subtle cursor-pointer text-text-accent-light-mode-only bg-components-panel-bg rounded-b-lg' onClick={() => { + onHide() + setShowAccountSettingModal({ payload: 'provider' }) + }}> + <span className='system-xs-medium'>{t('common.model.settingsLink')}</span> + <RiArrowRightUpLine className='ml-0.5 w-3 h-3' /> + </div> </div> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/rerank-trigger.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/rerank-trigger.tsx deleted file mode 100644 index 29afca1196..0000000000 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/rerank-trigger.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { - RiExternalLinkLine, -} from '@remixicon/react' -import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes' - -const ModelTrigger = () => { - return ( - <div className='flex items-center px-2 h-8 rounded-lg bg-gray-100 hover:bg-gray-200 cursor-pointer'> - <div className='grow flex items-center'> - <div className='mr-1.5 flex items-center justify-center w-4 h-4 rounded-[5px] border-dashed border-black/5'> - <CubeOutline className='w-[11px] h-[11px] text-gray-400' /> - </div> - <div - className='text-[13px] text-gray-500 truncate' - title='Select model' - > - Please setup the Rerank model - </div> - </div> - <div className='shrink-0 flex items-center justify-center w-4 h-4'> - <RiExternalLinkLine className='w-3.5 h-3.5 text-gray-500' /> - </div> - </div> - ) -} - -export default ModelTrigger diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/add-model-button.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/add-model-button.tsx index cc8fa67efc..410ab1c090 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/add-model-button.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/add-model-button.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react' import { useTranslation } from 'react-i18next' import { PlusCircle } from '@/app/components/base/icons/src/vender/solid/general' +import cn from '@/utils/classnames' type AddModelButtonProps = { className?: string @@ -14,10 +15,7 @@ const AddModelButton: FC<AddModelButtonProps> = ({ return ( <span - className={` - shrink-0 flex items-center px-1.5 h-6 text-xs font-medium text-gray-500 cursor-pointer - hover:bg-primary-50 hover:text-primary-600 rounded-md ${className} - `} + className={cn('shrink-0 flex items-center px-1.5 h-6 text-text-tertiary system-xs-medium cursor-pointer hover:bg-components-button-ghost-bg-hover hover:text-components-button-ghost-text rounded-md', className)} onClick={onClick} > <PlusCircle className='mr-1 w-3 h-3' /> diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx index bdf93fe527..a21483c29f 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx @@ -19,10 +19,10 @@ const CooldownTimer = ({ secondsRemaining, onFinish }: CooldownTimerProps) => { [currentTime], ) - const countdownTimeout = useRef<NodeJS.Timeout>() + const countdownTimeout = useRef<number>(undefined) const clearCountdown = useCallback(() => { if (countdownTimeout.current) { - clearTimeout(countdownTimeout.current) + window.clearTimeout(countdownTimeout.current) countdownTimeout.current = undefined } }, []) @@ -31,7 +31,7 @@ const CooldownTimer = ({ secondsRemaining, onFinish }: CooldownTimerProps) => { const countdown = useCallback(() => { clearCountdown() - countdownTimeout.current = setTimeout(() => { + countdownTimeout.current = window.setTimeout(() => { const now = Date.now() if (now <= targetTime.current) { setCurrentTime(Date.now()) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx index f141e0018c..f43b5359ab 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/credential-panel.tsx @@ -1,5 +1,6 @@ import type { FC } from 'react' import { useTranslation } from 'react-i18next' +import { RiEqualizer2Line } from '@remixicon/react' import type { ModelProvider } from '../declarations' import { ConfigurationMethodEnum, @@ -14,7 +15,6 @@ import PrioritySelector from './priority-selector' import PriorityUseTip from './priority-use-tip' import { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './index' import Indicator from '@/app/components/header/indicator' -import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' import Button from '@/app/components/base/button' import { changeModelProviderPriority } from '@/service/common' import { useToastContext } from '@/app/components/base/toast' @@ -66,10 +66,10 @@ const CredentialPanel: FC<CredentialPanelProps> = ({ <> { provider.provider_credential_schema && ( - <div className='shrink-0 relative ml-1 p-1 w-[112px] rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'> - <div className='flex items-center justify-between mb-1 pt-1 pl-2 pr-[7px] h-5 text-xs font-medium text-gray-500'> + <div className='shrink-0 relative ml-1 p-1 w-[112px] rounded-lg bg-white/[0.18] border-[0.5px] border-components-panel-border'> + <div className='flex items-center justify-between mb-1 pt-1 pl-2 pr-[7px] h-5 system-xs-medium-uppercase text-text-tertiary'> API-KEY - <Indicator color={isCustomConfigured ? 'green' : 'gray'} /> + <Indicator color={isCustomConfigured ? 'green' : 'red'} /> </div> <div className='flex items-center gap-0.5'> <Button @@ -77,7 +77,7 @@ const CredentialPanel: FC<CredentialPanelProps> = ({ size='small' onClick={onSetup} > - <Settings01 className='mr-1 w-3 h-3' /> + <RiEqualizer2Line className='mr-1 w-3.5 h-3.5' /> {t('common.operation.setup')} </Button> { diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx index 5e73b36c42..a3dddf9435 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/index.tsx @@ -2,6 +2,8 @@ import type { FC } from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' import { + RiArrowRightSLine, + RiInformation2Fill, RiLoader2Line, } from '@remixicon/react' import type { @@ -11,7 +13,6 @@ import type { } from '../declarations' import { ConfigurationMethodEnum } from '../declarations' import { - DEFAULT_BACKGROUND_COLOR, MODEL_PROVIDER_QUOTA_GET_PAID, modelTypeFormat, } from '../utils' @@ -21,18 +22,20 @@ import CredentialPanel from './credential-panel' import QuotaPanel from './quota-panel' import ModelList from './model-list' import AddModelButton from './add-model-button' -import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/arrows' import { fetchModelProviderModelList } from '@/service/common' import { useEventEmitterContextContext } from '@/context/event-emitter' import { IS_CE_EDITION } from '@/config' import { useAppContext } from '@/context/app-context' +import cn from '@/utils/classnames' export const UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST = 'UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST' type ProviderAddedCardProps = { + notConfigured?: boolean provider: ModelProvider onOpenModal: (configurationMethod: ConfigurationMethodEnum, currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields) => void } const ProviderAddedCard: FC<ProviderAddedCardProps> = ({ + notConfigured, provider, onOpenModal, }) => { @@ -47,6 +50,7 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({ const hasModelList = fetched && !!modelList.length const { isCurrentWorkspaceManager } = useAppContext() const showQuota = systemConfig.enabled && [...MODEL_PROVIDER_QUOTA_GET_PAID].includes(provider.provider) && !IS_CE_EDITION + const showCredential = configurationMethods.includes(ConfigurationMethodEnum.predefinedModel) && isCurrentWorkspaceManager const getModelList = async (providerName: string) => { if (loading) @@ -78,8 +82,11 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({ return ( <div - className='mb-2 rounded-xl border-[0.5px] border-black/5 shadow-xs' - style={{ background: provider.background || DEFAULT_BACKGROUND_COLOR }} + className={cn( + 'mb-2 rounded-xl border-[0.5px] border-divider-regular shadow-xs bg-third-party-model-bg-default', + provider.provider === 'langgenius/openai/openai' && 'bg-third-party-model-bg-openai', + provider.provider === 'langgenius/anthropic/anthropic' && 'bg-third-party-model-bg-anthropic', + )} > <div className='flex pl-3 py-2 pr-2 rounded-t-xl'> <div className='grow px-1 pt-1 pb-0.5'> @@ -105,7 +112,7 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({ ) } { - configurationMethods.includes(ConfigurationMethodEnum.predefinedModel) && isCurrentWorkspaceManager && ( + showCredential && ( <CredentialPanel onSetup={() => onOpenModal(ConfigurationMethodEnum.predefinedModel)} provider={provider} @@ -115,35 +122,46 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({ </div> { collapsed && ( - <div className='group flex items-center justify-between pl-2 py-1.5 pr-[11px] border-t border-t-black/5 bg-white/30 text-xs font-medium text-gray-500'> - <div className='group-hover:hidden pl-1 pr-1.5 h-6 leading-6'> - { - hasModelList - ? t('common.modelProvider.modelsNum', { num: modelList.length }) - : t('common.modelProvider.showModels') - } - </div> - <div - className='hidden group-hover:flex items-center pl-1 pr-1.5 h-6 rounded-lg hover:bg-white cursor-pointer' - onClick={handleOpenModelList} - > - <ChevronDownDouble className='mr-0.5 w-3 h-3' /> - { - hasModelList - ? t('common.modelProvider.showModelsNum', { num: modelList.length }) - : t('common.modelProvider.showModels') - } - { - loading && ( - <RiLoader2Line className='ml-0.5 animate-spin w-3 h-3' /> - ) - } - </div> + <div className='group flex items-center justify-between pl-2 py-1.5 pr-[11px] border-t border-t-divider-subtle text-text-tertiary system-xs-medium'> + {(showQuota || !notConfigured) && ( + <> + <div className='group-hover:hidden flex items-center pl-1 pr-1.5 h-6 leading-6'> + { + hasModelList + ? t('common.modelProvider.modelsNum', { num: modelList.length }) + : t('common.modelProvider.showModels') + } + {!loading && <RiArrowRightSLine className='w-4 h-4' />} + </div> + <div + className='hidden group-hover:flex items-center pl-1 pr-1.5 h-6 rounded-lg hover:bg-components-button-ghost-bg-hover cursor-pointer' + onClick={handleOpenModelList} + > + { + hasModelList + ? t('common.modelProvider.showModelsNum', { num: modelList.length }) + : t('common.modelProvider.showModels') + } + {!loading && <RiArrowRightSLine className='w-4 h-4' />} + { + loading && ( + <RiLoader2Line className='ml-0.5 animate-spin w-3 h-3' /> + ) + } + </div> + </> + )} + {!showQuota && notConfigured && ( + <div className='flex items-center pl-1 pr-1.5 h-6'> + <RiInformation2Fill className='mr-1 w-4 h-4 text-text-accent' /> + <span className='text-text-secondary system-xs-medium'>{t('common.modelProvider.configureTip')}</span> + </div> + )} { configurationMethods.includes(ConfigurationMethodEnum.customizableModel) && isCurrentWorkspaceManager && ( <AddModelButton onClick={() => onOpenModal(ConfigurationMethodEnum.customizableModel)} - className='hidden group-hover:flex group-hover:text-primary-600' + className='flex' /> ) } diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx index 3fc73a62b2..6c4a3f575e 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx @@ -49,7 +49,7 @@ const ModelListItem = ({ model, provider, isConfigurable, onConfig, onModifyLoad key={model.model} className={classNames( 'group flex items-center pl-2 pr-2.5 h-8 rounded-lg', - isConfigurable && 'hover:bg-gray-50', + isConfigurable && 'hover:bg-components-panel-on-panel-item-bg-hover', model.deprecated && 'opacity-60', )} > @@ -59,14 +59,14 @@ const ModelListItem = ({ model, provider, isConfigurable, onConfig, onModifyLoad modelName={model.model} /> <ModelName - className='grow text-sm font-normal text-gray-900' + className='grow system-md-regular text-text-secondary' modelItem={model} showModelType showMode showContextSize > {modelLoadBalancingEnabled && !model.deprecated && model.load_balancing_enabled && ( - <ModelBadge className='ml-1 uppercase text-indigo-600 border-indigo-300'> + <ModelBadge className='ml-1 uppercase text-text-accent-secondary border-text-accent-secondary'> <Balance className='w-3 h-3 mr-0.5' /> {t('common.modelProvider.loadBalancingHeadline')} </ModelBadge> @@ -77,20 +77,22 @@ const ModelListItem = ({ model, provider, isConfigurable, onConfig, onModifyLoad model.fetch_from === ConfigurationMethodEnum.customizableModel ? (isCurrentWorkspaceManager && ( <Button - className='hidden group-hover:flex h-7' + size='small' + className='hidden group-hover:flex' onClick={() => onConfig({ __model_name: model.model, __model_type: model.model_type })} > - <Settings01 className='mr-[5px] w-3.5 h-3.5' /> + <Settings01 className='mr-1 w-3.5 h-3.5' /> {t('common.modelProvider.config')} </Button> )) : (isCurrentWorkspaceManager && (modelLoadBalancingEnabled || plan.type === Plan.sandbox) && !model.deprecated && [ModelStatusEnum.active, ModelStatusEnum.disabled].includes(model.status)) ? ( <Button - className='opacity-0 group-hover:opacity-100 h-[28px] transition-opacity' + size='small' + className='opacity-0 group-hover:opacity-100 transition-opacity' onClick={() => onModifyLoadBalancing?.(model)} > - <Balance className='mr-1 w-[14px] h-[14px]' /> + <Balance className='mr-1 w-3.5 h-3.5' /> {t('common.modelProvider.configLoadBalancing')} </Button> ) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx index e321d4076d..b4b331c4bc 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list.tsx @@ -1,6 +1,9 @@ import type { FC } from 'react' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' +import { + RiArrowRightSLine, +} from '@remixicon/react' import type { CustomConfigurationModelFixedFields, ModelItem, @@ -12,7 +15,6 @@ import { // import Tab from './tab' import AddModelButton from './add-model-button' import ModelListItem from './model-list-item' -import { ChevronDownDouble } from '@/app/components/base/icons/src/vender/line/arrows' import { useModalContextSelector } from '@/context/modal-context' import { useAppContext } from '@/context/app-context' @@ -48,18 +50,19 @@ const ModelList: FC<ModelListProps> = ({ return ( <div className='px-2 pb-2 rounded-b-xl'> - <div className='py-1 bg-white rounded-lg'> + <div className='py-1 bg-components-panel-bg rounded-lg'> <div className='flex items-center pl-1 pr-[3px]'> <span className='group shrink-0 flex items-center mr-2'> - <span className='group-hover:hidden pl-1 pr-1.5 h-6 leading-6 text-xs font-medium text-gray-500'> + <span className='group-hover:hidden inline-flex items-center pl-1 pr-1.5 h-6 system-xs-medium text-text-tertiary'> {t('common.modelProvider.modelsNum', { num: models.length })} + <RiArrowRightSLine className='mr-0.5 w-4 h-4 rotate-90' /> </span> <span - className='hidden group-hover:inline-flex items-center pl-1 pr-1.5 h-6 text-xs font-medium text-gray-500 bg-gray-50 cursor-pointer rounded-lg' + className='hidden group-hover:inline-flex items-center pl-1 pr-1.5 h-6 system-xs-medium text-text-tertiary bg-state-base-hover cursor-pointer rounded-lg' onClick={() => onCollapse()} > - <ChevronDownDouble className='mr-0.5 w-3 h-3 rotate-180' /> - {t('common.modelProvider.collapse')} + {t('common.modelProvider.modelsNum', { num: models.length })} + <RiArrowRightSLine className='mr-0.5 w-4 h-4 rotate-90' /> </span> </span> {/* { diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx index 94184076fd..2d5cf26257 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx @@ -145,19 +145,19 @@ const ModelLoadBalancingConfigs = ({ <> <div className={classNames( - 'min-h-16 bg-gray-50 border rounded-xl transition-colors', - (withSwitch || !draftConfig.enabled) ? 'border-gray-200' : 'border-primary-400', + 'min-h-16 bg-components-panel-bg border rounded-xl transition-colors', + (withSwitch || !draftConfig.enabled) ? 'border-components-panel-border' : 'border-util-colors-blue-blue-600', (withSwitch || draftConfig.enabled) ? 'cursor-default' : 'cursor-pointer', className, )} onClick={(!withSwitch && !draftConfig.enabled) ? () => toggleModalBalancing(true) : undefined} > <div className='flex items-center px-[15px] py-3 gap-2 select-none'> - <div className='grow-0 shrink-0 flex items-center justify-center w-8 h-8 text-primary-600 bg-indigo-50 border border-indigo-100 rounded-lg'> + <div className='grow-0 shrink-0 flex items-center justify-center w-8 h-8 text-util-colors-blue-blue-600 bg-util-colors-indigo-indigo-50 border border-util-colors-indigo-indigo-100 rounded-lg'> <Balance className='w-4 h-4' /> </div> <div className='grow'> - <div className='flex items-center gap-1 text-sm'> + <div className='flex items-center gap-1 text-sm text-text-primary'> {t('common.modelProvider.loadBalancing')} <Tooltip popupContent={t('common.modelProvider.loadBalancingInfo')} @@ -165,7 +165,7 @@ const ModelLoadBalancingConfigs = ({ triggerClassName='w-3 h-3' /> </div> - <div className='text-xs text-gray-500'>{t('common.modelProvider.loadBalancingDescription')}</div> + <div className='text-xs text-text-tertiary'>{t('common.modelProvider.loadBalancingDescription')}</div> </div> { withSwitch && ( @@ -184,7 +184,7 @@ const ModelLoadBalancingConfigs = ({ {draftConfig.configs.map((config, index) => { const isProviderManaged = config.name === '__inherit__' return ( - <div key={config.id || index} className='group flex items-center px-3 h-10 bg-white border border-gray-200 rounded-lg shadow-xs'> + <div key={config.id || index} className='group flex items-center px-3 h-10 bg-components-panel-on-panel-item-bg border border-components-panel-border rounded-lg shadow-xs'> <div className='grow flex items-center'> <div className='flex items-center justify-center mr-2 w-3 h-3'> {(config.in_cooldown && Boolean(config.ttl)) @@ -201,7 +201,7 @@ const ModelLoadBalancingConfigs = ({ {isProviderManaged ? t('common.modelProvider.defaultConfig') : config.name} </div> {isProviderManaged && ( - <span className='px-1 text-2xs uppercase text-gray-500 border border-black/8 rounded-[5px]'>{t('common.modelProvider.providerManaged')}</span> + <span className='px-1 text-2xs uppercase text-text-tertiary border border-divider-regular rounded-[5px]'>{t('common.modelProvider.providerManaged')}</span> )} </div> <div className='flex items-center gap-1'> @@ -209,18 +209,18 @@ const ModelLoadBalancingConfigs = ({ <> <div className='flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100'> <span - className='flex items-center justify-center w-8 h-8 text-gray-500 bg-white rounded-lg transition-colors cursor-pointer hover:bg-black/5' + className='flex items-center justify-center w-8 h-8 text-text-tertiary bg-components-button-secondary-bg rounded-lg transition-colors cursor-pointer hover:bg-components-button-secondary-bg-hover' onClick={() => toggleEntryModal(index, config)} > <Edit02 className='w-4 h-4' /> </span> <span - className='flex items-center justify-center w-8 h-8 text-gray-500 bg-white rounded-lg transition-colors cursor-pointer hover:bg-black/5' + className='flex items-center justify-center w-8 h-8 text-text-tertiary bg-components-button-secondary-bg rounded-lg transition-colors cursor-pointer hover:bg-components-button-secondary-bg-hover' onClick={() => updateConfigEntry(index, () => undefined)} > <RiDeleteBinLine className='w-4 h-4' /> </span> - <span className='mr-2 h-3 border-r border-r-gray-100' /> + <span className='mr-2 h-3 border-r border-r-divider-subtle' /> </div> </> )} @@ -247,7 +247,7 @@ const ModelLoadBalancingConfigs = ({ )} { draftConfig.enabled && draftConfig.configs.length < 2 && ( - <div className='flex items-center px-6 h-[34px] text-xs text-gray-700 bg-black/2 border-t border-t-black/5'> + <div className='flex items-center px-6 h-[34px] text-xs text-text-secondary bg-components-panel-bg border-t border-t-divider-subtle'> <AlertTriangle className='mr-1 w-3 h-3 text-[#f79009]' /> {t('common.modelProvider.loadBalancingLeastKeyWarning')} </div> @@ -257,7 +257,7 @@ const ModelLoadBalancingConfigs = ({ {!modelLoadBalancingEnabled && !IS_CE_EDITION && ( <GridMask canvasClassName='!rounded-xl'> - <div className='flex items-center justify-between mt-2 px-4 h-14 border-[0.5px] border-gray-200 rounded-xl shadow-md'> + <div className='flex items-center justify-between mt-2 px-4 h-14 border-[0.5px] border-components-panel-border rounded-xl shadow-md'> <div className={classNames('text-sm font-semibold leading-tight text-gradient', s.textGradient)} > diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx index edbb4665e9..bdc6b13c2c 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx @@ -119,7 +119,7 @@ const ModelLoadBalancingModal = ({ provider, model, open = false, onClose, onSav modelName={model!.model} /> <ModelName - className='grow text-sm font-normal text-gray-900' + className='grow system-md-regular text-text-secondary' modelItem={model!} showModelType showMode @@ -137,20 +137,20 @@ const ModelLoadBalancingModal = ({ provider, model, open = false, onClose, onSav <div className='py-2'> <div className={classNames( - 'min-h-16 bg-gray-50 border rounded-xl transition-colors', - draftConfig.enabled ? 'border-gray-200 cursor-pointer' : 'border-primary-400 cursor-default', + 'min-h-16 bg-components-panel-bg border rounded-xl transition-colors', + draftConfig.enabled ? 'border-components-panel-border cursor-pointer' : 'border-util-colors-blue-blue-600 cursor-default', )} onClick={draftConfig.enabled ? () => toggleModalBalancing(false) : undefined} > <div className='flex items-center px-[15px] py-3 gap-2 select-none'> - <div className='grow-0 shrink-0 flex items-center justify-center w-8 h-8 bg-white border rounded-lg'> + <div className='grow-0 shrink-0 flex items-center justify-center w-8 h-8 bg-components-card-bg border border-components-card-border rounded-lg'> {Boolean(model) && ( <ModelIcon className='shrink-0' provider={provider} modelName={model!.model} /> )} </div> <div className='grow'> - <div className='text-sm'>{t('common.modelProvider.providerManaged')}</div> - <div className='text-xs text-gray-500'>{t('common.modelProvider.providerManagedDescription')}</div> + <div className='text-sm text-text-secondary'>{t('common.modelProvider.providerManaged')}</div> + <div className='text-xs text-text-tertiary'>{t('common.modelProvider.providerManagedDescription')}</div> </div> </div> </div> diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-selector.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-selector.tsx index 7e44011ead..e93c6636b5 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-selector.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-selector.tsx @@ -8,6 +8,7 @@ import { } from '@remixicon/react' import { PreferredProviderTypeEnum } from '../declarations' import Button from '@/app/components/base/button' +import cn from '@/utils/classnames' type SelectorProps = { value?: string @@ -34,11 +35,11 @@ const Selector: FC<SelectorProps> = ({ <Popover.Button> { ({ open }) => ( - <Button className={` - px-0 w-6 h-6 bg-white rounded-md - ${open && '!bg-gray-100'} - `}> - <RiMoreFill className='w-3 h-3 text-gray-700' /> + <Button className={cn( + 'px-0 w-6 h-6 rounded-md', + open && 'bg-components-button-secondary-bg-hover', + )}> + <RiMoreFill className='w-3 h-3' /> </Button> ) } @@ -49,18 +50,18 @@ const Selector: FC<SelectorProps> = ({ leaveFrom='opacity-100' leaveTo='opacity-0' > - <Popover.Panel className='absolute top-7 right-0 w-[144px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg z-10'> + <Popover.Panel className='absolute top-7 right-0 w-[144px] bg-components-panel-bg border-[0.5px] border-components-panel-border rounded-lg shadow-lg z-10'> <div className='p-1'> - <div className='px-3 pt-2 pb-1 text-sm font-medium text-gray-700'>{t('common.modelProvider.card.priorityUse')}</div> + <div className='px-3 pt-2 pb-1 text-sm font-medium text-text-secondary'>{t('common.modelProvider.card.priorityUse')}</div> { options.map(option => ( <Popover.Button as={Fragment} key={option.key}> <div - className='flex items-center justify-between px-3 h-9 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' + className='flex items-center justify-between px-3 h-9 text-sm text-text-secondary rounded-lg cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover' onClick={() => onSelect(option.key)} > <div className='grow'>{option.text}</div> - {value === option.key && <RiCheckLine className='w-4 h-4 text-primary-600' />} + {value === option.key && <RiCheckLine className='w-4 h-4 text-text-accent' />} </div> </Popover.Button> )) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx index 24e91d2214..91e45ad1a3 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx @@ -9,8 +9,8 @@ const PriorityUseTip = () => { <Tooltip popupContent={t('common.modelProvider.priorityUsing') || ''} > - <div className='absolute -right-[5px] -top-[5px] bg-indigo-50 rounded-[5px] border-[0.5px] border-indigo-100 cursor-pointer'> - <ChevronDownDouble className='rotate-180 w-3 h-3 text-indigo-600' /> + <div className='absolute -right-[5px] -top-[5px] bg-util-colors-indigo-indigo-50 rounded-[5px] border-[0.5px] border-components-panel-border-subtle shadow-xs cursor-pointer'> + <ChevronDownDouble className='rotate-180 w-3 h-3 text-util-colors-indigo-indigo-600' /> </div> </Tooltip> ) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx index 0f5c265d52..8d0ea83d65 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx @@ -28,8 +28,8 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ const openaiOrAnthropic = MODEL_PROVIDER_QUOTA_GET_PAID.includes(provider.provider) return ( - <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'> - <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'> + <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.18] border-[0.5px] border-components-panel-border shadow-xs'> + <div className='flex items-center mb-2 h-4 system-xs-medium-uppercase text-text-tertiary'> {t('common.modelProvider.quota')} <Tooltip popupContent={ openaiOrAnthropic @@ -40,8 +40,8 @@ const QuotaPanel: FC<QuotaPanelProps> = ({ </div> { currentQuota && ( - <div className='flex items-center h-4 text-xs text-gray-500'> - <span className='mr-0.5 text-sm font-semibold text-gray-700'>{formatNumber((currentQuota?.quota_limit || 0) - (currentQuota?.quota_used || 0))}</span> + <div className='flex items-center h-4 text-xs text-text-tertiary'> + <span className='mr-0.5 system-md-semibold-uppercase text-text-secondary'>{formatNumber((currentQuota?.quota_limit || 0) - (currentQuota?.quota_used || 0))}</span> { currentQuota?.quota_unit === QuotaUnitEnum.tokens && 'Tokens' } diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/tab.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/tab.tsx deleted file mode 100644 index 5a533947d2..0000000000 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/tab.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import type { FC } from 'react' - -type TabProps = { - active: string - onSelect: (active: string) => void -} -const Tab: FC<TabProps> = ({ - active, - onSelect, -}) => { - const tabs = [ - { - key: 'all', - text: 'All', - }, - { - key: 'added', - text: 'Added', - }, - { - key: 'build-in', - text: 'Build-in', - }, - ] - return ( - <div className='flex items-center'> - { - tabs.map(tab => ( - <div - key={tab.key} - className={` - flex items-center mr-1 px-[5px] h-[18px] rounded-md text-xs cursor-pointer - ${active === tab.key ? 'bg-gray-200 font-medium text-gray-900' : 'text-gray-500 font-normal'} - `} - onClick={() => onSelect(tab.key)} - > - {tab.text} - </div> - )) - } - </div> - ) -} - -export default Tab diff --git a/web/app/components/header/account-setting/model-provider-page/provider-card/index.module.css b/web/app/components/header/account-setting/model-provider-page/provider-card/index.module.css deleted file mode 100644 index 88c9fd015e..0000000000 --- a/web/app/components/header/account-setting/model-provider-page/provider-card/index.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.vender { - background: linear-gradient(131deg, #2250F2 0%, #0EBCF3 100%); - background-clip: text; -} \ No newline at end of file diff --git a/web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx b/web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx deleted file mode 100644 index ec66a9928b..0000000000 --- a/web/app/components/header/account-setting/model-provider-page/provider-card/index.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import type { FC } from 'react' -import { useTranslation } from 'react-i18next' -import { - RiAddLine, -} from '@remixicon/react' -import type { - ModelProvider, -} from '../declarations' -import { ConfigurationMethodEnum } from '../declarations' -import { - DEFAULT_BACKGROUND_COLOR, - modelTypeFormat, -} from '../utils' -import { - useLanguage, -} from '../hooks' -import ModelBadge from '../model-badge' -import ProviderIcon from '../provider-icon' -import s from './index.module.css' -import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' -import Button from '@/app/components/base/button' -import { useAppContext } from '@/context/app-context' - -type ProviderCardProps = { - provider: ModelProvider - onOpenModal: (configurateMethod: ConfigurationMethodEnum) => void -} - -const ProviderCard: FC<ProviderCardProps> = ({ - provider, - onOpenModal, -}) => { - const { t } = useTranslation() - const language = useLanguage() - const { isCurrentWorkspaceManager } = useAppContext() - const configurateMethods = provider.configurate_methods.filter(method => method !== ConfigurationMethodEnum.fetchFromRemote) - - return ( - <div - className='group relative flex flex-col px-4 py-3 h-[148px] border-[0.5px] border-black/5 rounded-xl shadow-xs hover:shadow-lg' - style={{ background: provider.background || DEFAULT_BACKGROUND_COLOR }} - > - <div className='grow h-0'> - <div className='py-0.5'> - <ProviderIcon provider={provider} /> - </div> - { - provider.description && ( - <div - className='mt-1 leading-4 text-xs text-black/[48] line-clamp-4' - title={provider.description[language] || provider.description.en_US} - > - {provider.description[language] || provider.description.en_US} - </div> - ) - } - </div> - <div className='shrink-0'> - <div className={'flex flex-wrap group-hover:hidden gap-0.5'}> - { - provider.supported_model_types.map(modelType => ( - <ModelBadge key={modelType}> - {modelTypeFormat(modelType)} - </ModelBadge> - )) - } - </div> - <div className={`hidden group-hover:grid grid-cols-${configurateMethods.length} gap-1`}> - { - configurateMethods.map((method) => { - if (method === ConfigurationMethodEnum.predefinedModel) { - return ( - <Button - key={method} - className={'h-7 text-xs shrink-0'} - onClick={() => onOpenModal(method)} - disabled={!isCurrentWorkspaceManager} - > - <Settings01 className={`mr-[5px] w-3.5 h-3.5 ${s.icon}`} /> - <span className='text-xs inline-flex items-center justify-center overflow-ellipsis shrink-0'>{t('common.operation.setup')}</span> - </Button> - ) - } - return ( - <Button - key={method} - className='px-0 h-7 text-xs' - onClick={() => onOpenModal(method)} - disabled={!isCurrentWorkspaceManager} - > - <RiAddLine className='mr-[5px] w-3.5 h-3.5' /> - {t('common.modelProvider.addModel')} - </Button> - ) - }) - } - </div> - </div> - </div> - ) -} - -export default ProviderCard diff --git a/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx b/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx index 768f2c2766..25105b1193 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx @@ -1,6 +1,8 @@ import type { FC } from 'react' import type { ModelProvider } from '../declarations' import { useLanguage } from '../hooks' +import { AnthropicText, Openai } from '@/app/components/base/icons/src/vender/other' +import cn from '@/utils/classnames' type ProviderIconProps = { provider: ModelProvider @@ -12,19 +14,30 @@ const ProviderIcon: FC<ProviderIconProps> = ({ }) => { const language = useLanguage() - if (provider.icon_large) { + if (provider.provider === 'langgenius/anthropic/anthropic') { return ( - <img - alt='provider-icon' - src={`${provider.icon_large[language] || provider.icon_large.en_US}`} - className={`w-auto h-6 ${className}`} - /> + <div className='mb-2'> + <AnthropicText className='w-auto h-6 text-text-inverted-dimmed' /> + </div> + ) + } + + if (provider.provider === 'langgenius/openai/openai') { + return ( + <div className='mb-2'> + <Openai className='w-auto h-6 text-text-inverted-dimmed' /> + </div> ) } return ( - <div className={`inline-flex items-center ${className}`}> - <div className='text-xs font-semibold text-black'> + <div className={cn('inline-flex items-center gap-2', className)}> + <img + alt='provider-icon' + src={`${provider.icon_small[language] || provider.icon_small.en_US}`} + className='w-6 h-6' + /> + <div className='system-md-semibold text-text-primary'> {provider.label[language] || provider.label.en_US} </div> </div> diff --git a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx index 1574785898..ec2bdc265f 100644 --- a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' +import { RiEqualizer2Line } from '@remixicon/react' import ModelSelector from '../model-selector' import { useModelList, @@ -13,7 +14,6 @@ import type { } from '../declarations' import { ModelTypeEnum } from '../declarations' import Tooltip from '@/app/components/base/tooltip' -import { Settings01 } from '@/app/components/base/icons/src/vender/line/general' import { PortalToFollowElem, PortalToFollowElemContent, @@ -31,6 +31,7 @@ type SystemModelSelectorProps = { rerankDefaultModel: DefaultModelResponse | undefined speech2textDefaultModel: DefaultModelResponse | undefined ttsDefaultModel: DefaultModelResponse | undefined + notConfigured: boolean } const SystemModel: FC<SystemModelSelectorProps> = ({ textGenerationDefaultModel, @@ -38,6 +39,7 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ rerankDefaultModel, speech2textDefaultModel, ttsDefaultModel, + notConfigured, }) => { const { t } = useTranslation() const { notify } = useToastContext() @@ -128,23 +130,23 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ }} > <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}> - <div className={` - flex items-center px-2 h-6 text-xs text-gray-700 cursor-pointer bg-white rounded-md border-[0.5px] border-gray-200 shadow-xs - hover:bg-gray-100 hover:shadow-none - ${open && 'bg-gray-100 shadow-none'} - `}> - <Settings01 className='mr-1 w-3 h-3 text-gray-500' /> + <Button + className='relative' + variant={notConfigured ? 'primary' : 'secondary'} + size='small' + > + <RiEqualizer2Line className='mr-1 w-3.5 h-3.5' /> {t('common.modelProvider.systemModelSettings')} - </div> + </Button> </PortalToFollowElemTrigger> - <PortalToFollowElemContent className='z-50'> - <div className='pt-4 w-[360px] rounded-xl border-[0.5px] border-black/5 bg-white shadow-xl'> + <PortalToFollowElemContent className='z-[60]'> + <div className='pt-4 w-[360px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl'> <div className='px-6 py-1'> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center h-8 text-[13px] font-medium text-text-primary'> {t('common.modelProvider.systemReasoningModel.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('common.modelProvider.systemReasoningModel.tip')} </div> } @@ -160,11 +162,11 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ </div> </div> <div className='px-6 py-1'> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center h-8 text-[13px] font-medium text-text-primary'> {t('common.modelProvider.embeddingModel.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('common.modelProvider.embeddingModel.tip')} </div> } @@ -180,11 +182,11 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ </div> </div> <div className='px-6 py-1'> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center h-8 text-[13px] font-medium text-text-primary'> {t('common.modelProvider.rerankModel.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('common.modelProvider.rerankModel.tip')} </div> } @@ -200,11 +202,11 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ </div> </div> <div className='px-6 py-1'> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center h-8 text-[13px] font-medium text-text-primary'> {t('common.modelProvider.speechToTextModel.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('common.modelProvider.speechToTextModel.tip')} </div> } @@ -220,11 +222,11 @@ const SystemModel: FC<SystemModelSelectorProps> = ({ </div> </div> <div className='px-6 py-1'> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center h-8 text-[13px] font-medium text-text-primary'> {t('common.modelProvider.ttsModel.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('common.modelProvider.ttsModel.tip')} </div> } diff --git a/web/app/components/header/account-setting/model-provider-page/utils.ts b/web/app/components/header/account-setting/model-provider-page/utils.ts index 165926b2bb..9056afe69b 100644 --- a/web/app/components/header/account-setting/model-provider-page/utils.ts +++ b/web/app/components/header/account-setting/model-provider-page/utils.ts @@ -18,9 +18,7 @@ import { validateModelProvider, } from '@/service/common' -export const MODEL_PROVIDER_QUOTA_GET_PAID = ['anthropic', 'openai', 'azure_openai'] - -export const DEFAULT_BACKGROUND_COLOR = '#F3F4F6' +export const MODEL_PROVIDER_QUOTA_GET_PAID = ['langgenius/anthropic/anthropic', 'langgenius/openai/openai', 'langgenius/azure_openai/azure_openai'] export const isNullOrUndefined = (value: any) => { return value === undefined || value === null diff --git a/web/app/components/header/app-nav/index.tsx b/web/app/components/header/app-nav/index.tsx index d4dd9e3ffd..3ac57926e9 100644 --- a/web/app/components/header/app-nav/index.tsx +++ b/web/app/components/header/app-nav/index.tsx @@ -11,7 +11,7 @@ import { RiRobot2Line, } from '@remixicon/react' import Nav from '../nav' -import { type NavItem } from '../nav/nav-selector' +import type { NavItem } from '../nav/nav-selector' import { fetchAppList } from '@/service/apps' import CreateAppTemplateDialog from '@/app/components/app/create-app-dialog' import CreateAppModal from '@/app/components/app/create-app-modal' diff --git a/web/app/components/header/index.tsx b/web/app/components/header/index.tsx index 9a32bbb37a..d0807ff8ad 100644 --- a/web/app/components/header/index.tsx +++ b/web/app/components/header/index.tsx @@ -4,23 +4,24 @@ import Link from 'next/link' import { useBoolean } from 'ahooks' import { useSelectedLayoutSegment } from 'next/navigation' import { Bars3Icon } from '@heroicons/react/20/solid' -import { useContextSelector } from 'use-context-selector' -import HeaderBillingBtn from '../billing/header-billing-btn' +import { SparklesSoft } from '@/app/components/base/icons/src/public/common' +import PremiumBadge from '../base/premium-badge' import AccountDropdown from './account-dropdown' import AppNav from './app-nav' import DatasetNav from './dataset-nav' import EnvNav from './env-nav' +import PluginsNav from './plugins-nav' import ExploreNav from './explore-nav' import ToolsNav from './tools-nav' -import GithubStar from './github-star' import LicenseNav from './license-env' import { WorkspaceProvider } from '@/context/workspace-context' -import AppContext, { useAppContext } from '@/context/app-context' +import { useAppContext } from '@/context/app-context' import LogoSite from '@/app/components/base/logo/logo-site' +import WorkplaceSelector from '@/app/components/header/account-dropdown/workplace-selector' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import { useProviderContext } from '@/context/provider-context' import { useModalContext } from '@/context/modal-context' -import { LicenseStatus } from '@/types/feature' +import { useTranslation } from 'react-i18next' const navClassName = ` flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl @@ -30,7 +31,8 @@ const navClassName = ` const Header = () => { const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext() - const systemFeatures = useContextSelector(AppContext, v => v.systemFeatures) + const { t } = useTranslation() + const selectedSegment = useSelectedLayoutSegment() const media = useBreakpoints() const isMobile = media === MediaType.mobile @@ -58,50 +60,84 @@ const Header = () => { > <Bars3Icon className="h-4 w-4 text-gray-500" /> </div>} - {!isMobile && <> - <Link href="/apps" className='flex items-center mr-4'> - <LogoSite className='object-contain' /> - </Link> - {systemFeatures.license.status === LicenseStatus.NONE && <GithubStar />} - </>} - </div> + { + !isMobile + && <div className='flex w-64 p-2 pl-3 gap-1.5 items-center shrink-0 self-stretch'> + <Link href="/apps" className='flex w-8 h-8 items-center justify-center gap-2 shrink-0'> + <LogoSite className='object-contain' /> + </Link> + <div className='font-light text-divider-deep'>/</div> + <div className='flex items-center gap-0.5'> + <WorkspaceProvider> + <WorkplaceSelector /> + </WorkspaceProvider> + {enableBilling && ( + <div className='select-none'> + <PremiumBadge color='blue' allowHover={true} onClick={handlePlanClick}> + <SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' /> + <div className='system-xs-medium'> + <span className='p-1'> + {t('billing.upgradeBtn.encourageShort')} + </span> + </div> + </PremiumBadge> + </div> + )} + </div> + </div> + } + </div > {isMobile && ( <div className='flex'> <Link href="/apps" className='flex items-center mr-4'> <LogoSite /> </Link> - {systemFeatures.license.status === LicenseStatus.NONE && <GithubStar />} - </div> + <div className='font-light text-divider-deep'>/</div> + { + enableBilling && ( + <div className='select-none'> + <PremiumBadge color='blue' allowHover={true} onClick={handlePlanClick}> + <SparklesSoft className='flex items-center py-[1px] pl-[3px] w-3.5 h-3.5 text-components-premium-badge-indigo-text-stop-0' /> + <div className='system-xs-medium'> + <span className='p-1'> + {t('billing.upgradeBtn.encourageShort')} + </span> + </div> + </PremiumBadge> + </div> + ) + } + </div > )} - {!isMobile && ( - <div className='flex items-center'> - {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} - {!isCurrentWorkspaceDatasetOperator && <AppNav />} - {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} - {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} - </div> - )} - <div className='flex items-center flex-shrink-0'> + { + !isMobile && ( + <div className='flex items-center'> + {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} + {!isCurrentWorkspaceDatasetOperator && <AppNav />} + {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} + {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} + </div> + ) + } + <div className='flex items-center shrink-0'> <LicenseNav /> <EnvNav /> - {enableBilling && ( - <div className='mr-3 select-none'> - <HeaderBillingBtn onClick={handlePlanClick} /> - </div> - )} - <WorkspaceProvider> - <AccountDropdown isMobile={isMobile} /> - </WorkspaceProvider> - </div> - {(isMobile && isShowNavMenu) && ( - <div className='w-full flex flex-col p-2 gap-y-1'> - {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} - {!isCurrentWorkspaceDatasetOperator && <AppNav />} - {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} - {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} + <div className='mr-3'> + <PluginsNav /> </div> - )} - </div> + <AccountDropdown isMobile={isMobile} /> + </div> + { + (isMobile && isShowNavMenu) && ( + <div className='w-full flex flex-col p-2 gap-y-1'> + {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} + {!isCurrentWorkspaceDatasetOperator && <AppNav />} + {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} + {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} + </div> + ) + } + </div > ) } export default Header diff --git a/web/app/components/header/nav/index.tsx b/web/app/components/header/nav/index.tsx index bfb4324320..de98593ddd 100644 --- a/web/app/components/header/nav/index.tsx +++ b/web/app/components/header/nav/index.tsx @@ -68,7 +68,7 @@ const Nav = ({ { curNav && isActivated && ( <> - <div className='font-light text-gray-300 '>/</div> + <div className='font-light text-divider-deep'>/</div> <NavSelector isApp={isApp} curNav={curNav} diff --git a/web/app/components/header/plugins-nav/downloading-icon.module.css b/web/app/components/header/plugins-nav/downloading-icon.module.css new file mode 100644 index 0000000000..c11a9f2f2c --- /dev/null +++ b/web/app/components/header/plugins-nav/downloading-icon.module.css @@ -0,0 +1,44 @@ +@keyframes realistic-blink { + 0% { fill: #37ff37; opacity: 0.4; } + 15% { fill: #37ff37; opacity: 0.9; } + 25% { fill: #37ff37; opacity: 0.3; } + 38% { fill: #ff4444; opacity: 0.8; } + 42% { fill: #ff4444; opacity: 0.3; } + 58% { fill: #37ff37; opacity: 0.9; } + 65% { fill: #37ff37; opacity: 0.4; } + 79% { fill: #ff4444; opacity: 0.8; } + 84% { fill: #ff4444; opacity: 0.3; } + 92% { fill: #37ff37; opacity: 0.8; } + 100% { fill: #37ff37; opacity: 0.4; } +} + +@keyframes drop { + 0% { + transform: translateY(-4px); + opacity: 0; + } + 5% { + transform: translateY(-4px); + opacity: 1; + } + 65% { + transform: translateY(2px); + opacity: 1; + } + 80% { + transform: translateY(2px); + opacity: 0; + } + 100% { + transform: translateY(2px); + opacity: 0; + } +} + +#downloadingIconLight { + animation: realistic-blink 3s infinite ease-in-out; +} + +#downloadingIconArrow { + animation: drop 1.2s cubic-bezier(0.4, 0, 1, 1) infinite; +} \ No newline at end of file diff --git a/web/app/components/header/plugins-nav/downloading-icon.tsx b/web/app/components/header/plugins-nav/downloading-icon.tsx new file mode 100644 index 0000000000..d3fc486445 --- /dev/null +++ b/web/app/components/header/plugins-nav/downloading-icon.tsx @@ -0,0 +1,17 @@ +import s from './downloading-icon.module.css' + +const DownloadingIcon = () => { + return ( + <div className="inline-flex text-components-button-secondary-text"> + <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="install-icon"> + <g id="install-line"> + <path d="M8 2V4H5L4.999 14H18.999L19 4H16V2H20C20.5523 2 21 2.44772 21 3V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V3C3 2.44772 3.44772 2 4 2H8ZM18.999 16H4.999L5 20H19L18.999 16Z" fill="currentColor"/> + <path id={s.downloadingIconLight} d="M17 19V17H15V19H17Z"/> + <path id={s.downloadingIconArrow} d="M13 2V7H16L12 11L8 7H11V2H13Z" fill="currentColor"/> + </g> + </svg> + </div> + ) +} + +export default DownloadingIcon diff --git a/web/app/components/header/plugins-nav/index.tsx b/web/app/components/header/plugins-nav/index.tsx new file mode 100644 index 0000000000..ab742c98cf --- /dev/null +++ b/web/app/components/header/plugins-nav/index.tsx @@ -0,0 +1,66 @@ +'use client' + +import { useTranslation } from 'react-i18next' +import Link from 'next/link' +import classNames from '@/utils/classnames' +import { Group } from '@/app/components/base/icons/src/vender/other' +import { useSelectedLayoutSegment } from 'next/navigation' +import DownloadingIcon from './downloading-icon' +import { usePluginTaskStatus } from '@/app/components/plugins/plugin-page/plugin-tasks/hooks' +import Indicator from '@/app/components/header/indicator' + +type PluginsNavProps = { + className?: string +} + +const PluginsNav = ({ + className, +}: PluginsNavProps) => { + const { t } = useTranslation() + const selectedSegment = useSelectedLayoutSegment() + const activated = selectedSegment === 'plugins' + const { + isInstalling, + isInstallingWithError, + isFailed, + } = usePluginTaskStatus() + + return ( + <Link href="/plugins" className={classNames( + className, 'group', 'plugins-nav-button', // used for use-fold-anim-into.ts + )}> + <div + className={classNames( + 'relative flex flex-row h-8 p-1.5 gap-0.5 border border-transparent items-center justify-center rounded-xl system-sm-medium-uppercase', + activated && 'border-components-main-nav-nav-button-border bg-components-main-nav-nav-button-bg-active shadow-md text-components-main-nav-nav-button-text', + !activated && 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary', + (isInstallingWithError || isFailed) && !activated && 'border-components-panel-border-subtle', + )} + > + { + (isFailed || isInstallingWithError) && !activated && ( + <Indicator + color='red' + className='absolute top-[-1px] left-[-1px]' + /> + ) + } + <div className='flex mr-0.5 w-5 h-5 justify-center items-center'> + { + (!(isInstalling || isInstallingWithError) || activated) && ( + <Group className='w-4 h-4' /> + ) + } + { + (isInstalling || isInstallingWithError) && !activated && ( + <DownloadingIcon /> + ) + } + </div> + <span className='px-0.5'>{t('common.menus.plugins')}</span> + </div> + </Link> + ) +} + +export default PluginsNav diff --git a/web/app/components/plugins/base/key-value-item.tsx b/web/app/components/plugins/base/key-value-item.tsx new file mode 100644 index 0000000000..9d6cda18d3 --- /dev/null +++ b/web/app/components/plugins/base/key-value-item.tsx @@ -0,0 +1,66 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useEffect, useState } from 'react' +import copy from 'copy-to-clipboard' +import { + RiClipboardLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { ClipboardCheck } from '../../base/icons/src/vender/line/files' +import Tooltip from '../../base/tooltip' +import cn from '@/utils/classnames' +import ActionButton from '@/app/components/base/action-button' + +type Props = { + label: string + labelWidthClassName?: string + value: string + maskedValue?: string + valueMaxWidthClassName?: string +} + +const KeyValueItem: FC<Props> = ({ + label, + labelWidthClassName = 'w-10', + value, + maskedValue, + valueMaxWidthClassName = 'max-w-[162px]', +}) => { + const { t } = useTranslation() + const [isCopied, setIsCopied] = useState(false) + const handleCopy = useCallback(() => { + copy(value) + setIsCopied(true) + }, [value]) + + useEffect(() => { + if (isCopied) { + const timer = setTimeout(() => { + setIsCopied(false) + }, 2000) + return () => { + clearTimeout(timer) + } + } + }, [isCopied]) + + const CopyIcon = isCopied ? ClipboardCheck : RiClipboardLine + + return ( + <div className='flex items-center gap-1'> + <span className={cn('flex flex-col justify-center items-start text-text-tertiary system-xs-medium', labelWidthClassName)}>{label}</span> + <div className='flex justify-center items-center gap-0.5'> + <span className={cn(valueMaxWidthClassName, ' truncate system-xs-medium text-text-secondary')}> + {maskedValue || value} + </span> + <Tooltip popupContent={t(`common.operation.${isCopied ? 'copied' : 'copy'}`)} position='top'> + <ActionButton onClick={handleCopy}> + <CopyIcon className='shrink-0 w-3.5 h-3.5 text-text-tertiary' /> + </ActionButton> + </Tooltip> + </div> + </div> + ) +} + +export default React.memo(KeyValueItem) diff --git a/web/app/components/plugins/card/base/card-icon.tsx b/web/app/components/plugins/card/base/card-icon.tsx new file mode 100644 index 0000000000..3587f3fd0d --- /dev/null +++ b/web/app/components/plugins/card/base/card-icon.tsx @@ -0,0 +1,66 @@ +import { RiCheckLine, RiCloseLine } from '@remixicon/react' +import AppIcon from '@/app/components/base/app-icon' +import cn from '@/utils/classnames' + +const iconSizeMap = { + xs: 'w-4 h-4 text-base', + tiny: 'w-6 h-6 text-base', + small: 'w-8 h-8', + medium: 'w-9 h-9', + large: 'w-10 h-10', +} +const Icon = ({ + className, + src, + installed = false, + installFailed = false, + size = 'large', +}: { + className?: string + src: string | { + content: string + background: string + } + installed?: boolean + installFailed?: boolean + size?: 'xs' | 'tiny' | 'small' | 'medium' | 'large' +}) => { + const iconClassName = 'flex justify-center items-center gap-2 absolute bottom-[-4px] right-[-4px] w-[18px] h-[18px] rounded-full border-2 border-components-panel-bg' + if (typeof src === 'object') { + return ( + <div className={cn('relative', className)}> + <AppIcon + size={size} + iconType={'emoji'} + icon={src.content} + background={src.background} + className='rounded-md' + /> + </div> + ) + } + + return ( + <div + className={cn('shrink-0 relative rounded-md bg-center bg-no-repeat bg-contain', iconSizeMap[size], className)} + style={{ + backgroundImage: `url(${src})`, + }} + > + { + installed + && <div className={cn(iconClassName, 'bg-state-success-solid')}> + <RiCheckLine className='w-3 h-3 text-text-primary-on-surface' /> + </div> + } + { + installFailed + && <div className={cn(iconClassName, 'bg-state-destructive-solid')}> + <RiCloseLine className='w-3 h-3 text-text-primary-on-surface' /> + </div> + } + </div> + ) +} + +export default Icon diff --git a/web/app/components/plugins/card/base/corner-mark.tsx b/web/app/components/plugins/card/base/corner-mark.tsx new file mode 100644 index 0000000000..cdb9eb5417 --- /dev/null +++ b/web/app/components/plugins/card/base/corner-mark.tsx @@ -0,0 +1,12 @@ +import { LeftCorner } from '../../../base/icons/src/vender/plugin' + +const CornerMark = ({ text }: { text: string }) => { + return ( + <div className='absolute top-0 right-0 flex pl-[13px] '> + <LeftCorner className="text-background-section" /> + <div className="h-5 leading-5 rounded-tr-xl pr-2 bg-background-section text-text-tertiary system-2xs-medium-uppercase">{text}</div> + </div> + ) +} + +export default CornerMark diff --git a/web/app/components/plugins/card/base/description.tsx b/web/app/components/plugins/card/base/description.tsx new file mode 100644 index 0000000000..247a55c628 --- /dev/null +++ b/web/app/components/plugins/card/base/description.tsx @@ -0,0 +1,31 @@ +import type { FC } from 'react' +import React, { useMemo } from 'react' +import cn from '@/utils/classnames' + +type Props = { + className?: string + text: string + descriptionLineRows: number +} + +const Description: FC<Props> = ({ + className, + text, + descriptionLineRows, +}) => { + const lineClassName = useMemo(() => { + if (descriptionLineRows === 1) + return 'h-4 truncate' + else if (descriptionLineRows === 2) + return 'h-8 line-clamp-2' + else + return 'h-12 line-clamp-3' + }, [descriptionLineRows]) + return ( + <div className={cn('text-text-tertiary system-xs-regular', lineClassName, className)}> + {text} + </div> + ) +} + +export default Description diff --git a/web/app/components/plugins/card/base/download-count.tsx b/web/app/components/plugins/card/base/download-count.tsx new file mode 100644 index 0000000000..0c28e6970e --- /dev/null +++ b/web/app/components/plugins/card/base/download-count.tsx @@ -0,0 +1,19 @@ +import { RiInstallLine } from '@remixicon/react' +import { formatNumber } from '@/utils/format' + +type Props = { + downloadCount: number +} + +const DownloadCount = ({ + downloadCount, +}: Props) => { + return ( + <div className="flex items-center space-x-1 text-text-tertiary"> + <RiInstallLine className="shrink-0 w-3 h-3" /> + <div className="system-xs-regular">{formatNumber(downloadCount)}</div> + </div> + ) +} + +export default DownloadCount diff --git a/web/app/components/plugins/card/base/org-info.tsx b/web/app/components/plugins/card/base/org-info.tsx new file mode 100644 index 0000000000..3d549d6c5e --- /dev/null +++ b/web/app/components/plugins/card/base/org-info.tsx @@ -0,0 +1,30 @@ +import cn from '@/utils/classnames' +type Props = { + className?: string + orgName?: string + packageName: string + packageNameClassName?: string +} + +const OrgInfo = ({ + className, + orgName, + packageName, + packageNameClassName, +}: Props) => { + return ( + <div className={cn('flex items-center h-4 space-x-0.5', className)}> + {orgName && ( + <> + <span className='shrink-0 text-text-tertiary system-xs-regular'>{orgName}</span> + <span className='shrink-0 text-text-quaternary system-xs-regular'>/</span> + </> + )} + <span className={cn('shrink-0 w-0 grow truncate text-text-tertiary system-xs-regular', packageNameClassName)}> + {packageName} + </span> + </div> + ) +} + +export default OrgInfo diff --git a/web/app/components/plugins/card/base/placeholder.tsx b/web/app/components/plugins/card/base/placeholder.tsx new file mode 100644 index 0000000000..62f373f922 --- /dev/null +++ b/web/app/components/plugins/card/base/placeholder.tsx @@ -0,0 +1,51 @@ +import { Group } from '../../../base/icons/src/vender/other' +import Title from './title' +import { SkeletonContainer, SkeletonPoint, SkeletonRectangle, SkeletonRow } from '@/app/components/base/skeleton' +import cn from '@/utils/classnames' + +type Props = { + wrapClassName: string + loadingFileName?: string +} + +export const LoadingPlaceholder = ({ className }: { className?: string }) => ( + <div className={cn('h-2 rounded-sm opacity-20 bg-text-quaternary', className)} /> +) + +const Placeholder = ({ + wrapClassName, + loadingFileName, +}: Props) => { + return ( + <div className={wrapClassName}> + <SkeletonRow> + <div + className='flex w-10 h-10 p-1 justify-center items-center gap-2 rounded-[10px] + border-[0.5px] border-components-panel-border bg-background-default backdrop-blur-sm'> + <div className='flex w-5 h-5 justify-center items-center'> + <Group className='text-text-tertiary' /> + </div> + </div> + <div className="grow"> + <SkeletonContainer> + <div className="flex items-center h-5"> + {loadingFileName ? ( + <Title title={loadingFileName} /> + ) : ( + <SkeletonRectangle className="w-[260px]" /> + )} + </div> + <SkeletonRow className="h-4"> + <SkeletonRectangle className="w-[41px]" /> + <SkeletonPoint /> + <SkeletonRectangle className="w-[180px]" /> + </SkeletonRow> + </SkeletonContainer> + </div> + </SkeletonRow> + <SkeletonRectangle className="mt-3 w-[420px]" /> + </div> + ) +} + +export default Placeholder diff --git a/web/app/components/plugins/card/base/title.tsx b/web/app/components/plugins/card/base/title.tsx new file mode 100644 index 0000000000..383e7b31c1 --- /dev/null +++ b/web/app/components/plugins/card/base/title.tsx @@ -0,0 +1,13 @@ +const Title = ({ + title, +}: { + title: string +}) => { + return ( + <div className='truncate text-text-secondary system-md-semibold'> + {title} + </div> + ) +} + +export default Title diff --git a/web/app/components/plugins/card/card-mock.ts b/web/app/components/plugins/card/card-mock.ts new file mode 100644 index 0000000000..201a7bc65d --- /dev/null +++ b/web/app/components/plugins/card/card-mock.ts @@ -0,0 +1,160 @@ +import type { PluginDeclaration } from '../types' +import { PluginType } from '../types' + +export const toolNeko: PluginDeclaration = { + plugin_unique_identifier: 'xxxxxx', + version: '0.0.1', + author: 'langgenius', + name: 'neko', + description: { + en_US: 'Neko is a cute cat.', + zh_Hans: '这是一只可爱的小猫。', + pt_BR: 'Neko is a cute cat.', + ja_JP: 'Neko is a cute cat.', + }, + icon: '241e5209ecc8b5ce6b7a29a8e50388e9c75b89c3047c6ecd8e552f26de758883.svg', + label: { + en_US: 'Neko', + zh_Hans: 'Neko', + pt_BR: 'Neko', + ja_JP: 'Neko', + }, + category: 'extension' as any, + created_at: '2024-07-12T08:03:44.658609Z', + resource: { + memory: 1048576, + permission: { + tool: { + enabled: true, + }, + model: { + enabled: true, + llm: true, + text_embedding: false, + rerank: false, + tts: false, + speech2text: false, + moderation: false, + }, + node: null, + endpoint: { + enabled: true, + }, + storage: { + enabled: true, + size: 1048576, + }, + }, + }, + plugins: { + tools: null, + models: null, + endpoints: [ + 'provider/neko.yaml', + ], + }, + tags: [], + verified: false, + tool: null, + model: null, + endpoint: null, +} + +export const toolNotion = { + type: PluginType.tool, + org: 'Notion', + name: 'notion page search', + version: '1.2.0', + latest_version: '1.3.0', + icon: 'https://via.placeholder.com/150', + label: { + 'en-US': 'Notion Page Search', + 'zh-Hans': 'Notion 页面搜索', + }, + brief: { + 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', + 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', + }, +} + +export const toolNotionManifest: PluginDeclaration = { + version: '1.2.0', + author: 'Notion', + icon: 'https://via.placeholder.com/150', + name: 'notion page search', + category: PluginType.tool, + label: { + 'en-US': 'Notion Page Search', + 'zh-Hans': 'Notion 页面搜索', + }, + description: { + 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', + 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', + }, + created_at: '2022-01-01', + resource: {}, + plugins: {}, + verified: true, + endpoint: { + settings: [], + endpoints: [], + }, + tool: { + } as any, + model: {}, +} + +export const extensionDallE = { + type: PluginType.extension, + org: 'OpenAI', + name: 'DALL-E', + version: '1.1.0', + latest_version: '1.2.0', + install_count: 1234, + icon: 'https://via.placeholder.com/150', + label: { + 'en-US': 'DALL-E', + 'zh-Hans': 'DALL-E', + }, + brief: { + 'en-US': 'Description: A simple plugin to use OpenAI DALL-E model.', + 'zh-Hans': '一个使用 OpenAI DALL-E 模型的简单插件。', + }, +} + +export const modelGPT4 = { + type: PluginType.model, + org: 'OpenAI', + name: 'GPT-4', + version: '1.0.0', + latest_version: '1.0.0', + install_count: 99999, + icon: 'https://via.placeholder.com/150', + label: { + 'en-US': 'GPT-4', + 'zh-Hans': 'GPT-4', + }, + brief: { + 'en-US': 'Description: A simple plugin to use OpenAI GPT-4 model.', + 'zh-Hans': '一个使用 OpenAI GPT-4 模型的简单插件。', + }, +} + +export const customTool = { + type: PluginType.tool, + name: 'notion page search', + version: '1.2.0', + latest_version: '1.3.0', + icon: { + content: '🕵️', + background: '#FEF7C3', + }, + label: { + 'en-US': 'Notion Page Search', + 'zh-Hans': 'Notion 页面搜索', + }, + brief: { + 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', + 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', + }, +} diff --git a/web/app/components/plugins/card/card-more-info.tsx b/web/app/components/plugins/card/card-more-info.tsx new file mode 100644 index 0000000000..b7ba8c1a53 --- /dev/null +++ b/web/app/components/plugins/card/card-more-info.tsx @@ -0,0 +1,36 @@ +import DownloadCount from './base/download-count' + +type Props = { + downloadCount?: number + tags: string[] +} + +const CardMoreInfo = ({ + downloadCount, + tags, +}: Props) => { + return ( + <div className="flex items-center h-5"> + {downloadCount !== undefined && <DownloadCount downloadCount={downloadCount} />} + {downloadCount !== undefined && tags && tags.length > 0 && <div className="mx-2 text-text-quaternary system-xs-regular">·</div>} + {tags && tags.length > 0 && ( + <> + <div className="flex flex-wrap space-x-2 h-4 overflow-hidden"> + {tags.map(tag => ( + <div + key={tag} + className="flex space-x-1 system-xs-regular max-w-[120px] overflow-hidden" + title={`# ${tag}`} + > + <span className="text-text-quaternary">#</span> + <span className="truncate text-text-tertiary">{tag}</span> + </div> + ))} + </div> + </> + )} + </div> + ) +} + +export default CardMoreInfo diff --git a/web/app/components/plugins/card/index.tsx b/web/app/components/plugins/card/index.tsx new file mode 100644 index 0000000000..04ef0dd1ee --- /dev/null +++ b/web/app/components/plugins/card/index.tsx @@ -0,0 +1,92 @@ +'use client' +import React from 'react' +import { RiVerifiedBadgeLine } from '@remixicon/react' +import type { Plugin } from '../types' +import Icon from '../card/base/card-icon' +import CornerMark from './base/corner-mark' +import Title from './base/title' +import OrgInfo from './base/org-info' +import Description from './base/description' +import Placeholder from './base/placeholder' +import cn from '@/utils/classnames' +import { useGetLanguage } from '@/context/i18n' +import { getLanguage } from '@/i18n/language' +import { useSingleCategories } from '../hooks' +import { renderI18nObject } from '@/hooks/use-i18n' + +export type Props = { + className?: string + payload: Plugin + titleLeft?: React.ReactNode + installed?: boolean + installFailed?: boolean + hideCornerMark?: boolean + descriptionLineRows?: number + footer?: React.ReactNode + isLoading?: boolean + loadingFileName?: string + locale?: string +} + +const Card = ({ + className, + payload, + titleLeft, + installed, + installFailed, + hideCornerMark, + descriptionLineRows = 2, + footer, + isLoading = false, + loadingFileName, + locale: localeFromProps, +}: Props) => { + const defaultLocale = useGetLanguage() + const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale + const { categoriesMap } = useSingleCategories() + const { category, type, name, org, label, brief, icon, verified } = payload + const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent_strategy'].includes(type) + const cornerMark = isBundle ? categoriesMap.bundle?.label : categoriesMap[category]?.label + const getLocalizedText = (obj: Record<string, string> | undefined) => + obj ? renderI18nObject(obj, locale) : '' + + const wrapClassName = cn('relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className) + if (isLoading) { + return ( + <Placeholder + wrapClassName={wrapClassName} + loadingFileName={loadingFileName!} + /> + ) + } + + return ( + <div className={wrapClassName}> + {!hideCornerMark && <CornerMark text={cornerMark} />} + {/* Header */} + <div className="flex"> + <Icon src={icon} installed={installed} installFailed={installFailed} /> + <div className="ml-3 w-0 grow"> + <div className="flex items-center h-5"> + <Title title={getLocalizedText(label)} /> + {verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />} + {titleLeft} {/* This can be version badge */} + </div> + <OrgInfo + className="mt-0.5" + orgName={org} + packageName={name} + /> + </div> + </div> + <Description + className="mt-3" + text={getLocalizedText(brief)} + descriptionLineRows={descriptionLineRows} + /> + {footer && <div>{footer}</div>} + </div> + ) +} + +export default React.memo(Card) diff --git a/web/app/components/plugins/constants.ts b/web/app/components/plugins/constants.ts new file mode 100644 index 0000000000..02439be510 --- /dev/null +++ b/web/app/components/plugins/constants.ts @@ -0,0 +1,27 @@ +export const tagKeys = [ + 'agent', + 'search', + 'image', + 'videos', + 'weather', + 'finance', + 'design', + 'travel', + 'social', + 'news', + 'medical', + 'productivity', + 'education', + 'business', + 'entertainment', + 'utilities', + 'other', +] + +export const categoryKeys = [ + 'model', + 'tool', + 'agent-strategy', + 'extension', + 'bundle', +] diff --git a/web/app/components/plugins/hooks.ts b/web/app/components/plugins/hooks.ts new file mode 100644 index 0000000000..f4b81d98c1 --- /dev/null +++ b/web/app/components/plugins/hooks.ts @@ -0,0 +1,94 @@ +import { useTranslation } from 'react-i18next' +import type { TFunction } from 'i18next' +import { + categoryKeys, + tagKeys, +} from './constants' + +type Tag = { + name: string + label: string +} + +export const useTags = (translateFromOut?: TFunction) => { + const { t: translation } = useTranslation() + const t = translateFromOut || translation + + const tags = tagKeys.map((tag) => { + return { + name: tag, + label: t(`pluginTags.tags.${tag}`), + } + }) + + const tagsMap = tags.reduce((acc, tag) => { + acc[tag.name] = tag + return acc + }, {} as Record<string, Tag>) + + return { + tags, + tagsMap, + } +} + +type Category = { + name: string + label: string +} + +export const useCategories = (translateFromOut?: TFunction) => { + const { t: translation } = useTranslation() + const t = translateFromOut || translation + + const categories = categoryKeys.map((category) => { + if (category === 'agent-strategy') { + return { + name: 'agent-strategy', + label: t('plugin.category.agents'), + } + } + return { + name: category, + label: t(`plugin.category.${category}s`), + } + }) + + const categoriesMap = categories.reduce((acc, category) => { + acc[category.name] = category + return acc + }, {} as Record<string, Category>) + + return { + categories, + categoriesMap, + } +} + +export const useSingleCategories = (translateFromOut?: TFunction) => { + const { t: translation } = useTranslation() + const t = translateFromOut || translation + + const categories = categoryKeys.map((category) => { + if (category === 'agent-strategy') { + return { + name: 'agent-strategy', + label: t('plugin.categorySingle.agent'), + } + } + return { + name: category, + label: t(`plugin.categorySingle.${category}`), + } + }) + + const categoriesMap = categories.reduce((acc, category) => { + acc[category.name] = category + return acc + }, {} as Record<string, Category>) + + return { + categories, + categoriesMap, + } +} diff --git a/web/app/components/plugins/install-plugin/base/check-task-status.ts b/web/app/components/plugins/install-plugin/base/check-task-status.ts new file mode 100644 index 0000000000..320f50d70a --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/check-task-status.ts @@ -0,0 +1,63 @@ +import { checkTaskStatus as fetchCheckTaskStatus } from '@/service/plugins' +import type { PluginStatus } from '../../types' +import { TaskStatus } from '../../types' +import { sleep } from '@/utils' + +const INTERVAL = 10 * 1000 // 10 seconds + +type Params = { + taskId: string + pluginUniqueIdentifier: string +} + +function checkTaskStatus() { + let nextStatus = TaskStatus.running + let isStop = false + + const doCheckStatus = async ({ + taskId, + pluginUniqueIdentifier, + }: Params) => { + if (isStop) { + return { + status: TaskStatus.success, + } + } + const res = await fetchCheckTaskStatus(taskId) + const { plugins } = res.task + const plugin = plugins.find((p: PluginStatus) => p.plugin_unique_identifier === pluginUniqueIdentifier) + if (!plugin) { + nextStatus = TaskStatus.failed + return { + status: TaskStatus.failed, + error: 'Plugin package not found', + } + } + nextStatus = plugin.status + if (nextStatus === TaskStatus.running) { + await sleep(INTERVAL) + return await doCheckStatus({ + taskId, + pluginUniqueIdentifier, + }) + } + if (nextStatus === TaskStatus.failed) { + return { + status: TaskStatus.failed, + error: plugin.message, + } + } + return ({ + status: TaskStatus.success, + }) + } + + return { + check: doCheckStatus, + stop: () => { + isStop = true + }, + } +} + +export default checkTaskStatus diff --git a/web/app/components/plugins/install-plugin/base/installed.tsx b/web/app/components/plugins/install-plugin/base/installed.tsx new file mode 100644 index 0000000000..efe8d4af76 --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/installed.tsx @@ -0,0 +1,60 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import Card from '../../card' +import Button from '@/app/components/base/button' +import type { Plugin, PluginDeclaration, PluginManifestInMarket } from '../../types' +import { pluginManifestInMarketToPluginProps, pluginManifestToCardPluginProps } from '../utils' +import Badge, { BadgeState } from '@/app/components/base/badge/index' + +type Props = { + payload?: Plugin | PluginDeclaration | PluginManifestInMarket | null + isMarketPayload?: boolean + isFailed: boolean + errMsg?: string | null + onCancel: () => void +} + +const Installed: FC<Props> = ({ + payload, + isMarketPayload, + isFailed, + errMsg, + onCancel, +}) => { + const { t } = useTranslation() + + const handleClose = () => { + onCancel() + } + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + <p className='text-text-secondary system-md-regular'>{(isFailed && errMsg) ? errMsg : t(`plugin.installModal.${isFailed ? 'installFailedDesc' : 'installedSuccessfullyDesc'}`)}</p> + {payload && ( + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + className='w-full' + payload={isMarketPayload ? pluginManifestInMarketToPluginProps(payload as PluginManifestInMarket) : pluginManifestToCardPluginProps(payload as PluginDeclaration)} + installed={!isFailed} + installFailed={isFailed} + titleLeft={<Badge className='mx-1' size="s" state={BadgeState.Default}>{(payload as PluginDeclaration).version || (payload as PluginManifestInMarket).latest_version}</Badge>} + /> + </div> + )} + </div> + {/* Action Buttons */} + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + <Button + variant='primary' + className='min-w-[72px]' + onClick={handleClose} + > + {t('common.operation.close')} + </Button> + </div> + </> + ) +} +export default React.memo(Installed) diff --git a/web/app/components/plugins/install-plugin/base/loading-error.tsx b/web/app/components/plugins/install-plugin/base/loading-error.tsx new file mode 100644 index 0000000000..eb698bb573 --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/loading-error.tsx @@ -0,0 +1,45 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { Group } from '../../../base/icons/src/vender/other' +import { LoadingPlaceholder } from '@/app/components/plugins/card/base/placeholder' +import Checkbox from '@/app/components/base/checkbox' +import { RiCloseLine } from '@remixicon/react' +import { useTranslation } from 'react-i18next' + +const LoadingError: FC = () => { + const { t } = useTranslation() + return ( + <div className='flex items-center space-x-2'> + <Checkbox + className='shrink-0' + checked={false} + disabled + /> + <div className='grow relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs'> + <div className="flex"> + <div + className='relative flex w-10 h-10 p-1 justify-center items-center gap-2 rounded-[10px] + border-[0.5px] border-state-destructive-border bg-state-destructive-hover backdrop-blur-sm'> + <div className='flex w-5 h-5 justify-center items-center'> + <Group className='text-text-quaternary' /> + </div> + <div className='absolute bottom-[-4px] right-[-4px] rounded-full border-[2px] border-components-panel-bg bg-state-destructive-solid'> + <RiCloseLine className='w-3 h-3 text-text-primary-on-surface' /> + </div> + </div> + <div className="ml-3 grow"> + <div className="flex items-center h-5 system-md-semibold text-text-destructive"> + {t('plugin.installModal.pluginLoadError')} + </div> + <div className='mt-0.5 system-xs-regular text-text-tertiary'> + {t('plugin.installModal.pluginLoadErrorDesc')} + </div> + </div> + </div> + <LoadingPlaceholder className="mt-3 w-[420px]" /> + </div> + </div> + ) +} +export default React.memo(LoadingError) diff --git a/web/app/components/plugins/install-plugin/base/loading.tsx b/web/app/components/plugins/install-plugin/base/loading.tsx new file mode 100644 index 0000000000..52cccc2cd0 --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/loading.tsx @@ -0,0 +1,23 @@ +'use client' +import React from 'react' +import Placeholder from '../../card/base/placeholder' +import Checkbox from '@/app/components/base/checkbox' + +const Loading = () => { + return ( + <div className='flex items-center space-x-2'> + <Checkbox + className='shrink-0' + checked={false} + disabled + /> + <div className='grow relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs'> + <Placeholder + wrapClassName='w-full' + /> + </div> + </div> + ) +} + +export default React.memo(Loading) diff --git a/web/app/components/plugins/install-plugin/base/use-get-icon.ts b/web/app/components/plugins/install-plugin/base/use-get-icon.ts new file mode 100644 index 0000000000..bb46f27f53 --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/use-get-icon.ts @@ -0,0 +1,16 @@ +import { useCallback } from 'react' +import { apiPrefix } from '@/config' +import { useSelector } from '@/context/app-context' + +const useGetIcon = () => { + const currentWorkspace = useSelector(s => s.currentWorkspace) + const getIconUrl = useCallback((fileName: string) => { + return `${apiPrefix}/workspaces/current/plugin/icon?tenant_id=${currentWorkspace.id}&filename=${fileName}` + }, [currentWorkspace.id]) + + return { + getIconUrl, + } +} + +export default useGetIcon diff --git a/web/app/components/plugins/install-plugin/base/version.tsx b/web/app/components/plugins/install-plugin/base/version.tsx new file mode 100644 index 0000000000..67bbc8ed2e --- /dev/null +++ b/web/app/components/plugins/install-plugin/base/version.tsx @@ -0,0 +1,34 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import Badge, { BadgeState } from '@/app/components/base/badge/index' +import type { VersionProps } from '../../types' + +const Version: FC<VersionProps> = ({ + hasInstalled, + installedVersion, + toInstallVersion, +}) => { + return ( + <> + { + !hasInstalled + ? ( + <Badge className='mx-1' size="s" state={BadgeState.Default}>{toInstallVersion}</Badge> + ) + : ( + <> + <Badge className='mx-1' size="s" state={BadgeState.Warning}> + {`${installedVersion} -> ${toInstallVersion}`} + </Badge> + {/* <div className='flex px-0.5 justify-center items-center gap-0.5'> + <div className='text-text-warning system-xs-medium'>Used in 3 apps</div> + <RiInformation2Line className='w-4 h-4 text-text-tertiary' /> + </div> */} + </> + ) + } + </> + ) +} +export default React.memo(Version) diff --git a/web/app/components/plugins/install-plugin/hooks.ts b/web/app/components/plugins/install-plugin/hooks.ts new file mode 100644 index 0000000000..5da4c75c51 --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks.ts @@ -0,0 +1,107 @@ +import Toast, { type IToastProps } from '@/app/components/base/toast' +import { uploadGitHub } from '@/service/plugins' +import { compareVersion, getLatestVersion } from '@/utils/semver' +import type { GitHubRepoReleaseResponse } from '../types' +import { GITHUB_ACCESS_TOKEN } from '@/config' + +const formatReleases = (releases: any) => { + return releases.map((release: any) => ({ + tag_name: release.tag_name, + assets: release.assets.map((asset: any) => ({ + browser_download_url: asset.browser_download_url, + name: asset.name, + })), + })) +} + +export const useGitHubReleases = () => { + const fetchReleases = async (owner: string, repo: string) => { + try { + if (!GITHUB_ACCESS_TOKEN) { + // Fetch releases without authentication from client + const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases`) + if (!res.ok) throw new Error('Failed to fetch repository releases') + const data = await res.json() + return formatReleases(data) + } + else { + // Fetch releases with authentication from server + const res = await fetch(`/repos/${owner}/${repo}/releases`) + const bodyJson = await res.json() + if (bodyJson.status !== 200) throw new Error(bodyJson.data.message) + return formatReleases(bodyJson.data) + } + } + catch (error) { + if (error instanceof Error) { + Toast.notify({ + type: 'error', + message: error.message, + }) + } + else { + Toast.notify({ + type: 'error', + message: 'Failed to fetch repository releases', + }) + } + return [] + } + } + + const checkForUpdates = (fetchedReleases: GitHubRepoReleaseResponse[], currentVersion: string) => { + let needUpdate = false + const toastProps: IToastProps = { + type: 'info', + message: 'No new version available', + } + if (fetchedReleases.length === 0) { + toastProps.type = 'error' + toastProps.message = 'Input releases is empty' + return { needUpdate, toastProps } + } + const versions = fetchedReleases.map(release => release.tag_name) + const latestVersion = getLatestVersion(versions) + try { + needUpdate = compareVersion(latestVersion, currentVersion) === 1 + if (needUpdate) + toastProps.message = `New version available: ${latestVersion}` + } + catch { + needUpdate = false + toastProps.type = 'error' + toastProps.message = 'Fail to compare versions, please check the version format' + } + return { needUpdate, toastProps } + } + + return { fetchReleases, checkForUpdates } +} + +export const useGitHubUpload = () => { + const handleUpload = async ( + repoUrl: string, + selectedVersion: string, + selectedPackage: string, + onSuccess?: (GitHubPackage: { manifest: any; unique_identifier: string }) => void, + ) => { + try { + const response = await uploadGitHub(repoUrl, selectedVersion, selectedPackage) + const GitHubPackage = { + manifest: response.manifest, + unique_identifier: response.unique_identifier, + } + if (onSuccess) onSuccess(GitHubPackage) + return GitHubPackage + } + catch (error) { + Toast.notify({ + type: 'error', + message: 'Error uploading package', + }) + throw error + } + } + + return { handleUpload } +} diff --git a/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx new file mode 100644 index 0000000000..e72648fcec --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-check-installed.tsx @@ -0,0 +1,32 @@ +import { useCheckInstalled as useDoCheckInstalled } from '@/service/use-plugins' + +import { useMemo } from 'react' +import type { VersionInfo } from '../../types' +type Props = { + pluginIds: string[], + enabled: boolean +} +const useCheckInstalled = (props: Props) => { + const { data, isLoading, error } = useDoCheckInstalled(props) + + const installedInfo = useMemo(() => { + if (!data) + return undefined + + const res: Record<string, VersionInfo> = {} + data?.plugins.forEach((plugin) => { + res[plugin.plugin_id] = { + installedVersion: plugin.declaration.version, + uniqueIdentifier: plugin.plugin_unique_identifier, + } + }) + return res + }, [data]) + return { + installedInfo, + isLoading, + error, + } +} + +export default useCheckInstalled diff --git a/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts new file mode 100644 index 0000000000..4b8d5e8293 --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts @@ -0,0 +1,57 @@ +import { sleep } from '@/utils' + +const animTime = 750 +const modalClassName = 'install-modal' +const COUNT_DOWN_TIME = 15000 // 15s + +function getElemCenter(elem: HTMLElement) { + const rect = elem.getBoundingClientRect() + return { + x: rect.left + rect.width / 2 + window.scrollX, + y: rect.top + rect.height / 2 + window.scrollY, + } +} + +const useFoldAnimInto = (onClose: () => void) => { + let countDownRunId: number + const clearCountDown = () => { + clearTimeout(countDownRunId) + } + // modalElem fold into plugin install task btn + const foldIntoAnim = async () => { + clearCountDown() + const modalElem = document.querySelector(`.${modalClassName}`) as HTMLElement + const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger') || document.querySelector('.plugins-nav-button') + + if (!modalElem || !pluginTaskTriggerElem) { + onClose() + return + } + + const modelCenter = getElemCenter(modalElem) + const modalElemRect = modalElem.getBoundingClientRect() + const pluginTaskTriggerCenter = getElemCenter(pluginTaskTriggerElem) + const xDiff = pluginTaskTriggerCenter.x - modelCenter.x + const yDiff = pluginTaskTriggerCenter.y - modelCenter.y + const scale = 1 / Math.max(modalElemRect.width, modalElemRect.height) + modalElem.style.transition = `all cubic-bezier(0.4, 0, 0.2, 1) ${animTime}ms` + modalElem.style.transform = `translate(${xDiff}px, ${yDiff}px) scale(${scale})` + await sleep(animTime) + onClose() + } + + const countDownFoldIntoAnim = async () => { + countDownRunId = window.setTimeout(() => { + foldIntoAnim() + }, COUNT_DOWN_TIME) + } + + return { + modalClassName, + foldIntoAnim, + clearCountDown, + countDownFoldIntoAnim, + } +} + +export default useFoldAnimInto diff --git a/web/app/components/plugins/install-plugin/hooks/use-hide-logic.ts b/web/app/components/plugins/install-plugin/hooks/use-hide-logic.ts new file mode 100644 index 0000000000..e5d2d1883a --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-hide-logic.ts @@ -0,0 +1,40 @@ +import { useCallback, useState } from 'react' +import useFoldAnimInto from './use-fold-anim-into' + +const useHideLogic = (onClose: () => void) => { + const { + modalClassName, + foldIntoAnim: doFoldAnimInto, + clearCountDown, + countDownFoldIntoAnim, + } = useFoldAnimInto(onClose) + + const [isInstalling, doSetIsInstalling] = useState(false) + const setIsInstalling = useCallback((isInstalling: boolean) => { + if (!isInstalling) + clearCountDown() + doSetIsInstalling(isInstalling) + }, [clearCountDown]) + + const foldAnimInto = useCallback(() => { + if (isInstalling) { + doFoldAnimInto() + return + } + onClose() + }, [doFoldAnimInto, isInstalling, onClose]) + + const handleStartToInstall = useCallback(() => { + setIsInstalling(true) + countDownFoldIntoAnim() + }, [countDownFoldIntoAnim, setIsInstalling]) + + return { + modalClassName, + foldAnimInto, + setIsInstalling, + handleStartToInstall, + } +} + +export default useHideLogic diff --git a/web/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list.tsx b/web/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list.tsx new file mode 100644 index 0000000000..acb486c703 --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list.tsx @@ -0,0 +1,45 @@ +import { useUpdateModelProviders } from '@/app/components/header/account-setting/model-provider-page/hooks' +import { useProviderContext } from '@/context/provider-context' +import { useInvalidateInstalledPluginList } from '@/service/use-plugins' +import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools' +import { useInvalidateStrategyProviders } from '@/service/use-strategy' +import type { Plugin, PluginDeclaration, PluginManifestInMarket } from '../../types' +import { PluginType } from '../../types' + +const useRefreshPluginList = () => { + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + const updateModelProviders = useUpdateModelProviders() + const { refreshModelProviders } = useProviderContext() + + const invalidateAllToolProviders = useInvalidateAllToolProviders() + const invalidateAllBuiltInTools = useInvalidateAllBuiltInTools() + + const invalidateStrategyProviders = useInvalidateStrategyProviders() + return { + refreshPluginList: (manifest?: PluginManifestInMarket | Plugin | PluginDeclaration | null, refreshAllType?: boolean) => { + // installed list + invalidateInstalledPluginList() + + if (!manifest) return + + // tool page, tool select + if (PluginType.tool.includes(manifest.category) || refreshAllType) { + invalidateAllToolProviders() + invalidateAllBuiltInTools() + // TODO: update suggested tools. It's a function in hook useMarketplacePlugins,handleUpdatePlugins + } + + // model select + if (PluginType.model.includes(manifest.category) || refreshAllType) { + updateModelProviders() + refreshModelProviders() + } + + // agent select + if (PluginType.agent.includes(manifest.category) || refreshAllType) + invalidateStrategyProviders() + }, + } +} + +export default useRefreshPluginList diff --git a/web/app/components/plugins/install-plugin/install-bundle/index.tsx b/web/app/components/plugins/install-plugin/install-bundle/index.tsx new file mode 100644 index 0000000000..84750d65ad --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/index.tsx @@ -0,0 +1,75 @@ +'use client' +import type { FC } from 'react' +import Modal from '@/app/components/base/modal' +import React, { useCallback, useState } from 'react' +import { InstallStep } from '../../types' +import type { Dependency } from '../../types' +import ReadyToInstall from './ready-to-install' +import { useTranslation } from 'react-i18next' +import useHideLogic from '../hooks/use-hide-logic' +import cn from '@/utils/classnames' + +const i18nPrefix = 'plugin.installModal' + +export enum InstallType { + fromLocal = 'fromLocal', + fromMarketplace = 'fromMarketplace', + fromDSL = 'fromDSL', +} + +type Props = { + installType?: InstallType + fromDSLPayload: Dependency[] + // plugins?: PluginDeclaration[] + onClose: () => void +} + +const InstallBundle: FC<Props> = ({ + installType = InstallType.fromMarketplace, + fromDSLPayload, + onClose, +}) => { + const { t } = useTranslation() + const [step, setStep] = useState<InstallStep>(installType === InstallType.fromMarketplace ? InstallStep.readyToInstall : InstallStep.uploading) + + const { + modalClassName, + foldAnimInto, + setIsInstalling, + handleStartToInstall, + } = useHideLogic(onClose) + + const getTitle = useCallback(() => { + if (step === InstallStep.uploadFailed) + return t(`${i18nPrefix}.uploadFailed`) + if (step === InstallStep.installed) + return t(`${i18nPrefix}.installComplete`) + + return t(`${i18nPrefix}.installPlugin`) + }, [step, t]) + + return ( + <Modal + isShow={true} + onClose={foldAnimInto} + className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')} + closable + > + <div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'> + <div className='self-stretch text-text-primary title-2xl-semi-bold'> + {getTitle()} + </div> + </div> + <ReadyToInstall + step={step} + onStepChange={setStep} + onStartToInstall={handleStartToInstall} + setIsInstalling={setIsInstalling} + allPlugins={fromDSLPayload} + onClose={onClose} + /> + </Modal> + ) +} + +export default React.memo(InstallBundle) diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx new file mode 100644 index 0000000000..96abaa2e1c --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/item/github-item.tsx @@ -0,0 +1,62 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect } from 'react' +import type { GitHubItemAndMarketPlaceDependency, Plugin } from '../../../types' +import { pluginManifestToCardPluginProps } from '../../utils' +import { useUploadGitHub } from '@/service/use-plugins' +import Loading from '../../base/loading' +import LoadedItem from './loaded-item' +import type { VersionProps } from '@/app/components/plugins/types' + +type Props = { + checked: boolean + onCheckedChange: (plugin: Plugin) => void + dependency: GitHubItemAndMarketPlaceDependency + versionInfo: VersionProps + onFetchedPayload: (payload: Plugin) => void + onFetchError: () => void +} + +const Item: FC<Props> = ({ + checked, + onCheckedChange, + dependency, + versionInfo, + onFetchedPayload, + onFetchError, +}) => { + const info = dependency.value + const { data, error } = useUploadGitHub({ + repo: info.repo!, + version: info.release! || info.version!, + package: info.packages! || info.package!, + }) + const [payload, setPayload] = React.useState<Plugin | null>(null) + useEffect(() => { + if (data) { + const payload = { + ...pluginManifestToCardPluginProps(data.manifest), + plugin_id: data.unique_identifier, + } + onFetchedPayload(payload) + setPayload(payload) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [data]) + useEffect(() => { + if (error) + onFetchError() + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error]) + if (!payload) return <Loading /> + return ( + <LoadedItem + payload={payload} + versionInfo={versionInfo} + checked={checked} + onCheckedChange={onCheckedChange} + /> + ) +} +export default React.memo(Item) diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx new file mode 100644 index 0000000000..5eb4c94abe --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/item/loaded-item.tsx @@ -0,0 +1,51 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { Plugin } from '../../../types' +import Card from '../../../card' +import Checkbox from '@/app/components/base/checkbox' +import useGetIcon from '../../base/use-get-icon' +import { MARKETPLACE_API_PREFIX } from '@/config' +import Version from '../../base/version' +import type { VersionProps } from '../../../types' + +type Props = { + checked: boolean + onCheckedChange: (plugin: Plugin) => void + payload: Plugin + isFromMarketPlace?: boolean + versionInfo: VersionProps +} + +const LoadedItem: FC<Props> = ({ + checked, + onCheckedChange, + payload, + isFromMarketPlace, + versionInfo: particleVersionInfo, +}) => { + const { getIconUrl } = useGetIcon() + const versionInfo = { + ...particleVersionInfo, + toInstallVersion: payload.version, + } + return ( + <div className='flex items-center space-x-2'> + <Checkbox + className='shrink-0' + checked={checked} + onCheck={() => onCheckedChange(payload)} + /> + <Card + className='grow' + payload={{ + ...payload, + icon: isFromMarketPlace ? `${MARKETPLACE_API_PREFIX}/plugins/${payload.org}/${payload.name}/icon` : getIconUrl(payload.icon), + }} + titleLeft={payload.version ? <Version {...versionInfo} /> : null} + /> + </div> + ) +} + +export default React.memo(LoadedItem) diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx new file mode 100644 index 0000000000..3389bdb0ad --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/item/marketplace-item.tsx @@ -0,0 +1,36 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { Plugin } from '../../../types' +import Loading from '../../base/loading' +import LoadedItem from './loaded-item' +import type { VersionProps } from '@/app/components/plugins/types' + +type Props = { + checked: boolean + onCheckedChange: (plugin: Plugin) => void + payload?: Plugin + version: string + versionInfo: VersionProps +} + +const MarketPlaceItem: FC<Props> = ({ + checked, + onCheckedChange, + payload, + version, + versionInfo, +}) => { + if (!payload) return <Loading /> + return ( + <LoadedItem + checked={checked} + onCheckedChange={onCheckedChange} + payload={{ ...payload, version }} + isFromMarketPlace + versionInfo={versionInfo} + /> + ) +} + +export default React.memo(MarketPlaceItem) diff --git a/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx b/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx new file mode 100644 index 0000000000..101c8facaf --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/item/package-item.tsx @@ -0,0 +1,41 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { Plugin } from '../../../types' +import type { PackageDependency } from '../../../types' +import { pluginManifestToCardPluginProps } from '../../utils' +import LoadedItem from './loaded-item' +import LoadingError from '../../base/loading-error' +import type { VersionProps } from '@/app/components/plugins/types' + +type Props = { + checked: boolean + onCheckedChange: (plugin: Plugin) => void + payload: PackageDependency + isFromMarketPlace?: boolean + versionInfo: VersionProps +} + +const PackageItem: FC<Props> = ({ + payload, + checked, + onCheckedChange, + isFromMarketPlace, + versionInfo, +}) => { + if (!payload.value?.manifest) + return <LoadingError /> + + const plugin = pluginManifestToCardPluginProps(payload.value.manifest) + return ( + <LoadedItem + payload={plugin} + checked={checked} + onCheckedChange={onCheckedChange} + isFromMarketPlace={isFromMarketPlace} + versionInfo={versionInfo} + /> + ) +} + +export default React.memo(PackageItem) diff --git a/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx b/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx new file mode 100644 index 0000000000..63c0b5b07e --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/ready-to-install.tsx @@ -0,0 +1,57 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useState } from 'react' +import { InstallStep } from '../../types' +import Install from './steps/install' +import Installed from './steps/installed' +import type { Dependency, InstallStatusResponse, Plugin } from '../../types' + +type Props = { + step: InstallStep + onStepChange: (step: InstallStep) => void, + onStartToInstall: () => void + setIsInstalling: (isInstalling: boolean) => void + allPlugins: Dependency[] + onClose: () => void + isFromMarketPlace?: boolean +} + +const ReadyToInstall: FC<Props> = ({ + step, + onStepChange, + onStartToInstall, + setIsInstalling, + allPlugins, + onClose, + isFromMarketPlace, +}) => { + const [installedPlugins, setInstalledPlugins] = useState<Plugin[]>([]) + const [installStatus, setInstallStatus] = useState<InstallStatusResponse[]>([]) + const handleInstalled = useCallback((plugins: Plugin[], installStatus: InstallStatusResponse[]) => { + setInstallStatus(installStatus) + setInstalledPlugins(plugins) + onStepChange(InstallStep.installed) + setIsInstalling(false) + }, [onStepChange, setIsInstalling]) + return ( + <> + {step === InstallStep.readyToInstall && ( + <Install + allPlugins={allPlugins} + onCancel={onClose} + onStartToInstall={onStartToInstall} + onInstalled={handleInstalled} + isFromMarketPlace={isFromMarketPlace} + /> + )} + {step === InstallStep.installed && ( + <Installed + list={installedPlugins} + installStatus={installStatus} + onCancel={onClose} + /> + )} + </> + ) +} +export default React.memo(ReadyToInstall) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx new file mode 100644 index 0000000000..48b1ecd325 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install-multi.tsx @@ -0,0 +1,218 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useEffect, useMemo, useState } from 'react' +import type { Dependency, GitHubItemAndMarketPlaceDependency, PackageDependency, Plugin, VersionInfo } from '../../../types' +import MarketplaceItem from '../item/marketplace-item' +import GithubItem from '../item/github-item' +import { useFetchPluginsInMarketPlaceByIds, useFetchPluginsInMarketPlaceByInfo } from '@/service/use-plugins' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' +import produce from 'immer' +import PackageItem from '../item/package-item' +import LoadingError from '../../base/loading-error' + +type Props = { + allPlugins: Dependency[] + selectedPlugins: Plugin[] + onSelect: (plugin: Plugin, selectedIndex: number) => void + onLoadedAllPlugin: (installedInfo: Record<string, VersionInfo>) => void + isFromMarketPlace?: boolean +} + +const InstallByDSLList: FC<Props> = ({ + allPlugins, + selectedPlugins, + onSelect, + onLoadedAllPlugin, + isFromMarketPlace, +}) => { + // DSL has id, to get plugin info to show more info + const { isLoading: isFetchingMarketplaceDataById, data: infoGetById, error: infoByIdError } = useFetchPluginsInMarketPlaceByIds(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value.plugin_unique_identifier!)) + // has meta(org,name,version), to get id + const { isLoading: isFetchingDataByMeta, data: infoByMeta, error: infoByMetaError } = useFetchPluginsInMarketPlaceByInfo(allPlugins.filter(d => d.type === 'marketplace').map(d => (d as GitHubItemAndMarketPlaceDependency).value!)) + + const [plugins, doSetPlugins] = useState<(Plugin | undefined)[]>((() => { + const hasLocalPackage = allPlugins.some(d => d.type === 'package') + if (!hasLocalPackage) + return [] + + const _plugins = allPlugins.map((d) => { + if (d.type === 'package') { + return { + ...(d as any).value.manifest, + plugin_id: (d as any).value.unique_identifier, + } + } + + return undefined + }) + return _plugins + })()) + + const pluginsRef = React.useRef<(Plugin | undefined)[]>(plugins) + + const setPlugins = useCallback((p: (Plugin | undefined)[]) => { + doSetPlugins(p) + pluginsRef.current = p + }, []) + + const [errorIndexes, setErrorIndexes] = useState<number[]>([]) + + const handleGitHubPluginFetched = useCallback((index: number) => { + return (p: Plugin) => { + const nextPlugins = produce(pluginsRef.current, (draft) => { + draft[index] = p + }) + setPlugins(nextPlugins) + } + }, [setPlugins]) + + const handleGitHubPluginFetchError = useCallback((index: number) => { + return () => { + setErrorIndexes([...errorIndexes, index]) + } + }, [errorIndexes]) + + const marketPlaceInDSLIndex = useMemo(() => { + const res: number[] = [] + allPlugins.forEach((d, index) => { + if (d.type === 'marketplace') + res.push(index) + }) + return res + }, [allPlugins]) + + useEffect(() => { + if (!isFetchingMarketplaceDataById && infoGetById?.data.plugins) { + const payloads = infoGetById?.data.plugins + const failedIndex: number[] = [] + const nextPlugins = produce(pluginsRef.current, (draft) => { + marketPlaceInDSLIndex.forEach((index, i) => { + if (payloads[i]) + draft[index] = payloads[i] + else + failedIndex.push(index) + }) + }) + setPlugins(nextPlugins) + + if (failedIndex.length > 0) + setErrorIndexes([...errorIndexes, ...failedIndex]) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isFetchingMarketplaceDataById]) + + useEffect(() => { + if (!isFetchingDataByMeta && infoByMeta?.data.list) { + const payloads = infoByMeta?.data.list + const failedIndex: number[] = [] + const nextPlugins = produce(pluginsRef.current, (draft) => { + marketPlaceInDSLIndex.forEach((index, i) => { + if (payloads[i]) { + const item = payloads[i] + draft[index] = { + ...item.plugin, + plugin_id: item.version.unique_identifier, + } + } + else { + failedIndex.push(index) + } + }) + }) + setPlugins(nextPlugins) + if (failedIndex.length > 0) + setErrorIndexes([...errorIndexes, ...failedIndex]) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isFetchingDataByMeta]) + + useEffect(() => { + // get info all failed + if (infoByMetaError || infoByIdError) + setErrorIndexes([...errorIndexes, ...marketPlaceInDSLIndex]) + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [infoByMetaError, infoByIdError]) + + const isLoadedAllData = (plugins.filter(p => !!p).length + errorIndexes.length) === allPlugins.length + + const { installedInfo } = useCheckInstalled({ + pluginIds: plugins?.filter(p => !!p).map((d) => { + return `${d?.org || d?.author}/${d?.name}` + }) || [], + enabled: isLoadedAllData, + }) + + const getVersionInfo = useCallback((pluginId: string) => { + const pluginDetail = installedInfo?.[pluginId] + const hasInstalled = !!pluginDetail + return { + hasInstalled, + installedVersion: pluginDetail?.installedVersion, + toInstallVersion: '', + } + }, [installedInfo]) + + useEffect(() => { + if (isLoadedAllData && installedInfo) + onLoadedAllPlugin(installedInfo!) + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isLoadedAllData, installedInfo]) + + const handleSelect = useCallback((index: number) => { + return () => { + onSelect(plugins[index]!, index) + } + }, [onSelect, plugins]) + return ( + <> + {allPlugins.map((d, index) => { + if (errorIndexes.includes(index)) { + return ( + <LoadingError key={index} /> + ) + } + const plugin = plugins[index] + if (d.type === 'github') { + return (<GithubItem + key={index} + checked={!!selectedPlugins.find(p => p.plugin_id === plugins[index]?.plugin_id)} + onCheckedChange={handleSelect(index)} + dependency={d as GitHubItemAndMarketPlaceDependency} + onFetchedPayload={handleGitHubPluginFetched(index)} + onFetchError={handleGitHubPluginFetchError(index)} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} + />) + } + + if (d.type === 'marketplace') { + return ( + <MarketplaceItem + key={index} + checked={!!selectedPlugins.find(p => p.plugin_id === plugins[index]?.plugin_id)} + onCheckedChange={handleSelect(index)} + payload={plugins[index] as Plugin} + version={(d as GitHubItemAndMarketPlaceDependency).value.version!} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} + /> + ) + } + + // Local package + return ( + <PackageItem + key={index} + checked={!!selectedPlugins.find(p => p.plugin_id === plugins[index]?.plugin_id)} + onCheckedChange={handleSelect(index)} + payload={d as PackageDependency} + isFromMarketPlace={isFromMarketPlace} + versionInfo={getVersionInfo(`${plugin?.org || plugin?.author}/${plugin?.name}`)} + /> + ) + }) + } + </> + ) +} +export default React.memo(InstallByDSLList) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx new file mode 100644 index 0000000000..c70e2759d0 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx @@ -0,0 +1,116 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useState } from 'react' +import type { Dependency, InstallStatusResponse, Plugin, VersionInfo } from '../../../types' +import Button from '@/app/components/base/button' +import { RiLoader2Line } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import InstallMulti from './install-multi' +import { useInstallOrUpdate } from '@/service/use-plugins' +import useRefreshPluginList from '../../hooks/use-refresh-plugin-list' +const i18nPrefix = 'plugin.installModal' + +type Props = { + allPlugins: Dependency[] + onStartToInstall?: () => void + onInstalled: (plugins: Plugin[], installStatus: InstallStatusResponse[]) => void + onCancel: () => void + isFromMarketPlace?: boolean + isHideButton?: boolean +} + +const Install: FC<Props> = ({ + allPlugins, + onStartToInstall, + onInstalled, + onCancel, + isFromMarketPlace, + isHideButton, +}) => { + const { t } = useTranslation() + const [selectedPlugins, setSelectedPlugins] = React.useState<Plugin[]>([]) + const [selectedIndexes, setSelectedIndexes] = React.useState<number[]>([]) + const selectedPluginsNum = selectedPlugins.length + const { refreshPluginList } = useRefreshPluginList() + const handleSelect = (plugin: Plugin, selectedIndex: number) => { + const isSelected = !!selectedPlugins.find(p => p.plugin_id === plugin.plugin_id) + let nextSelectedPlugins + if (isSelected) + nextSelectedPlugins = selectedPlugins.filter(p => p.plugin_id !== plugin.plugin_id) + else + nextSelectedPlugins = [...selectedPlugins, plugin] + setSelectedPlugins(nextSelectedPlugins) + const nextSelectedIndexes = isSelected ? selectedIndexes.filter(i => i !== selectedIndex) : [...selectedIndexes, selectedIndex] + setSelectedIndexes(nextSelectedIndexes) + } + + const [canInstall, setCanInstall] = React.useState(false) + const [installedInfo, setInstalledInfo] = useState<Record<string, VersionInfo> | undefined>(undefined) + + const handleLoadedAllPlugin = useCallback((installedInfo: Record<string, VersionInfo> | undefined) => { + setInstalledInfo(installedInfo) + setCanInstall(true) + }, []) + + // Install from marketplace and github + const { mutate: installOrUpdate, isPending: isInstalling } = useInstallOrUpdate({ + onSuccess: (res: InstallStatusResponse[]) => { + onInstalled(selectedPlugins, res.map((r, i) => { + return ({ + ...r, + isFromMarketPlace: allPlugins[selectedIndexes[i]].type === 'marketplace', + }) + })) + const hasInstallSuccess = res.some(r => r.success) + if (hasInstallSuccess) + refreshPluginList(undefined, true) + }, + }) + const handleInstall = () => { + onStartToInstall?.() + installOrUpdate({ + payload: allPlugins.filter((_d, index) => selectedIndexes.includes(index)), + plugin: selectedPlugins, + installedInfo: installedInfo!, + }) + } + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + <div className='text-text-secondary system-md-regular'> + <p>{t(`${i18nPrefix}.${selectedPluginsNum > 1 ? 'readyToInstallPackages' : 'readyToInstallPackage'}`, { num: selectedPluginsNum })}</p> + </div> + <div className='w-full p-2 rounded-2xl bg-background-section-burn space-y-1'> + <InstallMulti + allPlugins={allPlugins} + selectedPlugins={selectedPlugins} + onSelect={handleSelect} + onLoadedAllPlugin={handleLoadedAllPlugin} + isFromMarketPlace={isFromMarketPlace} + /> + </div> + </div> + {/* Action Buttons */} + {!isHideButton && ( + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + {!canInstall && ( + <Button variant='secondary' className='min-w-[72px]' onClick={onCancel}> + {t('common.operation.cancel')} + </Button> + )} + <Button + variant='primary' + className='min-w-[72px] flex space-x-0.5' + disabled={!canInstall || isInstalling || selectedPlugins.length === 0} + onClick={handleInstall} + > + {isInstalling && <RiLoader2Line className='w-4 h-4 animate-spin-slow' />} + <span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span> + </Button> + </div> + )} + + </> + ) +} +export default React.memo(Install) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx new file mode 100644 index 0000000000..8f267cafcc --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx @@ -0,0 +1,65 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { InstallStatusResponse, Plugin } from '../../../types' +import Card from '@/app/components/plugins/card' +import Button from '@/app/components/base/button' +import { useTranslation } from 'react-i18next' +import Badge, { BadgeState } from '@/app/components/base/badge/index' +import useGetIcon from '../../base/use-get-icon' +import { MARKETPLACE_API_PREFIX } from '@/config' + +type Props = { + list: Plugin[] + installStatus: InstallStatusResponse[] + onCancel: () => void + isHideButton?: boolean +} + +const Installed: FC<Props> = ({ + list, + installStatus, + onCancel, + isHideButton, +}) => { + const { t } = useTranslation() + const { getIconUrl } = useGetIcon() + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + {/* <p className='text-text-secondary system-md-regular'>{(isFailed && errMsg) ? errMsg : t(`plugin.installModal.${isFailed ? 'installFailedDesc' : 'installedSuccessfullyDesc'}`)}</p> */} + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn space-y-1'> + {list.map((plugin, index) => { + return ( + <Card + key={plugin.plugin_id} + className='w-full' + payload={{ + ...plugin, + icon: installStatus[index].isFromMarketPlace ? `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon` : getIconUrl(plugin.icon), + }} + installed={installStatus[index].success} + installFailed={!installStatus[index].success} + titleLeft={plugin.version ? <Badge className='mx-1' size="s" state={BadgeState.Default}>{plugin.version}</Badge> : null} + /> + ) + })} + </div> + </div> + {/* Action Buttons */} + {!isHideButton && ( + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + <Button + variant='primary' + className='min-w-[72px]' + onClick={onCancel} + > + {t('common.operation.close')} + </Button> + </div> + )} + </> + ) +} + +export default React.memo(Installed) diff --git a/web/app/components/plugins/install-plugin/install-from-github/index.tsx b/web/app/components/plugins/install-plugin/install-from-github/index.tsx new file mode 100644 index 0000000000..7e43907564 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-github/index.tsx @@ -0,0 +1,234 @@ +'use client' + +import React, { useCallback, useState } from 'react' +import Modal from '@/app/components/base/modal' +import type { Item } from '@/app/components/base/select' +import type { InstallState } from '@/app/components/plugins/types' +import { useGitHubReleases } from '../hooks' +import { convertRepoToUrl, parseGitHubUrl } from '../utils' +import type { PluginDeclaration, UpdateFromGitHubPayload } from '../../types' +import { InstallStepFromGitHub } from '../../types' +import Toast from '@/app/components/base/toast' +import SetURL from './steps/setURL' +import SelectPackage from './steps/selectPackage' +import Installed from '../base/installed' +import Loaded from './steps/loaded' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import { useTranslation } from 'react-i18next' +import useRefreshPluginList from '../hooks/use-refresh-plugin-list' +import cn from '@/utils/classnames' +import useHideLogic from '../hooks/use-hide-logic' + +const i18nPrefix = 'plugin.installFromGitHub' + +type InstallFromGitHubProps = { + updatePayload?: UpdateFromGitHubPayload + onClose: () => void + onSuccess: () => void +} + +const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, onClose, onSuccess }) => { + const { t } = useTranslation() + const { getIconUrl } = useGetIcon() + const { fetchReleases } = useGitHubReleases() + const { refreshPluginList } = useRefreshPluginList() + + const { + modalClassName, + foldAnimInto, + setIsInstalling, + handleStartToInstall, + } = useHideLogic(onClose) + + const [state, setState] = useState<InstallState>({ + step: updatePayload ? InstallStepFromGitHub.selectPackage : InstallStepFromGitHub.setUrl, + repoUrl: updatePayload?.originalPackageInfo?.repo + ? convertRepoToUrl(updatePayload.originalPackageInfo.repo) + : '', + selectedVersion: '', + selectedPackage: '', + releases: updatePayload ? updatePayload.originalPackageInfo.releases : [], + }) + const [uniqueIdentifier, setUniqueIdentifier] = useState<string | null>(null) + const [manifest, setManifest] = useState<PluginDeclaration | null>(null) + const [errorMsg, setErrorMsg] = useState<string | null>(null) + + const versions: Item[] = state.releases.map(release => ({ + value: release.tag_name, + name: release.tag_name, + })) + + const packages: Item[] = state.selectedVersion + ? (state.releases + .find(release => release.tag_name === state.selectedVersion) + ?.assets + .map(asset => ({ + value: asset.name, + name: asset.name, + })) || []) + : [] + + const getTitle = useCallback(() => { + if (state.step === InstallStepFromGitHub.installed) + return t(`${i18nPrefix}.installedSuccessfully`) + if (state.step === InstallStepFromGitHub.installFailed) + return t(`${i18nPrefix}.installFailed`) + + return updatePayload ? t(`${i18nPrefix}.updatePlugin`) : t(`${i18nPrefix}.installPlugin`) + }, [state.step, t, updatePayload]) + + const handleUrlSubmit = async () => { + const { isValid, owner, repo } = parseGitHubUrl(state.repoUrl) + if (!isValid || !owner || !repo) { + Toast.notify({ + type: 'error', + message: t('plugin.error.inValidGitHubUrl'), + }) + return + } + try { + const fetchedReleases = await fetchReleases(owner, repo) + if (fetchedReleases.length > 0) { + setState(prevState => ({ + ...prevState, + releases: fetchedReleases, + step: InstallStepFromGitHub.selectPackage, + })) + } + else { + Toast.notify({ + type: 'error', + message: t('plugin.error.noReleasesFound'), + }) + } + } + catch (error) { + Toast.notify({ + type: 'error', + message: t('plugin.error.fetchReleasesError'), + }) + } + } + + const handleError = (e: any, isInstall: boolean) => { + const message = e?.response?.message || t('plugin.installModal.installFailedDesc') + setErrorMsg(message) + setState(prevState => ({ ...prevState, step: isInstall ? InstallStepFromGitHub.installFailed : InstallStepFromGitHub.uploadFailed })) + } + + const handleUploaded = async (GitHubPackage: any) => { + try { + const icon = await getIconUrl(GitHubPackage.manifest.icon) + setManifest({ + ...GitHubPackage.manifest, + icon, + }) + setUniqueIdentifier(GitHubPackage.uniqueIdentifier) + setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.readyToInstall })) + } + catch (e) { + handleError(e, false) + } + } + + const handleUploadFail = useCallback((errorMsg: string) => { + setErrorMsg(errorMsg) + setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.uploadFailed })) + }, []) + + const handleInstalled = useCallback(() => { + setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.installed })) + refreshPluginList(manifest) + setIsInstalling(false) + onSuccess() + }, [manifest, onSuccess, refreshPluginList, setIsInstalling]) + + const handleFailed = useCallback((errorMsg?: string) => { + setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.installFailed })) + setIsInstalling(false) + if (errorMsg) + setErrorMsg(errorMsg) + }, [setIsInstalling]) + + const handleBack = () => { + setState((prevState) => { + switch (prevState.step) { + case InstallStepFromGitHub.selectPackage: + return { ...prevState, step: InstallStepFromGitHub.setUrl } + case InstallStepFromGitHub.readyToInstall: + return { ...prevState, step: InstallStepFromGitHub.selectPackage } + default: + return prevState + } + }) + } + + return ( + <Modal + isShow={true} + onClose={foldAnimInto} + className={cn(modalClassName, `flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] + border-components-panel-border bg-components-panel-bg shadows-shadow-xl`)} + closable + > + <div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'> + <div className='flex flex-col items-start gap-1 grow'> + <div className='self-stretch text-text-primary title-2xl-semi-bold'> + {getTitle()} + </div> + <div className='self-stretch text-text-tertiary system-xs-regular'> + {!([InstallStepFromGitHub.uploadFailed, InstallStepFromGitHub.installed, InstallStepFromGitHub.installFailed].includes(state.step)) && t('plugin.installFromGitHub.installNote')} + </div> + </div> + </div> + {([InstallStepFromGitHub.uploadFailed, InstallStepFromGitHub.installed, InstallStepFromGitHub.installFailed].includes(state.step)) + ? <Installed + payload={manifest} + isFailed={[InstallStepFromGitHub.uploadFailed, InstallStepFromGitHub.installFailed].includes(state.step)} + errMsg={errorMsg} + onCancel={onClose} + /> + : <div className={`flex px-6 py-3 flex-col justify-center items-start self-stretch ${state.step === InstallStepFromGitHub.installed ? 'gap-2' : 'gap-4'}`}> + {state.step === InstallStepFromGitHub.setUrl && ( + <SetURL + repoUrl={state.repoUrl} + onChange={value => setState(prevState => ({ ...prevState, repoUrl: value }))} + onNext={handleUrlSubmit} + onCancel={onClose} + /> + )} + {state.step === InstallStepFromGitHub.selectPackage && ( + <SelectPackage + updatePayload={updatePayload!} + repoUrl={state.repoUrl} + selectedVersion={state.selectedVersion} + versions={versions} + onSelectVersion={item => setState(prevState => ({ ...prevState, selectedVersion: item.value as string }))} + selectedPackage={state.selectedPackage} + packages={packages} + onSelectPackage={item => setState(prevState => ({ ...prevState, selectedPackage: item.value as string }))} + onUploaded={handleUploaded} + onFailed={handleUploadFail} + onBack={handleBack} + /> + )} + {state.step === InstallStepFromGitHub.readyToInstall && ( + <Loaded + updatePayload={updatePayload!} + uniqueIdentifier={uniqueIdentifier!} + payload={manifest as any} + repoUrl={state.repoUrl} + selectedVersion={state.selectedVersion} + selectedPackage={state.selectedPackage} + onBack={handleBack} + onStartToInstall={handleStartToInstall} + onInstalled={handleInstalled} + onFailed={handleFailed} + /> + )} + </div>} + </Modal> + ) +} + +export default InstallFromGitHub diff --git a/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx new file mode 100644 index 0000000000..b1bcf01251 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx @@ -0,0 +1,180 @@ +'use client' + +import React, { useEffect } from 'react' +import Button from '@/app/components/base/button' +import { type Plugin, type PluginDeclaration, TaskStatus, type UpdateFromGitHubPayload } from '../../../types' +import Card from '../../../card' +import { pluginManifestToCardPluginProps } from '../../utils' +import { useTranslation } from 'react-i18next' +import { updateFromGitHub } from '@/service/plugins' +import { useInstallPackageFromGitHub } from '@/service/use-plugins' +import { RiLoader2Line } from '@remixicon/react' +import { usePluginTaskList } from '@/service/use-plugins' +import checkTaskStatus from '../../base/check-task-status' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' +import { parseGitHubUrl } from '../../utils' +import Version from '../../base/version' + +type LoadedProps = { + updatePayload: UpdateFromGitHubPayload + uniqueIdentifier: string + payload: PluginDeclaration | Plugin + repoUrl: string + selectedVersion: string + selectedPackage: string + onBack: () => void + onStartToInstall?: () => void + onInstalled: () => void + onFailed: (message?: string) => void +} + +const i18nPrefix = 'plugin.installModal' + +const Loaded: React.FC<LoadedProps> = ({ + updatePayload, + uniqueIdentifier, + payload, + repoUrl, + selectedVersion, + selectedPackage, + onBack, + onStartToInstall, + onInstalled, + onFailed, +}) => { + const { t } = useTranslation() + const toInstallVersion = payload.version + const pluginId = (payload as Plugin).plugin_id + const { installedInfo, isLoading } = useCheckInstalled({ + pluginIds: [pluginId], + enabled: !!pluginId, + }) + const installedInfoPayload = installedInfo?.[pluginId] + const installedVersion = installedInfoPayload?.installedVersion + const hasInstalled = !!installedVersion + + const [isInstalling, setIsInstalling] = React.useState(false) + const { mutateAsync: installPackageFromGitHub } = useInstallPackageFromGitHub() + const { handleRefetch } = usePluginTaskList() + const { check } = checkTaskStatus() + + useEffect(() => { + if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) + onInstalled() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hasInstalled]) + + const handleInstall = async () => { + if (isInstalling) return + setIsInstalling(true) + onStartToInstall?.() + + try { + const { owner, repo } = parseGitHubUrl(repoUrl) + let taskId + let isInstalled + if (updatePayload) { + const { all_installed, task_id } = await updateFromGitHub( + `${owner}/${repo}`, + selectedVersion, + selectedPackage, + updatePayload.originalPackageInfo.id, + uniqueIdentifier, + ) + + taskId = task_id + isInstalled = all_installed + } + else { + if (hasInstalled) { + const { + all_installed, + task_id, + } = await updateFromGitHub( + `${owner}/${repo}`, + selectedVersion, + selectedPackage, + installedInfoPayload.uniqueIdentifier, + uniqueIdentifier, + ) + taskId = task_id + isInstalled = all_installed + } + else { + const { all_installed, task_id } = await installPackageFromGitHub({ + repoUrl: `${owner}/${repo}`, + selectedVersion, + selectedPackage, + uniqueIdentifier, + }) + + taskId = task_id + isInstalled = all_installed + } + } + if (isInstalled) { + onInstalled() + return + } + + handleRefetch() + + const { status, error } = await check({ + taskId, + pluginUniqueIdentifier: uniqueIdentifier, + }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } + onInstalled() + } + catch (e) { + if (typeof e === 'string') { + onFailed(e) + return + } + onFailed() + } + finally { + setIsInstalling(false) + } + } + + return ( + <> + <div className='text-text-secondary system-md-regular'> + <p>{t(`${i18nPrefix}.readyToInstall`)}</p> + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + className='w-full' + payload={pluginManifestToCardPluginProps(payload as PluginDeclaration)} + titleLeft={!isLoading && <Version + hasInstalled={hasInstalled} + installedVersion={installedVersion} + toInstallVersion={toInstallVersion} + />} + /> + </div> + <div className='flex justify-end items-center gap-2 self-stretch mt-4'> + {!isInstalling && ( + <Button variant='secondary' className='min-w-[72px]' onClick={onBack}> + {t('plugin.installModal.back')} + </Button> + )} + <Button + variant='primary' + className='min-w-[72px] flex space-x-0.5' + onClick={handleInstall} + disabled={isInstalling || isLoading} + > + {isInstalling && <RiLoader2Line className='w-4 h-4 animate-spin-slow' />} + <span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span> + </Button> + </div> + </> + ) +} + +export default Loaded diff --git a/web/app/components/plugins/install-plugin/install-from-github/steps/selectPackage.tsx b/web/app/components/plugins/install-plugin/install-from-github/steps/selectPackage.tsx new file mode 100644 index 0000000000..47a5d86498 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-github/steps/selectPackage.tsx @@ -0,0 +1,125 @@ +'use client' + +import React from 'react' +import type { Item } from '@/app/components/base/select' +import { PortalSelect } from '@/app/components/base/select' +import Button from '@/app/components/base/button' +import type { PluginDeclaration, UpdateFromGitHubPayload } from '../../../types' +import { useTranslation } from 'react-i18next' +import { useGitHubUpload } from '../../hooks' + +const i18nPrefix = 'plugin.installFromGitHub' + +type SelectPackageProps = { + updatePayload: UpdateFromGitHubPayload + repoUrl: string + selectedVersion: string + versions: Item[] + onSelectVersion: (item: Item) => void + selectedPackage: string + packages: Item[] + onSelectPackage: (item: Item) => void + onUploaded: (result: { + uniqueIdentifier: string + manifest: PluginDeclaration + }) => void + onFailed: (errorMsg: string) => void + onBack: () => void +} + +const SelectPackage: React.FC<SelectPackageProps> = ({ + updatePayload, + repoUrl, + selectedVersion, + versions, + onSelectVersion, + selectedPackage, + packages, + onSelectPackage, + onUploaded, + onFailed, + onBack, +}) => { + const { t } = useTranslation() + const isEdit = Boolean(updatePayload) + const [isUploading, setIsUploading] = React.useState(false) + const { handleUpload } = useGitHubUpload() + + const handleUploadPackage = async () => { + if (isUploading) return + setIsUploading(true) + try { + const repo = repoUrl.replace('https://github.com/', '') + await handleUpload(repo, selectedVersion, selectedPackage, (GitHubPackage) => { + onUploaded({ + uniqueIdentifier: GitHubPackage.unique_identifier, + manifest: GitHubPackage.manifest, + }) + }) + } + catch (e: any) { + if (e.response?.message) + onFailed(e.response?.message) + else + onFailed(t(`${i18nPrefix}.uploadFailed`)) + } + finally { + setIsUploading(false) + } + } + + return ( + <> + <label + htmlFor='version' + className='flex flex-col justify-center items-start self-stretch text-text-secondary' + > + <span className='system-sm-semibold'>{t(`${i18nPrefix}.selectVersion`)}</span> + </label> + <PortalSelect + value={selectedVersion} + onSelect={onSelectVersion} + items={versions} + installedValue={updatePayload?.originalPackageInfo.version} + placeholder={t(`${i18nPrefix}.selectVersionPlaceholder`) || ''} + popupClassName='w-[512px] z-[1001]' + /> + <label + htmlFor='package' + className='flex flex-col justify-center items-start self-stretch text-text-secondary' + > + <span className='system-sm-semibold'>{t(`${i18nPrefix}.selectPackage`)}</span> + </label> + <PortalSelect + value={selectedPackage} + onSelect={onSelectPackage} + items={packages} + readonly={!selectedVersion} + placeholder={t(`${i18nPrefix}.selectPackagePlaceholder`) || ''} + popupClassName='w-[512px] z-[1001]' + /> + <div className='flex justify-end items-center gap-2 self-stretch mt-4'> + {!isEdit + && <Button + variant='secondary' + className='min-w-[72px]' + onClick={onBack} + disabled={isUploading} + > + {t('plugin.installModal.back')} + </Button> + } + <Button + variant='primary' + className='min-w-[72px]' + onClick={handleUploadPackage} + disabled={!selectedVersion || !selectedPackage || isUploading} + > + {t('plugin.installModal.next')} + </Button> + </div> + </> + ) +} + +export default SelectPackage diff --git a/web/app/components/plugins/install-plugin/install-from-github/steps/setURL.tsx b/web/app/components/plugins/install-plugin/install-from-github/steps/setURL.tsx new file mode 100644 index 0000000000..c6ce006f37 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-github/steps/setURL.tsx @@ -0,0 +1,56 @@ +'use client' + +import React from 'react' +import Button from '@/app/components/base/button' +import { useTranslation } from 'react-i18next' + +type SetURLProps = { + repoUrl: string + onChange: (value: string) => void + onNext: () => void + onCancel: () => void +} + +const SetURL: React.FC<SetURLProps> = ({ repoUrl, onChange, onNext, onCancel }) => { + const { t } = useTranslation() + return ( + <> + <label + htmlFor='repoUrl' + className='flex flex-col justify-center items-start self-stretch text-text-secondary' + > + <span className='system-sm-semibold'>{t('plugin.installFromGitHub.gitHubRepo')}</span> + </label> + <input + type='url' + id='repoUrl' + name='repoUrl' + value={repoUrl} + onChange={e => onChange(e.target.value)} + className='flex items-center self-stretch rounded-lg border border-components-input-border-active + bg-components-input-bg-active shadows-shadow-xs p-2 gap-[2px] flex-grow overflow-hidden + text-components-input-text-filled text-ellipsis system-sm-regular' + placeholder='Please enter GitHub repo URL' + /> + <div className='flex justify-end items-center gap-2 self-stretch mt-4'> + <Button + variant='secondary' + className='min-w-[72px]' + onClick={onCancel} + > + {t('plugin.installModal.cancel')} + </Button> + <Button + variant='primary' + className='min-w-[72px]' + onClick={onNext} + disabled={!repoUrl.trim()} + > + {t('plugin.installModal.next')} + </Button> + </div> + </> + ) +} + +export default SetURL diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx new file mode 100644 index 0000000000..b37ab60079 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx @@ -0,0 +1,133 @@ +'use client' + +import React, { useCallback, useState } from 'react' +import Modal from '@/app/components/base/modal' +import type { Dependency, PluginDeclaration } from '../../types' +import { InstallStep } from '../../types' +import Uploading from './steps/uploading' +import { useTranslation } from 'react-i18next' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import ReadyToInstallPackage from './ready-to-install' +import ReadyToInstallBundle from '../install-bundle/ready-to-install' +import useHideLogic from '../hooks/use-hide-logic' +import cn from '@/utils/classnames' + +const i18nPrefix = 'plugin.installModal' + +type InstallFromLocalPackageProps = { + file: File + onSuccess: () => void + onClose: () => void +} + +const InstallFromLocalPackage: React.FC<InstallFromLocalPackageProps> = ({ + file, + onClose, +}) => { + const { t } = useTranslation() + // uploading -> !uploadFailed -> readyToInstall -> installed/failed + const [step, setStep] = useState<InstallStep>(InstallStep.uploading) + const [uniqueIdentifier, setUniqueIdentifier] = useState<string | null>(null) + const [manifest, setManifest] = useState<PluginDeclaration | null>(null) + const [errorMsg, setErrorMsg] = useState<string | null>(null) + const isBundle = file.name.endsWith('.difybndl') + const [dependencies, setDependencies] = useState<Dependency[]>([]) + + const { + modalClassName, + foldAnimInto, + setIsInstalling, + handleStartToInstall, + } = useHideLogic(onClose) + + const getTitle = useCallback(() => { + if (step === InstallStep.uploadFailed) + return t(`${i18nPrefix}.uploadFailed`) + if (isBundle && step === InstallStep.installed) + return t(`${i18nPrefix}.installComplete`) + if (step === InstallStep.installed) + return t(`${i18nPrefix}.installedSuccessfully`) + if (step === InstallStep.installFailed) + return t(`${i18nPrefix}.installFailed`) + + return t(`${i18nPrefix}.installPlugin`) + }, [isBundle, step, t]) + + const { getIconUrl } = useGetIcon() + + const handlePackageUploaded = useCallback(async (result: { + uniqueIdentifier: string + manifest: PluginDeclaration + }) => { + const { + manifest, + uniqueIdentifier, + } = result + const icon = await getIconUrl(manifest!.icon) + setUniqueIdentifier(uniqueIdentifier) + setManifest({ + ...manifest, + icon, + }) + setStep(InstallStep.readyToInstall) + }, [getIconUrl]) + + const handleBundleUploaded = useCallback((result: Dependency[]) => { + setDependencies(result) + setStep(InstallStep.readyToInstall) + }, []) + + const handleUploadFail = useCallback((errorMsg: string) => { + setErrorMsg(errorMsg) + setStep(InstallStep.uploadFailed) + }, []) + + return ( + <Modal + isShow={true} + onClose={foldAnimInto} + className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')} + closable + > + <div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'> + <div className='self-stretch text-text-primary title-2xl-semi-bold'> + {getTitle()} + </div> + </div> + {step === InstallStep.uploading && ( + <Uploading + isBundle={isBundle} + file={file} + onCancel={onClose} + onPackageUploaded={handlePackageUploaded} + onBundleUploaded={handleBundleUploaded} + onFailed={handleUploadFail} + /> + )} + {isBundle ? ( + <ReadyToInstallBundle + step={step} + onStepChange={setStep} + onStartToInstall={handleStartToInstall} + setIsInstalling={setIsInstalling} + onClose={onClose} + allPlugins={dependencies} + /> + ) : ( + <ReadyToInstallPackage + step={step} + onStepChange={setStep} + onStartToInstall={handleStartToInstall} + setIsInstalling={setIsInstalling} + onClose={onClose} + uniqueIdentifier={uniqueIdentifier} + manifest={manifest} + errorMsg={errorMsg} + onError={setErrorMsg} + /> + )} + </Modal> + ) +} + +export default InstallFromLocalPackage diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/ready-to-install.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/ready-to-install.tsx new file mode 100644 index 0000000000..cee7e4767f --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-local-package/ready-to-install.tsx @@ -0,0 +1,75 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import type { PluginDeclaration } from '../../types' +import { InstallStep } from '../../types' +import Install from './steps/install' +import Installed from '../base/installed' +import useRefreshPluginList from '../hooks/use-refresh-plugin-list' + +type Props = { + step: InstallStep + onStepChange: (step: InstallStep) => void, + onStartToInstall: () => void + setIsInstalling: (isInstalling: boolean) => void + onClose: () => void + uniqueIdentifier: string | null, + manifest: PluginDeclaration | null, + errorMsg: string | null, + onError: (errorMsg: string) => void, +} + +const ReadyToInstall: FC<Props> = ({ + step, + onStepChange, + onStartToInstall, + setIsInstalling, + onClose, + uniqueIdentifier, + manifest, + errorMsg, + onError, +}) => { + const { refreshPluginList } = useRefreshPluginList() + + const handleInstalled = useCallback(() => { + onStepChange(InstallStep.installed) + refreshPluginList(manifest) + setIsInstalling(false) + }, [manifest, onStepChange, refreshPluginList, setIsInstalling]) + + const handleFailed = useCallback((errorMsg?: string) => { + onStepChange(InstallStep.installFailed) + setIsInstalling(false) + if (errorMsg) + onError(errorMsg) + }, [onError, onStepChange, setIsInstalling]) + + return ( + <> + { + step === InstallStep.readyToInstall && ( + <Install + uniqueIdentifier={uniqueIdentifier!} + payload={manifest!} + onCancel={onClose} + onInstalled={handleInstalled} + onFailed={handleFailed} + onStartToInstall={onStartToInstall} + /> + ) + } + { + ([InstallStep.uploadFailed, InstallStep.installed, InstallStep.installFailed].includes(step)) && ( + <Installed + payload={manifest} + isFailed={[InstallStep.uploadFailed, InstallStep.installFailed].includes(step)} + errMsg={errorMsg} + onCancel={onClose} + /> + ) + } + </> + ) +} +export default React.memo(ReadyToInstall) diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx new file mode 100644 index 0000000000..19baa86d73 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx @@ -0,0 +1,162 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect } from 'react' +import { type PluginDeclaration, TaskStatus } from '../../../types' +import Card from '../../../card' +import { pluginManifestToCardPluginProps } from '../../utils' +import Button from '@/app/components/base/button' +import { Trans, useTranslation } from 'react-i18next' +import { RiLoader2Line } from '@remixicon/react' +import checkTaskStatus from '../../base/check-task-status' +import { useInstallPackageFromLocal, usePluginTaskList, useUpdatePackageFromMarketPlace } from '@/service/use-plugins' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' +import Version from '../../base/version' + +const i18nPrefix = 'plugin.installModal' + +type Props = { + uniqueIdentifier: string + payload: PluginDeclaration + onCancel: () => void + onStartToInstall?: () => void + onInstalled: () => void + onFailed: (message?: string) => void +} + +const Installed: FC<Props> = ({ + uniqueIdentifier, + payload, + onCancel, + onStartToInstall, + onInstalled, + onFailed, +}) => { + const { t } = useTranslation() + const toInstallVersion = payload.version + const pluginId = `${payload.author}/${payload.name}` + const { installedInfo, isLoading } = useCheckInstalled({ + pluginIds: [pluginId], + enabled: !!pluginId, + }) + const installedInfoPayload = installedInfo?.[pluginId] + const installedVersion = installedInfoPayload?.installedVersion + const hasInstalled = !!installedVersion + + useEffect(() => { + if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) + onInstalled() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hasInstalled]) + + const [isInstalling, setIsInstalling] = React.useState(false) + const { mutateAsync: installPackageFromLocal } = useInstallPackageFromLocal() + const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace() + + const { + check, + stop, + } = checkTaskStatus() + + const handleCancel = () => { + stop() + onCancel() + } + + const { handleRefetch } = usePluginTaskList() + const handleInstall = async () => { + if (isInstalling) return + setIsInstalling(true) + onStartToInstall?.() + + try { + let taskId + let isInstalled + if (hasInstalled) { + const { + all_installed, + task_id, + } = await updatePackageFromMarketPlace({ + original_plugin_unique_identifier: installedInfoPayload.uniqueIdentifier, + new_plugin_unique_identifier: uniqueIdentifier, + }) + taskId = task_id + isInstalled = all_installed + } + else { + const { + all_installed, + task_id, + } = await installPackageFromLocal(uniqueIdentifier) + taskId = task_id + isInstalled = all_installed + } + + if (isInstalled) { + onInstalled() + return + } + handleRefetch() + const { status, error } = await check({ + taskId, + pluginUniqueIdentifier: uniqueIdentifier, + }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } + onInstalled() + } + catch (e) { + if (typeof e === 'string') { + onFailed(e) + return + } + onFailed() + } + } + + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + <div className='text-text-secondary system-md-regular'> + <p>{t(`${i18nPrefix}.readyToInstall`)}</p> + <p> + <Trans + i18nKey={`${i18nPrefix}.fromTrustSource`} + components={{ trustSource: <span className='system-md-semibold' /> }} + /> + </p> + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + className='w-full' + payload={pluginManifestToCardPluginProps(payload)} + titleLeft={!isLoading && <Version + hasInstalled={hasInstalled} + installedVersion={installedVersion} + toInstallVersion={toInstallVersion} + />} + /> + </div> + </div> + {/* Action Buttons */} + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + {!isInstalling && ( + <Button variant='secondary' className='min-w-[72px]' onClick={handleCancel}> + {t('common.operation.cancel')} + </Button> + )} + <Button + variant='primary' + className='min-w-[72px] flex space-x-0.5' + disabled={isInstalling || isLoading} + onClick={handleInstall} + > + {isInstalling && <RiLoader2Line className='w-4 h-4 animate-spin-slow' />} + <span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span> + </Button> + </div> + </> + ) +} +export default React.memo(Installed) diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx new file mode 100644 index 0000000000..61e762ce60 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx @@ -0,0 +1,99 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { RiLoader2Line } from '@remixicon/react' +import Card from '../../../card' +import type { Dependency, PluginDeclaration } from '../../../types' +import Button from '@/app/components/base/button' +import { useTranslation } from 'react-i18next' +import { uploadFile } from '@/service/plugins' +const i18nPrefix = 'plugin.installModal' + +type Props = { + isBundle: boolean + file: File + onCancel: () => void + onPackageUploaded: (result: { + uniqueIdentifier: string + manifest: PluginDeclaration + }) => void + onBundleUploaded: (result: Dependency[]) => void + onFailed: (errorMsg: string) => void +} + +const Uploading: FC<Props> = ({ + isBundle, + file, + onCancel, + onPackageUploaded, + onBundleUploaded, + onFailed, +}) => { + const { t } = useTranslation() + const fileName = file.name + const handleUpload = async () => { + try { + await uploadFile(file, isBundle) + } + catch (e: any) { + if (e.response?.message) { + onFailed(e.response?.message) + } + else { // Why it would into this branch? + const res = e.response + if (isBundle) { + onBundleUploaded(res) + return + } + onPackageUploaded({ + uniqueIdentifier: res.unique_identifier, + manifest: res.manifest, + }) + } + } + } + + React.useEffect(() => { + handleUpload() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + <div className='flex items-center gap-1 self-stretch'> + <RiLoader2Line className='text-text-accent w-4 h-4 animate-spin-slow' /> + <div className='text-text-secondary system-md-regular'> + {t(`${i18nPrefix}.uploadingPackage`, { + packageName: fileName, + })} + </div> + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + className='w-full' + payload={{ name: fileName } as any} + isLoading + loadingFileName={fileName} + installed={false} + /> + </div> + </div> + + {/* Action Buttons */} + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + <Button variant='secondary' className='min-w-[72px]' onClick={onCancel}> + {t('common.operation.cancel')} + </Button> + <Button + variant='primary' + className='min-w-[72px]' + disabled + > + {t(`${i18nPrefix}.install`)} + </Button> + </div> + </> + ) +} + +export default React.memo(Uploading) diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx new file mode 100644 index 0000000000..a5ce01d041 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx @@ -0,0 +1,124 @@ +'use client' + +import React, { useCallback, useState } from 'react' +import Modal from '@/app/components/base/modal' +import type { Dependency, Plugin, PluginManifestInMarket } from '../../types' +import { InstallStep } from '../../types' +import Install from './steps/install' +import Installed from '../base/installed' +import { useTranslation } from 'react-i18next' +import useRefreshPluginList from '../hooks/use-refresh-plugin-list' +import ReadyToInstallBundle from '../install-bundle/ready-to-install' +import cn from '@/utils/classnames' +import useHideLogic from '../hooks/use-hide-logic' + +const i18nPrefix = 'plugin.installModal' + +type InstallFromMarketplaceProps = { + uniqueIdentifier: string + manifest: PluginManifestInMarket | Plugin + isBundle?: boolean + dependencies?: Dependency[] + onSuccess: () => void + onClose: () => void +} + +const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({ + uniqueIdentifier, + manifest, + isBundle, + dependencies, + onSuccess, + onClose, +}) => { + const { t } = useTranslation() + // readyToInstall -> check installed -> installed/failed + const [step, setStep] = useState<InstallStep>(InstallStep.readyToInstall) + const [errorMsg, setErrorMsg] = useState<string | null>(null) + const { refreshPluginList } = useRefreshPluginList() + + const { + modalClassName, + foldAnimInto, + setIsInstalling, + handleStartToInstall, + } = useHideLogic(onClose) + + const getTitle = useCallback(() => { + if (isBundle && step === InstallStep.installed) + return t(`${i18nPrefix}.installComplete`) + if (step === InstallStep.installed) + return t(`${i18nPrefix}.installedSuccessfully`) + if (step === InstallStep.installFailed) + return t(`${i18nPrefix}.installFailed`) + return t(`${i18nPrefix}.installPlugin`) + }, [isBundle, step, t]) + + const handleInstalled = useCallback(() => { + setStep(InstallStep.installed) + refreshPluginList(manifest) + setIsInstalling(false) + }, [manifest, refreshPluginList, setIsInstalling]) + + const handleFailed = useCallback((errorMsg?: string) => { + setStep(InstallStep.installFailed) + setIsInstalling(false) + if (errorMsg) + setErrorMsg(errorMsg) + }, [setIsInstalling]) + + return ( + <Modal + isShow={true} + onClose={foldAnimInto} + wrapperClassName='z-[9999]' + className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')} + closable + > + <div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'> + <div className='self-stretch text-text-primary title-2xl-semi-bold'> + {getTitle()} + </div> + </div> + { + isBundle ? ( + <ReadyToInstallBundle + step={step} + onStepChange={setStep} + onStartToInstall={handleStartToInstall} + setIsInstalling={setIsInstalling} + onClose={onClose} + allPlugins={dependencies!} + isFromMarketPlace + /> + ) : (<> + { + step === InstallStep.readyToInstall && ( + <Install + uniqueIdentifier={uniqueIdentifier} + payload={manifest!} + onCancel={onClose} + onInstalled={handleInstalled} + onFailed={handleFailed} + onStartToInstall={handleStartToInstall} + /> + )} + { + [InstallStep.installed, InstallStep.installFailed].includes(step) && ( + <Installed + payload={manifest!} + isMarketPayload + isFailed={step === InstallStep.installFailed} + errMsg={errorMsg} + onCancel={onSuccess} + /> + ) + } + </> + ) + } + </Modal > + ) +} + +export default InstallFromMarketplace diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx new file mode 100644 index 0000000000..0779f27ef6 --- /dev/null +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -0,0 +1,158 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect } from 'react' +// import { RiInformation2Line } from '@remixicon/react' +import { type Plugin, type PluginManifestInMarket, TaskStatus } from '../../../types' +import Card from '../../../card' +import { pluginManifestInMarketToPluginProps } from '../../utils' +import Button from '@/app/components/base/button' +import { useTranslation } from 'react-i18next' +import { RiLoader2Line } from '@remixicon/react' +import { useInstallPackageFromMarketPlace, useUpdatePackageFromMarketPlace } from '@/service/use-plugins' +import checkTaskStatus from '../../base/check-task-status' +import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' +import Version from '../../base/version' +import { usePluginTaskList } from '@/service/use-plugins' + +const i18nPrefix = 'plugin.installModal' + +type Props = { + uniqueIdentifier: string + payload: PluginManifestInMarket | Plugin + onCancel: () => void + onStartToInstall?: () => void + onInstalled: () => void + onFailed: (message?: string) => void +} + +const Installed: FC<Props> = ({ + uniqueIdentifier, + payload, + onCancel, + onStartToInstall, + onInstalled, + onFailed, +}) => { + const { t } = useTranslation() + const toInstallVersion = payload.version || payload.latest_version + const pluginId = (payload as Plugin).plugin_id + const { installedInfo, isLoading } = useCheckInstalled({ + pluginIds: [pluginId], + enabled: !!pluginId, + }) + const installedInfoPayload = installedInfo?.[pluginId] + const installedVersion = installedInfoPayload?.installedVersion + const hasInstalled = !!installedVersion + + const { mutateAsync: installPackageFromMarketPlace } = useInstallPackageFromMarketPlace() + const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace() + const [isInstalling, setIsInstalling] = React.useState(false) + const { + check, + stop, + } = checkTaskStatus() + const { handleRefetch } = usePluginTaskList() + + useEffect(() => { + if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) + onInstalled() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hasInstalled]) + + const handleCancel = () => { + stop() + onCancel() + } + + const handleInstall = async () => { + if (isInstalling) return + onStartToInstall?.() + setIsInstalling(true) + try { + let taskId + let isInstalled + if (hasInstalled) { + const { + all_installed, + task_id, + } = await updatePackageFromMarketPlace({ + original_plugin_unique_identifier: installedInfoPayload.uniqueIdentifier, + new_plugin_unique_identifier: uniqueIdentifier, + }) + taskId = task_id + isInstalled = all_installed + } + else { + const { + all_installed, + task_id, + } = await installPackageFromMarketPlace(uniqueIdentifier) + taskId = task_id + isInstalled = all_installed + } + + if (isInstalled) { + onInstalled() + return + } + + handleRefetch() + + const { status, error } = await check({ + taskId, + pluginUniqueIdentifier: uniqueIdentifier, + }) + if (status === TaskStatus.failed) { + onFailed(error) + return + } + onInstalled() + } + catch (e) { + if (typeof e === 'string') { + onFailed(e) + return + } + onFailed() + } + } + + return ( + <> + <div className='flex flex-col px-6 py-3 justify-center items-start gap-4 self-stretch'> + <div className='text-text-secondary system-md-regular'> + <p>{t(`${i18nPrefix}.readyToInstall`)}</p> + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + className='w-full' + payload={pluginManifestInMarketToPluginProps(payload as PluginManifestInMarket)} + titleLeft={!isLoading && <Version + hasInstalled={hasInstalled} + installedVersion={installedVersion} + toInstallVersion={toInstallVersion} + />} + /> + </div> + </div> + {/* Action Buttons */} + <div className='flex p-6 pt-5 justify-end items-center gap-2 self-stretch'> + {!isInstalling && ( + <Button variant='secondary' className='min-w-[72px]' onClick={handleCancel}> + {t('common.operation.cancel')} + </Button> + )} + <Button + variant='primary' + className='min-w-[72px] flex space-x-0.5' + disabled={isInstalling || isLoading} + onClick={handleInstall} + > + {isInstalling && <RiLoader2Line className='w-4 h-4 animate-spin-slow' />} + <span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span> + </Button> + </div> + </> + ) +} +export default React.memo(Installed) diff --git a/web/app/components/plugins/install-plugin/utils.ts b/web/app/components/plugins/install-plugin/utils.ts new file mode 100644 index 0000000000..dc3113e6a5 --- /dev/null +++ b/web/app/components/plugins/install-plugin/utils.ts @@ -0,0 +1,59 @@ +import type { Plugin, PluginDeclaration, PluginManifestInMarket } from '../types' +import type { GitHubUrlInfo } from '@/app/components/plugins/types' + +export const pluginManifestToCardPluginProps = (pluginManifest: PluginDeclaration): Plugin => { + return { + plugin_id: pluginManifest.plugin_unique_identifier, + type: pluginManifest.category, + category: pluginManifest.category, + name: pluginManifest.name, + version: pluginManifest.version, + latest_version: '', + latest_package_identifier: '', + org: pluginManifest.author, + label: pluginManifest.label, + brief: pluginManifest.description, + icon: pluginManifest.icon, + verified: pluginManifest.verified, + introduction: '', + repository: '', + install_count: 0, + endpoint: { + settings: [], + }, + tags: [], + } +} + +export const pluginManifestInMarketToPluginProps = (pluginManifest: PluginManifestInMarket): Plugin => { + return { + plugin_id: pluginManifest.plugin_unique_identifier, + type: pluginManifest.category, + category: pluginManifest.category, + name: pluginManifest.name, + version: pluginManifest.latest_version, + latest_version: pluginManifest.latest_version, + latest_package_identifier: '', + org: pluginManifest.org, + label: pluginManifest.label, + brief: pluginManifest.brief, + icon: pluginManifest.icon, + verified: pluginManifest.verified, + introduction: pluginManifest.introduction, + repository: '', + install_count: 0, + endpoint: { + settings: [], + }, + tags: [], + } +} + +export const parseGitHubUrl = (url: string): GitHubUrlInfo => { + const match = url.match(/^https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/?$/) + return match ? { isValid: true, owner: match[1], repo: match[2] } : { isValid: false } +} + +export const convertRepoToUrl = (repo: string) => { + return repo ? `https://github.com/${repo}` : '' +} diff --git a/web/app/components/plugins/marketplace/constants.ts b/web/app/components/plugins/marketplace/constants.ts new file mode 100644 index 0000000000..6bd4e29604 --- /dev/null +++ b/web/app/components/plugins/marketplace/constants.ts @@ -0,0 +1,4 @@ +export const DEFAULT_SORT = { + sortBy: 'install_count', + sortOrder: 'DESC', +} diff --git a/web/app/components/plugins/marketplace/context.tsx b/web/app/components/plugins/marketplace/context.tsx new file mode 100644 index 0000000000..e484f1e275 --- /dev/null +++ b/web/app/components/plugins/marketplace/context.tsx @@ -0,0 +1,314 @@ +'use client' + +import type { + ReactNode, +} from 'react' +import { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react' +import { + createContext, + useContextSelector, +} from 'use-context-selector' +import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch' +import type { Plugin } from '../types' +import { + getValidCategoryKeys, + getValidTagKeys, +} from '../utils' +import type { + MarketplaceCollection, + PluginsSort, + SearchParams, + SearchParamsFromCollection, +} from './types' +import { DEFAULT_SORT } from './constants' +import { + useMarketplaceCollectionsAndPlugins, + useMarketplaceContainerScroll, + useMarketplacePlugins, +} from './hooks' +import { + getMarketplaceListCondition, + getMarketplaceListFilterType, +} from './utils' +import { useInstalledPluginList } from '@/service/use-plugins' + +export type MarketplaceContextValue = { + intersected: boolean + setIntersected: (intersected: boolean) => void + searchPluginText: string + handleSearchPluginTextChange: (text: string) => void + filterPluginTags: string[] + handleFilterPluginTagsChange: (tags: string[]) => void + activePluginType: string + handleActivePluginTypeChange: (type: string) => void + page: number + handlePageChange: (page: number) => void + plugins?: Plugin[] + pluginsTotal?: number + resetPlugins: () => void + sort: PluginsSort + handleSortChange: (sort: PluginsSort) => void + handleQueryPlugins: () => void + handleMoreClick: (searchParams: SearchParamsFromCollection) => void + marketplaceCollectionsFromClient?: MarketplaceCollection[] + setMarketplaceCollectionsFromClient: (collections: MarketplaceCollection[]) => void + marketplaceCollectionPluginsMapFromClient?: Record<string, Plugin[]> + setMarketplaceCollectionPluginsMapFromClient: (map: Record<string, Plugin[]>) => void + isLoading: boolean + isSuccessCollections: boolean +} + +export const MarketplaceContext = createContext<MarketplaceContextValue>({ + intersected: true, + setIntersected: () => {}, + searchPluginText: '', + handleSearchPluginTextChange: () => {}, + filterPluginTags: [], + handleFilterPluginTagsChange: () => {}, + activePluginType: 'all', + handleActivePluginTypeChange: () => {}, + page: 1, + handlePageChange: () => {}, + plugins: undefined, + pluginsTotal: 0, + resetPlugins: () => {}, + sort: DEFAULT_SORT, + handleSortChange: () => {}, + handleQueryPlugins: () => {}, + handleMoreClick: () => {}, + marketplaceCollectionsFromClient: [], + setMarketplaceCollectionsFromClient: () => {}, + marketplaceCollectionPluginsMapFromClient: {}, + setMarketplaceCollectionPluginsMapFromClient: () => {}, + isLoading: false, + isSuccessCollections: false, +}) + +type MarketplaceContextProviderProps = { + children: ReactNode + searchParams?: SearchParams + shouldExclude?: boolean + scrollContainerId?: string +} + +export function useMarketplaceContext(selector: (value: MarketplaceContextValue) => any) { + return useContextSelector(MarketplaceContext, selector) +} + +export const MarketplaceContextProvider = ({ + children, + searchParams, + shouldExclude, + scrollContainerId, +}: MarketplaceContextProviderProps) => { + const { data, isSuccess } = useInstalledPluginList(!shouldExclude) + const exclude = useMemo(() => { + if (shouldExclude) + return data?.plugins.map(plugin => plugin.plugin_id) + }, [data?.plugins, shouldExclude]) + const queryFromSearchParams = searchParams?.q || '' + const tagsFromSearchParams = searchParams?.tags ? getValidTagKeys(searchParams.tags.split(',')) : [] + const hasValidTags = !!tagsFromSearchParams.length + const hasValidCategory = getValidCategoryKeys(searchParams?.category) + const categoryFromSearchParams = hasValidCategory || PLUGIN_TYPE_SEARCH_MAP.all + const [intersected, setIntersected] = useState(true) + const [searchPluginText, setSearchPluginText] = useState(queryFromSearchParams) + const searchPluginTextRef = useRef(searchPluginText) + const [filterPluginTags, setFilterPluginTags] = useState<string[]>(tagsFromSearchParams) + const filterPluginTagsRef = useRef(filterPluginTags) + const [activePluginType, setActivePluginType] = useState(categoryFromSearchParams) + const activePluginTypeRef = useRef(activePluginType) + const [page, setPage] = useState(1) + const pageRef = useRef(page) + const [sort, setSort] = useState(DEFAULT_SORT) + const sortRef = useRef(sort) + const { + marketplaceCollections: marketplaceCollectionsFromClient, + setMarketplaceCollections: setMarketplaceCollectionsFromClient, + marketplaceCollectionPluginsMap: marketplaceCollectionPluginsMapFromClient, + setMarketplaceCollectionPluginsMap: setMarketplaceCollectionPluginsMapFromClient, + queryMarketplaceCollectionsAndPlugins, + isLoading, + isSuccess: isSuccessCollections, + } = useMarketplaceCollectionsAndPlugins() + const { + plugins, + total: pluginsTotal, + resetPlugins, + queryPlugins, + queryPluginsWithDebounced, + isLoading: isPluginsLoading, + } = useMarketplacePlugins() + + useEffect(() => { + if (queryFromSearchParams || hasValidTags || hasValidCategory) { + queryPlugins({ + query: queryFromSearchParams, + category: hasValidCategory, + tags: hasValidTags ? tagsFromSearchParams : [], + sortBy: sortRef.current.sortBy, + sortOrder: sortRef.current.sortOrder, + type: getMarketplaceListFilterType(activePluginTypeRef.current), + page: pageRef.current, + }) + history.pushState({}, '', `/${searchParams?.language ? `?language=${searchParams?.language}` : ''}`) + } + else { + if (shouldExclude && isSuccess) { + queryMarketplaceCollectionsAndPlugins({ + exclude, + type: getMarketplaceListFilterType(activePluginTypeRef.current), + }) + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [queryPlugins, queryMarketplaceCollectionsAndPlugins, isSuccess, exclude]) + + const handleQueryMarketplaceCollectionsAndPlugins = useCallback(() => { + queryMarketplaceCollectionsAndPlugins({ + category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, + condition: getMarketplaceListCondition(activePluginTypeRef.current), + exclude, + type: getMarketplaceListFilterType(activePluginTypeRef.current), + }) + resetPlugins() + }, [exclude, queryMarketplaceCollectionsAndPlugins, resetPlugins]) + + const handleQueryPlugins = useCallback((debounced?: boolean) => { + if (debounced) { + queryPluginsWithDebounced({ + query: searchPluginTextRef.current, + category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, + tags: filterPluginTagsRef.current, + sortBy: sortRef.current.sortBy, + sortOrder: sortRef.current.sortOrder, + exclude, + type: getMarketplaceListFilterType(activePluginTypeRef.current), + page: pageRef.current, + }) + } + else { + queryPlugins({ + query: searchPluginTextRef.current, + category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, + tags: filterPluginTagsRef.current, + sortBy: sortRef.current.sortBy, + sortOrder: sortRef.current.sortOrder, + exclude, + type: getMarketplaceListFilterType(activePluginTypeRef.current), + page: pageRef.current, + }) + } + }, [exclude, queryPluginsWithDebounced, queryPlugins]) + + const handleQuery = useCallback((debounced?: boolean) => { + if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) { + handleQueryMarketplaceCollectionsAndPlugins() + return + } + + handleQueryPlugins(debounced) + }, [handleQueryMarketplaceCollectionsAndPlugins, handleQueryPlugins]) + + const handleSearchPluginTextChange = useCallback((text: string) => { + setSearchPluginText(text) + searchPluginTextRef.current = text + setPage(1) + pageRef.current = 1 + + handleQuery(true) + }, [handleQuery]) + + const handleFilterPluginTagsChange = useCallback((tags: string[]) => { + setFilterPluginTags(tags) + filterPluginTagsRef.current = tags + setPage(1) + pageRef.current = 1 + + handleQuery() + }, [handleQuery]) + + const handleActivePluginTypeChange = useCallback((type: string) => { + setActivePluginType(type) + activePluginTypeRef.current = type + setPage(1) + pageRef.current = 1 + + handleQuery() + }, [handleQuery]) + + const handleSortChange = useCallback((sort: PluginsSort) => { + setSort(sort) + sortRef.current = sort + setPage(1) + pageRef.current = 1 + + handleQueryPlugins() + }, [handleQueryPlugins]) + + const handlePageChange = useCallback(() => { + if (pluginsTotal && plugins && pluginsTotal > plugins.length) { + setPage(pageRef.current + 1) + pageRef.current++ + + handleQueryPlugins() + } + }, [handleQueryPlugins, plugins, pluginsTotal]) + + const handleMoreClick = useCallback((searchParams: SearchParamsFromCollection) => { + setSearchPluginText(searchParams?.query || '') + searchPluginTextRef.current = searchParams?.query || '' + setSort({ + sortBy: searchParams?.sort_by || DEFAULT_SORT.sortBy, + sortOrder: searchParams?.sort_order || DEFAULT_SORT.sortOrder, + }) + sortRef.current = { + sortBy: searchParams?.sort_by || DEFAULT_SORT.sortBy, + sortOrder: searchParams?.sort_order || DEFAULT_SORT.sortOrder, + } + setPage(1) + pageRef.current = 1 + + handleQueryPlugins() + }, [handleQueryPlugins]) + + useMarketplaceContainerScroll(handlePageChange, scrollContainerId) + + return ( + <MarketplaceContext.Provider + value={{ + intersected, + setIntersected, + searchPluginText, + handleSearchPluginTextChange, + filterPluginTags, + handleFilterPluginTagsChange, + activePluginType, + handleActivePluginTypeChange, + page, + handlePageChange, + plugins, + pluginsTotal, + resetPlugins, + sort, + handleSortChange, + handleQueryPlugins, + handleMoreClick, + marketplaceCollectionsFromClient, + setMarketplaceCollectionsFromClient, + marketplaceCollectionPluginsMapFromClient, + setMarketplaceCollectionPluginsMapFromClient, + isLoading: isLoading || isPluginsLoading, + isSuccessCollections, + }} + > + {children} + </MarketplaceContext.Provider> + ) +} diff --git a/web/app/components/plugins/marketplace/description/index.tsx b/web/app/components/plugins/marketplace/description/index.tsx new file mode 100644 index 0000000000..337f456e6d --- /dev/null +++ b/web/app/components/plugins/marketplace/description/index.tsx @@ -0,0 +1,49 @@ +import { + getLocaleOnServer, + useTranslation as translate, +} from '@/i18n/server' + +type DescriptionProps = { + locale?: string +} +const Description = async ({ + locale: localeFromProps, +}: DescriptionProps) => { + const localeDefault = getLocaleOnServer() + const { t } = await translate(localeFromProps || localeDefault, 'plugin') + const { t: tCommon } = await translate(localeFromProps || localeDefault, 'common') + + return ( + <> + <h1 className='shrink-0 mb-2 text-center title-4xl-semi-bold text-text-primary'> + {t('marketplace.empower')} + </h1> + <h2 className='shrink-0 flex justify-center items-center text-center body-md-regular text-text-tertiary'> + {t('marketplace.discover')} + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> + <span className='relative z-[2] lowercase'>{t('category.models')}</span> + </span> + , + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> + <span className='relative z-[2] lowercase'>{t('category.tools')}</span> + </span> + , + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> + <span className='relative z-[2] lowercase'>{t('category.agents')}</span> + </span> + , + <span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> + <span className='relative z-[2] lowercase'>{t('category.extensions')}</span> + </span> + {t('marketplace.and')} + <span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> + <span className='relative z-[2] lowercase'>{t('category.bundles')}</span> + </span> + <span className='mr-1'>{tCommon('operation.in')}</span> + {t('marketplace.difyMarketplace')} + </h2> + </> + ) +} + +export default Description diff --git a/web/app/components/plugins/marketplace/empty/index.tsx b/web/app/components/plugins/marketplace/empty/index.tsx new file mode 100644 index 0000000000..c190f0affe --- /dev/null +++ b/web/app/components/plugins/marketplace/empty/index.tsx @@ -0,0 +1,63 @@ +'use client' +import { Group } from '@/app/components/base/icons/src/vender/other' +import Line from './line' +import cn from '@/utils/classnames' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' + +type Props = { + text?: string + lightCard?: boolean + className?: string + locale?: string +} + +const Empty = ({ + text, + lightCard, + className, + locale, +}: Props) => { + const { t } = useMixedTranslation(locale) + + return ( + <div + className={cn('grow relative h-0 flex flex-wrap p-2 overflow-hidden', className)} + > + { + Array.from({ length: 16 }).map((_, index) => ( + <div + key={index} + className={cn( + 'mr-3 mb-3 h-[144px] w-[calc((100%-36px)/4)] rounded-xl bg-background-section-burn', + index % 4 === 3 && 'mr-0', + index > 11 && 'mb-0', + lightCard && 'bg-background-default-lighter opacity-75', + )} + > + </div> + )) + } + { + !lightCard && ( + <div + className='absolute inset-0 bg-marketplace-plugin-empty z-[1]' + ></div> + ) + } + <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[2] flex flex-col items-center'> + <div className='relative flex items-center justify-center mb-3 w-14 h-14 rounded-xl border border-dashed border-divider-deep bg-components-card-bg shadow-lg'> + <Group className='w-5 h-5' /> + <Line className='absolute right-[-1px] top-1/2 -translate-y-1/2' /> + <Line className='absolute left-[-1px] top-1/2 -translate-y-1/2' /> + <Line className='absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-90' /> + <Line className='absolute top-full left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-90' /> + </div> + <div className='text-center system-md-regular text-text-tertiary'> + {text || t('plugin.marketplace.noPluginFound')} + </div> + </div> + </div> + ) +} + +export default Empty diff --git a/web/app/components/plugins/marketplace/empty/line.tsx b/web/app/components/plugins/marketplace/empty/line.tsx new file mode 100644 index 0000000000..19837aa862 --- /dev/null +++ b/web/app/components/plugins/marketplace/empty/line.tsx @@ -0,0 +1,21 @@ +type LineProps = { + className?: string +} +const Line = ({ + className, +}: LineProps) => { + return ( + <svg xmlns="http://www.w3.org/2000/svg" width="2" height="241" viewBox="0 0 2 241" fill="none" className={className}> + <path d="M1 0.5L1 240.5" stroke="url(#paint0_linear_1989_74474)"/> + <defs> + <linearGradient id="paint0_linear_1989_74474" x1="-7.99584" y1="240.5" x2="-7.88094" y2="0.50004" gradientUnits="userSpaceOnUse"> + <stop stopColor="white" stopOpacity="0.01"/> + <stop offset="0.503965" stopColor="#101828" stopOpacity="0.08"/> + <stop offset="1" stopColor="white" stopOpacity="0.01"/> + </linearGradient> + </defs> + </svg> + ) +} + +export default Line diff --git a/web/app/components/plugins/marketplace/hooks.ts b/web/app/components/plugins/marketplace/hooks.ts new file mode 100644 index 0000000000..8f811d1b3e --- /dev/null +++ b/web/app/components/plugins/marketplace/hooks.ts @@ -0,0 +1,176 @@ +import { + useCallback, + useEffect, + useState, +} from 'react' +import { useTranslation } from 'react-i18next' +import { useDebounceFn } from 'ahooks' +import type { + Plugin, +} from '../types' +import type { + CollectionsAndPluginsSearchParams, + MarketplaceCollection, + PluginsSearchParams, +} from './types' +import { + getFormattedPlugin, + getMarketplaceCollectionsAndPlugins, +} from './utils' +import i18n from '@/i18n/i18next-config' +import { + useMutationPluginsFromMarketplace, +} from '@/service/use-plugins' + +export const useMarketplaceCollectionsAndPlugins = () => { + const [isLoading, setIsLoading] = useState(false) + const [isSuccess, setIsSuccess] = useState(false) + const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>() + const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>() + + const queryMarketplaceCollectionsAndPlugins = useCallback(async (query?: CollectionsAndPluginsSearchParams) => { + try { + setIsLoading(true) + setIsSuccess(false) + const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins(query) + setIsLoading(false) + setIsSuccess(true) + setMarketplaceCollections(marketplaceCollections) + setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap) + } + // eslint-disable-next-line unused-imports/no-unused-vars + catch (e) { + setIsLoading(false) + setIsSuccess(false) + } + }, []) + + return { + marketplaceCollections, + setMarketplaceCollections, + marketplaceCollectionPluginsMap, + setMarketplaceCollectionPluginsMap, + queryMarketplaceCollectionsAndPlugins, + isLoading, + isSuccess, + } +} + +export const useMarketplacePlugins = () => { + const { + data, + mutateAsync, + reset, + isPending, + } = useMutationPluginsFromMarketplace() + + const [prevPlugins, setPrevPlugins] = useState<Plugin[] | undefined>() + const resetPlugins = useCallback(() => { + reset() + setPrevPlugins(undefined) + }, [reset]) + const handleUpdatePlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => { + mutateAsync(pluginsSearchParams).then((res) => { + const currentPage = pluginsSearchParams.page || 1 + const resPlugins = res.data.plugins + if (currentPage > 1) { + setPrevPlugins(prevPlugins => [...(prevPlugins || []), ...resPlugins.map((plugin) => { + return getFormattedPlugin(plugin) + })]) + } + else { + setPrevPlugins(resPlugins.map((plugin) => { + return getFormattedPlugin(plugin) + })) + } + }) + }, [mutateAsync]) + const queryPlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => { + handleUpdatePlugins(pluginsSearchParams) + }, [handleUpdatePlugins]) + + const { run: queryPluginsWithDebounced } = useDebounceFn((pluginsSearchParams: PluginsSearchParams) => { + handleUpdatePlugins(pluginsSearchParams) + }, { + wait: 500, + }) + + return { + plugins: prevPlugins, + total: data?.data?.total, + resetPlugins, + queryPlugins, + queryPluginsWithDebounced, + isLoading: isPending, + } +} + +export const useMixedTranslation = (localeFromOuter?: string) => { + let t = useTranslation().t + + if (localeFromOuter) + t = i18n.getFixedT(localeFromOuter) + + return { + t, + } +} + +export const useMarketplaceContainerScroll = ( + callback: () => void, + scrollContainerId = 'marketplace-container', +) => { + const container = document.getElementById(scrollContainerId) + + const handleScroll = useCallback((e: Event) => { + const target = e.target as HTMLDivElement + const { + scrollTop, + scrollHeight, + clientHeight, + } = target + if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0) + callback() + }, [callback]) + + useEffect(() => { + if (container) + container.addEventListener('scroll', handleScroll) + + return () => { + if (container) + container.removeEventListener('scroll', handleScroll) + } + }, [container, handleScroll]) +} + +export const useSearchBoxAutoAnimate = (searchBoxAutoAnimate?: boolean) => { + const [searchBoxCanAnimate, setSearchBoxCanAnimate] = useState(true) + + const handleSearchBoxCanAnimateChange = useCallback(() => { + if (!searchBoxAutoAnimate) { + const clientWidth = document.documentElement.clientWidth + + if (clientWidth < 1400) + setSearchBoxCanAnimate(false) + else + setSearchBoxCanAnimate(true) + } + }, [searchBoxAutoAnimate]) + + useEffect(() => { + handleSearchBoxCanAnimateChange() + }, [handleSearchBoxCanAnimateChange]) + + useEffect(() => { + window.addEventListener('resize', handleSearchBoxCanAnimateChange) + + return () => { + window.removeEventListener('resize', handleSearchBoxCanAnimateChange) + } + }, [handleSearchBoxCanAnimateChange]) + + return { + searchBoxCanAnimate, + } +} diff --git a/web/app/components/plugins/marketplace/index.tsx b/web/app/components/plugins/marketplace/index.tsx new file mode 100644 index 0000000000..5e6fbeec97 --- /dev/null +++ b/web/app/components/plugins/marketplace/index.tsx @@ -0,0 +1,68 @@ +import { MarketplaceContextProvider } from './context' +import Description from './description' +import IntersectionLine from './intersection-line' +import SearchBoxWrapper from './search-box/search-box-wrapper' +import PluginTypeSwitch from './plugin-type-switch' +import ListWrapper from './list/list-wrapper' +import type { SearchParams } from './types' +import { getMarketplaceCollectionsAndPlugins } from './utils' +import { TanstackQueryIniter } from '@/context/query-client' + +type MarketplaceProps = { + locale: string + searchBoxAutoAnimate?: boolean + showInstallButton?: boolean + shouldExclude?: boolean + searchParams?: SearchParams + pluginTypeSwitchClassName?: string + intersectionContainerId?: string + scrollContainerId?: string +} +const Marketplace = async ({ + locale, + searchBoxAutoAnimate = true, + showInstallButton = true, + shouldExclude, + searchParams, + pluginTypeSwitchClassName, + intersectionContainerId, + scrollContainerId, +}: MarketplaceProps) => { + let marketplaceCollections: any = [] + let marketplaceCollectionPluginsMap = {} + if (!shouldExclude) { + const marketplaceCollectionsAndPluginsData = await getMarketplaceCollectionsAndPlugins() + marketplaceCollections = marketplaceCollectionsAndPluginsData.marketplaceCollections + marketplaceCollectionPluginsMap = marketplaceCollectionsAndPluginsData.marketplaceCollectionPluginsMap + } + + return ( + <TanstackQueryIniter> + <MarketplaceContextProvider + searchParams={searchParams} + shouldExclude={shouldExclude} + scrollContainerId={scrollContainerId} + > + <Description locale={locale} /> + <IntersectionLine intersectionContainerId={intersectionContainerId} /> + <SearchBoxWrapper + locale={locale} + searchBoxAutoAnimate={searchBoxAutoAnimate} + /> + <PluginTypeSwitch + locale={locale} + className={pluginTypeSwitchClassName} + searchBoxAutoAnimate={searchBoxAutoAnimate} + /> + <ListWrapper + locale={locale} + marketplaceCollections={marketplaceCollections} + marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap} + showInstallButton={showInstallButton} + /> + </MarketplaceContextProvider> + </TanstackQueryIniter> + ) +} + +export default Marketplace diff --git a/web/app/components/plugins/marketplace/intersection-line/hooks.ts b/web/app/components/plugins/marketplace/intersection-line/hooks.ts new file mode 100644 index 0000000000..fe30b707cb --- /dev/null +++ b/web/app/components/plugins/marketplace/intersection-line/hooks.ts @@ -0,0 +1,30 @@ +import { useEffect } from 'react' +import { useMarketplaceContext } from '@/app/components/plugins/marketplace/context' + +export const useScrollIntersection = ( + anchorRef: React.RefObject<HTMLDivElement>, + intersectionContainerId = 'marketplace-container', +) => { + const intersected = useMarketplaceContext(v => v.intersected) + const setIntersected = useMarketplaceContext(v => v.setIntersected) + + useEffect(() => { + const container = document.getElementById(intersectionContainerId) + let observer: IntersectionObserver | undefined + if (container && anchorRef.current) { + observer = new IntersectionObserver((entries) => { + const isIntersecting = entries[0].isIntersecting + + if (isIntersecting && !intersected) + setIntersected(true) + + if (!isIntersecting && intersected) + setIntersected(false) + }, { + root: container, + }) + observer.observe(anchorRef.current) + } + return () => observer?.disconnect() + }, [anchorRef, intersected, setIntersected, intersectionContainerId]) +} diff --git a/web/app/components/plugins/marketplace/intersection-line/index.tsx b/web/app/components/plugins/marketplace/intersection-line/index.tsx new file mode 100644 index 0000000000..6f8e4b02ab --- /dev/null +++ b/web/app/components/plugins/marketplace/intersection-line/index.tsx @@ -0,0 +1,21 @@ +'use client' + +import { useRef } from 'react' +import { useScrollIntersection } from './hooks' + +type IntersectionLineProps = { + intersectionContainerId?: string +} +const IntersectionLine = ({ + intersectionContainerId, +}: IntersectionLineProps) => { + const ref = useRef<HTMLDivElement>(null) + + useScrollIntersection(ref, intersectionContainerId) + + return ( + <div ref={ref} className='mb-4 h-[1px] bg-transparent'></div> + ) +} + +export default IntersectionLine diff --git a/web/app/components/plugins/marketplace/list/card-wrapper.tsx b/web/app/components/plugins/marketplace/list/card-wrapper.tsx new file mode 100644 index 0000000000..a379102efd --- /dev/null +++ b/web/app/components/plugins/marketplace/list/card-wrapper.tsx @@ -0,0 +1,103 @@ +'use client' +import { RiArrowRightUpLine } from '@remixicon/react' +import { getPluginLinkInMarketplace } from '../utils' +import Card from '@/app/components/plugins/card' +import CardMoreInfo from '@/app/components/plugins/card/card-more-info' +import type { Plugin } from '@/app/components/plugins/types' +import Button from '@/app/components/base/button' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' +import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace' +import { useBoolean } from 'ahooks' +import { useI18N } from '@/context/i18n' +import { useTags } from '@/app/components/plugins/hooks' + +type CardWrapperProps = { + plugin: Plugin + showInstallButton?: boolean + locale?: string +} +const CardWrapper = ({ + plugin, + showInstallButton, + locale, +}: CardWrapperProps) => { + const { t } = useMixedTranslation(locale) + const [isShowInstallFromMarketplace, { + setTrue: showInstallFromMarketplace, + setFalse: hideInstallFromMarketplace, + }] = useBoolean(false) + const { locale: localeFromLocale } = useI18N() + const { tagsMap } = useTags(t) + + if (showInstallButton) { + return ( + <div + className='group relative rounded-xl cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover' + > + <Card + key={plugin.name} + payload={plugin} + locale={locale} + footer={ + <CardMoreInfo + downloadCount={plugin.install_count} + tags={plugin.tags.map(tag => tagsMap[tag.name].label)} + /> + } + /> + { + showInstallButton && ( + <div className='hidden absolute bottom-0 group-hover:flex items-center space-x-2 px-4 pt-8 pb-4 w-full bg-gradient-to-tr from-components-panel-on-panel-item-bg to-background-gradient-mask-transparent rounded-b-xl'> + <Button + variant='primary' + className='w-[calc(50%-4px)]' + onClick={showInstallFromMarketplace} + > + {t('plugin.detailPanel.operation.install')} + </Button> + <a href={`${getPluginLinkInMarketplace(plugin)}?language=${localeFromLocale}`} target='_blank' className='block flex-1 shrink-0 w-[calc(50%-4px)]'> + <Button + className='w-full gap-0.5' + > + {t('plugin.detailPanel.operation.detail')} + <RiArrowRightUpLine className='ml-1 w-4 h-4' /> + </Button> + </a> + </div> + ) + } + { + isShowInstallFromMarketplace && ( + <InstallFromMarketplace + manifest={plugin as any} + uniqueIdentifier={plugin.latest_package_identifier} + onClose={hideInstallFromMarketplace} + onSuccess={hideInstallFromMarketplace} + /> + ) + } + </div> + ) + } + + return ( + <a + className='group inline-block relative rounded-xl cursor-pointer' + href={getPluginLinkInMarketplace(plugin)} + > + <Card + key={plugin.name} + payload={plugin} + locale={locale} + footer={ + <CardMoreInfo + downloadCount={plugin.install_count} + tags={plugin.tags.map(tag => tagsMap[tag.name].label)} + /> + } + /> + </a> + ) +} + +export default CardWrapper diff --git a/web/app/components/plugins/marketplace/list/index.tsx b/web/app/components/plugins/marketplace/list/index.tsx new file mode 100644 index 0000000000..673f37e642 --- /dev/null +++ b/web/app/components/plugins/marketplace/list/index.tsx @@ -0,0 +1,79 @@ +'use client' +import type { Plugin } from '../../types' +import type { MarketplaceCollection } from '../types' +import ListWithCollection from './list-with-collection' +import CardWrapper from './card-wrapper' +import Empty from '../empty' +import cn from '@/utils/classnames' + +type ListProps = { + marketplaceCollections: MarketplaceCollection[] + marketplaceCollectionPluginsMap: Record<string, Plugin[]> + plugins?: Plugin[] + showInstallButton?: boolean + locale: string + cardContainerClassName?: string + cardRender?: (plugin: Plugin) => JSX.Element | null + onMoreClick?: () => void + emptyClassName?: string +} +const List = ({ + marketplaceCollections, + marketplaceCollectionPluginsMap, + plugins, + showInstallButton, + locale, + cardContainerClassName, + cardRender, + onMoreClick, + emptyClassName, +}: ListProps) => { + return ( + <> + { + !plugins && ( + <ListWithCollection + marketplaceCollections={marketplaceCollections} + marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap} + showInstallButton={showInstallButton} + locale={locale} + cardContainerClassName={cardContainerClassName} + cardRender={cardRender} + onMoreClick={onMoreClick} + /> + ) + } + { + plugins && !!plugins.length && ( + <div className={cn( + 'grid grid-cols-4 gap-3', + cardContainerClassName, + )}> + { + plugins.map((plugin) => { + if (cardRender) + return cardRender(plugin) + + return ( + <CardWrapper + key={plugin.name} + plugin={plugin} + showInstallButton={showInstallButton} + locale={locale} + /> + ) + }) + } + </div> + ) + } + { + plugins && !plugins.length && ( + <Empty className={emptyClassName} locale={locale} /> + ) + } + </> + ) +} + +export default List diff --git a/web/app/components/plugins/marketplace/list/list-with-collection.tsx b/web/app/components/plugins/marketplace/list/list-with-collection.tsx new file mode 100644 index 0000000000..aed84d77dd --- /dev/null +++ b/web/app/components/plugins/marketplace/list/list-with-collection.tsx @@ -0,0 +1,84 @@ +'use client' + +import { RiArrowRightSLine } from '@remixicon/react' +import type { MarketplaceCollection } from '../types' +import CardWrapper from './card-wrapper' +import type { Plugin } from '@/app/components/plugins/types' +import { getLanguage } from '@/i18n/language' +import cn from '@/utils/classnames' +import type { SearchParamsFromCollection } from '@/app/components/plugins/marketplace/types' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' + +type ListWithCollectionProps = { + marketplaceCollections: MarketplaceCollection[] + marketplaceCollectionPluginsMap: Record<string, Plugin[]> + showInstallButton?: boolean + locale: string + cardContainerClassName?: string + cardRender?: (plugin: Plugin) => JSX.Element | null + onMoreClick?: (searchParams?: SearchParamsFromCollection) => void +} +const ListWithCollection = ({ + marketplaceCollections, + marketplaceCollectionPluginsMap, + showInstallButton, + locale, + cardContainerClassName, + cardRender, + onMoreClick, +}: ListWithCollectionProps) => { + const { t } = useMixedTranslation(locale) + + return ( + <> + { + marketplaceCollections.map(collection => ( + <div + key={collection.name} + className='py-3' + > + <div className='flex justify-between items-end'> + <div> + <div className='title-xl-semi-bold text-text-primary'>{collection.label[getLanguage(locale)]}</div> + <div className='system-xs-regular text-text-tertiary'>{collection.description[getLanguage(locale)]}</div> + </div> + { + collection.searchable && onMoreClick && ( + <div + className='flex items-center system-xs-medium text-text-accent cursor-pointer ' + onClick={() => onMoreClick?.(collection.search_params)} + > + {t('plugin.marketplace.viewMore')} + <RiArrowRightSLine className='w-4 h-4' /> + </div> + ) + } + </div> + <div className={cn( + 'grid grid-cols-4 gap-3 mt-2', + cardContainerClassName, + )}> + { + marketplaceCollectionPluginsMap[collection.name].map((plugin) => { + if (cardRender) + return cardRender(plugin) + + return ( + <CardWrapper + key={plugin.name} + plugin={plugin} + showInstallButton={showInstallButton} + locale={locale} + /> + ) + }) + } + </div> + </div> + )) + } + </> + ) +} + +export default ListWithCollection diff --git a/web/app/components/plugins/marketplace/list/list-wrapper.tsx b/web/app/components/plugins/marketplace/list/list-wrapper.tsx new file mode 100644 index 0000000000..2dc83ee831 --- /dev/null +++ b/web/app/components/plugins/marketplace/list/list-wrapper.tsx @@ -0,0 +1,73 @@ +'use client' +import { useEffect } from 'react' +import type { Plugin } from '../../types' +import type { MarketplaceCollection } from '../types' +import { useMarketplaceContext } from '../context' +import List from './index' +import SortDropdown from '../sort-dropdown' +import Loading from '@/app/components/base/loading' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' + +type ListWrapperProps = { + marketplaceCollections: MarketplaceCollection[] + marketplaceCollectionPluginsMap: Record<string, Plugin[]> + showInstallButton?: boolean + locale: string +} +const ListWrapper = ({ + marketplaceCollections, + marketplaceCollectionPluginsMap, + showInstallButton, + locale, +}: ListWrapperProps) => { + const { t } = useMixedTranslation(locale) + const plugins = useMarketplaceContext(v => v.plugins) + const pluginsTotal = useMarketplaceContext(v => v.pluginsTotal) + const marketplaceCollectionsFromClient = useMarketplaceContext(v => v.marketplaceCollectionsFromClient) + const marketplaceCollectionPluginsMapFromClient = useMarketplaceContext(v => v.marketplaceCollectionPluginsMapFromClient) + const isLoading = useMarketplaceContext(v => v.isLoading) + const isSuccessCollections = useMarketplaceContext(v => v.isSuccessCollections) + const handleQueryPlugins = useMarketplaceContext(v => v.handleQueryPlugins) + const page = useMarketplaceContext(v => v.page) + const handleMoreClick = useMarketplaceContext(v => v.handleMoreClick) + + useEffect(() => { + if (!marketplaceCollectionsFromClient?.length && isSuccessCollections) + handleQueryPlugins() + }, [handleQueryPlugins, marketplaceCollections, marketplaceCollectionsFromClient, isSuccessCollections]) + + return ( + <div className='relative flex flex-col grow h-0 px-12 py-2 bg-background-default-subtle'> + { + plugins && ( + <div className='flex items-center mb-4 pt-3'> + <div className='title-xl-semi-bold text-text-primary'>{t('plugin.marketplace.pluginsResult', { num: pluginsTotal })}</div> + <div className='mx-3 w-[1px] h-3.5 bg-divider-regular'></div> + <SortDropdown locale={locale} /> + </div> + ) + } + { + isLoading && page === 1 && ( + <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'> + <Loading /> + </div> + ) + } + { + (!isLoading || page > 1) && ( + <List + marketplaceCollections={marketplaceCollectionsFromClient || marketplaceCollections} + marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMapFromClient || marketplaceCollectionPluginsMap} + plugins={plugins} + showInstallButton={showInstallButton} + locale={locale} + onMoreClick={handleMoreClick} + /> + ) + } + </div> + ) +} + +export default ListWrapper diff --git a/web/app/components/plugins/marketplace/plugin-type-switch.tsx b/web/app/components/plugins/marketplace/plugin-type-switch.tsx new file mode 100644 index 0000000000..0be1c9f535 --- /dev/null +++ b/web/app/components/plugins/marketplace/plugin-type-switch.tsx @@ -0,0 +1,100 @@ +'use client' +import { + RiArchive2Line, + RiBrain2Line, + RiHammerLine, + RiPuzzle2Line, + RiSpeakAiLine, +} from '@remixicon/react' +import { PluginType } from '../types' +import { useMarketplaceContext } from './context' +import { + useMixedTranslation, + useSearchBoxAutoAnimate, +} from './hooks' +import cn from '@/utils/classnames' + +export const PLUGIN_TYPE_SEARCH_MAP = { + all: 'all', + model: PluginType.model, + tool: PluginType.tool, + agent: PluginType.agent, + extension: PluginType.extension, + bundle: 'bundle', +} +type PluginTypeSwitchProps = { + locale?: string + className?: string + searchBoxAutoAnimate?: boolean +} +const PluginTypeSwitch = ({ + locale, + className, + searchBoxAutoAnimate, +}: PluginTypeSwitchProps) => { + const { t } = useMixedTranslation(locale) + const activePluginType = useMarketplaceContext(s => s.activePluginType) + const handleActivePluginTypeChange = useMarketplaceContext(s => s.handleActivePluginTypeChange) + const { searchBoxCanAnimate } = useSearchBoxAutoAnimate(searchBoxAutoAnimate) + + const options = [ + { + value: PLUGIN_TYPE_SEARCH_MAP.all, + text: t('plugin.category.all'), + icon: null, + }, + { + value: PLUGIN_TYPE_SEARCH_MAP.model, + text: t('plugin.category.models'), + icon: <RiBrain2Line className='mr-1.5 w-4 h-4' />, + }, + { + value: PLUGIN_TYPE_SEARCH_MAP.tool, + text: t('plugin.category.tools'), + icon: <RiHammerLine className='mr-1.5 w-4 h-4' />, + }, + { + value: PLUGIN_TYPE_SEARCH_MAP.agent, + text: t('plugin.category.agents'), + icon: <RiSpeakAiLine className='mr-1.5 w-4 h-4' />, + }, + { + value: PLUGIN_TYPE_SEARCH_MAP.extension, + text: t('plugin.category.extensions'), + icon: <RiPuzzle2Line className='mr-1.5 w-4 h-4' />, + }, + { + value: PLUGIN_TYPE_SEARCH_MAP.bundle, + text: t('plugin.category.bundles'), + icon: <RiArchive2Line className='mr-1.5 w-4 h-4' />, + }, + ] + + return ( + <div className={cn( + 'shrink-0 flex items-center justify-center py-3 bg-background-body space-x-2', + searchBoxCanAnimate && 'sticky top-[56px] z-10', + className, + )}> + { + options.map(option => ( + <div + key={option.value} + className={cn( + 'flex items-center px-3 h-8 border border-transparent rounded-xl cursor-pointer hover:bg-state-base-hover hover:text-text-secondary system-md-medium text-text-tertiary', + activePluginType === option.value && 'border-components-main-nav-nav-button-border !bg-components-main-nav-nav-button-bg-active !text-components-main-nav-nav-button-text-active shadow-xs', + )} + onClick={() => { + handleActivePluginTypeChange(option.value) + }} + > + {option.icon} + {option.text} + </div> + )) + } + </div> + ) +} + +export default PluginTypeSwitch diff --git a/web/app/components/plugins/marketplace/search-box/index.tsx b/web/app/components/plugins/marketplace/search-box/index.tsx new file mode 100644 index 0000000000..61fff2c7a9 --- /dev/null +++ b/web/app/components/plugins/marketplace/search-box/index.tsx @@ -0,0 +1,70 @@ +'use client' +import { RiCloseLine } from '@remixicon/react' +import TagsFilter from './tags-filter' +import ActionButton from '@/app/components/base/action-button' +import cn from '@/utils/classnames' + +type SearchBoxProps = { + search: string + onSearchChange: (search: string) => void + inputClassName?: string + tags: string[] + onTagsChange: (tags: string[]) => void + size?: 'small' | 'large' + placeholder?: string + locale?: string +} +const SearchBox = ({ + search, + onSearchChange, + inputClassName, + tags, + onTagsChange, + size = 'small', + placeholder = '', + locale, +}: SearchBoxProps) => { + return ( + <div + className={cn( + 'flex items-center z-[11]', + size === 'large' && 'p-1.5 bg-components-panel-bg-blur rounded-xl shadow-md border border-components-chat-input-border', + size === 'small' && 'p-0.5 bg-components-input-bg-normal rounded-lg', + inputClassName, + )} + > + <TagsFilter + tags={tags} + onTagsChange={onTagsChange} + size={size} + locale={locale} + /> + <div className='mx-1 w-[1px] h-3.5 bg-divider-regular'></div> + <div className='relative grow flex items-center p-1 pl-2'> + <div className='flex items-center mr-2 w-full'> + <input + className={cn( + 'grow block outline-none appearance-none body-md-medium text-text-secondary bg-transparent', + )} + value={search} + onChange={(e) => { + onSearchChange(e.target.value) + }} + placeholder={placeholder} + /> + { + search && ( + <div className='absolute right-2 top-1/2 -translate-y-1/2'> + <ActionButton onClick={() => onSearchChange('')}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> + </div> + ) + } + </div> + </div> + </div> + ) +} + +export default SearchBox diff --git a/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx b/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx new file mode 100644 index 0000000000..beb1c947fd --- /dev/null +++ b/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx @@ -0,0 +1,45 @@ +'use client' + +import { useMarketplaceContext } from '../context' +import { + useMixedTranslation, + useSearchBoxAutoAnimate, +} from '../hooks' +import SearchBox from './index' +import cn from '@/utils/classnames' + +type SearchBoxWrapperProps = { + locale?: string + searchBoxAutoAnimate?: boolean +} +const SearchBoxWrapper = ({ + locale, + searchBoxAutoAnimate, +}: SearchBoxWrapperProps) => { + const { t } = useMixedTranslation(locale) + const intersected = useMarketplaceContext(v => v.intersected) + const searchPluginText = useMarketplaceContext(v => v.searchPluginText) + const handleSearchPluginTextChange = useMarketplaceContext(v => v.handleSearchPluginTextChange) + const filterPluginTags = useMarketplaceContext(v => v.filterPluginTags) + const handleFilterPluginTagsChange = useMarketplaceContext(v => v.handleFilterPluginTagsChange) + const { searchBoxCanAnimate } = useSearchBoxAutoAnimate(searchBoxAutoAnimate) + + return ( + <SearchBox + inputClassName={cn( + 'mx-auto w-[640px] shrink-0 z-[0]', + searchBoxCanAnimate && 'sticky top-3 z-[11]', + !intersected && searchBoxCanAnimate && 'w-[508px] transition-[width] duration-300', + )} + search={searchPluginText} + onSearchChange={handleSearchPluginTextChange} + tags={filterPluginTags} + onTagsChange={handleFilterPluginTagsChange} + size='large' + locale={locale} + placeholder={t('plugin.searchPlugins')} + /> + ) +} + +export default SearchBoxWrapper diff --git a/web/app/components/plugins/marketplace/search-box/tags-filter.tsx b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx new file mode 100644 index 0000000000..dec07d0319 --- /dev/null +++ b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx @@ -0,0 +1,138 @@ +'use client' + +import { useState } from 'react' +import { + RiArrowDownSLine, + RiCloseCircleFill, + RiFilter3Line, +} from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Checkbox from '@/app/components/base/checkbox' +import cn from '@/utils/classnames' +import Input from '@/app/components/base/input' +import { useTags } from '@/app/components/plugins/hooks' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' + +type TagsFilterProps = { + tags: string[] + onTagsChange: (tags: string[]) => void + size: 'small' | 'large' + locale?: string +} +const TagsFilter = ({ + tags, + onTagsChange, + size, + locale, +}: TagsFilterProps) => { + const { t } = useMixedTranslation(locale) + const [open, setOpen] = useState(false) + const [searchText, setSearchText] = useState('') + const { tags: options, tagsMap } = useTags(t) + const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchText.toLowerCase())) + const handleCheck = (id: string) => { + if (tags.includes(id)) + onTagsChange(tags.filter((tag: string) => tag !== id)) + else + onTagsChange([...tags, id]) + } + const selectedTagsLength = tags.length + + return ( + <PortalToFollowElem + placement='bottom-start' + offset={{ + mainAxis: 4, + crossAxis: -6, + }} + open={open} + onOpenChange={setOpen} + > + <PortalToFollowElemTrigger + className='shrink-0' + onClick={() => setOpen(v => !v)} + > + <div className={cn( + 'flex items-center text-text-tertiary rounded-lg hover:bg-state-base-hover cursor-pointer', + size === 'large' && 'px-2 py-1 h-8', + size === 'small' && 'pr-1.5 py-0.5 h-7 pl-1 ', + selectedTagsLength && 'text-text-secondary', + open && 'bg-state-base-hover', + )}> + <div className='p-0.5'> + <RiFilter3Line className='w-4 h-4' /> + </div> + <div className={cn( + 'flex items-center p-1 system-sm-medium', + size === 'large' && 'p-1', + size === 'small' && 'px-0.5 py-1', + )}> + { + !selectedTagsLength && t('pluginTags.allTags') + } + { + !!selectedTagsLength && tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',') + } + { + selectedTagsLength > 2 && ( + <div className='ml-1 system-xs-medium text-text-tertiary'> + +{selectedTagsLength - 2} + </div> + ) + } + </div> + { + !!selectedTagsLength && ( + <RiCloseCircleFill + className='w-4 h-4 text-text-quaternary cursor-pointer' + onClick={() => onTagsChange([])} + /> + ) + } + { + !selectedTagsLength && ( + <RiArrowDownSLine className='w-4 h-4' /> + ) + } + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[1000]'> + <div className='w-[240px] border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-xl shadow-lg'> + <div className='p-2 pb-1'> + <Input + showLeftIcon + value={searchText} + onChange={e => setSearchText(e.target.value)} + placeholder={t('pluginTags.searchTags') || ''} + /> + </div> + <div className='p-1 max-h-[448px] overflow-y-auto'> + { + filteredOptions.map(option => ( + <div + key={option.name} + className='flex items-center px-2 py-1.5 h-7 rounded-lg cursor-pointer hover:bg-state-base-hover' + onClick={() => handleCheck(option.name)} + > + <Checkbox + className='mr-1' + checked={tags.includes(option.name)} + /> + <div className='px-1 system-sm-medium text-text-secondary'> + {option.label} + </div> + </div> + )) + } + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default TagsFilter diff --git a/web/app/components/plugins/marketplace/sort-dropdown/index.tsx b/web/app/components/plugins/marketplace/sort-dropdown/index.tsx new file mode 100644 index 0000000000..b39cbe86ce --- /dev/null +++ b/web/app/components/plugins/marketplace/sort-dropdown/index.tsx @@ -0,0 +1,94 @@ +'use client' +import { useState } from 'react' +import { + RiArrowDownSLine, + RiCheckLine, +} from '@remixicon/react' +import { useMarketplaceContext } from '../context' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' + +type SortDropdownProps = { + locale?: string +} +const SortDropdown = ({ + locale, +}: SortDropdownProps) => { + const { t } = useMixedTranslation(locale) + const options = [ + { + value: 'install_count', + order: 'DESC', + text: t('plugin.marketplace.sortOption.mostPopular'), + }, + { + value: 'version_updated_at', + order: 'DESC', + text: t('plugin.marketplace.sortOption.recentlyUpdated'), + }, + { + value: 'created_at', + order: 'DESC', + text: t('plugin.marketplace.sortOption.newlyReleased'), + }, + { + value: 'created_at', + order: 'ASC', + text: t('plugin.marketplace.sortOption.firstReleased'), + }, + ] + const sort = useMarketplaceContext(v => v.sort) + const handleSortChange = useMarketplaceContext(v => v.handleSortChange) + const [open, setOpen] = useState(false) + const selectedOption = options.find(option => option.value === sort.sortBy && option.order === sort.sortOrder)! + + return ( + <PortalToFollowElem + placement='bottom-start' + offset={{ + mainAxis: 4, + crossAxis: 0, + }} + open={open} + onOpenChange={setOpen} + > + <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}> + <div className='flex items-center px-2 pr-3 h-8 rounded-lg bg-state-base-hover-alt cursor-pointer'> + <span className='mr-1 system-sm-regular text-text-secondary'> + {t('plugin.marketplace.sortBy')} + </span> + <span className='mr-1 system-sm-medium text-text-primary'> + {selectedOption.text} + </span> + <RiArrowDownSLine className='w-4 h-4 text-text-tertiary' /> + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent> + <div className='p-1 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur backdrop-blur-sm shadow-lg'> + { + options.map(option => ( + <div + key={`${option.value}-${option.order}`} + className='flex items-center justify-between px-3 pr-2 h-8 cursor-pointer system-md-regular text-text-primary rounded-lg hover:bg-components-panel-on-panel-item-bg-hover' + onClick={() => handleSortChange({ sortBy: option.value, sortOrder: option.order })} + > + {option.text} + { + sort.sortBy === option.value && sort.sortOrder === option.order && ( + <RiCheckLine className='ml-2 w-4 h-4 text-text-accent' /> + ) + } + </div> + )) + } + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default SortDropdown diff --git a/web/app/components/plugins/marketplace/types.ts b/web/app/components/plugins/marketplace/types.ts new file mode 100644 index 0000000000..4145f69248 --- /dev/null +++ b/web/app/components/plugins/marketplace/types.ts @@ -0,0 +1,59 @@ +import type { Plugin } from '../types' + +export type SearchParamsFromCollection = { + query?: string + sort_by?: string + sort_order?: string +} + +export type MarketplaceCollection = { + name: string + label: Record<string, string> + description: Record<string, string> + rule: string + created_at: string + updated_at: string + searchable?: boolean + search_params?: SearchParamsFromCollection +} + +export type MarketplaceCollectionsResponse = { + collections: MarketplaceCollection[] + total: number +} + +export type MarketplaceCollectionPluginsResponse = { + plugins: Plugin[] + total: number +} + +export type PluginsSearchParams = { + query: string + page?: number + pageSize?: number + sortBy?: string + sortOrder?: string + category?: string + tags?: string[] + exclude?: string[] + type?: 'plugin' | 'bundle' +} + +export type PluginsSort = { + sortBy: string + sortOrder: string +} + +export type CollectionsAndPluginsSearchParams = { + category?: string + condition?: string + exclude?: string[] + type?: 'plugin' | 'bundle' +} + +export type SearchParams = { + language?: string + q?: string + tags?: string + category?: string +} diff --git a/web/app/components/plugins/marketplace/utils.ts b/web/app/components/plugins/marketplace/utils.ts new file mode 100644 index 0000000000..78d4437681 --- /dev/null +++ b/web/app/components/plugins/marketplace/utils.ts @@ -0,0 +1,124 @@ +import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch' +import type { Plugin } from '@/app/components/plugins/types' +import { PluginType } from '@/app/components/plugins/types' +import type { + CollectionsAndPluginsSearchParams, + MarketplaceCollection, +} from '@/app/components/plugins/marketplace/types' +import { + MARKETPLACE_API_PREFIX, + MARKETPLACE_URL_PREFIX, +} from '@/config' + +export const getPluginIconInMarketplace = (plugin: Plugin) => { + if (plugin.type === 'bundle') + return `${MARKETPLACE_API_PREFIX}/bundles/${plugin.org}/${plugin.name}/icon` + return `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon` +} + +export const getFormattedPlugin = (bundle: any) => { + if (bundle.type === 'bundle') { + return { + ...bundle, + icon: getPluginIconInMarketplace(bundle), + brief: bundle.description, + label: bundle.labels, + } + } + return { + ...bundle, + icon: getPluginIconInMarketplace(bundle), + } +} + +export const getPluginLinkInMarketplace = (plugin: Plugin) => { + if (plugin.type === 'bundle') + return `${MARKETPLACE_URL_PREFIX}/bundles/${plugin.org}/${plugin.name}` + return `${MARKETPLACE_URL_PREFIX}/plugins/${plugin.org}/${plugin.name}` +} + +export const getMarketplacePluginsByCollectionId = async (collectionId: string, query?: CollectionsAndPluginsSearchParams) => { + let plugins = [] as Plugin[] + + try { + const url = `${MARKETPLACE_API_PREFIX}/collections/${collectionId}/plugins` + const marketplaceCollectionPluginsData = await globalThis.fetch( + url, + { + cache: 'no-store', + method: 'POST', + body: JSON.stringify({ + category: query?.category, + exclude: query?.exclude, + type: query?.type, + }), + }, + ) + const marketplaceCollectionPluginsDataJson = await marketplaceCollectionPluginsData.json() + plugins = marketplaceCollectionPluginsDataJson.data.plugins.map((plugin: Plugin) => { + return getFormattedPlugin(plugin) + }) + } + // eslint-disable-next-line unused-imports/no-unused-vars + catch (e) { + plugins = [] + } + + return plugins +} + +export const getMarketplaceCollectionsAndPlugins = async (query?: CollectionsAndPluginsSearchParams) => { + let marketplaceCollections = [] as MarketplaceCollection[] + let marketplaceCollectionPluginsMap = {} as Record<string, Plugin[]> + try { + let marketplaceUrl = `${MARKETPLACE_API_PREFIX}/collections?page=1&page_size=100` + if (query?.condition) + marketplaceUrl += `&condition=${query.condition}` + if (query?.type) + marketplaceUrl += `&type=${query.type}` + const marketplaceCollectionsData = await globalThis.fetch(marketplaceUrl, { cache: 'no-store' }) + const marketplaceCollectionsDataJson = await marketplaceCollectionsData.json() + marketplaceCollections = marketplaceCollectionsDataJson.data.collections + await Promise.all(marketplaceCollections.map(async (collection: MarketplaceCollection) => { + const plugins = await getMarketplacePluginsByCollectionId(collection.name, query) + + marketplaceCollectionPluginsMap[collection.name] = plugins + })) + } + // eslint-disable-next-line unused-imports/no-unused-vars + catch (e) { + marketplaceCollections = [] + marketplaceCollectionPluginsMap = {} + } + + return { + marketplaceCollections, + marketplaceCollectionPluginsMap, + } +} + +export const getMarketplaceListCondition = (pluginType: string) => { + if (pluginType === PluginType.tool) + return 'category=tool' + + if (pluginType === PluginType.agent) + return 'category=agent-strategy' + + if (pluginType === PluginType.model) + return 'category=model' + + if (pluginType === PluginType.extension) + return 'category=endpoint' + + return '' +} + +export const getMarketplaceListFilterType = (category: string) => { + if (category === PLUGIN_TYPE_SEARCH_MAP.all) + return undefined + + if (category === PLUGIN_TYPE_SEARCH_MAP.bundle) + return 'bundle' + + return 'plugin' +} diff --git a/web/app/components/plugins/permission-setting-modal/modal.tsx b/web/app/components/plugins/permission-setting-modal/modal.tsx new file mode 100644 index 0000000000..b5eaa4765c --- /dev/null +++ b/web/app/components/plugins/permission-setting-modal/modal.tsx @@ -0,0 +1,93 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Modal from '@/app/components/base/modal' +import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card' +import Button from '@/app/components/base/button' +import type { Permissions } from '@/app/components/plugins/types' +import { PermissionType } from '@/app/components/plugins/types' + +const i18nPrefix = 'plugin.privilege' +type Props = { + payload: Permissions + onHide: () => void + onSave: (payload: Permissions) => void +} + +const PluginSettingModal: FC<Props> = ({ + payload, + onHide, + onSave, +}) => { + const { t } = useTranslation() + const [tempPrivilege, setTempPrivilege] = useState<Permissions>(payload) + const handlePrivilegeChange = useCallback((key: string) => { + return (value: PermissionType) => { + setTempPrivilege({ + ...tempPrivilege, + [key]: value, + }) + } + }, [tempPrivilege]) + + const handleSave = useCallback(async () => { + await onSave(tempPrivilege) + onHide() + }, [onHide, onSave, tempPrivilege]) + + return ( + <Modal + isShow + onClose={onHide} + closable + className='!p-0 w-[420px]' + > + <div className='flex flex-col items-start w-[420px] rounded-2xl border border-components-panel-border bg-components-panel-bg shadows-shadow-xl'> + <div className='flex pt-6 pb-3 pl-6 pr-14 items-start gap-2 self-stretch'> + <span className='self-stretch text-text-primary title-2xl-semi-bold'>{t(`${i18nPrefix}.title`)}</span> + </div> + <div className='flex px-6 py-3 flex-col justify-center items-start gap-4 self-stretch'> + {[ + { title: t(`${i18nPrefix}.whoCanInstall`), key: 'install_permission', value: tempPrivilege.install_permission }, + { title: t(`${i18nPrefix}.whoCanDebug`), key: 'debug_permission', value: tempPrivilege.debug_permission }, + ].map(({ title, key, value }) => ( + <div key={key} className='flex flex-col items-start gap-1 self-stretch'> + <div className='flex h-6 items-center gap-0.5'> + <span className='text-text-secondary system-sm-semibold'>{title}</span> + </div> + <div className='flex items-start gap-2 justify-between w-full'> + {[PermissionType.everyone, PermissionType.admin, PermissionType.noOne].map(option => ( + <OptionCard + key={option} + title={t(`${i18nPrefix}.${option}`)} + onSelect={() => handlePrivilegeChange(key)(option)} + selected={value === option} + className="flex-1" + /> + ))} + </div> + </div> + ))} + </div> + <div className='flex h-[76px] p-6 pt-5 justify-end items-center gap-2 self-stretch'> + <Button + className='min-w-[72px]' + onClick={onHide} + > + {t('common.operation.cancel')} + </Button> + <Button + className='min-w-[72px]' + variant={'primary'} + onClick={handleSave} + > + {t('common.operation.save')} + </Button> + </div> + </div> + </Modal> + ) +} + +export default React.memo(PluginSettingModal) diff --git a/web/app/components/plugins/permission-setting-modal/style.module.css b/web/app/components/plugins/permission-setting-modal/style.module.css new file mode 100644 index 0000000000..7ad3180a5a --- /dev/null +++ b/web/app/components/plugins/permission-setting-modal/style.module.css @@ -0,0 +1,7 @@ +.textGradient { + background: linear-gradient(92deg, #2250F2 -29.55%, #0EBCF3 75.22%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; +} \ No newline at end of file diff --git a/web/app/components/plugins/plugin-detail-panel/action-list.tsx b/web/app/components/plugins/plugin-detail-panel/action-list.tsx new file mode 100644 index 0000000000..46818d40f5 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/action-list.tsx @@ -0,0 +1,112 @@ +import React, { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useAppContext } from '@/context/app-context' +import Button from '@/app/components/base/button' +import Toast from '@/app/components/base/toast' +import Indicator from '@/app/components/header/indicator' +import ToolItem from '@/app/components/tools/provider/tool-item' +import ConfigCredential from '@/app/components/tools/setting/build-in/config-credentials' +import { + useAllToolProviders, + useBuiltinTools, + useInvalidateAllToolProviders, + useRemoveProviderCredentials, + useUpdateProviderCredentials, +} from '@/service/use-tools' +import type { PluginDetail } from '@/app/components/plugins/types' + +type Props = { + detail: PluginDetail +} + +const ActionList = ({ + detail, +}: Props) => { + const { t } = useTranslation() + const { isCurrentWorkspaceManager } = useAppContext() + const providerBriefInfo = detail.declaration.tool.identity + const providerKey = `${detail.plugin_id}/${providerBriefInfo.name}` + const { data: collectionList = [] } = useAllToolProviders() + const invalidateAllToolProviders = useInvalidateAllToolProviders() + const provider = useMemo(() => { + return collectionList.find(collection => collection.name === providerKey) + }, [collectionList, providerKey]) + const { data } = useBuiltinTools(providerKey) + + const [showSettingAuth, setShowSettingAuth] = useState(false) + + const handleCredentialSettingUpdate = () => { + invalidateAllToolProviders() + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + setShowSettingAuth(false) + } + + const { mutate: updatePermission, isPending } = useUpdateProviderCredentials({ + onSuccess: handleCredentialSettingUpdate, + }) + + const { mutate: removePermission } = useRemoveProviderCredentials({ + onSuccess: handleCredentialSettingUpdate, + }) + + if (!data || !provider) + return null + + return ( + <div className='px-4 pt-2 pb-4'> + <div className='mb-1 py-1'> + <div className='mb-1 h-6 flex items-center justify-between text-text-secondary system-sm-semibold-uppercase'> + {t('plugin.detailPanel.actionNum', { num: data.length, action: data.length > 1 ? 'actions' : 'action' })} + {provider.is_team_authorization && provider.allow_delete && ( + <Button + variant='secondary' + size='small' + onClick={() => setShowSettingAuth(true)} + disabled={!isCurrentWorkspaceManager} + > + <Indicator className='mr-2' color={'green'} /> + {t('tools.auth.authorized')} + </Button> + )} + </div> + {!provider.is_team_authorization && provider.allow_delete && ( + <Button + variant='primary' + className='w-full' + onClick={() => setShowSettingAuth(true)} + disabled={!isCurrentWorkspaceManager} + >{t('tools.auth.unauthorized')}</Button> + )} + </div> + <div className='flex flex-col gap-2'> + {data.map(tool => ( + <ToolItem + key={`${detail.plugin_id}${tool.name}`} + disabled={false} + collection={provider} + tool={tool} + isBuiltIn={true} + isModel={false} + /> + ))} + </div> + {showSettingAuth && ( + <ConfigCredential + collection={provider} + onCancel={() => setShowSettingAuth(false)} + onSaved={async value => updatePermission({ + providerName: provider.name, + credentials: value, + })} + onRemove={async () => removePermission(provider.name)} + isSaving={isPending} + /> + )} + </div> + ) +} + +export default ActionList diff --git a/web/app/components/plugins/plugin-detail-panel/agent-strategy-list.tsx b/web/app/components/plugins/plugin-detail-panel/agent-strategy-list.tsx new file mode 100644 index 0000000000..fafcf1439c --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/agent-strategy-list.tsx @@ -0,0 +1,58 @@ +import React, { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import StrategyItem from '@/app/components/plugins/plugin-detail-panel/strategy-item' +import { + useStrategyProviderDetail, +} from '@/service/use-strategy' +import type { PluginDetail } from '@/app/components/plugins/types' + +type Props = { + detail: PluginDetail +} + +const AgentStrategyList = ({ + detail, +}: Props) => { + const { t } = useTranslation() + const providerBriefInfo = detail.declaration.agent_strategy.identity + const providerKey = `${detail.plugin_id}/${providerBriefInfo.name}` + const { data: strategyProviderDetail } = useStrategyProviderDetail(providerKey) + + const providerDetail = useMemo(() => { + return { + ...strategyProviderDetail?.declaration.identity, + tenant_id: detail.tenant_id, + } + }, [detail.tenant_id, strategyProviderDetail?.declaration.identity]) + + const strategyList = useMemo(() => { + if (!strategyProviderDetail) + return [] + + return strategyProviderDetail.declaration.strategies + }, [strategyProviderDetail]) + + if (!strategyProviderDetail) + return null + + return ( + <div className='px-4 pt-2 pb-4'> + <div className='mb-1 py-1'> + <div className='mb-1 h-6 flex items-center justify-between text-text-secondary system-sm-semibold-uppercase'> + {t('plugin.detailPanel.strategyNum', { num: strategyList.length, strategy: strategyList.length > 1 ? 'strategies' : 'strategy' })} + </div> + </div> + <div className='flex flex-col gap-2'> + {strategyList.map(strategyDetail => ( + <StrategyItem + key={`${strategyDetail.identity.provider}${strategyDetail.identity.name}`} + provider={providerDetail as any} + detail={strategyDetail} + /> + ))} + </div> + </div> + ) +} + +export default AgentStrategyList diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-form.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-form.tsx new file mode 100644 index 0000000000..6dd9926d35 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-form.tsx @@ -0,0 +1,125 @@ +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import Input from '@/app/components/base/input' +import Textarea from '@/app/components/base/textarea' +import { PortalSelect } from '@/app/components/base/select' +import { InputVarType } from '@/app/components/workflow/types' +import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader' + +type Props = { + inputsForms: any[] + inputs: Record<string, any> + inputsRef: any + onFormChange: (value: Record<string, any>) => void +} +const AppInputsForm = ({ + inputsForms, + inputs, + inputsRef, + onFormChange, +}: Props) => { + const { t } = useTranslation() + + const handleFormChange = useCallback((variable: string, value: any) => { + onFormChange({ + ...inputsRef.current, + [variable]: value, + }) + }, [onFormChange, inputsRef]) + + const renderField = (form: any) => { + const { + label, + variable, + options, + } = form + if (form.type === InputVarType.textInput) { + return ( + <Input + value={inputs[variable] || ''} + onChange={e => handleFormChange(variable, e.target.value)} + placeholder={label} + /> + ) + } + if (form.type === InputVarType.number) { + return ( + <Input + type="number" + value={inputs[variable] || ''} + onChange={e => handleFormChange(variable, e.target.value)} + placeholder={label} + /> + ) + } + if (form.type === InputVarType.paragraph) { + return ( + <Textarea + value={inputs[variable] || ''} + onChange={e => handleFormChange(variable, e.target.value)} + placeholder={label} + /> + ) + } + if (form.type === InputVarType.select) { + return ( + <PortalSelect + popupClassName="w-[356px] z-[1050]" + value={inputs[variable] || ''} + items={options.map((option: string) => ({ value: option, name: option }))} + onSelect={item => handleFormChange(variable, item.value as string)} + placeholder={label} + /> + ) + } + if (form.type === InputVarType.singleFile) { + return ( + <FileUploaderInAttachmentWrapper + value={inputs[variable] ? [inputs[variable]] : []} + onChange={files => handleFormChange(variable, files[0])} + fileConfig={{ + allowed_file_types: form.allowed_file_types, + allowed_file_extensions: form.allowed_file_extensions, + allowed_file_upload_methods: form.allowed_file_upload_methods, + number_limits: 1, + fileUploadConfig: (form as any).fileUploadConfig, + }} + /> + ) + } + if (form.type === InputVarType.multiFiles) { + return ( + <FileUploaderInAttachmentWrapper + value={inputs[variable]} + onChange={files => handleFormChange(variable, files)} + fileConfig={{ + allowed_file_types: form.allowed_file_types, + allowed_file_extensions: form.allowed_file_extensions, + allowed_file_upload_methods: form.allowed_file_upload_methods, + number_limits: form.max_length, + fileUploadConfig: (form as any).fileUploadConfig, + }} + /> + ) + } + } + + if (!inputsForms.length) + return null + + return ( + <div className='px-4 py-2 flex flex-col gap-4'> + {inputsForms.map(form => ( + <div key={form.variable}> + <div className='h-6 mb-1 flex items-center gap-1 text-text-secondary system-sm-semibold'> + <div className='truncate'>{form.label}</div> + {!form.required && <span className='text-text-tertiary system-xs-regular'>{t('workflow.panel.optional')}</span>} + </div> + {renderField(form)} + </div> + ))} + </div> + ) +} + +export default AppInputsForm diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel.tsx new file mode 100644 index 0000000000..d293be3aad --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel.tsx @@ -0,0 +1,180 @@ +'use client' +import React, { useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import Loading from '@/app/components/base/loading' +import AppInputsForm from '@/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-form' +import { useAppDetail } from '@/service/use-apps' +import { useAppWorkflow } from '@/service/use-workflow' +import { useFileUploadConfig } from '@/service/use-common' +import { Resolution } from '@/types/app' +import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' +import type { App } from '@/types/app' +import type { FileUpload } from '@/app/components/base/features/types' +import { BlockEnum, InputVarType, SupportUploadFileTypes } from '@/app/components/workflow/types' + +import cn from '@/utils/classnames' + +type Props = { + value?: { + app_id: string + inputs: Record<string, any> + } + appDetail: App + onFormChange: (value: Record<string, any>) => void +} + +const AppInputsPanel = ({ + value, + appDetail, + onFormChange, +}: Props) => { + const { t } = useTranslation() + const inputsRef = useRef<any>(value?.inputs || {}) + const isBasicApp = appDetail.mode !== 'advanced-chat' && appDetail.mode !== 'workflow' + const { data: fileUploadConfig } = useFileUploadConfig() + const { data: currentApp, isFetching: isAppLoading } = useAppDetail(appDetail.id) + const { data: currentWorkflow, isFetching: isWorkflowLoading } = useAppWorkflow(isBasicApp ? '' : appDetail.id) + const isLoading = isAppLoading || isWorkflowLoading + + const basicAppFileConfig = useMemo(() => { + let fileConfig: FileUpload + if (isBasicApp) + fileConfig = currentApp?.model_config?.file_upload as FileUpload + else + fileConfig = currentWorkflow?.features?.file_upload as FileUpload + return { + image: { + detail: fileConfig?.image?.detail || Resolution.high, + enabled: !!fileConfig?.image?.enabled, + number_limits: fileConfig?.image?.number_limits || 3, + transfer_methods: fileConfig?.image?.transfer_methods || ['local_file', 'remote_url'], + }, + enabled: !!(fileConfig?.enabled || fileConfig?.image?.enabled), + allowed_file_types: fileConfig?.allowed_file_types || [SupportUploadFileTypes.image], + allowed_file_extensions: fileConfig?.allowed_file_extensions || [...FILE_EXTS[SupportUploadFileTypes.image]].map(ext => `.${ext}`), + allowed_file_upload_methods: fileConfig?.allowed_file_upload_methods || fileConfig?.image?.transfer_methods || ['local_file', 'remote_url'], + number_limits: fileConfig?.number_limits || fileConfig?.image?.number_limits || 3, + } + }, [currentApp?.model_config?.file_upload, currentWorkflow?.features?.file_upload, isBasicApp]) + + const inputFormSchema = useMemo(() => { + if (!currentApp) + return [] + let inputFormSchema = [] + if (isBasicApp) { + inputFormSchema = currentApp.model_config.user_input_form.filter((item: any) => !item.external_data_tool).map((item: any) => { + if (item.paragraph) { + return { + ...item.paragraph, + type: 'paragraph', + required: false, + } + } + if (item.number) { + return { + ...item.number, + type: 'number', + required: false, + } + } + if (item.select) { + return { + ...item.select, + type: 'select', + required: false, + } + } + + if (item['file-list']) { + return { + ...item['file-list'], + type: 'file-list', + required: false, + fileUploadConfig, + } + } + + if (item.file) { + return { + ...item.file, + type: 'file', + required: false, + fileUploadConfig, + } + } + + return { + ...item['text-input'], + type: 'text-input', + required: false, + } + }) + } + else { + const startNode = currentWorkflow?.graph.nodes.find(node => node.data.type === BlockEnum.Start) as any + inputFormSchema = startNode?.data.variables.map((variable: any) => { + if (variable.type === InputVarType.multiFiles) { + return { + ...variable, + required: false, + fileUploadConfig, + } + } + + if (variable.type === InputVarType.singleFile) { + return { + ...variable, + required: false, + fileUploadConfig, + } + } + return { + ...variable, + required: false, + } + }) + } + if ((currentApp.mode === 'completion' || currentApp.mode === 'workflow') && basicAppFileConfig.enabled) { + inputFormSchema.push({ + label: 'Image Upload', + variable: '#image#', + type: InputVarType.singleFile, + required: false, + ...basicAppFileConfig, + fileUploadConfig, + }) + } + return inputFormSchema + }, [basicAppFileConfig, currentApp, currentWorkflow, fileUploadConfig, isBasicApp]) + + const handleFormChange = (value: Record<string, any>) => { + inputsRef.current = value + onFormChange(value) + } + + return ( + <div className={cn('max-h-[240px] flex flex-col pb-4 rounded-b-2xl border-t border-divider-subtle')}> + {isLoading && <div className='pt-3'><Loading type='app' /></div>} + {!isLoading && ( + <div className='shrink-0 mt-3 mb-2 px-4 h-6 flex items-center system-sm-semibold text-text-secondary'>{t('app.appSelector.params')}</div> + )} + {!isLoading && !inputFormSchema.length && ( + <div className='h-16 flex flex-col justify-center items-center'> + <div className='text-text-tertiary system-sm-regular'>{t('app.appSelector.noParams')}</div> + </div> + )} + {!isLoading && !!inputFormSchema.length && ( + <div className='grow overflow-y-auto'> + <AppInputsForm + inputs={value?.inputs || {}} + inputsRef={inputsRef} + inputsForms={inputFormSchema} + onFormChange={handleFormChange} + /> + </div> + )} + </div> + ) +} + +export default AppInputsPanel diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx new file mode 100644 index 0000000000..841663a5b4 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx @@ -0,0 +1,123 @@ +'use client' +import type { FC } from 'react' +import React, { useMemo } from 'react' +import { useState } from 'react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import type { + OffsetOptions, + Placement, +} from '@floating-ui/react' +import Input from '@/app/components/base/input' +import AppIcon from '@/app/components/base/app-icon' +import type { App } from '@/types/app' + +type Props = { + appList: App[] + scope: string + disabled: boolean + trigger: React.ReactNode + placement?: Placement + offset?: OffsetOptions + isShow: boolean + onShowChange: (isShow: boolean) => void + onSelect: (app: App) => void +} + +const AppPicker: FC<Props> = ({ + scope, + appList, + disabled, + trigger, + placement = 'right-start', + offset = 0, + isShow, + onShowChange, + onSelect, +}) => { + const [searchText, setSearchText] = useState('') + const filteredAppList = useMemo(() => { + return (appList || []) + .filter(app => app.name.toLowerCase().includes(searchText.toLowerCase())) + .filter(app => (app.mode !== 'advanced-chat' && app.mode !== 'workflow') || !!app.workflow) + .filter(app => scope === 'all' + || (scope === 'completion' && app.mode === 'completion') + || (scope === 'workflow' && app.mode === 'workflow') + || (scope === 'chat' && app.mode === 'advanced-chat') + || (scope === 'chat' && app.mode === 'agent-chat') + || (scope === 'chat' && app.mode === 'chat')) + }, [appList, scope, searchText]) + const getAppType = (app: App) => { + switch (app.mode) { + case 'advanced-chat': + return 'chatflow' + case 'agent-chat': + return 'agent' + case 'chat': + return 'chat' + case 'completion': + return 'completion' + case 'workflow': + return 'workflow' + } + } + + const handleTriggerClick = () => { + if (disabled) return + onShowChange(true) + } + + return ( + <PortalToFollowElem + placement={placement} + offset={offset} + open={isShow} + onOpenChange={onShowChange} + > + <PortalToFollowElemTrigger + onClick={handleTriggerClick} + > + {trigger} + </PortalToFollowElemTrigger> + + <PortalToFollowElemContent className='z-[1000]'> + <div className="relative w-[356px] min-h-20 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg"> + <div className='p-2 pb-1'> + <Input + showLeftIcon + showClearIcon + value={searchText} + onChange={e => setSearchText(e.target.value)} + onClear={() => setSearchText('')} + /> + </div> + <div className='p-1'> + {filteredAppList.map(app => ( + <div + key={app.id} + className='flex items-center gap-3 py-1 pl-2 pr-3 rounded-lg hover:bg-state-base-hover cursor-pointer' + onClick={() => onSelect(app)} + > + <AppIcon + className='shrink-0' + size='xs' + iconType={app.icon_type} + icon={app.icon} + background={app.icon_background} + imageUrl={app.icon_url} + /> + <div title={app.name} className='grow system-sm-medium text-components-input-text-filled'>{app.name}</div> + <div className='shrink-0 text-text-tertiary system-2xs-medium-uppercase'>{getAppType(app)}</div> + </div> + ))} + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default React.memo(AppPicker) diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-trigger.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-trigger.tsx new file mode 100644 index 0000000000..2706597a86 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-trigger.tsx @@ -0,0 +1,48 @@ +'use client' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { + RiArrowDownSLine, +} from '@remixicon/react' +import AppIcon from '@/app/components/base/app-icon' +import type { App } from '@/types/app' +import cn from '@/utils/classnames' + +type Props = { + open: boolean + appDetail?: App +} + +const AppTrigger = ({ + open, + appDetail, +}: Props) => { + const { t } = useTranslation() + return ( + <div className={cn( + 'group flex items-center p-2 pl-3 bg-components-input-bg-normal rounded-lg cursor-pointer hover:bg-state-base-hover-alt', + open && 'bg-state-base-hover-alt', + appDetail && 'pl-1.5 py-1.5', + )}> + {appDetail && ( + <AppIcon + className='mr-2' + size='xs' + iconType={appDetail.icon_type} + icon={appDetail.icon} + background={appDetail.icon_background} + imageUrl={appDetail.icon_url} + /> + )} + {appDetail && ( + <div title={appDetail.name} className='grow system-sm-medium text-components-input-text-filled'>{appDetail.name}</div> + )} + {!appDetail && ( + <div className='grow text-components-input-text-placeholder system-sm-regular truncate'>{t('app.appSelector.placeholder')}</div> + )} + <RiArrowDownSLine className={cn('shrink-0 ml-0.5 w-4 h-4 text-text-quaternary group-hover:text-text-secondary', open && 'text-text-secondary')} /> + </div> + ) +} + +export default AppTrigger diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx new file mode 100644 index 0000000000..5f5a0d7e3e --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/index.tsx @@ -0,0 +1,143 @@ +'use client' +import type { FC } from 'react' +import React, { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import AppTrigger from '@/app/components/plugins/plugin-detail-panel/app-selector/app-trigger' +import AppPicker from '@/app/components/plugins/plugin-detail-panel/app-selector/app-picker' +import AppInputsPanel from '@/app/components/plugins/plugin-detail-panel/app-selector/app-inputs-panel' +import { useAppFullList } from '@/service/use-apps' +import type { App } from '@/types/app' +import type { + OffsetOptions, + Placement, +} from '@floating-ui/react' + +type Props = { + value?: { + app_id: string + inputs: Record<string, any> + files?: any[] + } + scope?: string + disabled?: boolean + placement?: Placement + offset?: OffsetOptions + onSelect: (app: { + app_id: string + inputs: Record<string, any> + files?: any[] + }) => void + supportAddCustomTool?: boolean +} +const AppSelector: FC<Props> = ({ + value, + scope, + disabled, + placement = 'bottom', + offset = 4, + onSelect, +}) => { + const { t } = useTranslation() + const [isShow, onShowChange] = useState(false) + const handleTriggerClick = () => { + if (disabled) return + onShowChange(true) + } + + const { data: appList } = useAppFullList() + const currentAppInfo = useMemo(() => { + if (!appList?.data || !value) + return undefined + return appList.data.find(app => app.id === value.app_id) + }, [appList?.data, value]) + + const [isShowChooseApp, setIsShowChooseApp] = useState(false) + const handleSelectApp = (app: App) => { + const clearValue = app.id !== value?.app_id + const appValue = { + app_id: app.id, + inputs: clearValue ? {} : value?.inputs || {}, + files: clearValue ? [] : value?.files || [], + } + onSelect(appValue) + setIsShowChooseApp(false) + } + const handleFormChange = (inputs: Record<string, any>) => { + const newFiles = inputs['#image#'] + delete inputs['#image#'] + const newValue = { + app_id: value?.app_id || '', + inputs, + files: newFiles ? [newFiles] : value?.files || [], + } + onSelect(newValue) + } + + const formattedValue = useMemo(() => { + return { + app_id: value?.app_id || '', + inputs: { + ...value?.inputs, + ...(value?.files?.length ? { '#image#': value.files[0] } : {}), + }, + } + }, [value]) + + return ( + <> + <PortalToFollowElem + placement={placement} + offset={offset} + open={isShow} + onOpenChange={onShowChange} + > + <PortalToFollowElemTrigger + className='w-full' + onClick={handleTriggerClick} + > + <AppTrigger + open={isShow} + appDetail={currentAppInfo} + /> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[1000]'> + <div className="relative w-[389px] min-h-20 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg"> + <div className='px-4 py-3 flex flex-col gap-1'> + <div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('app.appSelector.label')}</div> + <AppPicker + placement='bottom' + offset={offset} + trigger={ + <AppTrigger + open={isShowChooseApp} + appDetail={currentAppInfo} + /> + } + isShow={isShowChooseApp} + onShowChange={setIsShowChooseApp} + disabled={false} + appList={appList?.data || []} + onSelect={handleSelectApp} + scope={scope || 'all'} + /> + </div> + {/* app inputs config panel */} + {currentAppInfo && ( + <AppInputsPanel + value={formattedValue} + appDetail={currentAppInfo} + onFormChange={handleFormChange} + /> + )} + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + </> + ) +} +export default React.memo(AppSelector) diff --git a/web/app/components/plugins/plugin-detail-panel/detail-header.tsx b/web/app/components/plugins/plugin-detail-panel/detail-header.tsx new file mode 100644 index 0000000000..75239a424f --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/detail-header.tsx @@ -0,0 +1,306 @@ +import React, { useCallback, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useBoolean } from 'ahooks' +import { + RiArrowLeftRightLine, + RiBugLine, + RiCloseLine, + RiHardDrive3Line, + RiVerifiedBadgeLine, +} from '@remixicon/react' +import type { PluginDetail } from '../types' +import { PluginSource, PluginType } from '../types' +import Description from '../card/base/description' +import Icon from '../card/base/card-icon' +import Title from '../card/base/title' +import OrgInfo from '../card/base/org-info' +import { useGitHubReleases } from '../install-plugin/hooks' +import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker' +import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place' +import OperationDropdown from '@/app/components/plugins/plugin-detail-panel/operation-dropdown' +import PluginInfo from '@/app/components/plugins/plugin-page/plugin-info' +import ActionButton from '@/app/components/base/action-button' +import Button from '@/app/components/base/button' +import Badge from '@/app/components/base/badge' +import Confirm from '@/app/components/base/confirm' +import Tooltip from '@/app/components/base/tooltip' +import Toast from '@/app/components/base/toast' +import { BoxSparkleFill } from '@/app/components/base/icons/src/vender/plugin' +import { Github } from '@/app/components/base/icons/src/public/common' +import { uninstallPlugin } from '@/service/plugins' +import { useGetLanguage } from '@/context/i18n' +import { useModalContext } from '@/context/modal-context' +import { useProviderContext } from '@/context/provider-context' +import { useInvalidateAllToolProviders } from '@/service/use-tools' +import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config' +import cn from '@/utils/classnames' + +const i18nPrefix = 'plugin.action' + +type Props = { + detail: PluginDetail + onHide: () => void + onUpdate: (isDelete?: boolean) => void +} + +const DetailHeader = ({ + detail, + onHide, + onUpdate, +}: Props) => { + const { t } = useTranslation() + const locale = useGetLanguage() + const { checkForUpdates, fetchReleases } = useGitHubReleases() + const { setShowUpdatePluginModal } = useModalContext() + const { refreshModelProviders } = useProviderContext() + const invalidateAllToolProviders = useInvalidateAllToolProviders() + + const { + installation_id, + source, + tenant_id, + version, + latest_unique_identifier, + latest_version, + meta, + plugin_id, + } = detail + const { author, category, name, label, description, icon, verified } = detail.declaration + const isFromGitHub = source === PluginSource.github + const isFromMarketplace = source === PluginSource.marketplace + + const [isShow, setIsShow] = useState(false) + const [targetVersion, setTargetVersion] = useState({ + version: latest_version, + unique_identifier: latest_unique_identifier, + }) + const hasNewVersion = useMemo(() => { + if (isFromMarketplace) + return !!latest_version && latest_version !== version + + return false + }, [isFromMarketplace, latest_version, version]) + + const detailUrl = useMemo(() => { + if (isFromGitHub) + return `https://github.com/${meta!.repo}` + if (isFromMarketplace) + return `${MARKETPLACE_URL_PREFIX}/plugins/${author}/${name}` + return '' + }, [author, isFromGitHub, isFromMarketplace, meta, name]) + + const [isShowUpdateModal, { + setTrue: showUpdateModal, + setFalse: hideUpdateModal, + }] = useBoolean(false) + + const handleUpdate = async () => { + if (isFromMarketplace) { + showUpdateModal() + return + } + + const fetchedReleases = await fetchReleases(author, name) + if (fetchedReleases.length === 0) return + const { needUpdate, toastProps } = checkForUpdates(fetchedReleases, meta!.version) + Toast.notify(toastProps) + if (needUpdate) { + setShowUpdatePluginModal({ + onSaveCallback: () => { + onUpdate() + }, + payload: { + type: PluginSource.github, + github: { + originalPackageInfo: { + id: detail.plugin_unique_identifier, + repo: meta!.repo, + version: meta!.version, + package: meta!.package, + releases: fetchedReleases, + }, + }, + }, + }) + } + } + + const handleUpdatedFromMarketplace = () => { + onUpdate() + hideUpdateModal() + } + + const [isShowPluginInfo, { + setTrue: showPluginInfo, + setFalse: hidePluginInfo, + }] = useBoolean(false) + + const [isShowDeleteConfirm, { + setTrue: showDeleteConfirm, + setFalse: hideDeleteConfirm, + }] = useBoolean(false) + + const [deleting, { + setTrue: showDeleting, + setFalse: hideDeleting, + }] = useBoolean(false) + + const handleDelete = useCallback(async () => { + showDeleting() + const res = await uninstallPlugin(installation_id) + hideDeleting() + if (res.success) { + hideDeleteConfirm() + onUpdate(true) + if (PluginType.model.includes(category)) + refreshModelProviders() + if (PluginType.tool.includes(category)) + invalidateAllToolProviders() + } + }, [showDeleting, installation_id, hideDeleting, hideDeleteConfirm, onUpdate, category, refreshModelProviders, invalidateAllToolProviders]) + + // #plugin TODO# used in apps + // const usedInApps = 3 + + return ( + <div className={cn('shrink-0 p-4 pb-3 border-b border-divider-subtle bg-components-panel-bg')}> + <div className="flex"> + <div className='overflow-hidden border-components-panel-border-subtle border rounded-xl'> + <Icon src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`} /> + </div> + <div className="ml-3 w-0 grow"> + <div className="flex items-center h-5"> + <Title title={label[locale]} /> + {verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />} + <PluginVersionPicker + disabled={!isFromMarketplace} + isShow={isShow} + onShowChange={setIsShow} + pluginID={plugin_id} + currentVersion={version} + onSelect={(state) => { + setTargetVersion(state) + handleUpdate() + }} + trigger={ + <Badge + className={cn( + 'mx-1', + isShow && 'bg-state-base-hover', + (isShow || isFromMarketplace) && 'hover:bg-state-base-hover', + )} + uppercase={false} + text={ + <> + <div>{isFromGitHub ? meta!.version : version}</div> + {isFromMarketplace && <RiArrowLeftRightLine className='ml-1 w-3 h-3 text-text-tertiary' />} + </> + } + hasRedCornerMark={hasNewVersion} + /> + } + /> + {(hasNewVersion || isFromGitHub) && ( + <Button variant='secondary-accent' size='small' className='!h-5' onClick={() => { + if (isFromMarketplace) { + setTargetVersion({ + version: latest_version, + unique_identifier: latest_unique_identifier, + }) + } + handleUpdate() + }}>{t('plugin.detailPanel.operation.update')}</Button> + )} + </div> + <div className='mb-1 flex justify-between items-center h-4'> + <div className='mt-0.5 flex items-center'> + <OrgInfo + packageNameClassName='w-auto' + orgName={author} + packageName={name} + /> + <div className='ml-1 mr-0.5 text-text-quaternary system-xs-regular'>·</div> + {detail.source === PluginSource.marketplace && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.marketplace')} > + <div><BoxSparkleFill className='w-3.5 h-3.5 text-text-tertiary hover:text-text-accent' /></div> + </Tooltip> + )} + {detail.source === PluginSource.github && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.github')} > + <div><Github className='w-3.5 h-3.5 text-text-secondary hover:text-text-primary' /></div> + </Tooltip> + )} + {detail.source === PluginSource.local && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.local')} > + <div><RiHardDrive3Line className='w-3.5 h-3.5 text-text-tertiary' /></div> + </Tooltip> + )} + {detail.source === PluginSource.debugging && ( + <Tooltip popupContent={t('plugin.detailPanel.categoryTip.debugging')} > + <div><RiBugLine className='w-3.5 h-3.5 text-text-tertiary hover:text-text-warning' /></div> + </Tooltip> + )} + </div> + </div> + </div> + <div className='flex gap-1'> + <OperationDropdown + source={detail.source} + onInfo={showPluginInfo} + onCheckVersion={handleUpdate} + onRemove={showDeleteConfirm} + detailUrl={detailUrl} + /> + <ActionButton onClick={onHide}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> + </div> + </div> + <Description className='mt-3' text={description[locale]} descriptionLineRows={2}></Description> + {isShowPluginInfo && ( + <PluginInfo + repository={isFromGitHub ? meta?.repo : ''} + release={version} + packageName={meta?.package || ''} + onHide={hidePluginInfo} + /> + )} + {isShowDeleteConfirm && ( + <Confirm + isShow + title={t(`${i18nPrefix}.delete`)} + content={ + <div> + {t(`${i18nPrefix}.deleteContentLeft`)}<span className='system-md-semibold'>{label[locale]}</span>{t(`${i18nPrefix}.deleteContentRight`)}<br /> + {/* {usedInApps > 0 && t(`${i18nPrefix}.usedInApps`, { num: usedInApps })} */} + </div> + } + onCancel={hideDeleteConfirm} + onConfirm={handleDelete} + isLoading={deleting} + isDisabled={deleting} + /> + )} + { + isShowUpdateModal && ( + <UpdateFromMarketplace + payload={{ + originalPackageInfo: { + id: detail.plugin_unique_identifier, + payload: detail.declaration, + }, + targetPackageInfo: { + id: targetVersion.unique_identifier, + version: targetVersion.version, + }, + }} + onCancel={hideUpdateModal} + onSave={handleUpdatedFromMarketplace} + /> + ) + } + </div> + ) +} + +export default DetailHeader diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx new file mode 100644 index 0000000000..b2b04a6f1e --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-card.tsx @@ -0,0 +1,219 @@ +import React, { useEffect, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useBoolean } from 'ahooks' +import copy from 'copy-to-clipboard' +import { RiClipboardLine, RiDeleteBinLine, RiEditLine, RiLoginCircleLine } from '@remixicon/react' +import type { EndpointListItem } from '../types' +import EndpointModal from './endpoint-modal' +import { NAME_FIELD } from './utils' +import { addDefaultValue, toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema' +import { ClipboardCheck } from '@/app/components/base/icons/src/vender/line/files' +import ActionButton from '@/app/components/base/action-button' +import Confirm from '@/app/components/base/confirm' +import Indicator from '@/app/components/header/indicator' +import Switch from '@/app/components/base/switch' +import Toast from '@/app/components/base/toast' +import Tooltip from '@/app/components/base/tooltip' +import { + useDeleteEndpoint, + useDisableEndpoint, + useEnableEndpoint, + useUpdateEndpoint, +} from '@/service/use-endpoints' + +type Props = { + data: EndpointListItem + handleChange: () => void +} + +const EndpointCard = ({ + data, + handleChange, +}: Props) => { + const { t } = useTranslation() + const [active, setActive] = useState(data.enabled) + const endpointID = data.id + + // switch + const [isShowDisableConfirm, { + setTrue: showDisableConfirm, + setFalse: hideDisableConfirm, + }] = useBoolean(false) + const { mutate: enableEndpoint } = useEnableEndpoint({ + onSuccess: async () => { + await handleChange() + }, + onError: () => { + Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + setActive(false) + }, + }) + const { mutate: disableEndpoint } = useDisableEndpoint({ + onSuccess: async () => { + await handleChange() + hideDisableConfirm() + }, + onError: () => { + Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + setActive(false) + }, + }) + const handleSwitch = (state: boolean) => { + if (state) { + setActive(true) + enableEndpoint(endpointID) + } + else { + setActive(false) + showDisableConfirm() + } + } + + // delete + const [isShowDeleteConfirm, { + setTrue: showDeleteConfirm, + setFalse: hideDeleteConfirm, + }] = useBoolean(false) + const { mutate: deleteEndpoint } = useDeleteEndpoint({ + onSuccess: async () => { + await handleChange() + hideDeleteConfirm() + }, + onError: () => { + Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + }, + }) + + // update + const [isShowEndpointModal, { + setTrue: showEndpointModalConfirm, + setFalse: hideEndpointModalConfirm, + }] = useBoolean(false) + const formSchemas = useMemo(() => { + return toolCredentialToFormSchemas([NAME_FIELD, ...data.declaration.settings]) + }, [data.declaration.settings]) + const formValue = useMemo(() => { + const formValue = { + name: data.name, + ...data.settings, + } + return addDefaultValue(formValue, formSchemas) + }, [data.name, data.settings, formSchemas]) + const { mutate: updateEndpoint } = useUpdateEndpoint({ + onSuccess: async () => { + await handleChange() + hideEndpointModalConfirm() + }, + onError: () => { + Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + }, + }) + const handleUpdate = (state: any) => updateEndpoint({ + endpointID, + state, + }) + + const [isCopied, setIsCopied] = useState(false) + const handleCopy = (value: string) => { + copy(value) + setIsCopied(true) + } + + useEffect(() => { + if (isCopied) { + const timer = setTimeout(() => { + setIsCopied(false) + }, 2000) + return () => { + clearTimeout(timer) + } + } + }, [isCopied]) + + const CopyIcon = isCopied ? ClipboardCheck : RiClipboardLine + + return ( + <div className='p-0.5 bg-background-section-burn rounded-xl'> + <div className='group p-2.5 pl-3 bg-components-panel-on-panel-item-bg rounded-[10px] border-[0.5px] border-components-panel-border'> + <div className='flex items-center'> + <div className='grow mb-1 h-6 flex items-center gap-1 text-text-secondary system-md-semibold'> + <RiLoginCircleLine className='w-4 h-4' /> + <div>{data.name}</div> + </div> + <div className='hidden group-hover:flex items-center'> + <ActionButton onClick={showEndpointModalConfirm}> + <RiEditLine className='w-4 h-4' /> + </ActionButton> + <ActionButton onClick={showDeleteConfirm} className='hover:bg-state-destructive-hover text-text-tertiary hover:text-text-destructive'> + <RiDeleteBinLine className='w-4 h-4' /> + </ActionButton> + </div> + </div> + {data.declaration.endpoints.map((endpoint, index) => ( + <div key={index} className='h-6 flex items-center'> + <div className='shrink-0 w-12 text-text-tertiary system-xs-regular'>{endpoint.method}</div> + <div className='group/item grow flex items-center text-text-secondary system-xs-regular truncate'> + <div title={`${data.url}${endpoint.path}`} className='truncate'>{`${data.url}${endpoint.path}`}</div> + <Tooltip popupContent={t(`common.operation.${isCopied ? 'copied' : 'copy'}`)} position='top'> + <ActionButton className='hidden shrink-0 ml-2 group-hover/item:flex' onClick={() => handleCopy(`${data.url}${endpoint.path}`)}> + <CopyIcon className='w-3.5 h-3.5 text-text-tertiary' /> + </ActionButton> + </Tooltip> + </div> + </div> + ))} + </div> + <div className='p-2 pl-3 flex items-center justify-between'> + {active && ( + <div className='flex items-center gap-1 system-xs-semibold-uppercase text-util-colors-green-green-600'> + <Indicator color='green' /> + {t('plugin.detailPanel.serviceOk')} + </div> + )} + {!active && ( + <div className='flex items-center gap-1 system-xs-semibold-uppercase text-text-tertiary'> + <Indicator color='gray' /> + {t('plugin.detailPanel.disabled')} + </div> + )} + <Switch + className='ml-3' + defaultValue={active} + onChange={handleSwitch} + size='sm' + /> + </div> + {isShowDisableConfirm && ( + <Confirm + isShow + title={t('plugin.detailPanel.endpointDisableTip')} + content={<div>{t('plugin.detailPanel.endpointDisableContent', { name: data.name })}</div>} + onCancel={() => { + hideDisableConfirm() + setActive(true) + }} + onConfirm={() => disableEndpoint(endpointID)} + /> + )} + {isShowDeleteConfirm && ( + <Confirm + isShow + title={t('plugin.detailPanel.endpointDeleteTip')} + content={<div>{t('plugin.detailPanel.endpointDeleteContent', { name: data.name })}</div>} + onCancel={hideDeleteConfirm} + onConfirm={() => deleteEndpoint(endpointID)} + /> + )} + {isShowEndpointModal && ( + <EndpointModal + formSchemas={formSchemas} + defaultValues={formValue} + onCancel={hideEndpointModalConfirm} + onSaved={handleUpdate} + /> + )} + </div> + ) +} + +export default EndpointCard diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx new file mode 100644 index 0000000000..2116a5474a --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-list.tsx @@ -0,0 +1,122 @@ +import React, { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import { useContext } from 'use-context-selector' +import { useBoolean } from 'ahooks' +import { + RiAddLine, + RiApps2AddLine, + RiBookOpenLine, +} from '@remixicon/react' +import EndpointModal from './endpoint-modal' +import EndpointCard from './endpoint-card' +import { NAME_FIELD } from './utils' +import { toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema' +import ActionButton from '@/app/components/base/action-button' +import Tooltip from '@/app/components/base/tooltip' +import Toast from '@/app/components/base/toast' +import { + useCreateEndpoint, + useEndpointList, + useInvalidateEndpointList, +} from '@/service/use-endpoints' +import type { PluginDetail } from '@/app/components/plugins/types' +import { LanguagesSupported } from '@/i18n/language' +import I18n from '@/context/i18n' +import cn from '@/utils/classnames' + +type Props = { + detail: PluginDetail +} +const EndpointList = ({ detail }: Props) => { + const { t } = useTranslation() + const { locale } = useContext(I18n) + const pluginUniqueID = detail.plugin_unique_identifier + const declaration = detail.declaration.endpoint + const showTopBorder = detail.declaration.tool + const { data } = useEndpointList(detail.plugin_id) + const invalidateEndpointList = useInvalidateEndpointList() + + const [isShowEndpointModal, { + setTrue: showEndpointModal, + setFalse: hideEndpointModal, + }] = useBoolean(false) + + const formSchemas = useMemo(() => { + return toolCredentialToFormSchemas([NAME_FIELD, ...declaration.settings]) + }, [declaration.settings]) + + const { mutate: createEndpoint } = useCreateEndpoint({ + onSuccess: async () => { + await invalidateEndpointList(detail.plugin_id) + hideEndpointModal() + }, + onError: () => { + Toast.notify({ type: 'error', message: t('common.actionMsg.modifiedUnsuccessfully') }) + }, + }) + + const handleCreate = (state: any) => createEndpoint({ + pluginUniqueID, + state, + }) + + if (!data) + return null + + return ( + <div className={cn('px-4 py-2 border-divider-subtle', showTopBorder && 'border-t')}> + <div className='mb-1 h-6 flex items-center justify-between text-text-secondary system-sm-semibold-uppercase'> + <div className='flex items-center gap-0.5'> + {t('plugin.detailPanel.endpoints')} + <Tooltip + position='right' + needsDelay + popupClassName='w-[240px] p-4 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border' + popupContent={ + <div className='flex flex-col gap-2'> + <div className='w-8 h-8 flex items-center justify-center bg-background-default-subtle rounded-lg border-[0.5px] border-components-panel-border-subtle'> + <RiApps2AddLine className='w-4 h-4 text-text-tertiary' /> + </div> + <div className='text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.endpointsTip')}</div> + <a + href={`https://docs.dify.ai/${locale === LanguagesSupported[1] ? 'v/zh-hans/' : ''}guides/api-documentation/endpoint`} + target='_blank' + rel='noopener noreferrer' + > + <div className='inline-flex items-center gap-1 text-text-accent system-xs-regular cursor-pointer'> + <RiBookOpenLine className='w-3 h-3' /> + {t('plugin.detailPanel.endpointsDocLink')} + </div> + </a> + </div> + } + /> + </div> + <ActionButton onClick={showEndpointModal}> + <RiAddLine className='w-4 h-4' /> + </ActionButton> + </div> + {data.endpoints.length === 0 && ( + <div className='mb-1 p-3 flex justify-center rounded-[10px] bg-background-section text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.endpointsEmpty')}</div> + )} + <div className='flex flex-col gap-2'> + {data.endpoints.map((item, index) => ( + <EndpointCard + key={index} + data={item} + handleChange={() => invalidateEndpointList(detail.plugin_id)} + /> + ))} + </div> + {isShowEndpointModal && ( + <EndpointModal + formSchemas={formSchemas} + onCancel={hideEndpointModal} + onSaved={handleCreate} + /> + )} + </div> + ) +} + +export default EndpointList diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx new file mode 100644 index 0000000000..e150d72dc3 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx @@ -0,0 +1,96 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { RiArrowRightUpLine, RiCloseLine } from '@remixicon/react' +import ActionButton from '@/app/components/base/action-button' +import Button from '@/app/components/base/button' +import Drawer from '@/app/components/base/drawer' +import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +import Toast from '@/app/components/base/toast' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import cn from '@/utils/classnames' + +type Props = { + formSchemas: any + defaultValues?: any + onCancel: () => void + onSaved: (value: Record<string, any>) => void +} + +const EndpointModal: FC<Props> = ({ + formSchemas, + defaultValues = {}, + onCancel, + onSaved, +}) => { + const getValueFromI18nObject = useRenderI18nObject() + const { t } = useTranslation() + const [tempCredential, setTempCredential] = React.useState<any>(defaultValues) + + const handleSave = () => { + for (const field of formSchemas) { + if (field.required && !tempCredential[field.name]) { + Toast.notify({ type: 'error', message: t('common.errorMsg.fieldRequired', { field: getValueFromI18nObject(field.label) }) }) + return + } + } + onSaved(tempCredential) + } + + return ( + <Drawer + isOpen + clickOutsideNotOpen={false} + onClose={onCancel} + footer={null} + mask + positionCenter={false} + panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')} + > + <> + <div className='p-4 pb-2'> + <div className='flex items-center justify-between'> + <div className='text-text-primary system-xl-semibold'>{t('plugin.detailPanel.endpointModalTitle')}</div> + <ActionButton onClick={onCancel}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> + </div> + <div className='mt-0.5 text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.endpointModalDesc')}</div> + </div> + <div className='grow overflow-y-auto'> + <div className='px-4 py-2'> + <Form + value={tempCredential} + onChange={(v) => { + setTempCredential(v) + }} + formSchemas={formSchemas} + isEditMode={true} + showOnVariableMap={{}} + validating={false} + inputClassName='bg-components-input-bg-normal hover:bg-components-input-bg-hover' + fieldMoreInfo={item => item.url + ? (<a + href={item.url} + target='_blank' rel='noopener noreferrer' + className='inline-flex items-center body-xs-regular text-text-accent-secondary' + > + {t('tools.howToGet')} + <RiArrowRightUpLine className='ml-1 w-3 h-3' /> + </a>) + : null} + /> + </div> + <div className={cn('p-4 pt-0 flex justify-end')} > + <div className='flex gap-2'> + <Button onClick={onCancel}>{t('common.operation.cancel')}</Button> + <Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button> + </div> + </div> + </div> + </> + </Drawer> + ) +} +export default React.memo(EndpointModal) diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx new file mode 100644 index 0000000000..4d20c0877d --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -0,0 +1,62 @@ +'use client' +import React from 'react' +import type { FC } from 'react' +import DetailHeader from './detail-header' +import EndpointList from './endpoint-list' +import ActionList from './action-list' +import ModelList from './model-list' +import AgentStrategyList from './agent-strategy-list' +import Drawer from '@/app/components/base/drawer' +import type { PluginDetail } from '@/app/components/plugins/types' +import cn from '@/utils/classnames' + +type Props = { + detail?: PluginDetail + onUpdate: () => void + onHide: () => void +} + +const PluginDetailPanel: FC<Props> = ({ + detail, + onUpdate, + onHide, +}) => { + const handleUpdate = (isDelete = false) => { + if (isDelete) + onHide() + onUpdate() + } + + if (!detail) + return null + + return ( + <Drawer + isOpen={!!detail} + clickOutsideNotOpen={false} + onClose={onHide} + footer={null} + mask={false} + positionCenter={false} + panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')} + > + {detail && ( + <> + <DetailHeader + detail={detail} + onHide={onHide} + onUpdate={handleUpdate} + /> + <div className='grow overflow-y-auto'> + {!!detail.declaration.tool && <ActionList detail={detail} />} + {!!detail.declaration.agent_strategy && <AgentStrategyList detail={detail} />} + {!!detail.declaration.endpoint && <EndpointList detail={detail} />} + {!!detail.declaration.model && <ModelList detail={detail} />} + </div> + </> + )} + </Drawer> + ) +} + +export default PluginDetailPanel diff --git a/web/app/components/plugins/plugin-detail-panel/model-list.tsx b/web/app/components/plugins/plugin-detail-panel/model-list.tsx new file mode 100644 index 0000000000..5989a75945 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/model-list.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import ModelIcon from '@/app/components/header/account-setting/model-provider-page/model-icon' +import ModelName from '@/app/components/header/account-setting/model-provider-page/model-name' +import { useModelProviderModelList } from '@/service/use-models' +import type { PluginDetail } from '@/app/components/plugins/types' + +type Props = { + detail: PluginDetail +} + +const ModelList = ({ + detail, +}: Props) => { + const { t } = useTranslation() + const { data: res } = useModelProviderModelList(`${detail.plugin_id}/${detail.name}`) + + if (!res) + return null + + return ( + <div className='px-4 py-2'> + <div className='mb-1 h-6 flex items-center text-text-secondary system-sm-semibold-uppercase'>{t('plugin.detailPanel.modelNum', { num: res.data.length })}</div> + <div className='flex flex-col'> + {res.data.map(model => ( + <div key={model.model} className='h-6 py-1 flex items-center'> + <ModelIcon + className='shrink-0 mr-2' + provider={(model as any).provider} + modelName={model.model} + /> + <ModelName + className='grow text-text-secondary system-md-regular' + modelItem={model} + showModelType + showMode + showContextSize + /> + </div> + ))} + </div> + </div> + ) +} + +export default ModelList diff --git a/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx new file mode 100644 index 0000000000..1408b4f9be --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/model-selector/index.tsx @@ -0,0 +1,250 @@ +import type { + FC, + ReactNode, +} from 'react' +import { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import type { + DefaultModel, + FormValue, +} from '@/app/components/header/account-setting/model-provider-page/declarations' +import { ModelStatusEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' +import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' +import { + useModelList, +} from '@/app/components/header/account-setting/model-provider-page/hooks' +import AgentModelTrigger from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger' +import Trigger from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger' +import type { TriggerProps } from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import LLMParamsPanel from './llm-params-panel' +import TTSParamsPanel from './tts-params-panel' +import { useProviderContext } from '@/context/provider-context' +import cn from '@/utils/classnames' + +export type ModelParameterModalProps = { + popupClassName?: string + portalToFollowElemContentClassName?: string + isAdvancedMode: boolean + value: any + setModel: (model: any) => void + renderTrigger?: (v: TriggerProps) => ReactNode + readonly?: boolean + isInWorkflow?: boolean + isAgentStrategy?: boolean + scope?: string +} + +const ModelParameterModal: FC<ModelParameterModalProps> = ({ + popupClassName, + portalToFollowElemContentClassName, + isAdvancedMode, + value, + setModel, + renderTrigger, + readonly, + isInWorkflow, + isAgentStrategy, + scope = ModelTypeEnum.textGeneration, +}) => { + const { t } = useTranslation() + const { isAPIKeySet } = useProviderContext() + const [open, setOpen] = useState(false) + const scopeArray = scope.split('&') + const scopeFeatures = useMemo(() => { + if (scopeArray.includes('all')) + return [] + return scopeArray.filter(item => ![ + ModelTypeEnum.textGeneration, + ModelTypeEnum.textEmbedding, + ModelTypeEnum.rerank, + ModelTypeEnum.moderation, + ModelTypeEnum.speech2text, + ModelTypeEnum.tts, + ].includes(item as ModelTypeEnum)) + }, [scopeArray]) + + const { data: textGenerationList } = useModelList(ModelTypeEnum.textGeneration) + const { data: textEmbeddingList } = useModelList(ModelTypeEnum.textEmbedding) + const { data: rerankList } = useModelList(ModelTypeEnum.rerank) + const { data: moderationList } = useModelList(ModelTypeEnum.moderation) + const { data: sttList } = useModelList(ModelTypeEnum.speech2text) + const { data: ttsList } = useModelList(ModelTypeEnum.tts) + + const scopedModelList = useMemo(() => { + const resultList: any[] = [] + if (scopeArray.includes('all')) { + return [ + ...textGenerationList, + ...textEmbeddingList, + ...rerankList, + ...sttList, + ...ttsList, + ...moderationList, + ] + } + if (scopeArray.includes(ModelTypeEnum.textGeneration)) + return textGenerationList + if (scopeArray.includes(ModelTypeEnum.textEmbedding)) + return textEmbeddingList + if (scopeArray.includes(ModelTypeEnum.rerank)) + return rerankList + if (scopeArray.includes(ModelTypeEnum.moderation)) + return moderationList + if (scopeArray.includes(ModelTypeEnum.speech2text)) + return sttList + if (scopeArray.includes(ModelTypeEnum.tts)) + return ttsList + return resultList + }, [scopeArray, textGenerationList, textEmbeddingList, rerankList, sttList, ttsList, moderationList]) + + const { currentProvider, currentModel } = useMemo(() => { + const currentProvider = scopedModelList.find(item => item.provider === value?.provider) + const currentModel = currentProvider?.models.find((model: { model: string }) => model.model === value?.model) + return { + currentProvider, + currentModel, + } + }, [scopedModelList, value?.provider, value?.model]) + + const hasDeprecated = useMemo(() => { + return !currentProvider || !currentModel + }, [currentModel, currentProvider]) + const modelDisabled = useMemo(() => { + return currentModel?.status !== ModelStatusEnum.active + }, [currentModel?.status]) + const disabled = useMemo(() => { + return !isAPIKeySet || hasDeprecated || modelDisabled + }, [hasDeprecated, isAPIKeySet, modelDisabled]) + + const handleChangeModel = ({ provider, model }: DefaultModel) => { + const targetProvider = scopedModelList.find(modelItem => modelItem.provider === provider) + const targetModelItem = targetProvider?.models.find((modelItem: { model: string }) => modelItem.model === model) + const model_type = targetModelItem?.model_type as string + setModel({ + provider, + model, + model_type, + ...(model_type === ModelTypeEnum.textGeneration ? { + mode: targetModelItem?.model_properties.mode as string, + } : {}), + }) + } + + const handleLLMParamsChange = (newParams: FormValue) => { + const newValue = { + ...(value?.completionParams || {}), + completion_params: newParams, + } + setModel({ + ...value, + ...newValue, + }) + } + + const handleTTSParamsChange = (language: string, voice: string) => { + setModel({ + ...value, + language, + voice, + }) + } + + return ( + <PortalToFollowElem + open={open} + onOpenChange={setOpen} + placement={isInWorkflow ? 'left' : 'bottom-end'} + offset={4} + > + <div className='relative'> + <PortalToFollowElemTrigger + onClick={() => { + if (readonly) + return + setOpen(v => !v) + }} + className='block' + > + { + renderTrigger + ? renderTrigger({ + open, + disabled, + modelDisabled, + hasDeprecated, + currentProvider, + currentModel, + providerName: value?.provider, + modelId: value?.model, + }) + : (isAgentStrategy + ? <AgentModelTrigger + disabled={disabled} + hasDeprecated={hasDeprecated} + currentProvider={currentProvider} + currentModel={currentModel} + providerName={value?.provider} + modelId={value?.model} + scope={scope} + /> + : <Trigger + disabled={disabled} + isInWorkflow={isInWorkflow} + modelDisabled={modelDisabled} + hasDeprecated={hasDeprecated} + currentProvider={currentProvider} + currentModel={currentModel} + providerName={value?.provider} + modelId={value?.model} + /> + ) + } + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className={cn('z-50', portalToFollowElemContentClassName)}> + <div className={cn(popupClassName, 'w-[389px] rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg')}> + <div className={cn('max-h-[420px] p-4 pt-3 overflow-y-auto')}> + <div className='relative'> + <div className={cn('mb-1 h-6 flex items-center text-text-secondary system-sm-semibold')}> + {t('common.modelProvider.model').toLocaleUpperCase()} + </div> + <ModelSelector + defaultModel={(value?.provider || value?.model) ? { provider: value?.provider, model: value?.model } : undefined} + modelList={scopedModelList} + scopeFeatures={scopeFeatures} + onSelect={handleChangeModel} + /> + </div> + {(currentModel?.model_type === ModelTypeEnum.textGeneration || currentModel?.model_type === ModelTypeEnum.tts) && ( + <div className='my-3 h-[1px] bg-divider-subtle' /> + )} + {currentModel?.model_type === ModelTypeEnum.textGeneration && ( + <LLMParamsPanel + provider={value?.provider} + modelId={value?.model} + completionParams={value?.completion_params || {}} + onCompletionParamsChange={handleLLMParamsChange} + isAdvancedMode={isAdvancedMode} + /> + )} + {currentModel?.model_type === ModelTypeEnum.tts && ( + <TTSParamsPanel + currentModel={currentModel} + language={value?.language} + voice={value?.voice} + onChange={handleTTSParamsChange} + /> + )} + </div> + </div> + </PortalToFollowElemContent> + </div> + </PortalToFollowElem> + ) +} + +export default ModelParameterModal diff --git a/web/app/components/plugins/plugin-detail-panel/model-selector/llm-params-panel.tsx b/web/app/components/plugins/plugin-detail-panel/model-selector/llm-params-panel.tsx new file mode 100644 index 0000000000..eb3c1102aa --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/model-selector/llm-params-panel.tsx @@ -0,0 +1,126 @@ +import React, { useMemo } from 'react' +import useSWR from 'swr' +import { useTranslation } from 'react-i18next' +import PresetsParameter from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/presets-parameter' +import ParameterItem from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item' +import Loading from '@/app/components/base/loading' +import type { + FormValue, + ModelParameterRule, +} from '@/app/components/header/account-setting/model-provider-page/declarations' +import type { ParameterValue } from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item' +import { fetchModelParameterRules } from '@/service/common' +import { TONE_LIST } from '@/config' +import cn from '@/utils/classnames' + +const PROVIDER_WITH_PRESET_TONE = ['langgenius/openai/openai', 'langgenius/azure_openai/azure_openai'] +const stopParameterRule: ModelParameterRule = { + default: [], + help: { + en_US: 'Up to four sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.', + zh_Hans: '最多四个序列,API 将停止生成更多的 token。返回的文本将不包含停止序列。', + }, + label: { + en_US: 'Stop sequences', + zh_Hans: '停止序列', + }, + name: 'stop', + required: false, + type: 'tag', + tagPlaceholder: { + en_US: 'Enter sequence and press Tab', + zh_Hans: '输入序列并按 Tab 键', + }, +} + +type Props = { + isAdvancedMode: boolean + provider: string + modelId: string + completionParams: FormValue + onCompletionParamsChange: (newParams: FormValue) => void +} + +const LLMParamsPanel = ({ + isAdvancedMode, + provider, + modelId, + completionParams, + onCompletionParamsChange, +}: Props) => { + const { t } = useTranslation() + const { data: parameterRulesData, isLoading } = useSWR( + (provider && modelId) + ? `/workspaces/current/model-providers/${provider}/models/parameter-rules?model=${modelId}` + : null, fetchModelParameterRules, + ) + + const parameterRules: ModelParameterRule[] = useMemo(() => { + return parameterRulesData?.data || [] + }, [parameterRulesData]) + + const handleSelectPresetParameter = (toneId: number) => { + const tone = TONE_LIST.find(tone => tone.id === toneId) + if (tone) { + onCompletionParamsChange({ + ...completionParams, + ...tone.config, + }) + } + } + const handleParamChange = (key: string, value: ParameterValue) => { + onCompletionParamsChange({ + ...completionParams, + [key]: value, + }) + } + const handleSwitch = (key: string, value: boolean, assignValue: ParameterValue) => { + if (!value) { + const newCompletionParams = { ...completionParams } + delete newCompletionParams[key] + + onCompletionParamsChange(newCompletionParams) + } + if (value) { + onCompletionParamsChange({ + ...completionParams, + [key]: assignValue, + }) + } + } + + if (isLoading) { + return ( + <div className='mt-5'><Loading /></div> + ) + } + + return ( + <> + <div className='flex items-center justify-between mb-2'> + <div className={cn('h-6 flex items-center text-text-secondary system-sm-semibold')}>{t('common.modelProvider.parameters')}</div> + { + PROVIDER_WITH_PRESET_TONE.includes(provider) && ( + <PresetsParameter onSelect={handleSelectPresetParameter} /> + ) + } + </div> + {!!parameterRules.length && ( + [ + ...parameterRules, + ...(isAdvancedMode ? [stopParameterRule] : []), + ].map(parameter => ( + <ParameterItem + key={`${modelId}-${parameter.name}`} + parameterRule={parameter} + value={completionParams?.[parameter.name]} + onChange={v => handleParamChange(parameter.name, v)} + onSwitch={(checked, assignValue) => handleSwitch(parameter.name, checked, assignValue)} + isInWorkflow + /> + )))} + </> + ) +} + +export default LLMParamsPanel diff --git a/web/app/components/plugins/plugin-detail-panel/model-selector/tts-params-panel.tsx b/web/app/components/plugins/plugin-detail-panel/model-selector/tts-params-panel.tsx new file mode 100644 index 0000000000..a13b9905d3 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/model-selector/tts-params-panel.tsx @@ -0,0 +1,67 @@ +import React, { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import { languages } from '@/i18n/language' +import { PortalSelect } from '@/app/components/base/select' +import cn from '@/utils/classnames' + +type Props = { + currentModel: any + language: string + voice: string + onChange: (language: string, voice: string) => void +} + +const TTSParamsPanel = ({ + currentModel, + language, + voice, + onChange, +}: Props) => { + const { t } = useTranslation() + const voiceList = useMemo(() => { + if (!currentModel) + return [] + return currentModel.model_properties.voices.map((item: { mode: any }) => ({ + ...item, + value: item.mode, + })) + }, [currentModel]) + const setLanguage = (language: string) => { + onChange(language, voice) + } + const setVoice = (voice: string) => { + onChange(language, voice) + } + return ( + <> + <div className='mb-3'> + <div className='mb-1 py-1 flex items-center text-text-secondary system-sm-semibold'> + {t('appDebug.voice.voiceSettings.language')} + </div> + <PortalSelect + triggerClassName='h-8' + popupClassName={cn('z-[1000]')} + popupInnerClassName={cn('w-[354px]')} + value={language} + items={languages.filter(item => item.supported)} + onSelect={item => setLanguage(item.value as string)} + /> + </div> + <div className='mb-3'> + <div className='mb-1 py-1 flex items-center text-text-secondary system-sm-semibold'> + {t('appDebug.voice.voiceSettings.voice')} + </div> + <PortalSelect + triggerClassName='h-8' + popupClassName={cn('z-[1000]')} + popupInnerClassName={cn('w-[354px]')} + value={voice} + items={voiceList} + onSelect={item => setVoice(item.value as string)} + /> + </div> + </> + ) +} + +export default TTSParamsPanel diff --git a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx new file mode 100644 index 0000000000..33375e60ec --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx @@ -0,0 +1,149 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { + RiAddLine, + RiArrowDropDownLine, + RiQuestionLine, +} from '@remixicon/react' +import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import ActionButton from '@/app/components/base/action-button' +import Tooltip from '@/app/components/base/tooltip' +import Divider from '@/app/components/base/divider' +import type { ToolValue } from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import cn from '@/utils/classnames' + +type Props = { + disabled?: boolean + value: ToolValue[] + label: string + required?: boolean + tooltip?: any + supportCollapse?: boolean + scope?: string + onChange: (value: ToolValue[]) => void +} + +const MultipleToolSelector = ({ + disabled, + value = [], + label, + required, + tooltip, + supportCollapse, + scope, + onChange, +}: Props) => { + const { t } = useTranslation() + const enabledCount = value.filter(item => item.enabled).length + // collapse control + const [collapse, setCollapse] = React.useState(false) + const handleCollapse = () => { + if (supportCollapse) + setCollapse(!collapse) + } + + // add tool + const [open, setOpen] = React.useState(false) + const handleAdd = (val: ToolValue) => { + const newValue = [...value, val] + // deduplication + const deduplication = newValue.reduce((acc, cur) => { + if (!acc.find(item => item.provider_name === cur.provider_name && item.tool_name === cur.tool_name)) + acc.push(cur) + return acc + }, [] as ToolValue[]) + // update value + onChange(deduplication) + setOpen(false) + } + + // delete tool + const handleDelete = (index: number) => { + const newValue = [...value] + newValue.splice(index, 1) + onChange(newValue) + } + + // configure tool + const handleConfigure = (val: ToolValue, index: number) => { + const newValue = [...value] + newValue[index] = val + onChange(newValue) + } + + return ( + <> + <div className='flex items-center mb-1'> + <div + className={cn('relative grow flex items-center gap-0.5', supportCollapse && 'cursor-pointer')} + onClick={handleCollapse} + > + <div className='h-6 flex items-center text-text-secondary system-sm-semibold-uppercase'>{label}</div> + {required && <div className='text-red-500'>*</div>} + {tooltip && ( + <Tooltip + popupContent={tooltip} + needsDelay + > + <div><RiQuestionLine className='w-3.5 h-3.5 text-text-quaternary hover:text-text-tertiary'/></div> + </Tooltip> + )} + {supportCollapse && ( + <div className='absolute -left-4 top-1'> + <RiArrowDropDownLine + className={cn( + 'w-4 h-4 text-text-tertiary', + collapse && 'transform -rotate-90', + )} + /> + </div> + )} + </div> + {value.length > 0 && ( + <> + <div className='flex items-center gap-1 text-text-tertiary system-xs-medium'> + <span>{`${enabledCount}/${value.length}`}</span> + <span>{t('appDebug.agent.tools.enabled')}</span> + </div> + <Divider type='vertical' className='ml-3 mr-1 h-3' /> + </> + )} + {!disabled && ( + <ActionButton className='mx-1' onClick={() => setOpen(!open)}> + <RiAddLine className='w-4 h-4' /> + </ActionButton> + )} + </div> + {!collapse && ( + <> + <ToolSelector + scope={scope} + value={undefined} + onSelect={handleAdd} + controlledState={open} + onControlledStateChange={setOpen} + trigger={ + <div className=''></div> + } + /> + {value.length === 0 && ( + <div className='p-3 flex justify-center rounded-[10px] bg-background-section text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.toolSelector.empty')}</div> + )} + {value.length > 0 && value.map((item, index) => ( + <div className='mb-1' key={index}> + <ToolSelector + scope={scope} + value={item} + onSelect={item => handleConfigure(item, index)} + onDelete={() => handleDelete(index)} + supportEnableSwitch + /> + </div> + ))} + </> + )} + </> + ) +} + +export default MultipleToolSelector diff --git a/web/app/components/plugins/plugin-detail-panel/operation-dropdown.tsx b/web/app/components/plugins/plugin-detail-panel/operation-dropdown.tsx new file mode 100644 index 0000000000..422ff447a4 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/operation-dropdown.tsx @@ -0,0 +1,101 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { PluginSource } from '../types' +import { RiArrowRightUpLine, RiMoreFill } from '@remixicon/react' +import ActionButton from '@/app/components/base/action-button' +// import Button from '@/app/components/base/button' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import cn from '@/utils/classnames' + +type Props = { + source: PluginSource + onInfo: () => void + onCheckVersion: () => void + onRemove: () => void + detailUrl: string +} + +const OperationDropdown: FC<Props> = ({ + source, + detailUrl, + onInfo, + onCheckVersion, + onRemove, +}) => { + const { t } = useTranslation() + const [open, doSetOpen] = useState(false) + const openRef = useRef(open) + const setOpen = useCallback((v: boolean) => { + doSetOpen(v) + openRef.current = v + }, [doSetOpen]) + + const handleTrigger = useCallback(() => { + setOpen(!openRef.current) + }, [setOpen]) + + return ( + <PortalToFollowElem + open={open} + onOpenChange={setOpen} + placement='bottom-end' + offset={{ + mainAxis: -12, + crossAxis: 36, + }} + > + <PortalToFollowElemTrigger onClick={handleTrigger}> + <div> + <ActionButton className={cn(open && 'bg-state-base-hover')}> + <RiMoreFill className='w-4 h-4' /> + </ActionButton> + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-50'> + <div className='w-[160px] p-1 bg-components-panel-bg-blur rounded-xl border-[0.5px] border-components-panel-border shadow-lg'> + {source === PluginSource.github && ( + <div + onClick={() => { + onInfo() + handleTrigger() + }} + className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover' + >{t('plugin.detailPanel.operation.info')}</div> + )} + {source === PluginSource.github && ( + <div + onClick={() => { + onCheckVersion() + handleTrigger() + }} + className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover' + >{t('plugin.detailPanel.operation.checkUpdate')}</div> + )} + {(source === PluginSource.marketplace || source === PluginSource.github) && ( + <a href={detailUrl} target='_blank' className='flex items-center px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover'> + <span className='grow'>{t('plugin.detailPanel.operation.viewDetail')}</span> + <RiArrowRightUpLine className='shrink-0 w-3.5 h-3.5 text-text-tertiary' /> + </a> + )} + {(source === PluginSource.marketplace || source === PluginSource.github) && ( + <div className='my-1 h-px bg-divider-subtle'></div> + )} + <div + onClick={() => { + onRemove() + handleTrigger() + }} + className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:text-text-destructive hover:bg-state-destructive-hover' + >{t('plugin.detailPanel.operation.remove')}</div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} +export default React.memo(OperationDropdown) diff --git a/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx b/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx new file mode 100644 index 0000000000..a7f1d84071 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx @@ -0,0 +1,164 @@ +'use client' +import type { FC } from 'react' +import React, { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import { + RiArrowLeftLine, + RiCloseLine, +} from '@remixicon/react' +import Drawer from '@/app/components/base/drawer' +import ActionButton from '@/app/components/base/action-button' +import Icon from '@/app/components/plugins/card/base/card-icon' +import Description from '@/app/components/plugins/card/base/description' +import Divider from '@/app/components/base/divider' +import type { + StrategyDetail, +} from '@/app/components/plugins/types' +import type { Locale } from '@/i18n' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import { API_PREFIX } from '@/config' +import cn from '@/utils/classnames' + +type Props = { + provider: { + author: string + name: string + description: Record<Locale, string> + tenant_id: string + icon: string + label: Record<Locale, string> + tags: string[] + } + detail: StrategyDetail + onHide: () => void +} + +const StrategyDetail: FC<Props> = ({ + provider, + detail, + onHide, +}) => { + const getValueFromI18nObject = useRenderI18nObject() + const { t } = useTranslation() + + const outputSchema = useMemo(() => { + const res: any[] = [] + if (!detail.output_schema) + return [] + Object.keys(detail.output_schema.properties).forEach((outputKey) => { + const output = detail.output_schema.properties[outputKey] + res.push({ + name: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`, + description: output.description, + }) + }) + return res + }, [detail.output_schema]) + + const getType = (type: string) => { + if (type === 'number-input') + return t('tools.setBuiltInTools.number') + if (type === 'text-input') + return t('tools.setBuiltInTools.string') + if (type === 'file') + return t('tools.setBuiltInTools.file') + if (type === 'array[tools]') + return 'multiple-tool-select' + return type + } + + return ( + <Drawer + isOpen + clickOutsideNotOpen={false} + onClose={onHide} + footer={null} + mask={false} + positionCenter={false} + panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')} + > + <> + {/* header */} + <div className='relative p-4 pb-3 border-b border-divider-subtle'> + <div className='absolute top-3 right-3'> + <ActionButton onClick={onHide}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> + </div> + <div + className='mb-2 flex items-center gap-1 text-text-accent-secondary system-xs-semibold-uppercase cursor-pointer' + onClick={onHide} + > + <RiArrowLeftLine className='w-4 h-4' /> + BACK + </div> + <div className='flex items-center gap-1'> + <Icon size='tiny' className='w-6 h-6' src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${provider.tenant_id}&filename=${provider.icon}`} /> + <div className=''>{getValueFromI18nObject(provider.label)}</div> + </div> + <div className='mt-1 text-text-primary system-md-semibold'>{getValueFromI18nObject(detail.identity.label)}</div> + <Description className='mt-3' text={getValueFromI18nObject(detail.description)} descriptionLineRows={2}></Description> + </div> + {/* form */} + <div className='h-full'> + <div className='flex flex-col h-full overflow-y-auto'> + <div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>{t('tools.setBuiltInTools.parameters')}</div> + <div className='px-4'> + {detail.parameters.length > 0 && ( + <div className='py-2 space-y-1'> + {detail.parameters.map((item: any, index) => ( + <div key={index} className='py-1'> + <div className='flex items-center gap-2'> + <div className='text-text-secondary code-sm-semibold'>{getValueFromI18nObject(item.label)}</div> + <div className='text-text-tertiary system-xs-regular'> + {getType(item.type)} + </div> + {item.required && ( + <div className='text-text-warning-secondary system-xs-medium'>{t('tools.setBuiltInTools.required')}</div> + )} + </div> + {item.human_description && ( + <div className='mt-0.5 text-text-tertiary system-xs-regular'> + {getValueFromI18nObject(item.human_description)} + </div> + )} + </div> + ))} + </div> + )} + </div> + {detail.output_schema && ( + <> + <div className='px-4'> + <Divider className="!mt-2" /> + </div> + <div className='p-4 pb-1 text-text-primary system-sm-semibold-uppercase'>OUTPUT</div> + {outputSchema.length > 0 && ( + <div className='px-4 py-2 space-y-1'> + {outputSchema.map((outputItem, index) => ( + <div key={index} className='py-1'> + <div className='flex items-center gap-2'> + <div className='text-text-secondary code-sm-semibold'>{outputItem.name}</div> + <div className='text-text-tertiary system-xs-regular'>{outputItem.type}</div> + </div> + {outputItem.description && ( + <div className='mt-0.5 text-text-tertiary system-xs-regular'> + {outputItem.description} + </div> + )} + </div> + ))} + </div> + )} + </> + )} + </div> + </div> + </> + </Drawer> + ) +} +export default StrategyDetail diff --git a/web/app/components/plugins/plugin-detail-panel/strategy-item.tsx b/web/app/components/plugins/plugin-detail-panel/strategy-item.tsx new file mode 100644 index 0000000000..fd2fea99e0 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/strategy-item.tsx @@ -0,0 +1,50 @@ +'use client' +import React, { useState } from 'react' +import StrategyDetailPanel from './strategy-detail' +import type { + StrategyDetail, +} from '@/app/components/plugins/types' +import type { Locale } from '@/i18n' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import cn from '@/utils/classnames' + +type Props = { + provider: { + author: string + name: string + description: Record<Locale, string> + tenant_id: string + icon: string + label: Record<Locale, string> + tags: string[] + } + detail: StrategyDetail +} + +const StrategyItem = ({ + provider, + detail, +}: Props) => { + const getValueFromI18nObject = useRenderI18nObject() + const [showDetail, setShowDetail] = useState(false) + + return ( + <> + <div + className={cn('mb-2 px-4 py-3 bg-components-panel-item-bg rounded-xl border-[0.5px] border-components-panel-border-subtle shadow-xs cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover')} + onClick={() => setShowDetail(true)} + > + <div className='pb-0.5 text-text-secondary system-md-semibold'>{getValueFromI18nObject(detail.identity.label)}</div> + <div className='text-text-tertiary system-xs-regular line-clamp-2' title={getValueFromI18nObject(detail.description)}>{getValueFromI18nObject(detail.description)}</div> + </div> + {showDetail && ( + <StrategyDetailPanel + provider={provider} + detail={detail} + onHide={() => setShowDetail(false)} + /> + )} + </> + ) +} +export default StrategyItem diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks.ts b/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks.ts new file mode 100644 index 0000000000..57c1fbd7c3 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks.ts @@ -0,0 +1,14 @@ +import { + usePluginManifestInfo, +} from '@/service/use-plugins' + +export const usePluginInstalledCheck = (providerName = '') => { + const pluginID = providerName?.split('/').splice(0, 2).join('/') + + const { data: manifest } = usePluginManifestInfo(pluginID) + + return { + inMarketPlace: !!manifest, + manifest: manifest?.data.plugin, + } +} diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx new file mode 100644 index 0000000000..1be8498788 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx @@ -0,0 +1,374 @@ +'use client' +import type { FC } from 'react' +import React, { useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Link from 'next/link' +import { + RiArrowLeftLine, + RiArrowRightUpLine, +} from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import ToolTrigger from '@/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger' +import ToolItem from '@/app/components/plugins/plugin-detail-panel/tool-selector/tool-item' +import ToolPicker from '@/app/components/workflow/block-selector/tool-picker' +import Button from '@/app/components/base/button' +import Indicator from '@/app/components/header/indicator' +import ToolCredentialForm from '@/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form' +import Toast from '@/app/components/base/toast' +import Textarea from '@/app/components/base/textarea' +import Divider from '@/app/components/base/divider' +import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' + +import { useAppContext } from '@/context/app-context' +import { + useAllBuiltInTools, + useAllCustomTools, + useAllWorkflowTools, + useInvalidateAllBuiltInTools, + useUpdateProviderCredentials, +} from '@/service/use-tools' +import { useInvalidateInstalledPluginList } from '@/service/use-plugins' +import { usePluginInstalledCheck } from '@/app/components/plugins/plugin-detail-panel/tool-selector/hooks' +import { CollectionType } from '@/app/components/tools/types' +import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types' +import type { + OffsetOptions, + Placement, +} from '@floating-ui/react' +import { MARKETPLACE_API_PREFIX } from '@/config' +import cn from '@/utils/classnames' + +export type ToolValue = { + provider_name: string + tool_name: string + parameters?: Record<string, any> + enabled?: boolean + extra?: Record<string, any> +} + +type Props = { + disabled?: boolean + placement?: Placement + offset?: OffsetOptions + scope?: string + value?: ToolValue + onSelect: (tool: { + provider_name: string + tool_name: string + parameters?: Record<string, any> + extra?: Record<string, any> + }) => void + onDelete?: () => void + supportEnableSwitch?: boolean + supportAddCustomTool?: boolean + trigger?: React.ReactNode + controlledState?: boolean + onControlledStateChange?: (state: boolean) => void +} +const ToolSelector: FC<Props> = ({ + value, + disabled, + placement = 'left', + offset = 4, + onSelect, + onDelete, + scope, + supportEnableSwitch, + trigger, + controlledState, + onControlledStateChange, +}) => { + const { t } = useTranslation() + const [isShow, onShowChange] = useState(false) + const handleTriggerClick = () => { + if (disabled) return + onShowChange(true) + } + + const { data: buildInTools } = useAllBuiltInTools() + const { data: customTools } = useAllCustomTools() + const { data: workflowTools } = useAllWorkflowTools() + const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools() + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + + // plugin info check + const { inMarketPlace, manifest } = usePluginInstalledCheck(value?.provider_name) + + const currentProvider = useMemo(() => { + const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])] + return mergedTools.find((toolWithProvider) => { + return toolWithProvider.id === value?.provider_name + }) + }, [value, buildInTools, customTools, workflowTools]) + + const [isShowChooseTool, setIsShowChooseTool] = useState(false) + const handleSelectTool = (tool: ToolDefaultValue) => { + const paramValues = addDefaultValue(tool.params, toolParametersToFormSchemas(tool.paramSchemas.filter(param => param.form !== 'llm') as any)) + const toolValue = { + provider_name: tool.provider_id, + tool_name: tool.tool_name, + parameters: paramValues, + enabled: tool.is_team_authorization, + extra: { + description: '', + }, + } + onSelect(toolValue) + // setIsShowChooseTool(false) + } + + const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { + onSelect({ + ...value, + extra: { + ...value?.extra, + description: e.target.value || '', + }, + } as any) + } + + const currentToolParams = useMemo(() => { + if (!currentProvider) return [] + return currentProvider.tools.find(tool => tool.name === value?.tool_name)?.parameters.filter(param => param.form !== 'llm') || [] + }, [currentProvider, value]) + + const formSchemas = useMemo(() => toolParametersToFormSchemas(currentToolParams), [currentToolParams]) + + const handleFormChange = (v: Record<string, any>) => { + const toolValue = { + ...value, + parameters: v, + } + onSelect(toolValue as any) + } + + const handleEnabledChange = (state: boolean) => { + onSelect({ + ...value, + enabled: state, + } as any) + } + + // authorization + const { isCurrentWorkspaceManager } = useAppContext() + const [isShowSettingAuth, setShowSettingAuth] = useState(false) + const handleCredentialSettingUpdate = () => { + invalidateAllBuiltinTools() + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + setShowSettingAuth(false) + onShowChange(false) + } + + const { mutate: updatePermission } = useUpdateProviderCredentials({ + onSuccess: handleCredentialSettingUpdate, + }) + + // install from marketplace + const currentTool = useMemo(() => { + return currentProvider?.tools.find(tool => tool.name === value?.tool_name) + }, [currentProvider?.tools, value?.tool_name]) + const manifestIcon = useMemo(() => { + if (!manifest) + return '' + return `${MARKETPLACE_API_PREFIX}/plugins/${(manifest as any).plugin_id}/icon` + }, [manifest]) + const handleInstall = async () => { + invalidateAllBuiltinTools() + invalidateInstalledPluginList() + } + + return ( + <> + <PortalToFollowElem + placement={placement} + offset={offset} + open={trigger ? controlledState : isShow} + onOpenChange={trigger ? onControlledStateChange : onShowChange} + > + <PortalToFollowElemTrigger + className='w-full' + onClick={() => { + if (!currentProvider || !currentTool) return + handleTriggerClick() + }} + > + {trigger} + {!trigger && !value?.provider_name && ( + <ToolTrigger + isConfigure + open={isShow} + value={value} + provider={currentProvider} + /> + )} + {!trigger && value?.provider_name && ( + <ToolItem + open={isShow} + icon={currentProvider?.icon || manifestIcon} + providerName={value.provider_name} + toolName={value.tool_name} + showSwitch={supportEnableSwitch} + switchValue={value.enabled} + onSwitchChange={handleEnabledChange} + onDelete={onDelete} + noAuth={currentProvider && currentTool && !currentProvider.is_team_authorization} + onAuth={() => setShowSettingAuth(true)} + uninstalled={!currentProvider && inMarketPlace} + versionMismatch={currentProvider && inMarketPlace && !currentTool} + installInfo={manifest?.latest_package_identifier} + onInstall={() => handleInstall()} + isError={(!currentProvider || !currentTool) && !inMarketPlace} + errorTip={ + <div className='space-y-1 max-w-[240px] text-xs'> + <h3 className='text-text-primary font-semibold'>{currentTool ? t('plugin.detailPanel.toolSelector.uninstalledTitle') : t('plugin.detailPanel.toolSelector.unsupportedTitle')}</h3> + <p className='text-text-secondary tracking-tight'>{currentTool ? t('plugin.detailPanel.toolSelector.uninstalledContent') : t('plugin.detailPanel.toolSelector.unsupportedContent')}</p> + <p> + <Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('plugin.detailPanel.toolSelector.uninstalledLink')}</Link> + </p> + </div> + } + /> + )} + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[1000]'> + <div className={cn('relative w-[361px] min-h-20 max-h-[642px] pb-4 rounded-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg', !isShowSettingAuth && 'overflow-y-auto pb-2')}> + {!isShowSettingAuth && ( + <> + <div className='px-4 pt-3.5 pb-1 text-text-primary system-xl-semibold'>{t('plugin.detailPanel.toolSelector.title')}</div> + {/* base form */} + <div className='px-4 py-2 flex flex-col gap-3'> + <div className='flex flex-col gap-1'> + <div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('plugin.detailPanel.toolSelector.toolLabel')}</div> + <ToolPicker + placement='bottom' + offset={offset} + trigger={ + <ToolTrigger + open={isShowChooseTool} + value={value} + provider={currentProvider} + /> + } + isShow={isShowChooseTool} + onShowChange={setIsShowChooseTool} + disabled={false} + supportAddCustomTool + onSelect={handleSelectTool} + scope={scope} + /> + </div> + <div className='flex flex-col gap-1'> + <div className='h-6 flex items-center system-sm-semibold text-text-secondary'>{t('plugin.detailPanel.toolSelector.descriptionLabel')}</div> + <Textarea + className='resize-none' + placeholder={t('plugin.detailPanel.toolSelector.descriptionPlaceholder')} + value={value?.extra?.description || ''} + onChange={handleDescriptionChange} + disabled={!value?.provider_name} + /> + </div> + </div> + {/* authorization */} + {currentProvider && currentProvider.type === CollectionType.builtIn && currentProvider.allow_delete && ( + <div className='px-4 pt-3 flex flex-col'> + <div className='flex items-center gap-2'> + <div className='shrink-0 text-text-tertiary system-xs-medium-uppercase'>{t('plugin.detailPanel.toolSelector.auth')}</div> + <Divider bgStyle='gradient' className='grow' /> + </div> + <div className='py-2'> + {!currentProvider.is_team_authorization && ( + <Button + variant='primary' + className={cn('shrink-0 w-full')} + onClick={() => setShowSettingAuth(true)} + disabled={!isCurrentWorkspaceManager} + > + {t('tools.auth.unauthorized')} + </Button> + )} + {currentProvider.is_team_authorization && ( + <Button + variant='secondary' + className={cn('shrink-0 w-full')} + onClick={() => setShowSettingAuth(true)} + disabled={!isCurrentWorkspaceManager} + > + <Indicator className='mr-2' color={'green'} /> + {t('tools.auth.authorized')} + </Button> + )} + </div> + </div> + )} + {/* tool settings */} + {currentToolParams.length > 0 && currentProvider?.is_team_authorization && ( + <div className='px-4 pt-3'> + <div className='flex items-center gap-2'> + <div className='shrink-0 text-text-tertiary system-xs-medium-uppercase'>{t('plugin.detailPanel.toolSelector.settings')}</div> + <Divider bgStyle='gradient' className='grow' /> + </div> + <div className='py-2'> + <Form + value={value?.parameters || {}} + onChange={handleFormChange} + formSchemas={formSchemas as any} + isEditMode={true} + showOnVariableMap={{}} + validating={false} + inputClassName='bg-components-input-bg-normal hover:bg-components-input-bg-hover' + fieldMoreInfo={item => item.url + ? (<a + href={item.url} + target='_blank' rel='noopener noreferrer' + className='inline-flex items-center text-xs text-text-accent' + > + {t('tools.howToGet')} + <RiArrowRightUpLine className='ml-1 w-3 h-3' /> + </a>) + : null} + /> + </div> + </div> + )} + </> + )} + {/* authorization panel */} + {isShowSettingAuth && currentProvider && ( + <> + <div className='relative pt-3.5 flex flex-col gap-1'> + <div className='absolute -top-2 left-2 w-[345px] pt-2 rounded-t-xl backdrop-blur-sm bg-components-panel-bg-blur border-[0.5px] border-components-panel-border'></div> + <div + className='px-3 h-6 flex items-center gap-1 text-text-accent-secondary system-xs-semibold-uppercase cursor-pointer' + onClick={() => setShowSettingAuth(false)} + > + <RiArrowLeftLine className='w-4 h-4' /> + BACK + </div> + <div className='px-4 text-text-primary system-xl-semibold'>{t('tools.auth.setupModalTitle')}</div> + <div className='px-4 text-text-tertiary system-xs-regular'>{t('tools.auth.setupModalTitleDescription')}</div> + </div> + <ToolCredentialForm + collection={currentProvider} + onCancel={() => setShowSettingAuth(false)} + onSaved={async value => updatePermission({ + providerName: currentProvider.name, + credentials: value, + })} + /> + </> + )} + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + </> + ) +} +export default React.memo(ToolSelector) diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form.tsx new file mode 100644 index 0000000000..6334e792f9 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-credentials-form.tsx @@ -0,0 +1,97 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + RiArrowRightUpLine, +} from '@remixicon/react' +import { addDefaultValue, toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema' +import type { Collection } from '@/app/components/tools/types' +import Button from '@/app/components/base/button' +import Toast from '@/app/components/base/toast' +import { fetchBuiltInToolCredential, fetchBuiltInToolCredentialSchema } from '@/service/tools' +import Loading from '@/app/components/base/loading' +import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import cn from '@/utils/classnames' + +type Props = { + collection: Collection + onCancel: () => void + onSaved: (value: Record<string, any>) => void +} + +const ToolCredentialForm: FC<Props> = ({ + collection, + onCancel, + onSaved, +}) => { + const getValueFromI18nObject = useRenderI18nObject() + const { t } = useTranslation() + const [credentialSchema, setCredentialSchema] = useState<any>(null) + const { name: collectionName } = collection + const [tempCredential, setTempCredential] = React.useState<any>({}) + useEffect(() => { + fetchBuiltInToolCredentialSchema(collectionName).then(async (res) => { + const toolCredentialSchemas = toolCredentialToFormSchemas(res) + const credentialValue = await fetchBuiltInToolCredential(collectionName) + setTempCredential(credentialValue) + const defaultCredentials = addDefaultValue(credentialValue, toolCredentialSchemas) + setCredentialSchema(toolCredentialSchemas) + setTempCredential(defaultCredentials) + }) + }, []) + + const handleSave = () => { + for (const field of credentialSchema) { + if (field.required && !tempCredential[field.name]) { + Toast.notify({ type: 'error', message: t('common.errorMsg.fieldRequired', { field: getValueFromI18nObject(field.label) }) }) + return + } + } + onSaved(tempCredential) + } + + return ( + <> + {!credentialSchema + ? <div className='pt-3'><Loading type='app' /></div> + : ( + <> + <div className='px-4 max-h-[464px] overflow-y-auto'> + <Form + value={tempCredential} + onChange={(v) => { + setTempCredential(v) + }} + formSchemas={credentialSchema} + isEditMode={true} + showOnVariableMap={{}} + validating={false} + inputClassName='bg-components-input-bg-normal hover:bg-components-input-bg-hover' + fieldMoreInfo={item => item.url + ? (<a + href={item.url} + target='_blank' rel='noopener noreferrer' + className='inline-flex items-center text-xs text-text-accent' + > + {t('tools.howToGet')} + <RiArrowRightUpLine className='ml-1 w-3 h-3' /> + </a>) + : null} + /> + </div> + <div className={cn('mt-1 flex justify-end px-4')} > + <div className='flex space-x-2'> + <Button onClick={onCancel}>{t('common.operation.cancel')}</Button> + <Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button> + </div> + </div> + </> + ) + } + + </> + ) +} +export default React.memo(ToolCredentialForm) diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-item.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-item.tsx new file mode 100644 index 0000000000..3e32e66929 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-item.tsx @@ -0,0 +1,163 @@ +'use client' +import React, { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { + RiDeleteBinLine, + RiEqualizer2Line, + RiErrorWarningFill, +} from '@remixicon/react' +import { Group } from '@/app/components/base/icons/src/vender/other' +import AppIcon from '@/app/components/base/app-icon' +import Switch from '@/app/components/base/switch' +import Button from '@/app/components/base/button' +import Indicator from '@/app/components/header/indicator' +import ActionButton from '@/app/components/base/action-button' +import Tooltip from '@/app/components/base/tooltip' +import { ToolTipContent } from '@/app/components/base/tooltip/content' +import { InstallPluginButton } from '@/app/components/workflow/nodes/_base/components/install-plugin-button' +import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version' +import cn from '@/utils/classnames' + +type Props = { + icon?: any + providerName?: string + toolName?: string + showSwitch?: boolean + switchValue?: boolean + onSwitchChange?: (value: boolean) => void + onDelete?: () => void + noAuth?: boolean + onAuth?: () => void + isError?: boolean + errorTip?: any + uninstalled?: boolean + installInfo?: string + onInstall?: () => void + versionMismatch?: boolean + open: boolean +} + +const ToolItem = ({ + open, + icon, + providerName, + toolName, + showSwitch, + switchValue, + onSwitchChange, + onDelete, + noAuth, + onAuth, + uninstalled, + installInfo, + onInstall, + isError, + errorTip, + versionMismatch, +}: Props) => { + const { t } = useTranslation() + const providerNameText = providerName?.split('/').pop() + const isTransparent = uninstalled || versionMismatch || isError + const [isDeleting, setIsDeleting] = useState(false) + + return ( + <div className={cn( + 'group p-1.5 pr-2 flex items-center gap-1 bg-components-panel-on-panel-item-bg border-[0.5px] border-components-panel-border-subtle rounded-lg shadow-xs cursor-default hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-sm', + open && 'bg-components-panel-on-panel-item-bg-hover shadow-sm', + isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border shadow-xs', + )}> + {icon && ( + <div className={cn('shrink-0', isTransparent && 'opacity-50')}> + {typeof icon === 'string' && <div className='w-7 h-7 bg-cover bg-center border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' style={{ backgroundImage: `url(${icon})` }} />} + {typeof icon !== 'string' && <AppIcon className='w-7 h-7 border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' size='xs' icon={icon?.content} background={icon?.background} />} + </div> + )} + {!icon && ( + <div className={cn( + 'flex items-center justify-center w-7 h-7 rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle', + )}> + <div className='flex w-5 h-5 items-center justify-center opacity-35'> + <Group className='text-text-tertiary' /> + </div> + </div> + )} + <div className={cn('pl-0.5 grow truncate', isTransparent && 'opacity-50')}> + <div className='text-text-tertiary system-2xs-medium-uppercase'>{providerNameText}</div> + <div className='text-text-secondary system-xs-medium'>{toolName}</div> + </div> + <div className='hidden group-hover:flex items-center gap-1'> + {!noAuth && !isError && !uninstalled && !versionMismatch && ( + <ActionButton> + <RiEqualizer2Line className='w-4 h-4' /> + </ActionButton> + )} + <div + className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive' + onClick={(e) => { + e.stopPropagation() + onDelete?.() + }} + onMouseOver={() => setIsDeleting(true)} + onMouseLeave={() => setIsDeleting(false)} + > + <RiDeleteBinLine className='w-4 h-4' /> + </div> + </div> + {!isError && !uninstalled && !noAuth && !versionMismatch && showSwitch && ( + <div className='mr-1' onClick={e => e.stopPropagation()}> + <Switch + size='md' + defaultValue={switchValue} + onChange={onSwitchChange} + /> + </div> + )} + {!isError && !uninstalled && !versionMismatch && noAuth && ( + <Button variant='secondary' size='small' onClick={onAuth}> + {t('tools.notAuthorized')} + <Indicator className='ml-2' color='orange' /> + </Button> + )} + {!isError && !uninstalled && versionMismatch && installInfo && ( + <div onClick={e => e.stopPropagation()}> + <SwitchPluginVersion + className='-mt-1' + uniqueIdentifier={installInfo} + tooltip={ + <ToolTipContent + title={t('plugin.detailPanel.toolSelector.unsupportedTitle')} + > + {`${t('plugin.detailPanel.toolSelector.unsupportedContent')} ${t('plugin.detailPanel.toolSelector.unsupportedContent2')}`} + </ToolTipContent> + } + onChange={() => { + onInstall?.() + }} + /> + </div> + )} + {!isError && uninstalled && installInfo && ( + <InstallPluginButton + onClick={e => e.stopPropagation()} + size={'small'} + uniqueIdentifier={installInfo} + onSuccess={() => { + onInstall?.() + }} + /> + )} + {isError && ( + <Tooltip + popupContent={errorTip} + needsDelay + > + <div> + <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> + </div> + </Tooltip> + )} + </div> + ) +} + +export default ToolItem diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger.tsx new file mode 100644 index 0000000000..adea79adf5 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/tool-trigger.tsx @@ -0,0 +1,63 @@ +'use client' +import React from 'react' +import { useTranslation } from 'react-i18next' +import { + RiArrowDownSLine, + RiEqualizer2Line, +} from '@remixicon/react' +import BlockIcon from '@/app/components/workflow/block-icon' +import { BlockEnum } from '@/app/components/workflow/types' +import type { ToolWithProvider } from '@/app/components/workflow/types' +import cn from '@/utils/classnames' + +type Props = { + open: boolean + provider?: ToolWithProvider + value?: { + provider_name: string + tool_name: string + } + isConfigure?: boolean +} + +const ToolTrigger = ({ + open, + provider, + value, + isConfigure, +}: Props) => { + const { t } = useTranslation() + return ( + <div className={cn( + 'group flex items-center p-2 pl-3 bg-components-input-bg-normal rounded-lg cursor-pointer hover:bg-state-base-hover-alt', + open && 'bg-state-base-hover-alt', + value?.provider_name && 'pl-1.5 py-1.5', + )}> + {value?.provider_name && provider && ( + <div className='shrink-0 mr-1 p-px rounded-lg bg-components-panel-bg border border-components-panel-border'> + <BlockIcon + className='!w-4 !h-4' + type={BlockEnum.Tool} + toolIcon={provider.icon} + /> + </div> + )} + {value?.tool_name && ( + <div className='grow system-sm-medium text-components-input-text-filled'>{value.tool_name}</div> + )} + {!value?.provider_name && ( + <div className='grow text-components-input-text-placeholder system-sm-regular'> + {!isConfigure ? t('plugin.detailPanel.toolSelector.placeholder') : t('plugin.detailPanel.configureTool')} + </div> + )} + {isConfigure && ( + <RiEqualizer2Line className={cn('shrink-0 ml-0.5 w-4 h-4 text-text-quaternary group-hover:text-text-secondary', open && 'text-text-secondary')} /> + )} + {!isConfigure && ( + <RiArrowDownSLine className={cn('shrink-0 ml-0.5 w-4 h-4 text-text-quaternary group-hover:text-text-secondary', open && 'text-text-secondary')} /> + )} + </div> + ) +} + +export default ToolTrigger diff --git a/web/app/components/plugins/plugin-detail-panel/utils.ts b/web/app/components/plugins/plugin-detail-panel/utils.ts new file mode 100644 index 0000000000..fd51142a38 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/utils.ts @@ -0,0 +1,21 @@ +import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' + +export const NAME_FIELD = { + type: FormTypeEnum.textInput, + name: 'name', + label: { + en_US: 'Endpoint Name', + zh_Hans: '端点名称', + ja_JP: 'エンドポイント名', + pt_BR: 'Nome do ponto final', + }, + placeholder: { + en_US: 'Endpoint Name', + zh_Hans: '端点名称', + ja_JP: 'エンドポイント名', + pt_BR: 'Nome do ponto final', + }, + required: true, + default: '', + help: null, +} diff --git a/web/app/components/plugins/plugin-item/action.tsx b/web/app/components/plugins/plugin-item/action.tsx new file mode 100644 index 0000000000..1bc34c9928 --- /dev/null +++ b/web/app/components/plugins/plugin-item/action.tsx @@ -0,0 +1,159 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import { type MetaData, PluginSource } from '../types' +import { RiDeleteBinLine, RiInformation2Line, RiLoopLeftLine } from '@remixicon/react' +import { useBoolean } from 'ahooks' +import { useTranslation } from 'react-i18next' +import PluginInfo from '../plugin-page/plugin-info' +import ActionButton from '../../base/action-button' +import Tooltip from '../../base/tooltip' +import Confirm from '../../base/confirm' +import { uninstallPlugin } from '@/service/plugins' +import { useGitHubReleases } from '../install-plugin/hooks' +import Toast from '@/app/components/base/toast' +import { useModalContext } from '@/context/modal-context' +import { useInvalidateInstalledPluginList } from '@/service/use-plugins' + +const i18nPrefix = 'plugin.action' + +type Props = { + author: string + installationId: string + pluginUniqueIdentifier: string + pluginName: string + usedInApps: number + isShowFetchNewVersion: boolean + isShowInfo: boolean + isShowDelete: boolean + onDelete: () => void + meta?: MetaData +} +const Action: FC<Props> = ({ + author, + installationId, + pluginUniqueIdentifier, + pluginName, + isShowFetchNewVersion, + isShowInfo, + isShowDelete, + onDelete, + meta, +}) => { + const { t } = useTranslation() + const [isShowPluginInfo, { + setTrue: showPluginInfo, + setFalse: hidePluginInfo, + }] = useBoolean(false) + const [deleting, { + setTrue: showDeleting, + setFalse: hideDeleting, + }] = useBoolean(false) + const { checkForUpdates, fetchReleases } = useGitHubReleases() + const { setShowUpdatePluginModal } = useModalContext() + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + + const handleFetchNewVersion = async () => { + const fetchedReleases = await fetchReleases(author, pluginName) + if (fetchedReleases.length === 0) return + const { needUpdate, toastProps } = checkForUpdates(fetchedReleases, meta!.version) + Toast.notify(toastProps) + if (needUpdate) { + setShowUpdatePluginModal({ + onSaveCallback: () => { + invalidateInstalledPluginList() + }, + payload: { + type: PluginSource.github, + github: { + originalPackageInfo: { + id: pluginUniqueIdentifier, + repo: meta!.repo, + version: meta!.version, + package: meta!.package, + releases: fetchedReleases, + }, + }, + }, + }) + } + } + + const [isShowDeleteConfirm, { + setTrue: showDeleteConfirm, + setFalse: hideDeleteConfirm, + }] = useBoolean(false) + + const handleDelete = useCallback(async () => { + showDeleting() + const res = await uninstallPlugin(installationId) + hideDeleting() + if (res.success) { + hideDeleteConfirm() + onDelete() + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [installationId, onDelete]) + return ( + <div className='flex space-x-1'> + {/* Only plugin installed from GitHub need to check if it's the new version */} + {isShowFetchNewVersion + && ( + <Tooltip popupContent={t(`${i18nPrefix}.checkForUpdates`)}> + <ActionButton onClick={handleFetchNewVersion}> + <RiLoopLeftLine className='w-4 h-4 text-text-tertiary' /> + </ActionButton> + </Tooltip> + ) + } + { + isShowInfo + && ( + <Tooltip popupContent={t(`${i18nPrefix}.pluginInfo`)}> + <ActionButton onClick={showPluginInfo}> + <RiInformation2Line className='w-4 h-4 text-text-tertiary' /> + </ActionButton> + </Tooltip> + ) + } + { + isShowDelete + && ( + <Tooltip popupContent={t(`${i18nPrefix}.delete`)}> + <ActionButton + className='hover:bg-state-destructive-hover text-text-tertiary hover:text-text-destructive' + onClick={showDeleteConfirm} + > + <RiDeleteBinLine className='w-4 h-4' /> + </ActionButton> + </Tooltip> + ) + } + + {isShowPluginInfo && ( + <PluginInfo + repository={meta!.repo} + release={meta!.version} + packageName={meta!.package} + onHide={hidePluginInfo} + /> + )} + <Confirm + isShow={isShowDeleteConfirm} + title={t(`${i18nPrefix}.delete`)} + content={ + <div> + {t(`${i18nPrefix}.deleteContentLeft`)}<span className='system-md-semibold'>{pluginName}</span>{t(`${i18nPrefix}.deleteContentRight`)}<br /> + {/* // todo: add usedInApps */} + {/* {usedInApps > 0 && t(`${i18nPrefix}.usedInApps`, { num: usedInApps })} */} + </div> + } + onCancel={hideDeleteConfirm} + onConfirm={handleDelete} + isLoading={deleting} + isDisabled={deleting} + /> + </div> + ) +} +export default React.memo(Action) diff --git a/web/app/components/plugins/plugin-item/index.tsx b/web/app/components/plugins/plugin-item/index.tsx new file mode 100644 index 0000000000..0c74f90a1b --- /dev/null +++ b/web/app/components/plugins/plugin-item/index.tsx @@ -0,0 +1,187 @@ +'use client' +import type { FC } from 'react' +import React, { useMemo } from 'react' +import { + RiArrowRightUpLine, + RiBugLine, + RiHardDrive3Line, + RiLoginCircleLine, + RiVerifiedBadgeLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { usePluginPageContext } from '../plugin-page/context' +import { Github } from '../../base/icons/src/public/common' +import Badge from '../../base/badge' +import { type PluginDetail, PluginSource, PluginType } from '../types' +import CornerMark from '../card/base/corner-mark' +import Description from '../card/base/description' +import OrgInfo from '../card/base/org-info' +import Title from '../card/base/title' +import Action from './action' +import cn from '@/utils/classnames' +import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config' +import { useInvalidateInstalledPluginList } from '@/service/use-plugins' +import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools' +import { useSingleCategories } from '../hooks' +import { useProviderContext } from '@/context/provider-context' +import { useRenderI18nObject } from '@/hooks/use-i18n' + +type Props = { + className?: string + plugin: PluginDetail +} + +const PluginItem: FC<Props> = ({ + className, + plugin, +}) => { + const { t } = useTranslation() + const { categoriesMap } = useSingleCategories() + const currentPluginID = usePluginPageContext(v => v.currentPluginID) + const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID) + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + const invalidateAllToolProviders = useInvalidateAllToolProviders() + const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools() + const { refreshModelProviders } = useProviderContext() + + const { + source, + tenant_id, + installation_id, + plugin_unique_identifier, + endpoints_active, + meta, + plugin_id, + } = plugin + const { category, author, name, label, description, icon, verified } = plugin.declaration + + const orgName = useMemo(() => { + return [PluginSource.github, PluginSource.marketplace].includes(source) ? author : '' + }, [source, author]) + + const handleDelete = () => { + invalidateInstalledPluginList() + if (PluginType.model.includes(category)) + refreshModelProviders() + if (PluginType.tool.includes(category)) { + invalidateAllToolProviders() + invalidateAllBuiltinTools() + } + } + const getValueFromI18nObject = useRenderI18nObject() + const title = getValueFromI18nObject(label) + const descriptionText = getValueFromI18nObject(description) + + return ( + <div + className={cn( + 'p-1 rounded-xl border-[1.5px] border-background-section-burn', + currentPluginID === plugin_id && 'border-components-option-card-option-selected-border', + source === PluginSource.debugging + ? 'bg-[repeating-linear-gradient(-45deg,rgba(16,24,40,0.04),rgba(16,24,40,0.04)_5px,rgba(0,0,0,0.02)_5px,rgba(0,0,0,0.02)_10px)]' + : 'bg-background-section-burn', + )} + onClick={() => { + setCurrentPluginID(plugin.plugin_id) + }} + > + <div className={cn('relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover-bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className)}> + <CornerMark text={categoriesMap[category].label} /> + {/* Header */} + <div className="flex"> + <div className='flex items-center justify-center w-10 h-10 overflow-hidden border-components-panel-border-subtle border-[1px] rounded-xl'> + <img + className='w-full h-full' + src={`${API_PREFIX}/workspaces/current/plugin/icon?tenant_id=${tenant_id}&filename=${icon}`} + alt={`plugin-${plugin_unique_identifier}-logo`} + /> + </div> + <div className="ml-3 w-0 grow"> + <div className="flex items-center h-5"> + <Title title={title} /> + {verified && <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" />} + <Badge className='shrink-0 ml-1' text={source === PluginSource.github ? plugin.meta!.version : plugin.version} /> + </div> + <div className='flex items-center justify-between'> + <Description text={descriptionText} descriptionLineRows={1}></Description> + <div onClick={e => e.stopPropagation()}> + <Action + pluginUniqueIdentifier={plugin_unique_identifier} + installationId={installation_id} + author={author} + pluginName={name} + usedInApps={5} + isShowFetchNewVersion={source === PluginSource.github} + isShowInfo={source === PluginSource.github} + isShowDelete + meta={meta} + onDelete={handleDelete} + /> + </div> + </div> + </div> + </div> + </div> + <div className='mt-1.5 mb-1 flex justify-between items-center h-4 px-4'> + <div className='flex items-center'> + <OrgInfo + className="mt-0.5" + orgName={orgName} + packageName={name} + packageNameClassName='w-auto max-w-[150px]' + /> + {category === PluginType.extension && ( + <> + <div className='mx-2 text-text-quaternary system-xs-regular'>·</div> + <div className='flex text-text-tertiary system-xs-regular space-x-1'> + <RiLoginCircleLine className='w-4 h-4' /> + <span>{t('plugin.endpointsEnabled', { num: endpoints_active })}</span> + </div> + </> + )} + </div> + + <div className='flex items-center'> + {source === PluginSource.github + && <> + <a href={`https://github.com/${meta!.repo}`} target='_blank' className='flex items-center gap-1'> + <div className='text-text-tertiary system-2xs-medium-uppercase'>{t('plugin.from')}</div> + <div className='flex items-center space-x-0.5 text-text-secondary'> + <Github className='w-3 h-3' /> + <div className='system-2xs-semibold-uppercase'>GitHub</div> + <RiArrowRightUpLine className='w-3 h-3' /> + </div> + </a> + </> + } + {source === PluginSource.marketplace + && <> + <a href={`${MARKETPLACE_URL_PREFIX}/plugins/${author}/${name}`} target='_blank' className='flex items-center gap-0.5'> + <div className='text-text-tertiary system-2xs-medium-uppercase'>{t('plugin.from')} <span className='text-text-secondary'>marketplace</span></div> + <RiArrowRightUpLine className='w-3 h-3 text-text-tertiary' /> + </a> + </> + } + {source === PluginSource.local + && <> + <div className='flex items-center gap-1'> + <RiHardDrive3Line className='text-text-tertiary w-3 h-3' /> + <div className='text-text-tertiary system-2xs-medium-uppercase'>Local Plugin</div> + </div> + </> + } + {source === PluginSource.debugging + && <> + <div className='flex items-center gap-1'> + <RiBugLine className='w-3 h-3 text-text-warning' /> + <div className='text-text-warning system-2xs-medium-uppercase'>Debugging Plugin</div> + </div> + </> + } + </div> + </div> + </div> + ) +} + +export default React.memo(PluginItem) diff --git a/web/app/components/plugins/plugin-mutation-model/index.tsx b/web/app/components/plugins/plugin-mutation-model/index.tsx new file mode 100644 index 0000000000..36ab670ab3 --- /dev/null +++ b/web/app/components/plugins/plugin-mutation-model/index.tsx @@ -0,0 +1,79 @@ +import type { FC, ReactNode } from 'react' +import React, { memo } from 'react' +import Card from '@/app/components/plugins/card' +import Modal from '@/app/components/base/modal' +import Button from '@/app/components/base/button' +import type { Plugin } from '../types' +import type { UseMutationResult } from '@tanstack/react-query' + +type Props = { + plugin: Plugin + onCancel: () => void + mutation: Pick<UseMutationResult, 'isSuccess' | 'isPending'> + mutate: () => void + confirmButtonText: ReactNode + cancelButtonText: ReactNode + modelTitle: ReactNode + description: ReactNode + cardTitleLeft: ReactNode + modalBottomLeft?: ReactNode +} + +const PluginMutationModal: FC<Props> = ({ + plugin, + onCancel, + mutation, + confirmButtonText, + cancelButtonText, + modelTitle, + description, + cardTitleLeft, + mutate, + modalBottomLeft, +}: Props) => { + return ( + <Modal + isShow={true} + onClose={onCancel} + className='min-w-[560px]' + closable + title={modelTitle} + > + <div className='mt-3 mb-2 text-text-secondary system-md-regular'> + {description} + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + installed={mutation.isSuccess} + payload={plugin} + className='w-full' + titleLeft={cardTitleLeft} + /> + </div> + <div className='flex pt-5 items-center gap-2 self-stretch'> + <div> + {modalBottomLeft} + </div> + <div className='ml-auto flex gap-2'> + {!mutation.isPending && ( + <Button onClick={onCancel}> + {cancelButtonText} + </Button> + )} + <Button + variant='primary' + loading={mutation.isPending} + onClick={mutate} + disabled={mutation.isPending} + > + {confirmButtonText} + </Button> + </div> + </div> + </Modal> + ) +} + +PluginMutationModal.displayName = 'PluginMutationModal' + +export default memo(PluginMutationModal) diff --git a/web/app/components/plugins/plugin-page/context.tsx b/web/app/components/plugins/plugin-page/context.tsx new file mode 100644 index 0000000000..6363bcae69 --- /dev/null +++ b/web/app/components/plugins/plugin-page/context.tsx @@ -0,0 +1,95 @@ +'use client' + +import type { ReactNode } from 'react' +import { + useMemo, + useRef, + useState, +} from 'react' +import { + createContext, + useContextSelector, +} from 'use-context-selector' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import type { FilterState } from './filter-management' +import { useTranslation } from 'react-i18next' +import { useTabSearchParams } from '@/hooks/use-tab-searchparams' + +export type PluginPageContextValue = { + containerRef: React.RefObject<HTMLDivElement> + currentPluginID: string | undefined + setCurrentPluginID: (pluginID?: string) => void + filters: FilterState + setFilters: (filter: FilterState) => void + activeTab: string + setActiveTab: (tab: string) => void + options: Array<{ value: string, text: string }> +} + +export const PluginPageContext = createContext<PluginPageContextValue>({ + containerRef: { current: null }, + currentPluginID: undefined, + setCurrentPluginID: () => { }, + filters: { + categories: [], + tags: [], + searchQuery: '', + }, + setFilters: () => { }, + activeTab: '', + setActiveTab: () => { }, + options: [], +}) + +type PluginPageContextProviderProps = { + children: ReactNode +} + +export function usePluginPageContext(selector: (value: PluginPageContextValue) => any) { + return useContextSelector(PluginPageContext, selector) +} + +export const PluginPageContextProvider = ({ + children, +}: PluginPageContextProviderProps) => { + const { t } = useTranslation() + const containerRef = useRef<HTMLDivElement>(null) + const [filters, setFilters] = useState<FilterState>({ + categories: [], + tags: [], + searchQuery: '', + }) + const [currentPluginID, setCurrentPluginID] = useState<string | undefined>() + + const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) + const options = useMemo(() => { + return [ + { value: 'plugins', text: t('common.menus.plugins') }, + ...( + enable_marketplace + ? [{ value: 'discover', text: t('common.menus.exploreMarketplace') }] + : [] + ), + ] + }, [t, enable_marketplace]) + const [activeTab, setActiveTab] = useTabSearchParams({ + defaultTab: options[0].value, + }) + + return ( + <PluginPageContext.Provider + value={{ + containerRef, + currentPluginID, + setCurrentPluginID, + filters, + setFilters, + activeTab, + setActiveTab, + options, + }} + > + {children} + </PluginPageContext.Provider> + ) +} diff --git a/web/app/components/plugins/plugin-page/debug-info.tsx b/web/app/components/plugins/plugin-page/debug-info.tsx new file mode 100644 index 0000000000..e4d249f3e2 --- /dev/null +++ b/web/app/components/plugins/plugin-page/debug-info.tsx @@ -0,0 +1,63 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { + RiArrowRightUpLine, + RiBugLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import KeyValueItem from '../base/key-value-item' +import Tooltip from '@/app/components/base/tooltip' +import Button from '@/app/components/base/button' +import { useDebugKey } from '@/service/use-plugins' + +const i18nPrefix = 'plugin.debugInfo' + +const DebugInfo: FC = () => { + const { t } = useTranslation() + const { data: info, isLoading } = useDebugKey() + + // info.key likes 4580bdb7-b878-471c-a8a4-bfd760263a53 mask the middle part using *. + const maskedKey = info?.key?.replace(/(.{8})(.*)(.{8})/, '$1********$3') + + if (isLoading) return null + + return ( + <Tooltip + triggerMethod='click' + disabled={!info} + popupContent={ + <> + <div className='flex items-center gap-1 self-stretch'> + <span className='flex flex-col justify-center items-start flex-grow flex-shrink-0 basis-0 text-text-secondary system-sm-semibold'>{t(`${i18nPrefix}.title`)}</span> + <a href='' target='_blank' className='flex items-center gap-0.5 text-text-accent-light-mode-only cursor-pointer'> + <span className='system-xs-medium'>{t(`${i18nPrefix}.viewDocs`)}</span> + <RiArrowRightUpLine className='w-3 h-3' /> + </a> + </div> + <div className='space-y-0.5'> + <KeyValueItem + label={'URL'} + value={`${info?.host}:${info?.port}`} + /> + <KeyValueItem + label={'Key'} + value={info?.key || ''} + maskedValue={maskedKey} + /> + </div> + </> + } + popupClassName='flex flex-col items-start w-[256px] px-4 py-3.5 gap-1 border border-components-panel-border + rounded-xl bg-components-tooltip-bg shadows-shadow-lg z-50' + asChild={false} + position='bottom' + > + <Button className='w-full h-full p-2 text-components-button-secondary-text'> + <RiBugLine className='w-4 h-4' /> + </Button> + </Tooltip> + ) +} + +export default React.memo(DebugInfo) diff --git a/web/app/components/plugins/plugin-page/empty/index.tsx b/web/app/components/plugins/plugin-page/empty/index.tsx new file mode 100644 index 0000000000..3263f6a0c3 --- /dev/null +++ b/web/app/components/plugins/plugin-page/empty/index.tsx @@ -0,0 +1,120 @@ +import React, { useMemo, useRef, useState } from 'react' +import { MagicBox } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' +import { FileZip } from '@/app/components/base/icons/src/vender/solid/files' +import { Github } from '@/app/components/base/icons/src/vender/solid/general' +import InstallFromGitHub from '@/app/components/plugins/install-plugin/install-from-github' +import InstallFromLocalPackage from '@/app/components/plugins/install-plugin/install-from-local-package' +import { usePluginPageContext } from '../context' +import { Group } from '@/app/components/base/icons/src/vender/other' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import Line from '../../marketplace/empty/line' +import { useInstalledPluginList } from '@/service/use-plugins' +import { useTranslation } from 'react-i18next' +import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' + +const Empty = () => { + const { t } = useTranslation() + const fileInputRef = useRef<HTMLInputElement>(null) + const [selectedAction, setSelectedAction] = useState<string | null>(null) + const [selectedFile, setSelectedFile] = useState<File | null>(null) + const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) + const setActiveTab = usePluginPageContext(v => v.setActiveTab) + + const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const file = event.target.files?.[0] + if (file) { + setSelectedFile(file) + setSelectedAction('local') + } + } + const filters = usePluginPageContext(v => v.filters) + const { data: pluginList } = useInstalledPluginList() + + const text = useMemo(() => { + if (pluginList?.plugins.length === 0) + return t('plugin.list.noInstalled') + if (filters.categories.length > 0 || filters.tags.length > 0 || filters.searchQuery) + return t('plugin.list.notFound') + }, [pluginList?.plugins.length, t, filters.categories.length, filters.tags.length, filters.searchQuery]) + + return ( + <div className='grow w-full relative z-0'> + {/* skeleton */} + <div className='h-full w-full px-12 absolute top-0 grid grid-cols-2 gap-2 overflow-hidden z-10'> + {Array.from({ length: 20 }).fill(0).map((_, i) => ( + <div key={i} className='h-[100px] bg-components-card-bg rounded-xl' /> + ))} + </div> + {/* mask */} + <div className='h-full w-full absolute z-20 bg-gradient-to-b from-background-gradient-mask-transparent to-white' /> + <div className='flex items-center justify-center h-full relative z-30'> + <div className='flex flex-col items-center gap-y-3'> + <div className='relative -z-10 flex items-center justify-center w-[52px] h-[52px] rounded-xl + bg-components-card-bg border-[1px] border-dashed border-divider-deep shadow-xl shadow-shadow-shadow-5'> + <Group className='text-text-tertiary w-5 h-5' /> + <Line className='absolute -right-[1px] top-1/2 -translate-y-1/2' /> + <Line className='absolute -left-[1px] top-1/2 -translate-y-1/2' /> + <Line className='absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-90' /> + <Line className='absolute top-full left-1/2 -translate-x-1/2 -translate-y-1/2 rotate-90' /> + </div> + <div className='text-text-tertiary text-sm font-normal'> + {text} + </div> + <div className='flex flex-col w-[240px]'> + <input + type='file' + ref={fileInputRef} + style={{ display: 'none' }} + onChange={handleFileChange} + accept={SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS} + /> + <div className='w-full flex flex-col gap-y-1'> + {[ + ...( + (enable_marketplace || true) + ? [{ icon: MagicBox, text: t('plugin.list.source.marketplace'), action: 'marketplace' }] + : [] + ), + { icon: Github, text: t('plugin.list.source.github'), action: 'github' }, + { icon: FileZip, text: t('plugin.list.source.local'), action: 'local' }, + ].map(({ icon: Icon, text, action }) => ( + <div + key={action} + className='flex items-center px-3 py-2 gap-x-1 rounded-lg bg-components-button-secondary-bg + hover:bg-state-base-hover cursor-pointer border-[0.5px] shadow-shadow-shadow-3 shadow-xs' + onClick={() => { + if (action === 'local') + fileInputRef.current?.click() + else if (action === 'marketplace') + setActiveTab('discover') + else + setSelectedAction(action) + }} + > + <Icon className="w-4 h-4 text-text-tertiary" /> + <span className='text-text-secondary system-md-regular'>{text}</span> + </div> + ))} + </div> + </div> + </div> + {selectedAction === 'github' && <InstallFromGitHub + onSuccess={() => { }} + onClose={() => setSelectedAction(null)} + />} + {selectedAction === 'local' && selectedFile + && (<InstallFromLocalPackage + file={selectedFile} + onClose={() => setSelectedAction(null)} + onSuccess={() => { }} + /> + ) + } + </div> + </div> + ) +} + +Empty.displayName = 'Empty' + +export default React.memo(Empty) diff --git a/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx b/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx new file mode 100644 index 0000000000..7c3417eec3 --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx @@ -0,0 +1,127 @@ +'use client' + +import { useState } from 'react' +import { + RiArrowDownSLine, + RiCloseCircleFill, +} from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Checkbox from '@/app/components/base/checkbox' +import cn from '@/utils/classnames' +import Input from '@/app/components/base/input' +import { useCategories } from '../../hooks' +import { useTranslation } from 'react-i18next' + +type CategoriesFilterProps = { + value: string[] + onChange: (categories: string[]) => void +} +const CategoriesFilter = ({ + value, + onChange, +}: CategoriesFilterProps) => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const [searchText, setSearchText] = useState('') + const { categories: options, categoriesMap } = useCategories() + const filteredOptions = options.filter(option => option.name.toLowerCase().includes(searchText.toLowerCase())) + const handleCheck = (id: string) => { + if (value.includes(id)) + onChange(value.filter(tag => tag !== id)) + else + onChange([...value, id]) + } + const selectedTagsLength = value.length + + return ( + <PortalToFollowElem + placement='bottom-start' + offset={{ + mainAxis: 4, + }} + open={open} + onOpenChange={setOpen} + > + <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}> + <div className={cn( + 'flex items-center px-2 py-1 h-8 text-text-tertiary rounded-lg bg-components-input-bg-normal hover:bg-state-base-hover-alt cursor-pointer', + selectedTagsLength && 'text-text-secondary', + open && 'bg-state-base-hover', + )}> + <div className={cn( + 'flex items-center p-1 system-sm-medium', + )}> + { + !selectedTagsLength && t('plugin.allCategories') + } + { + !!selectedTagsLength && value.map(val => categoriesMap[val].label).slice(0, 2).join(',') + } + { + selectedTagsLength > 2 && ( + <div className='ml-1 system-xs-medium text-text-tertiary'> + +{selectedTagsLength - 2} + </div> + ) + } + </div> + { + !!selectedTagsLength && ( + <RiCloseCircleFill + className='w-4 h-4 text-text-quaternary cursor-pointer' + onClick={ + (e) => { + e.stopPropagation() + onChange([]) + } + } + /> + ) + } + { + !selectedTagsLength && ( + <RiArrowDownSLine className='w-4 h-4' /> + ) + } + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-10'> + <div className='w-[240px] border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-xl shadow-lg'> + <div className='p-2 pb-1'> + <Input + showLeftIcon + value={searchText} + onChange={e => setSearchText(e.target.value)} + placeholder={t('plugin.searchCategories')} + /> + </div> + <div className='p-1 max-h-[448px] overflow-y-auto'> + { + filteredOptions.map(option => ( + <div + key={option.name} + className='flex items-center px-2 py-1.5 h-7 rounded-lg cursor-pointer hover:bg-state-base-hover' + onClick={() => handleCheck(option.name)} + > + <Checkbox + className='mr-1' + checked={value.includes(option.name)} + /> + <div className='px-1 system-sm-medium text-text-secondary'> + {option.label} + </div> + </div> + )) + } + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default CategoriesFilter diff --git a/web/app/components/plugins/plugin-page/filter-management/constant.ts b/web/app/components/plugins/plugin-page/filter-management/constant.ts new file mode 100644 index 0000000000..80f786230c --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/constant.ts @@ -0,0 +1,11 @@ +export type Tag = { + id: string + name: string + type: string + binding_count: number +} + +export type Category = { + name: 'model' | 'tool' | 'extension' | 'bundle' + binding_count: number +} diff --git a/web/app/components/plugins/plugin-page/filter-management/index.tsx b/web/app/components/plugins/plugin-page/filter-management/index.tsx new file mode 100644 index 0000000000..c7a0bc7cd9 --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/index.tsx @@ -0,0 +1,45 @@ +import React, { useState } from 'react' +import CategoriesFilter from './category-filter' +import TagFilter from './tag-filter' +import SearchBox from './search-box' +import { usePluginPageContext } from '../context' + +export type FilterState = { + categories: string[] + tags: string[] + searchQuery: string +} + +type FilterManagementProps = { + onFilterChange: (filters: FilterState) => void +} + +const FilterManagement: React.FC<FilterManagementProps> = ({ onFilterChange }) => { + const initFilters = usePluginPageContext(v => v.filters) as FilterState + const [filters, setFilters] = useState<FilterState>(initFilters) + + const updateFilters = (newFilters: Partial<FilterState>) => { + const updatedFilters = { ...filters, ...newFilters } + setFilters(updatedFilters) + onFilterChange(updatedFilters) + } + + return ( + <div className='flex items-center gap-2 self-stretch'> + <CategoriesFilter + value={filters.categories} + onChange={categories => updateFilters({ categories })} + /> + <TagFilter + value={filters.tags} + onChange={tags => updateFilters({ tags })} + /> + <SearchBox + searchQuery={filters.searchQuery} + onChange={searchQuery => updateFilters({ searchQuery })} + /> + </div> + ) +} + +export default FilterManagement diff --git a/web/app/components/plugins/plugin-page/filter-management/search-box.tsx b/web/app/components/plugins/plugin-page/filter-management/search-box.tsx new file mode 100644 index 0000000000..ad3547e89b --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/search-box.tsx @@ -0,0 +1,30 @@ +'use client' + +import Input from '@/app/components/base/input' +import { useTranslation } from 'react-i18next' +type SearchBoxProps = { + searchQuery: string + onChange: (query: string) => void +} + +const SearchBox: React.FC<SearchBoxProps> = ({ + searchQuery, + onChange, +}) => { + const { t } = useTranslation() + + return ( + <Input + wrapperClassName='flex w-[200px] items-center rounded-lg' + className='bg-components-input-bg-normal' + showLeftIcon + value={searchQuery} + placeholder={t('plugin.search')} + onChange={(e) => { + onChange(e.target.value) + }} + /> + ) +} + +export default SearchBox diff --git a/web/app/components/plugins/plugin-page/filter-management/store.ts b/web/app/components/plugins/plugin-page/filter-management/store.ts new file mode 100644 index 0000000000..4b55bf2681 --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/store.ts @@ -0,0 +1,27 @@ +import { create } from 'zustand' +import type { Category, Tag } from './constant' + +type State = { + tagList: Tag[] + categoryList: Category[] + showTagManagementModal: boolean + showCategoryManagementModal: boolean +} + +type Action = { + setTagList: (tagList?: Tag[]) => void + setCategoryList: (categoryList?: Category[]) => void + setShowTagManagementModal: (showTagManagementModal: boolean) => void + setShowCategoryManagementModal: (showCategoryManagementModal: boolean) => void +} + +export const useStore = create<State & Action>(set => ({ + tagList: [], + categoryList: [], + setTagList: tagList => set(() => ({ tagList })), + setCategoryList: categoryList => set(() => ({ categoryList })), + showTagManagementModal: false, + showCategoryManagementModal: false, + setShowTagManagementModal: showTagManagementModal => set(() => ({ showTagManagementModal })), + setShowCategoryManagementModal: showCategoryManagementModal => set(() => ({ showCategoryManagementModal })), +})) diff --git a/web/app/components/plugins/plugin-page/filter-management/tag-filter.tsx b/web/app/components/plugins/plugin-page/filter-management/tag-filter.tsx new file mode 100644 index 0000000000..dd1781d9f4 --- /dev/null +++ b/web/app/components/plugins/plugin-page/filter-management/tag-filter.tsx @@ -0,0 +1,122 @@ +'use client' + +import { useState } from 'react' +import { + RiArrowDownSLine, + RiCloseCircleFill, +} from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Checkbox from '@/app/components/base/checkbox' +import cn from '@/utils/classnames' +import Input from '@/app/components/base/input' +import { useTags } from '../../hooks' +import { useTranslation } from 'react-i18next' + +type TagsFilterProps = { + value: string[] + onChange: (tags: string[]) => void +} +const TagsFilter = ({ + value, + onChange, +}: TagsFilterProps) => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const [searchText, setSearchText] = useState('') + const { tags: options, tagsMap } = useTags() + const filteredOptions = options.filter(option => option.name.toLowerCase().includes(searchText.toLowerCase())) + const handleCheck = (id: string) => { + if (value.includes(id)) + onChange(value.filter(tag => tag !== id)) + else + onChange([...value, id]) + } + const selectedTagsLength = value.length + + return ( + <PortalToFollowElem + placement='bottom-start' + offset={{ + mainAxis: 4, + }} + open={open} + onOpenChange={setOpen} + > + <PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}> + <div className={cn( + 'flex items-center px-2 py-1 h-8 text-text-tertiary rounded-lg bg-components-input-bg-normal hover:bg-state-base-hover-alt cursor-pointer', + selectedTagsLength && 'text-text-secondary', + open && 'bg-state-base-hover', + )}> + <div className={cn( + 'flex items-center p-1 system-sm-medium', + )}> + { + !selectedTagsLength && t('pluginTags.allTags') + } + { + !!selectedTagsLength && value.map(val => tagsMap[val].label).slice(0, 2).join(',') + } + { + selectedTagsLength > 2 && ( + <div className='ml-1 system-xs-medium text-text-tertiary'> + +{selectedTagsLength - 2} + </div> + ) + } + </div> + { + !!selectedTagsLength && ( + <RiCloseCircleFill + className='w-4 h-4 text-text-quaternary cursor-pointer' + onClick={() => onChange([])} + /> + ) + } + { + !selectedTagsLength && ( + <RiArrowDownSLine className='w-4 h-4' /> + ) + } + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-10'> + <div className='w-[240px] border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-xl shadow-lg'> + <div className='p-2 pb-1'> + <Input + showLeftIcon + value={searchText} + onChange={e => setSearchText(e.target.value)} + placeholder={t('pluginTags.searchTags')} + /> + </div> + <div className='p-1 max-h-[448px] overflow-y-auto'> + { + filteredOptions.map(option => ( + <div + key={option.name} + className='flex items-center px-2 py-1.5 h-7 rounded-lg cursor-pointer hover:bg-state-base-hover' + onClick={() => handleCheck(option.name)} + > + <Checkbox + className='mr-1' + checked={value.includes(option.name)} + /> + <div className='px-1 system-sm-medium text-text-secondary'> + {option.label} + </div> + </div> + )) + } + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default TagsFilter diff --git a/web/app/components/plugins/plugin-page/index.tsx b/web/app/components/plugins/plugin-page/index.tsx new file mode 100644 index 0000000000..7eea8fea0f --- /dev/null +++ b/web/app/components/plugins/plugin-page/index.tsx @@ -0,0 +1,276 @@ +'use client' + +import { useEffect, useMemo, useState } from 'react' +import { useTranslation } from 'react-i18next' +import Link from 'next/link' +import { + RiBookOpenLine, + RiDragDropLine, + RiEqualizer2Line, +} from '@remixicon/react' +import { useBoolean } from 'ahooks' +import InstallFromLocalPackage from '../install-plugin/install-from-local-package' +import { + PluginPageContextProvider, + usePluginPageContext, +} from './context' +import InstallPluginDropdown from './install-plugin-dropdown' +import { useUploader } from './use-uploader' +import usePermission from './use-permission' +import DebugInfo from './debug-info' +import PluginTasks from './plugin-tasks' +import Button from '@/app/components/base/button' +import TabSlider from '@/app/components/base/tab-slider' +import Tooltip from '@/app/components/base/tooltip' +import cn from '@/utils/classnames' +import PermissionSetModal from '@/app/components/plugins/permission-setting-modal/modal' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import InstallFromMarketplace from '../install-plugin/install-from-marketplace' +import { + useRouter, + useSearchParams, +} from 'next/navigation' +import type { Dependency } from '../types' +import type { PluginDeclaration, PluginManifestInMarket } from '../types' +import { sleep } from '@/utils' +import { fetchBundleInfoFromMarketPlace, fetchManifestFromMarketPlace } from '@/service/plugins' +import { marketplaceApiPrefix } from '@/config' +import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' + +const PACKAGE_IDS_KEY = 'package-ids' +const BUNDLE_INFO_KEY = 'bundle-info' + +export type PluginPageProps = { + plugins: React.ReactNode + marketplace: React.ReactNode +} +const PluginPage = ({ + plugins, + marketplace, +}: PluginPageProps) => { + const { t } = useTranslation() + const searchParams = useSearchParams() + const { replace } = useRouter() + + // just support install one package now + const packageId = useMemo(() => { + const idStrings = searchParams.get(PACKAGE_IDS_KEY) + try { + return idStrings ? JSON.parse(idStrings)[0] : '' + } + catch (e) { + return '' + } + }, [searchParams]) + + const [dependencies, setDependencies] = useState<Dependency[]>([]) + const bundleInfo = useMemo(() => { + const info = searchParams.get(BUNDLE_INFO_KEY) + try { + return info ? JSON.parse(info) : undefined + } + catch (e) { + return undefined + } + }, [searchParams]) + + const [isShowInstallFromMarketplace, { + setTrue: showInstallFromMarketplace, + setFalse: doHideInstallFromMarketplace, + }] = useBoolean(false) + + const hideInstallFromMarketplace = () => { + doHideInstallFromMarketplace() + const url = new URL(window.location.href) + url.searchParams.delete(PACKAGE_IDS_KEY) + url.searchParams.delete(BUNDLE_INFO_KEY) + replace(url.toString()) + } + const [manifest, setManifest] = useState<PluginDeclaration | PluginManifestInMarket | null>(null) + + useEffect(() => { + (async () => { + await sleep(100) + if (packageId) { + const { data } = await fetchManifestFromMarketPlace(encodeURIComponent(packageId)) + const { plugin, version } = data + setManifest({ + ...plugin, + version: version.version, + icon: `${marketplaceApiPrefix}/plugins/${plugin.org}/${plugin.name}/icon`, + }) + showInstallFromMarketplace() + return + } + if (bundleInfo) { + const { data } = await fetchBundleInfoFromMarketPlace(bundleInfo) + setDependencies(data.version.dependencies) + showInstallFromMarketplace() + } + })() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [packageId, bundleInfo]) + + const { + canManagement, + canDebugger, + canSetPermissions, + permissions, + setPermissions, + } = usePermission() + const [showPluginSettingModal, { + setTrue: setShowPluginSettingModal, + setFalse: setHidePluginSettingModal, + }] = useBoolean() + const [currentFile, setCurrentFile] = useState<File | null>(null) + const containerRef = usePluginPageContext(v => v.containerRef) + const options = usePluginPageContext(v => v.options) + const activeTab = usePluginPageContext(v => v.activeTab) + const setActiveTab = usePluginPageContext(v => v.setActiveTab) + const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) + + const uploaderProps = useUploader({ + onFileChange: setCurrentFile, + containerRef, + enabled: activeTab === 'plugins', + }) + + const { dragging, fileUploader, fileChangeHandle, removeFile } = uploaderProps + + return ( + <div + id='marketplace-container' + ref={containerRef} + className={cn('grow relative flex flex-col overflow-y-auto border-t border-divider-subtle', activeTab === 'plugins' + ? 'rounded-t-xl bg-components-panel-bg' + : 'bg-background-body', + )} + > + <div + className={cn( + 'sticky top-0 flex min-h-[60px] px-12 pt-4 pb-2 items-center self-stretch gap-1 z-10 bg-components-panel-bg', activeTab === 'discover' && 'bg-background-body', + )} + > + <div className='flex justify-between items-center w-full'> + <div className='flex-1'> + <TabSlider + value={activeTab} + onChange={setActiveTab} + options={options} + /> + </div> + <div className='flex shrink-0 items-center gap-1'> + { + activeTab === 'discover' && ( + <> + <Link + href='https://docs.dify.ai/plugins/publish-plugins/publish-to-dify-marketplace' + target='_blank' + > + <Button + className='px-3' + variant='secondary-accent' + > + <RiBookOpenLine className='mr-1 w-4 h-4' /> + {t('plugin.submitPlugin')} + </Button> + </Link> + <div className='mx-2 w-[1px] h-3.5 bg-divider-regular'></div> + </> + ) + } + <PluginTasks /> + {canManagement && ( + <InstallPluginDropdown + onSwitchToMarketplaceTab={() => setActiveTab('discover')} + /> + )} + { + canDebugger && ( + <DebugInfo /> + ) + } + { + canSetPermissions && ( + <Tooltip + popupContent={t('plugin.privilege.title')} + > + <Button + className='w-full h-full p-2 text-components-button-secondary-text group' + onClick={setShowPluginSettingModal} + > + <RiEqualizer2Line className='w-4 h-4' /> + </Button> + </Tooltip> + ) + } + </div> + </div> + </div> + {activeTab === 'plugins' && ( + <> + {plugins} + {dragging && ( + <div + className="absolute inset-0 m-0.5 p-2 rounded-2xl bg-[rgba(21,90,239,0.14)] border-2 + border-dashed border-components-dropzone-border-accent"> + </div> + )} + <div className={`flex py-4 justify-center items-center gap-2 ${dragging ? 'text-text-accent' : 'text-text-quaternary'}`}> + <RiDragDropLine className="w-4 h-4" /> + <span className="system-xs-regular">{t('plugin.installModal.dropPluginToInstall')}</span> + </div> + {currentFile && ( + <InstallFromLocalPackage + file={currentFile} + onClose={removeFile ?? (() => { })} + onSuccess={() => { }} + /> + )} + <input + ref={fileUploader} + className="hidden" + type="file" + id="fileUploader" + accept={SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS} + onChange={fileChangeHandle ?? (() => { })} + /> + </> + )} + { + activeTab === 'discover' && enable_marketplace && marketplace + } + + {showPluginSettingModal && ( + <PermissionSetModal + payload={permissions!} + onHide={setHidePluginSettingModal} + onSave={setPermissions} + /> + )} + + { + isShowInstallFromMarketplace && ( + <InstallFromMarketplace + manifest={manifest! as PluginManifestInMarket} + uniqueIdentifier={packageId} + isBundle={!!bundleInfo} + dependencies={dependencies} + onClose={hideInstallFromMarketplace} + onSuccess={hideInstallFromMarketplace} + /> + ) + } + </div> + ) +} + +const PluginPageWithContext = (props: PluginPageProps) => { + return ( + <PluginPageContextProvider> + <PluginPage {...props} /> + </PluginPageContextProvider> + ) +} + +export default PluginPageWithContext diff --git a/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx b/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx new file mode 100644 index 0000000000..4c2d543e14 --- /dev/null +++ b/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx @@ -0,0 +1,139 @@ +'use client' + +import { useRef, useState } from 'react' +import { RiAddLine, RiArrowDownSLine } from '@remixicon/react' +import Button from '@/app/components/base/button' +import { MagicBox } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' +import { FileZip } from '@/app/components/base/icons/src/vender/solid/files' +import { Github } from '@/app/components/base/icons/src/vender/solid/general' +import InstallFromGitHub from '@/app/components/plugins/install-plugin/install-from-github' +import InstallFromLocalPackage from '@/app/components/plugins/install-plugin/install-from-local-package' +import cn from '@/utils/classnames' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import { useTranslation } from 'react-i18next' +import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config' + +type Props = { + onSwitchToMarketplaceTab: () => void +} +const InstallPluginDropdown = ({ + onSwitchToMarketplaceTab, +}: Props) => { + const { t } = useTranslation() + const fileInputRef = useRef<HTMLInputElement>(null) + const [isMenuOpen, setIsMenuOpen] = useState(false) + const [selectedAction, setSelectedAction] = useState<string | null>(null) + const [selectedFile, setSelectedFile] = useState<File | null>(null) + const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) + + const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const file = event.target.files?.[0] + if (file) { + setSelectedFile(file) + setSelectedAction('local') + setIsMenuOpen(false) + } + } + + // TODO TEST INSTALL : uninstall + // const [pluginLists, setPluginLists] = useState<any>([]) + // useEffect(() => { + // (async () => { + // const list: any = await get('workspaces/current/plugin/list') + // })() + // }) + + // const handleUninstall = async (id: string) => { + // const res = await post('workspaces/current/plugin/uninstall', { body: { plugin_installation_id: id } }) + // console.log(res) + // } + + return ( + <PortalToFollowElem + open={isMenuOpen} + onOpenChange={setIsMenuOpen} + placement='bottom-start' + offset={4} + > + <div className="relative"> + <PortalToFollowElemTrigger onClick={() => setIsMenuOpen(v => !v)}> + <Button + className={cn('w-full h-full p-2 text-components-button-secondary-text', isMenuOpen && 'bg-state-base-hover')} + > + <RiAddLine className='w-4 h-4' /> + <span className='pl-1'>{t('plugin.installPlugin')}</span> + <RiArrowDownSLine className='w-4 h-4 ml-1' /> + </Button> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[1002]'> + <div className='flex flex-col p-1 pb-2 items-start w-[200px] bg-components-panel-bg-blur border border-components-panel-border rounded-xl shadows-shadow-lg'> + <span className='flex pt-1 pb-0.5 pl-2 pr-3 items-start self-stretch text-text-tertiary system-xs-medium-uppercase'> + {t('plugin.installFrom')} + </span> + <input + type='file' + ref={fileInputRef} + style={{ display: 'none' }} + onChange={handleFileChange} + accept={SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS} + /> + <div className='w-full'> + {[ + ...( + (enable_marketplace || true) + ? [{ icon: MagicBox, text: t('plugin.source.marketplace'), action: 'marketplace' }] + : [] + ), + { icon: Github, text: t('plugin.source.github'), action: 'github' }, + { icon: FileZip, text: t('plugin.source.local'), action: 'local' }, + ].map(({ icon: Icon, text, action }) => ( + <div + key={action} + className='flex items-center w-full px-2 py-1.5 gap-1 rounded-lg hover:bg-state-base-hover !cursor-pointer' + onClick={() => { + if (action === 'local') { + fileInputRef.current?.click() + } + else if (action === 'marketplace') { + onSwitchToMarketplaceTab() + setIsMenuOpen(false) + } + else { + setSelectedAction(action) + setIsMenuOpen(false) + } + }} + > + <Icon className="w-4 h-4 text-text-tertiary" /> + <span className='px-1 text-text-secondary system-md-regular'>{text}</span> + </div> + ))} + </div> + </div> + </PortalToFollowElemContent> + </div> + {selectedAction === 'github' && <InstallFromGitHub + onSuccess={() => { }} + onClose={() => setSelectedAction(null)} + />} + {selectedAction === 'local' && selectedFile + && (<InstallFromLocalPackage + file={selectedFile} + onClose={() => setSelectedAction(null)} + onSuccess={() => { }} + /> + ) + } + {/* {pluginLists.map((item: any) => ( + <div key={item.id} onClick={() => handleUninstall(item.id)}>{item.name} 卸载</div> + ))} */} + </PortalToFollowElem> + ) +} + +export default InstallPluginDropdown diff --git a/web/app/components/plugins/plugin-page/list/index.tsx b/web/app/components/plugins/plugin-page/list/index.tsx new file mode 100644 index 0000000000..9e9cf00c9f --- /dev/null +++ b/web/app/components/plugins/plugin-page/list/index.tsx @@ -0,0 +1,23 @@ +import type { FC } from 'react' +import PluginItem from '../../plugin-item' +import type { PluginDetail } from '../../types' + +type IPluginListProps = { + pluginList: PluginDetail[] +} + +const PluginList: FC<IPluginListProps> = ({ pluginList }) => { + return ( + <div className='pb-3'> + <div className='grid grid-cols-2 gap-3'> + {pluginList.map(plugin => ( + <PluginItem + key={plugin.plugin_id} + plugin={plugin} + /> + ))} + </div> + </div> + ) +} +export default PluginList diff --git a/web/app/components/plugins/plugin-page/plugin-info.tsx b/web/app/components/plugins/plugin-page/plugin-info.tsx new file mode 100644 index 0000000000..abd297905a --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugin-info.tsx @@ -0,0 +1,41 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useTranslation } from 'react-i18next' +import KeyValueItem from '../base/key-value-item' +import Modal from '../../base/modal' +import { convertRepoToUrl } from '../install-plugin/utils' + +const i18nPrefix = 'plugin.pluginInfoModal' +type Props = { + repository?: string + release?: string + packageName?: string + onHide: () => void +} + +const PlugInfo: FC<Props> = ({ + repository, + release, + packageName, + onHide, +}) => { + const { t } = useTranslation() + const labelWidthClassName = 'w-[96px]' + return ( + <Modal + title={t(`${i18nPrefix}.title`)} + className='w-[480px]' + isShow + onClose={onHide} + closable + > + <div className='mt-5 space-y-3'> + {repository && <KeyValueItem label={t(`${i18nPrefix}.repository`)} labelWidthClassName={labelWidthClassName} value={`${convertRepoToUrl(repository)}`} valueMaxWidthClassName='max-w-[190px]' />} + {release && <KeyValueItem label={t(`${i18nPrefix}.release`)} labelWidthClassName={labelWidthClassName} value={release} />} + {packageName && <KeyValueItem label={t(`${i18nPrefix}.packageName`)} labelWidthClassName={labelWidthClassName} value={packageName} />} + </div> + </Modal> + ) +} +export default React.memo(PlugInfo) diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts new file mode 100644 index 0000000000..f32a812c13 --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts @@ -0,0 +1,100 @@ +import { + useCallback, + useEffect, + useRef, + useState, +} from 'react' +import { TaskStatus } from '@/app/components/plugins/types' +import type { PluginStatus } from '@/app/components/plugins/types' +import { + useMutationClearAllTaskPlugin, + useMutationClearTaskPlugin, + usePluginTaskList, +} from '@/service/use-plugins' + +export const usePluginTaskStatus = () => { + const { + pluginTasks, + handleRefetch, + } = usePluginTaskList() + const { mutateAsync } = useMutationClearTaskPlugin() + const { mutateAsync: mutateAsyncClearAll } = useMutationClearAllTaskPlugin() + const allPlugins = pluginTasks.filter(task => task.status !== TaskStatus.success).map(task => task.plugins.map((plugin) => { + return { + ...plugin, + taskId: task.id, + } + })).flat() + const errorPlugins: PluginStatus[] = [] + const successPlugins: PluginStatus[] = [] + const runningPlugins: PluginStatus[] = [] + + allPlugins.forEach((plugin) => { + if (plugin.status === TaskStatus.running) + runningPlugins.push(plugin) + if (plugin.status === TaskStatus.failed) + errorPlugins.push(plugin) + if (plugin.status === TaskStatus.success) + successPlugins.push(plugin) + }) + + const handleClearErrorPlugin = useCallback(async (taskId: string, pluginId: string) => { + await mutateAsync({ + taskId, + pluginId, + }) + handleRefetch() + }, [mutateAsync, handleRefetch]) + const handleClearAllErrorPlugin = useCallback(async () => { + await mutateAsyncClearAll() + handleRefetch() + }, [mutateAsyncClearAll, handleRefetch]) + const totalPluginsLength = allPlugins.length + const runningPluginsLength = runningPlugins.length + const errorPluginsLength = errorPlugins.length + const successPluginsLength = successPlugins.length + + const isInstalling = runningPluginsLength > 0 && errorPluginsLength === 0 && successPluginsLength === 0 + const isInstallingWithSuccess = runningPluginsLength > 0 && successPluginsLength > 0 && errorPluginsLength === 0 + const isInstallingWithError = runningPluginsLength > 0 && errorPluginsLength > 0 + const isSuccess = successPluginsLength === totalPluginsLength && totalPluginsLength > 0 + const isFailed = runningPluginsLength === 0 && (errorPluginsLength + successPluginsLength) === totalPluginsLength && totalPluginsLength > 0 && errorPluginsLength > 0 + + const [opacity, setOpacity] = useState(1) + const timerRef = useRef<NodeJS.Timeout | null>(null) + + useEffect(() => { + if (isSuccess) { + if (timerRef.current) { + clearTimeout(timerRef.current) + timerRef.current = null + } + if (opacity > 0) { + timerRef.current = setTimeout(() => { + setOpacity(v => v - 0.1) + }, 200) + } + } + + if (!isSuccess) + setOpacity(1) + }, [isSuccess, opacity]) + + return { + errorPlugins, + successPlugins, + runningPlugins, + runningPluginsLength, + errorPluginsLength, + successPluginsLength, + totalPluginsLength, + isInstalling, + isInstallingWithSuccess, + isInstallingWithError, + isSuccess, + isFailed, + handleClearErrorPlugin, + handleClearAllErrorPlugin, + opacity, + } +} diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx new file mode 100644 index 0000000000..997877e3a4 --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx @@ -0,0 +1,194 @@ +import { + useMemo, + useState, +} from 'react' +import { + RiCheckboxCircleFill, + RiErrorWarningFill, + RiInstallLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { usePluginTaskStatus } from './hooks' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Tooltip from '@/app/components/base/tooltip' +import Button from '@/app/components/base/button' +import ProgressCircle from '@/app/components/base/progress-bar/progress-circle' +import CardIcon from '@/app/components/plugins/card/base/card-icon' +import cn from '@/utils/classnames' +import { useGetLanguage } from '@/context/i18n' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import DownloadingIcon from '@/app/components/header/plugins-nav/downloading-icon' + +const PluginTasks = () => { + const { t } = useTranslation() + const language = useGetLanguage() + const [open, setOpen] = useState(false) + const { + errorPlugins, + runningPluginsLength, + successPluginsLength, + errorPluginsLength, + totalPluginsLength, + isInstalling, + isInstallingWithSuccess, + isInstallingWithError, + isSuccess, + isFailed, + handleClearErrorPlugin, + handleClearAllErrorPlugin, + opacity, + } = usePluginTaskStatus() + const { getIconUrl } = useGetIcon() + + const tip = useMemo(() => { + if (isInstalling) + return t('plugin.task.installing', { installingLength: runningPluginsLength }) + + if (isInstallingWithSuccess) + return t('plugin.task.installingWithSuccess', { installingLength: runningPluginsLength, successLength: successPluginsLength }) + + if (isInstallingWithError) + return t('plugin.task.installingWithError', { installingLength: runningPluginsLength, successLength: successPluginsLength, errorLength: errorPluginsLength }) + + if (isFailed) + return t('plugin.task.installError', { errorLength: errorPluginsLength }) + }, [isInstalling, isInstallingWithSuccess, isInstallingWithError, isFailed, errorPluginsLength, runningPluginsLength, successPluginsLength, t]) + + if (!totalPluginsLength) + return null + + return ( + <div + className='flex items-center' + style={{ opacity }} + > + <PortalToFollowElem + open={open} + onOpenChange={setOpen} + placement='bottom-start' + offset={{ + mainAxis: 4, + crossAxis: 79, + }} + > + <PortalToFollowElemTrigger + onClick={() => { + if (isFailed) + setOpen(v => !v) + }} + > + <Tooltip popupContent={tip}> + <div + className={cn( + 'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover', + (isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt cursor-pointer', + )} + id="plugin-task-trigger" + > + { + (isInstalling || isInstallingWithError) && ( + <DownloadingIcon /> + ) + } + { + !(isInstalling || isInstallingWithError) && ( + <RiInstallLine + className={cn( + 'w-4 h-4 text-components-button-secondary-text', + (isInstallingWithError || isFailed) && 'text-components-button-destructive-secondary-text', + )} + /> + ) + } + <div className='absolute -right-1 -top-1'> + { + (isInstalling || isInstallingWithSuccess) && ( + <ProgressCircle + percentage={successPluginsLength / totalPluginsLength * 100} + circleFillColor='fill-components-progress-brand-bg' + /> + ) + } + { + isInstallingWithError && ( + <ProgressCircle + percentage={runningPluginsLength / totalPluginsLength * 100} + circleFillColor='fill-components-progress-brand-bg' + sectorFillColor='fill-components-progress-error-border' + circleStrokeColor='stroke-components-progress-error-border' + /> + ) + } + { + isSuccess && ( + <RiCheckboxCircleFill className='w-3.5 h-3.5 text-text-success' /> + ) + } + { + isFailed && ( + <RiErrorWarningFill className='w-3.5 h-3.5 text-text-destructive' /> + ) + } + </div> + </div> + </Tooltip> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[11]'> + <div className='p-1 pb-2 w-[320px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'> + <div className='sticky top-0 flex items-center justify-between px-2 pt-1 h-7 system-sm-semibold-uppercase'> + {t('plugin.task.installedError', { errorLength: errorPluginsLength })} + <Button + className='shrink-0' + size='small' + variant='ghost' + onClick={() => handleClearAllErrorPlugin()} + > + {t('plugin.task.clearAll')} + </Button> + </div> + <div className='max-h-[400px] overflow-y-auto'> + { + errorPlugins.map(errorPlugin => ( + <div + key={errorPlugin.plugin_unique_identifier} + className='flex p-2 rounded-lg hover:bg-state-base-hover' + > + <div className='relative flex items-center justify-center mr-2 w-6 h-6 rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'> + <RiErrorWarningFill className='absolute -right-0.5 -bottom-0.5 z-10 w-3 h-3 text-text-destructive' /> + <CardIcon + size='tiny' + src={getIconUrl(errorPlugin.icon)} + /> + </div> + <div className='grow'> + <div className='system-md-regular text-text-secondary truncate'> + {errorPlugin.labels[language]} + </div> + <div className='system-xs-regular text-text-destructive break-all'> + {errorPlugin.message} + </div> + </div> + <Button + className='shrink-0' + size='small' + variant='ghost' + onClick={() => handleClearErrorPlugin(errorPlugin.taskId, errorPlugin.plugin_unique_identifier)} + > + {t('common.operation.clear')} + </Button> + </div> + )) + } + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + </div> + ) +} + +export default PluginTasks diff --git a/web/app/components/plugins/plugin-page/plugins-panel.tsx b/web/app/components/plugins/plugin-page/plugins-panel.tsx new file mode 100644 index 0000000000..f1a5fba1b9 --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugins-panel.tsx @@ -0,0 +1,70 @@ +'use client' +import { useMemo } from 'react' +import type { FilterState } from './filter-management' +import FilterManagement from './filter-management' +import List from './list' +import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' +import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel' +import { usePluginPageContext } from './context' +import { useDebounceFn } from 'ahooks' +import Empty from './empty' +import Loading from '../../base/loading' + +const PluginsPanel = () => { + const filters = usePluginPageContext(v => v.filters) as FilterState + const setFilters = usePluginPageContext(v => v.setFilters) + const { data: pluginList, isLoading: isPluginListLoading } = useInstalledPluginList() + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + const currentPluginID = usePluginPageContext(v => v.currentPluginID) + const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID) + + const { run: handleFilterChange } = useDebounceFn((filters: FilterState) => { + setFilters(filters) + }, { wait: 500 }) + + const filteredList = useMemo(() => { + const { categories, searchQuery, tags } = filters + const filteredList = pluginList?.plugins.filter((plugin) => { + return ( + (categories.length === 0 || categories.includes(plugin.declaration.category)) + && (tags.length === 0 || tags.some(tag => plugin.declaration.tags.includes(tag))) + && (searchQuery === '' || plugin.plugin_id.toLowerCase().includes(searchQuery.toLowerCase())) + ) + }) + return filteredList + }, [pluginList, filters]) + + const currentPluginDetail = useMemo(() => { + const detail = pluginList?.plugins.find(plugin => plugin.plugin_id === currentPluginID) + return detail + }, [currentPluginID, pluginList?.plugins]) + + const handleHide = () => setCurrentPluginID(undefined) + + return ( + <> + <div className='flex flex-col pt-1 pb-3 px-12 justify-center items-start gap-3 self-stretch'> + <div className='h-px self-stretch bg-divider-subtle'></div> + <FilterManagement + onFilterChange={handleFilterChange} + /> + </div> + {isPluginListLoading ? <Loading type='app' /> : (filteredList?.length ?? 0) > 0 ? ( + <div className='flex px-12 items-start content-start gap-2 grow self-stretch flex-wrap'> + <div className='w-full'> + <List pluginList={filteredList || []} /> + </div> + </div> + ) : ( + <Empty /> + )} + <PluginDetailPanel + detail={currentPluginDetail} + onUpdate={() => invalidateInstalledPluginList()} + onHide={handleHide} + /> + </> + ) +} + +export default PluginsPanel diff --git a/web/app/components/plugins/plugin-page/use-permission.ts b/web/app/components/plugins/plugin-page/use-permission.ts new file mode 100644 index 0000000000..c4fc01f2c3 --- /dev/null +++ b/web/app/components/plugins/plugin-page/use-permission.ts @@ -0,0 +1,45 @@ +import { PermissionType } from '../types' +import { useAppContext } from '@/context/app-context' +import Toast from '../../base/toast' +import { useTranslation } from 'react-i18next' +import { useInvalidatePermissions, useMutationPermissions, usePermissions } from '@/service/use-plugins' + +const hasPermission = (permission: PermissionType | undefined, isAdmin: boolean) => { + if (!permission) + return false + if (permission === PermissionType.noOne) + return false + + if (permission === PermissionType.everyone) + return true + + return isAdmin +} + +const usePermission = () => { + const { t } = useTranslation() + const { isCurrentWorkspaceManager, isCurrentWorkspaceOwner } = useAppContext() + const { data: permissions } = usePermissions() + const invalidatePermissions = useInvalidatePermissions() + const { mutate: updatePermission, isPending: isUpdatePending } = useMutationPermissions({ + onSuccess: () => { + invalidatePermissions() + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + }, + }) + const isAdmin = isCurrentWorkspaceManager || isCurrentWorkspaceOwner + + return { + canManagement: hasPermission(permissions?.install_permission, isAdmin), + canDebugger: hasPermission(permissions?.debug_permission, isAdmin), + canSetPermissions: isAdmin, + permissions, + setPermissions: updatePermission, + isUpdatePending, + } +} + +export default usePermission diff --git a/web/app/components/plugins/plugin-page/use-uploader.ts b/web/app/components/plugins/plugin-page/use-uploader.ts new file mode 100644 index 0000000000..fb3974c448 --- /dev/null +++ b/web/app/components/plugins/plugin-page/use-uploader.ts @@ -0,0 +1,86 @@ +import { useEffect, useRef, useState } from 'react' + +type UploaderHookProps = { + onFileChange: (file: File | null) => void + containerRef: React.RefObject<HTMLDivElement> + enabled?: boolean +} + +export const useUploader = ({ onFileChange, containerRef, enabled = true }: UploaderHookProps) => { + const [dragging, setDragging] = useState(false) + const fileUploader = useRef<HTMLInputElement>(null) + + const handleDragEnter = (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + if (e.dataTransfer?.types.includes('Files')) + setDragging(true) + } + + const handleDragOver = (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + } + + const handleDragLeave = (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + if (e.relatedTarget === null || !containerRef.current?.contains(e.relatedTarget as Node)) + setDragging(false) + } + + const handleDrop = (e: DragEvent) => { + e.preventDefault() + e.stopPropagation() + setDragging(false) + if (!e.dataTransfer) + return + const files = [...e.dataTransfer.files] + if (files.length > 0) + onFileChange(files[0]) + } + + const fileChangeHandle = enabled + ? (e: React.ChangeEvent<HTMLInputElement>) => { + const file = e.target.files?.[0] || null + onFileChange(file) + } + : null + + const removeFile = enabled + ? () => { + if (fileUploader.current) + fileUploader.current.value = '' + + onFileChange(null) + } + : null + + useEffect(() => { + if (!enabled) + return + + const current = containerRef.current + if (current) { + current.addEventListener('dragenter', handleDragEnter) + current.addEventListener('dragover', handleDragOver) + current.addEventListener('dragleave', handleDragLeave) + current.addEventListener('drop', handleDrop) + } + return () => { + if (current) { + current.removeEventListener('dragenter', handleDragEnter) + current.removeEventListener('dragover', handleDragOver) + current.removeEventListener('dragleave', handleDragLeave) + current.removeEventListener('drop', handleDrop) + } + } + }, [containerRef, enabled]) + + return { + dragging: enabled ? dragging : false, + fileUploader, + fileChangeHandle, + removeFile, + } +} diff --git a/web/app/components/plugins/provider-card.tsx b/web/app/components/plugins/provider-card.tsx new file mode 100644 index 0000000000..ed9ad9769f --- /dev/null +++ b/web/app/components/plugins/provider-card.tsx @@ -0,0 +1,97 @@ +'use client' +import React from 'react' +import type { FC } from 'react' +import { useTranslation } from 'react-i18next' +import { RiArrowRightUpLine } from '@remixicon/react' +import Badge from '../base/badge' +import type { Plugin } from './types' +import Description from './card/base/description' +import Icon from './card/base/card-icon' +import Title from './card/base/title' +import DownloadCount from './card/base/download-count' +import Button from '@/app/components/base/button' +import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace' +import cn from '@/utils/classnames' +import { useBoolean } from 'ahooks' +import { getPluginLinkInMarketplace } from '@/app/components/plugins/marketplace/utils' +import { useI18N } from '@/context/i18n' +import { useRenderI18nObject } from '@/hooks/use-i18n' + +type Props = { + className?: string + payload: Plugin +} + +const ProviderCard: FC<Props> = ({ + className, + payload, +}) => { + const getValueFromI18nObject = useRenderI18nObject() + const { t } = useTranslation() + const [isShowInstallFromMarketplace, { + setTrue: showInstallFromMarketplace, + setFalse: hideInstallFromMarketplace, + }] = useBoolean(false) + const { org, label } = payload + const { locale } = useI18N() + + return ( + <div className={cn('group relative p-4 pb-3 border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg hover:bg-components-panel-on-panel-item-bg rounded-xl shadow-xs', className)}> + {/* Header */} + <div className="flex"> + <Icon src={payload.icon} /> + <div className="ml-3 w-0 grow"> + <div className="flex items-center h-5"> + <Title title={getValueFromI18nObject(label)} /> + {/* <RiVerifiedBadgeLine className="shrink-0 ml-0.5 w-4 h-4 text-text-accent" /> */} + </div> + <div className='mb-1 flex justify-between items-center h-4'> + <div className='flex items-center'> + <div className='text-text-tertiary system-xs-regular'>{org}</div> + <div className='mx-2 text-text-quaternary system-xs-regular'>·</div> + <DownloadCount downloadCount={payload.install_count || 0} /> + </div> + </div> + </div> + </div> + <Description className='mt-3' text={getValueFromI18nObject(payload.brief)} descriptionLineRows={2}></Description> + <div className='mt-3 flex space-x-0.5'> + {payload.tags.map(tag => ( + <Badge key={tag.name} text={tag.name} /> + ))} + </div> + <div + className='hidden group-hover:flex items-center gap-2 absolute bottom-0 left-0 right-0 p-4 pt-8 rounded-xl bg-gradient-to-tr from-components-panel-on-panel-item-bg to-background-gradient-mask-transparent' + > + <Button + className='grow' + variant='primary' + onClick={showInstallFromMarketplace} + > + {t('plugin.detailPanel.operation.install')} + </Button> + <Button + className='grow' + variant='secondary' + > + <a href={`${getPluginLinkInMarketplace(payload)}?language=${locale}`} target='_blank' className='flex items-center gap-0.5'> + {t('plugin.detailPanel.operation.detail')} + <RiArrowRightUpLine className='w-4 h-4' /> + </a> + </Button> + </div> + { + isShowInstallFromMarketplace && ( + <InstallFromMarketplace + manifest={payload as any} + uniqueIdentifier={payload.latest_package_identifier} + onClose={hideInstallFromMarketplace} + onSuccess={() => hideInstallFromMarketplace()} + /> + ) + } + </div> + ) +} + +export default ProviderCard diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts new file mode 100644 index 0000000000..15da9991a6 --- /dev/null +++ b/web/app/components/plugins/types.ts @@ -0,0 +1,435 @@ +import type { CredentialFormSchemaBase } from '../header/account-setting/model-provider-page/declarations' +import type { ToolCredential } from '@/app/components/tools/types' +import type { Locale } from '@/i18n' + +export enum PluginType { + tool = 'tool', + model = 'model', + extension = 'extension', + agent = 'agent-strategy', +} + +export enum PluginSource { + marketplace = 'marketplace', + github = 'github', + local = 'package', + debugging = 'remote', +} + +export type PluginToolDeclaration = { + identity: { + author: string + name: string + description: Record<Locale, string> + icon: string + label: Record<Locale, string> + tags: string[] + } + credentials_schema: ToolCredential[] // TODO +} + +export type PluginEndpointDeclaration = { + settings: ToolCredential[] + endpoints: EndpointItem[] +} + +export type EndpointItem = { + path: string + method: string +} + +export type EndpointListItem = { + id: string + created_at: string + updated_at: string + settings: Record<string, any> + tenant_id: string + plugin_id: string + expired_at: string + declaration: PluginEndpointDeclaration + name: string + enabled: boolean + url: string + hook_id: string +} + +// Plugin manifest +export type PluginDeclaration = { + plugin_unique_identifier: string + version: string + author: string + icon: string + name: string + category: PluginType + label: Record<Locale, string> + description: Record<Locale, string> + created_at: string + resource: any // useless in frontend + plugins: any // useless in frontend + verified: boolean + endpoint: PluginEndpointDeclaration + tool: PluginToolDeclaration + model: any + tags: string[] + agent_strategy: any +} + +export type PluginManifestInMarket = { + plugin_unique_identifier: string + name: string + org: string + icon: string + label: Record<Locale, string> + category: PluginType + version: string // combine the other place to it + latest_version: string + brief: Record<Locale, string> + introduction: string + verified: boolean + install_count: number +} + +export type PluginDetail = { + id: string + created_at: string + updated_at: string + name: string + plugin_id: string + plugin_unique_identifier: string + declaration: PluginDeclaration + installation_id: string + tenant_id: string + endpoints_setups: number + endpoints_active: number + version: string + latest_version: string + latest_unique_identifier: string + source: PluginSource + meta?: MetaData +} + +export type PluginInfoFromMarketPlace = { + category: PluginType + latest_package_identifier: string + latest_version: string +} + +export type Plugin = { + type: 'plugin' | 'bundle' | 'model' | 'extension' | 'tool' | 'agent_strategy' + org: string + author?: string + name: string + plugin_id: string + version: string + latest_version: string + latest_package_identifier: string + icon: string + verified: boolean + label: Record<Locale, string> + brief: Record<Locale, string> + description: Record<Locale, string> + // Repo readme.md content + introduction: string + repository: string + category: PluginType + install_count: number + endpoint: { + settings: CredentialFormSchemaBase[] + } + tags: { name: string }[] +} + +export enum PermissionType { + everyone = 'everyone', + admin = 'admins', + noOne = 'noone', +} + +export type Permissions = { + install_permission: PermissionType + debug_permission: PermissionType +} + +export type UpdateFromMarketPlacePayload = { + originalPackageInfo: { + id: string + payload: PluginDeclaration + }, + targetPackageInfo: { + id: string + version: string + } +} + +export type UpdateFromGitHubPayload = { + originalPackageInfo: { + id: string + repo: string + version: string + package: string + releases: GitHubRepoReleaseResponse[] + } +} + +export type UpdatePluginPayload = { + type: PluginSource + marketPlace?: UpdateFromMarketPlacePayload + github?: UpdateFromGitHubPayload +} + +export type UpdatePluginModalType = UpdatePluginPayload & { + onCancel: () => void + onSave: () => void +} + +export enum InstallStepFromGitHub { + setUrl = 'url', + selectPackage = 'selecting', + readyToInstall = 'readyToInstall', + uploadFailed = 'uploadFailed', + installed = 'installed', + installFailed = 'failed', +} + +export type InstallState = { + step: InstallStepFromGitHub + repoUrl: string + selectedVersion: string + selectedPackage: string + releases: GitHubRepoReleaseResponse[] +} + +export type GitHubUrlInfo = { + isValid: boolean + owner?: string + repo?: string +} + +// endpoint +export type EndpointOperationResponse = { + result: 'success' | 'error' +} + +export type EndpointsResponse = { + endpoints: EndpointListItem[] + has_more: boolean + limit: number + total: number + page: number +} +export type UpdateEndpointRequest = { + endpoint_id: string + settings: Record<string, any> + name: string +} + +export enum InstallStep { + uploading = 'uploading', + uploadFailed = 'uploadFailed', + readyToInstall = 'readyToInstall', + installing = 'installing', + installed = 'installed', + installFailed = 'failed', +} + +export type GitHubAsset = { + id: number + name: string + browser_download_url: string +} + +export type GitHubRepoReleaseResponse = { + tag_name: string + assets: GitHubAsset[] +} + +export type InstallPackageResponse = { + plugin_unique_identifier: string + all_installed: boolean + task_id: string +} + +export type InstallStatusResponse = { + success: boolean, + isFromMarketPlace?: boolean +} + +export type updatePackageResponse = { + all_installed: boolean + task_id: string +} + +export type uploadGitHubResponse = { + unique_identifier: string + manifest: PluginDeclaration +} + +export type DebugInfo = { + key: string + host: string + port: number +} + +export enum TaskStatus { + running = 'running', + success = 'success', + failed = 'failed', +} + +export type PluginStatus = { + plugin_unique_identifier: string + plugin_id: string + status: TaskStatus + message: string + icon: string + labels: Record<Locale, string> + taskId: string +} + +export type PluginTask = { + id: string + created_at: string + updated_at: string + status: string + total_plugins: number + completed_plugins: number + plugins: PluginStatus[] +} + +export type TaskStatusResponse = { + task: PluginTask +} + +export type PluginTasksResponse = { + tasks: PluginTask[] +} + +export type MetaData = { + repo: string + version: string + package: string +} + +export type InstalledPluginListResponse = { + plugins: PluginDetail[] +} + +export type UninstallPluginResponse = { + success: boolean +} + +export type PluginsFromMarketplaceResponse = { + plugins: Plugin[] + total: number +} +export type PluginsFromMarketplaceByInfoResponse = { + list: { + plugin: Plugin + version: { + plugin_name: string + plugin_org: string + unique_identifier: string + } + }[] +} + +export type GitHubItemAndMarketPlaceDependency = { + type: 'github' | 'marketplace' | 'package' + value: { + repo?: string + version?: string // from app DSL + package?: string // from app DSL + release?: string // from local package. same to the version + packages?: string // from local package. same to the package + github_plugin_unique_identifier?: string + marketplace_plugin_unique_identifier?: string + plugin_unique_identifier?: string + } +} + +export type PackageDependency = { + type: 'github' | 'marketplace' | 'package' + value: { + unique_identifier: string + manifest: PluginDeclaration + } +} + +export type Dependency = GitHubItemAndMarketPlaceDependency | PackageDependency + +export type Version = { + plugin_org: string + plugin_name: string + version: string + file_name: string + checksum: string + created_at: string + unique_identifier: string +} + +export type VersionListResponse = { + versions: Version[] +} + +export type VersionInfo = { + installedVersion: string, + uniqueIdentifier: string +} + +export type VersionProps = { + hasInstalled: boolean + installedVersion?: string + toInstallVersion: string +} + +export type StrategyParamItem = { + name: string + label: Record<Locale, string> + human_description: Record<Locale, string> + llm_description: string + placeholder: Record<Locale, string> + type: string + scope: string + required: boolean + default: any + options: any[] + template: { + enabled: boolean + }, + auto_generate: { + type: string + } +} + +export type StrategyDetail = { + identity: { + author: string + name: string + icon: string + label: Record<Locale, string> + provider: string + }, + parameters: StrategyParamItem[] + description: Record<Locale, string> + output_schema: Record<string, any> +} + +export type StrategyDeclaration = { + identity: { + author: string + name: string + description: Record<Locale, string> + icon: string + label: Record<Locale, string> + tags: string[] + }, + plugin_id: string + strategies: StrategyDetail[] +} + +export type StrategyPluginDetail = { + provider: string + plugin_unique_identifier: string + plugin_id: string + declaration: StrategyDeclaration +} diff --git a/web/app/components/plugins/update-plugin/from-github.tsx b/web/app/components/plugins/update-plugin/from-github.tsx new file mode 100644 index 0000000000..9bc2f2ad3e --- /dev/null +++ b/web/app/components/plugins/update-plugin/from-github.tsx @@ -0,0 +1,26 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { UpdateFromGitHubPayload } from '../types' +import InstallFromGitHub from '../install-plugin/install-from-github' + +type Props = { + payload: UpdateFromGitHubPayload + onSave: () => void + onCancel: () => void +} + +const FromGitHub: FC<Props> = ({ + payload, + onSave, + onCancel, +}) => { + return ( + <InstallFromGitHub + updatePayload={payload} + onClose={onCancel} + onSuccess={onSave} + /> + ) +} +export default React.memo(FromGitHub) diff --git a/web/app/components/plugins/update-plugin/from-market-place.tsx b/web/app/components/plugins/update-plugin/from-market-place.tsx new file mode 100644 index 0000000000..6177ddce1a --- /dev/null +++ b/web/app/components/plugins/update-plugin/from-market-place.tsx @@ -0,0 +1,164 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { RiInformation2Line } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import Card from '@/app/components/plugins/card' +import Modal from '@/app/components/base/modal' +import Button from '@/app/components/base/button' +import Badge, { BadgeState } from '@/app/components/base/badge/index' +import { TaskStatus, type UpdateFromMarketPlacePayload } from '../types' +import { pluginManifestToCardPluginProps } from '@/app/components/plugins/install-plugin/utils' +import useGetIcon from '../install-plugin/base/use-get-icon' +import { updateFromMarketPlace } from '@/service/plugins' +import checkTaskStatus from '@/app/components/plugins/install-plugin/base/check-task-status' +import { usePluginTaskList } from '@/service/use-plugins' +import Toast from '../../base/toast' + +const i18nPrefix = 'plugin.upgrade' + +type Props = { + payload: UpdateFromMarketPlacePayload + onSave: () => void + onCancel: () => void +} + +enum UploadStep { + notStarted = 'notStarted', + upgrading = 'upgrading', + installed = 'installed', +} + +const UpdatePluginModal: FC<Props> = ({ + payload, + onSave, + onCancel, +}) => { + const { + originalPackageInfo, + targetPackageInfo, + } = payload + const { t } = useTranslation() + const { getIconUrl } = useGetIcon() + const [icon, setIcon] = useState<string>(originalPackageInfo.payload.icon) + useEffect(() => { + (async () => { + const icon = await getIconUrl(originalPackageInfo.payload.icon) + setIcon(icon) + })() + }, [originalPackageInfo, getIconUrl]) + const { + check, + stop, + } = checkTaskStatus() + const handleCancel = () => { + stop() + onCancel() + } + + const [uploadStep, setUploadStep] = useState<UploadStep>(UploadStep.notStarted) + const { handleRefetch } = usePluginTaskList() + + const configBtnText = useMemo(() => { + return ({ + [UploadStep.notStarted]: t(`${i18nPrefix}.upgrade`), + [UploadStep.upgrading]: t(`${i18nPrefix}.upgrading`), + [UploadStep.installed]: t(`${i18nPrefix}.close`), + })[uploadStep] + }, [t, uploadStep]) + + const handleConfirm = useCallback(async () => { + if (uploadStep === UploadStep.notStarted) { + setUploadStep(UploadStep.upgrading) + try { + const { + all_installed: isInstalled, + task_id: taskId, + } = await updateFromMarketPlace({ + original_plugin_unique_identifier: originalPackageInfo.id, + new_plugin_unique_identifier: targetPackageInfo.id, + }) + + if (isInstalled) { + onSave() + return + } + handleRefetch() + const { status, error } = await check({ + taskId, + pluginUniqueIdentifier: targetPackageInfo.id, + }) + if (status === TaskStatus.failed) { + Toast.notify({ type: 'error', message: error! }) + return + } + onSave() + } + // eslint-disable-next-line unused-imports/no-unused-vars + catch (e) { + setUploadStep(UploadStep.notStarted) + } + return + } + if (uploadStep === UploadStep.installed) + onSave() + }, [onSave, uploadStep, check, originalPackageInfo.id, handleRefetch, targetPackageInfo.id]) + const usedInAppInfo = useMemo(() => { + return ( + <div className='flex px-0.5 justify-center items-center gap-0.5'> + <div className='text-text-warning system-xs-medium'>{t(`${i18nPrefix}.usedInApps`, { num: 3 })}</div> + {/* show the used apps */} + <RiInformation2Line className='w-4 h-4 text-text-tertiary' /> + </div> + ) + }, [t]) + return ( + <Modal + isShow={true} + onClose={onCancel} + className='min-w-[560px]' + closable + title={t(`${i18nPrefix}.${uploadStep === UploadStep.installed ? 'successfulTitle' : 'title'}`)} + > + <div className='mt-3 mb-2 text-text-secondary system-md-regular'> + {t(`${i18nPrefix}.description`)} + </div> + <div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'> + <Card + installed={uploadStep === UploadStep.installed} + payload={pluginManifestToCardPluginProps({ + ...originalPackageInfo.payload, + icon: icon!, + })} + className='w-full' + titleLeft={ + <> + <Badge className='mx-1' size="s" state={BadgeState.Warning}> + {`${originalPackageInfo.payload.version} -> ${targetPackageInfo.version}`} + </Badge> + {false && usedInAppInfo} + </> + } + /> + </div> + <div className='flex pt-5 justify-end items-center gap-2 self-stretch'> + {uploadStep === UploadStep.notStarted && ( + <Button + onClick={handleCancel} + > + {t('common.operation.cancel')} + </Button> + )} + <Button + variant='primary' + loading={uploadStep === UploadStep.upgrading} + onClick={handleConfirm} + disabled={uploadStep === UploadStep.upgrading} + > + {configBtnText} + </Button> + </div> + </Modal> + ) +} +export default React.memo(UpdatePluginModal) diff --git a/web/app/components/plugins/update-plugin/index.tsx b/web/app/components/plugins/update-plugin/index.tsx new file mode 100644 index 0000000000..f9b49a6073 --- /dev/null +++ b/web/app/components/plugins/update-plugin/index.tsx @@ -0,0 +1,33 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { UpdatePluginModalType } from '../types' +import { PluginSource } from '../types' +import UpdateFromGitHub from './from-github' +import UpdateFromMarketplace from './from-market-place' + +const UpdatePlugin: FC<UpdatePluginModalType> = ({ + type, + marketPlace, + github, + onCancel, + onSave, +}) => { + if (type === PluginSource.github) { + return ( + <UpdateFromGitHub + payload={github!} + onSave={onSave} + onCancel={onCancel} + /> + ) + } + return ( + <UpdateFromMarketplace + payload={marketPlace!} + onSave={onSave} + onCancel={onCancel} + /> + ) +} +export default React.memo(UpdatePlugin) diff --git a/web/app/components/plugins/update-plugin/plugin-version-picker.tsx b/web/app/components/plugins/update-plugin/plugin-version-picker.tsx new file mode 100644 index 0000000000..b05ddc0062 --- /dev/null +++ b/web/app/components/plugins/update-plugin/plugin-version-picker.tsx @@ -0,0 +1,118 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Badge from '@/app/components/base/badge' +import type { + OffsetOptions, + Placement, +} from '@floating-ui/react' +import { useVersionListOfPlugin } from '@/service/use-plugins' +import useTimestamp from '@/hooks/use-timestamp' +import cn from '@/utils/classnames' + +type Props = { + disabled?: boolean + isShow: boolean + onShowChange: (isShow: boolean) => void + pluginID: string + currentVersion: string + trigger: React.ReactNode + placement?: Placement + offset?: OffsetOptions + onSelect: ({ + version, + unique_identifier, + }: { + version: string + unique_identifier: string + }) => void +} + +const PluginVersionPicker: FC<Props> = ({ + disabled = false, + isShow, + onShowChange, + pluginID, + currentVersion, + trigger, + placement = 'bottom-start', + offset = { + mainAxis: 4, + crossAxis: -16, + }, + onSelect, +}) => { + const { t } = useTranslation() + const format = t('appLog.dateTimeFormat').split(' ')[0] + const { formatDate } = useTimestamp() + + const handleTriggerClick = () => { + if (disabled) return + onShowChange(true) + } + + const { data: res } = useVersionListOfPlugin(pluginID) + + const handleSelect = useCallback(({ version, unique_identifier }: { + version: string + unique_identifier: string + }) => { + if (currentVersion === version) + return + onSelect({ version, unique_identifier }) + onShowChange(false) + }, [currentVersion, onSelect, onShowChange]) + + return ( + <PortalToFollowElem + placement={placement} + offset={offset} + open={isShow} + onOpenChange={onShowChange} + > + <PortalToFollowElemTrigger + className={cn('inline-flex items-center cursor-pointer', disabled && 'cursor-default')} + onClick={handleTriggerClick} + > + {trigger} + </PortalToFollowElemTrigger> + + <PortalToFollowElemContent className='z-[1000]'> + <div className="relative w-[209px] p-1 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg"> + <div className='px-3 pt-1 pb-0.5 text-text-tertiary system-xs-medium-uppercase'> + {t('plugin.detailPanel.switchVersion')} + </div> + <div className='relative'> + {res?.data.versions.map(version => ( + <div + key={version.unique_identifier} + className={cn( + 'h-7 px-3 py-1 flex items-center gap-1 rounded-lg hover:bg-state-base-hover cursor-pointer', + currentVersion === version.version && 'opacity-30 cursor-default hover:bg-transparent', + )} + onClick={() => handleSelect({ + version: version.version, + unique_identifier: version.unique_identifier, + })} + > + <div className='grow flex items-center'> + <div className='text-text-secondary system-sm-medium'>{version.version}</div> + {currentVersion === version.version && <Badge className='ml-1' text='CURRENT'/>} + </div> + <div className='shrink-0 text-text-tertiary system-xs-regular'>{formatDate(version.created_at, format)}</div> + </div> + ))} + </div> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default React.memo(PluginVersionPicker) diff --git a/web/app/components/plugins/utils.ts b/web/app/components/plugins/utils.ts new file mode 100644 index 0000000000..95f6d716d9 --- /dev/null +++ b/web/app/components/plugins/utils.ts @@ -0,0 +1,12 @@ +import { + categoryKeys, + tagKeys, +} from './constants' + +export const getValidTagKeys = (tags: string[]) => { + return tags.filter(tag => tagKeys.includes(tag)) +} + +export const getValidCategoryKeys = (category?: string) => { + return categoryKeys.find(key => key === category) +} diff --git a/web/app/components/share/text-generation/index.tsx b/web/app/components/share/text-generation/index.tsx index 16571b6451..fd8447c4cf 100644 --- a/web/app/components/share/text-generation/index.tsx +++ b/web/app/components/share/text-generation/index.tsx @@ -137,9 +137,11 @@ const TextGeneration: FC<IMainProps> = ({ const handleSend = () => { setIsCallBatchAPI(false) setControlSend(Date.now()) - // eslint-disable-next-line @typescript-eslint/no-use-before-define + + // eslint-disable-next-line ts/no-use-before-define setAllTaskList([]) // clear batch task running status - // eslint-disable-next-line @typescript-eslint/no-use-before-define + + // eslint-disable-next-line ts/no-use-before-define showResSidebar() } @@ -319,7 +321,8 @@ const TextGeneration: FC<IMainProps> = ({ setControlSend(Date.now()) // clear run once task status setControlStopResponding(Date.now()) - // eslint-disable-next-line @typescript-eslint/no-use-before-define + + // eslint-disable-next-line ts/no-use-before-define showResSidebar() } const handleCompleted = (completionRes: string, taskId?: number, isSuccess?: boolean) => { diff --git a/web/app/components/share/text-generation/result/index.tsx b/web/app/components/share/text-generation/result/index.tsx index cd4ed5d287..6d5c63273a 100644 --- a/web/app/components/share/text-generation/result/index.tsx +++ b/web/app/components/share/text-generation/result/index.tsx @@ -24,7 +24,7 @@ import { getFilesInLogs, } from '@/app/components/base/file-uploader/utils' -export type IResultProps = { +export interface IResultProps { isWorkflow: boolean isCallBatchAPI: boolean isPC: boolean diff --git a/web/app/components/swr-initor.tsx b/web/app/components/swr-initor.tsx index 2a119df996..a2ae003139 100644 --- a/web/app/components/swr-initor.tsx +++ b/web/app/components/swr-initor.tsx @@ -6,7 +6,7 @@ import type { ReactNode } from 'react' import { usePathname, useRouter, useSearchParams } from 'next/navigation' import { fetchSetupStatus } from '@/service/common' -type SwrInitorProps = { +interface SwrInitorProps { children: ReactNode } const SwrInitor = ({ diff --git a/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx b/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx index 4b24bcb931..4b5b0560f9 100644 --- a/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx +++ b/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next' import Tooltip from '@/app/components/base/tooltip' import cn from '@/utils/classnames' import type { Credential } from '@/app/components/tools/types' +import Input from '@/app/components/base/input' import Drawer from '@/app/components/base/drawer-plus' import Button from '@/app/components/base/button' import Radio from '@/app/components/base/radio/ui' @@ -16,7 +17,6 @@ type Props = { onChange: (credential: Credential) => void onHide: () => void } -const keyClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900' type ItemProps = { text: string @@ -28,11 +28,11 @@ type ItemProps = { const SelectItem: FC<ItemProps> = ({ text, value, isChecked, onClick }) => { return ( <div - className={cn(isChecked ? 'border-[2px] border-indigo-600 shadow-sm bg-white' : 'border border-gray-100', 'mb-2 flex items-center h-9 pl-3 w-[150px] rounded-xl bg-gray-25 hover:bg-gray-50 cursor-pointer space-x-2')} + className={cn(isChecked ? 'border-[2px] border-util-colors-indigo-indigo-600 shadow-sm bg-components-panel-on-panel-item-bg' : 'border border-components-card-border', 'mb-2 flex items-center h-9 pl-3 w-[150px] rounded-xl bg-components-panel-on-panel-item-bg hover:bg-components-panel-on-panel-item-bg-hover cursor-pointer space-x-2')} onClick={() => onClick(value)} > <Radio isChecked={isChecked} /> - <div className='text-sm font-normal text-gray-900'>{text}</div> + <div className='system-sm-regular text-text-primary'>{text}</div> </div> ) } @@ -55,12 +55,12 @@ const ConfigCredential: FC<Props> = ({ panelClassName='mt-2 !w-[520px] h-fit' maxWidthClassName='!max-w-[520px]' height={'fit-content'} - headerClassName='!border-b-black/5' + headerClassName='!border-b-divider-regular' body={ <div className='pt-2 px-6'> <div className='space-y-4'> <div> - <div className={keyClassNames}>{t('tools.createTool.authMethod.type')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authMethod.type')}</div> <div className='flex space-x-3'> <SelectItem text={t('tools.createTool.authMethod.types.none')} @@ -84,52 +84,52 @@ const ConfigCredential: FC<Props> = ({ </div> {tempCredential.auth_type === AuthType.apiKey && ( <> - <div className={keyClassNames}>{t('tools.createTool.authHeaderPrefix.title')}</div> - <div className='flex space-x-3'> - <SelectItem - text={t('tools.createTool.authHeaderPrefix.types.basic')} - value={AuthHeaderPrefix.basic} - isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.basic} - onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} - /> - <SelectItem - text={t('tools.createTool.authHeaderPrefix.types.bearer')} - value={AuthHeaderPrefix.bearer} - isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.bearer} - onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} - /> - <SelectItem - text={t('tools.createTool.authHeaderPrefix.types.custom')} - value={AuthHeaderPrefix.custom} - isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.custom} - onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} - /> + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authHeaderPrefix.title')}</div> + <div className='flex space-x-3'> + <SelectItem + text={t('tools.createTool.authHeaderPrefix.types.basic')} + value={AuthHeaderPrefix.basic} + isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.basic} + onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} + /> + <SelectItem + text={t('tools.createTool.authHeaderPrefix.types.bearer')} + value={AuthHeaderPrefix.bearer} + isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.bearer} + onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} + /> + <SelectItem + text={t('tools.createTool.authHeaderPrefix.types.custom')} + value={AuthHeaderPrefix.custom} + isChecked={tempCredential.api_key_header_prefix === AuthHeaderPrefix.custom} + onClick={value => setTempCredential({ ...tempCredential, api_key_header_prefix: value as AuthHeaderPrefix })} + /> + </div> </div> <div> - <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'> + <div className='flex items-center py-2 system-sm-medium text-text-primary'> {t('tools.createTool.authMethod.key')} <Tooltip popupContent={ - <div className='w-[261px] text-gray-500'> + <div className='w-[261px] text-text-tertiary'> {t('tools.createTool.authMethod.keyTooltip')} </div> } triggerClassName='ml-0.5 w-4 h-4' /> </div> - <input + <Input value={tempCredential.api_key_header} onChange={e => setTempCredential({ ...tempCredential, api_key_header: e.target.value })} - className='w-full h-10 px-3 text-sm font-normal border border-transparent bg-gray-100 rounded-lg grow outline-none focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs' placeholder={t('tools.createTool.authMethod.types.apiKeyPlaceholder')!} /> </div> <div> - <div className={keyClassNames}>{t('tools.createTool.authMethod.value')}</div> - <input + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authMethod.value')}</div> + <Input value={tempCredential.api_key_value} onChange={e => setTempCredential({ ...tempCredential, api_key_value: e.target.value })} - className='w-full h-10 px-3 text-sm font-normal border border-transparent bg-gray-100 rounded-lg grow outline-none focus:bg-components-input-bg-active focus:border-components-input-border-active focus:shadow-xs' placeholder={t('tools.createTool.authMethod.types.apiValuePlaceholder')!} /> </div> diff --git a/web/app/components/tools/edit-custom-collection-modal/get-schema.tsx b/web/app/components/tools/edit-custom-collection-modal/get-schema.tsx index 2552c67568..a43440bda4 100644 --- a/web/app/components/tools/edit-custom-collection-modal/get-schema.tsx +++ b/web/app/components/tools/edit-custom-collection-modal/get-schema.tsx @@ -10,6 +10,7 @@ import { import Toast from '../../base/toast' import examples from './examples' import Button from '@/app/components/base/button' +import Input from '@/app/components/base/input' import { importSchemaFromURL } from '@/service/tools' type Props = { @@ -63,14 +64,14 @@ const GetSchema: FC<Props> = ({ onClick={() => { setShowImportFromUrl(!showImportFromUrl) }} > <RiAddLine className='w-3 h-3' /> - <div className='text-xs font-medium text-gray-700'>{t('tools.createTool.importFromUrl')}</div> + <div className='system-xs-medium text-text-secondary'>{t('tools.createTool.importFromUrl')}</div> </Button> {showImportFromUrl && ( - <div className=' absolute left-[-35px] top-[26px] p-2 rounded-lg border border-gray-200 bg-white shadow-lg'> + <div className=' absolute left-[-35px] top-[26px] p-2 rounded-lg border border-components-panel-border bg-components-panel-bg shadow-lg'> <div className='relative'> - <input + <Input type='text' - className='w-[244px] h-8 pl-1.5 pr-[44px] overflow-x-auto border border-gray-200 rounded-lg text-[13px] focus:outline-none focus:border-components-input-border-active' + className='w-[244px]' placeholder={t('tools.createTool.importFromUrlPlaceHolder')!} value={importUrl} onChange={e => setImportUrl(e.target.value)} @@ -95,11 +96,11 @@ const GetSchema: FC<Props> = ({ className='space-x-1' onClick={() => { setShowExamples(!showExamples) }} > - <div className='text-xs font-medium text-gray-700'>{t('tools.createTool.examples')}</div> + <div className='system-xs-medium text-text-secondary'>{t('tools.createTool.examples')}</div> <RiArrowDownSLine className='w-3 h-3' /> </Button> {showExamples && ( - <div className='absolute top-7 right-0 p-1 rounded-lg bg-white shadow-sm'> + <div className='absolute top-7 right-0 p-1 rounded-lg bg-components-panel-bg shadow-sm'> {examples.map(item => ( <div key={item.key} @@ -107,7 +108,7 @@ const GetSchema: FC<Props> = ({ onChange(item.content) setShowExamples(false) }} - className='px-3 py-1.5 rounded-lg hover:bg-gray-50 leading-5 text-sm font-normal text-gray-700 cursor-pointer whitespace-nowrap' + className='px-3 py-1.5 rounded-lg hover:bg-components-panel-on-panel-item-bg-hover leading-5 system-sm-regular text-text-secondary cursor-pointer whitespace-nowrap' > {t(`tools.createTool.exampleOptions.${item.key}`)} </div> diff --git a/web/app/components/tools/edit-custom-collection-modal/index.tsx b/web/app/components/tools/edit-custom-collection-modal/index.tsx index 555fd0dd08..786d3a4625 100644 --- a/web/app/components/tools/edit-custom-collection-modal/index.tsx +++ b/web/app/components/tools/edit-custom-collection-modal/index.tsx @@ -3,8 +3,9 @@ import type { FC } from 'react' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useDebounce, useGetState } from 'ahooks' +import { RiSettings2Line } from '@remixicon/react' import produce from 'immer' -import { LinkExternal02, Settings01 } from '../../base/icons/src/vender/line/general' +import { LinkExternal02 } from '../../base/icons/src/vender/line/general' import type { Credential, CustomCollectionBackend, CustomParamSchema, Emoji } from '../types' import { AuthHeaderPrefix, AuthType } from '../types' import GetSchema from './get-schema' @@ -21,7 +22,6 @@ import { parseParamsSchema } from '@/service/tools' import LabelSelector from '@/app/components/tools/labels/selector' import Toast from '@/app/components/base/toast' -const fieldNameClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900' type Props = { positionLeft?: boolean payload: any @@ -189,12 +189,12 @@ const EditCustomCollectionModal: FC<Props> = ({ panelClassName='mt-2 !w-[640px]' maxWidthClassName='!max-w-[640px]' height='calc(100vh - 16px)' - headerClassName='!border-b-black/5' + headerClassName='!border-b-divider-regular' body={ <div className='flex flex-col h-full'> <div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'> <div> - <div className={fieldNameClassNames}>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div> <div className='flex items-center justify-between gap-3'> <AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} /> <Input @@ -214,12 +214,12 @@ const EditCustomCollectionModal: FC<Props> = ({ <div className='select-none'> <div className='flex justify-between items-center'> <div className='flex items-center'> - <div className={fieldNameClassNames}>{t('tools.createTool.schema')}<span className='ml-1 text-red-500'>*</span></div> - <div className='mx-2 w-px h-3 bg-black/5'></div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.schema')}<span className='ml-1 text-red-500'>*</span></div> + <div className='mx-2 w-px h-3 bg-divider-regular'></div> <a href="https://swagger.io/specification/" target='_blank' rel='noopener noreferrer' - className='flex items-center h-[18px] space-x-1 text-[#155EEF]' + className='flex items-center h-[18px] space-x-1 text-text-accent' > <div className='text-xs font-normal'>{t('tools.createTool.viewSchemaSpec')}</div> <LinkExternal02 className='w-3 h-3' /> @@ -238,11 +238,11 @@ const EditCustomCollectionModal: FC<Props> = ({ {/* Available Tools */} <div> - <div className={fieldNameClassNames}>{t('tools.createTool.availableTools.title')}</div> - <div className='rounded-lg border border-gray-200 w-full overflow-x-auto'> - <table className='w-full leading-[18px] text-xs text-gray-700 font-normal'> - <thead className='text-gray-500 uppercase'> - <tr className={cn(paramsSchemas.length > 0 && 'border-b', 'border-gray-200')}> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.availableTools.title')}</div> + <div className='rounded-lg border border-divider-regular w-full overflow-x-auto'> + <table className='w-full system-xs-regular text-text-secondary'> + <thead className='text-text-tertiary uppercase'> + <tr className={cn(paramsSchemas.length > 0 && 'border-b', 'border-divider-regular')}> <th className="p-2 pl-3 font-medium">{t('tools.createTool.availableTools.name')}</th> <th className="p-2 pl-3 font-medium w-[236px]">{t('tools.createTool.availableTools.description')}</th> <th className="p-2 pl-3 font-medium">{t('tools.createTool.availableTools.method')}</th> @@ -252,9 +252,9 @@ const EditCustomCollectionModal: FC<Props> = ({ </thead> <tbody> {paramsSchemas.map((item, index) => ( - <tr key={index} className='border-b last:border-0 border-gray-200'> + <tr key={index} className='border-b last:border-0 border-divider-regular'> <td className="p-2 pl-3">{item.operation_id}</td> - <td className="p-2 pl-3 text-gray-500 w-[236px]">{item.summary}</td> + <td className="p-2 pl-3 w-[236px]">{item.summary}</td> <td className="p-2 pl-3">{item.method}</td> <td className="p-2 pl-3">{getPath(item.server_url)}</td> <td className="p-2 pl-3 w-[62px]"> @@ -277,22 +277,22 @@ const EditCustomCollectionModal: FC<Props> = ({ {/* Authorization method */} <div> - <div className={fieldNameClassNames}>{t('tools.createTool.authMethod.title')}</div> - <div className='flex items-center h-9 justify-between px-2.5 bg-gray-100 rounded-lg cursor-pointer' onClick={() => setCredentialsModalShow(true)}> - <div className='text-sm font-normal text-gray-900'>{t(`tools.createTool.authMethod.types.${credential.auth_type}`)}</div> - <Settings01 className='w-4 h-4 text-gray-700 opacity-60' /> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authMethod.title')}</div> + <div className='flex items-center h-9 justify-between px-2.5 bg-components-input-bg-normal rounded-lg cursor-pointer' onClick={() => setCredentialsModalShow(true)}> + <div className='system-xs-regular text-text-primary'>{t(`tools.createTool.authMethod.types.${credential.auth_type}`)}</div> + <RiSettings2Line className='w-4 h-4 text-text-secondary' /> </div> </div> {/* Labels */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.toolInput.label')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.toolInput.label')}</div> <LabelSelector value={labels} onChange={handleLabelSelect} /> </div> {/* Privacy Policy */} <div> - <div className={fieldNameClassNames}>{t('tools.createTool.privacyPolicy')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.privacyPolicy')}</div> <Input value={customCollection.privacy_policy} onChange={(e) => { @@ -305,7 +305,7 @@ const EditCustomCollectionModal: FC<Props> = ({ </div> <div> - <div className={fieldNameClassNames}>{t('tools.createTool.customDisclaimer')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.customDisclaimer')}</div> <Input value={customCollection.custom_disclaimer} onChange={(e) => { @@ -318,10 +318,10 @@ const EditCustomCollectionModal: FC<Props> = ({ </div> </div> - <div className={cn(isEdit ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-gray-50 border-t border-black/5')} > + <div className={cn(isEdit ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-background-section-burn border-t border-divider-regular')} > { isEdit && ( - <Button onClick={onRemove} className='text-red-500 border-red-50 hover:border-red-500'>{t('common.operation.delete')}</Button> + <Button variant='warning' onClick={onRemove}>{t('common.operation.delete')}</Button> ) } <div className='flex space-x-2 '> diff --git a/web/app/components/tools/edit-custom-collection-modal/modal.tsx b/web/app/components/tools/edit-custom-collection-modal/modal.tsx new file mode 100644 index 0000000000..0b4447850c --- /dev/null +++ b/web/app/components/tools/edit-custom-collection-modal/modal.tsx @@ -0,0 +1,360 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { useDebounce, useGetState } from 'ahooks' +import produce from 'immer' +import { LinkExternal02, Settings01 } from '../../base/icons/src/vender/line/general' +import type { Credential, CustomCollectionBackend, CustomParamSchema, Emoji } from '../types' +import { AuthHeaderPrefix, AuthType } from '../types' +import GetSchema from './get-schema' +import ConfigCredentials from './config-credentials' +import TestApi from './test-api' +import cn from '@/utils/classnames' +import Input from '@/app/components/base/input' +import Textarea from '@/app/components/base/textarea' +import EmojiPicker from '@/app/components/base/emoji-picker' +import AppIcon from '@/app/components/base/app-icon' +import { parseParamsSchema } from '@/service/tools' +import LabelSelector from '@/app/components/tools/labels/selector' +import Toast from '@/app/components/base/toast' +import Modal from '../../base/modal' +import Button from '@/app/components/base/button' + +type Props = { + positionLeft?: boolean + payload: any + onHide: () => void + onAdd?: (payload: CustomCollectionBackend) => void + onRemove?: () => void + onEdit?: (payload: CustomCollectionBackend) => void +} +// Add and Edit +const EditCustomCollectionModal: FC<Props> = ({ + payload, + onHide, + onAdd, + onEdit, + onRemove, +}) => { + const { t } = useTranslation() + const isAdd = !payload + const isEdit = !!payload + + const [editFirst, setEditFirst] = useState(!isAdd) + const [paramsSchemas, setParamsSchemas] = useState<CustomParamSchema[]>(payload?.tools || []) + const [customCollection, setCustomCollection, getCustomCollection] = useGetState<CustomCollectionBackend>(isAdd + ? { + provider: '', + credentials: { + auth_type: AuthType.none, + api_key_header: 'Authorization', + api_key_header_prefix: AuthHeaderPrefix.basic, + }, + icon: { + content: '🕵️', + background: '#FEF7C3', + }, + schema_type: '', + schema: '', + } + : payload) + + const originalProvider = isEdit ? payload.provider : '' + + const [showEmojiPicker, setShowEmojiPicker] = useState(false) + const emoji = customCollection.icon + const setEmoji = (emoji: Emoji) => { + const newCollection = produce(customCollection, (draft) => { + draft.icon = emoji + }) + setCustomCollection(newCollection) + } + const schema = customCollection.schema + const debouncedSchema = useDebounce(schema, { wait: 500 }) + const setSchema = (schema: any) => { + const newCollection = produce(customCollection, (draft) => { + draft.schema = schema + }) + setCustomCollection(newCollection) + } + + useEffect(() => { + if (!debouncedSchema) + return + if (isEdit && editFirst) { + setEditFirst(false) + return + } + (async () => { + try { + const { parameters_schema, schema_type } = await parseParamsSchema(debouncedSchema) + const customCollection = getCustomCollection() + const newCollection = produce(customCollection, (draft) => { + draft.schema_type = schema_type + }) + setCustomCollection(newCollection) + setParamsSchemas(parameters_schema) + } + catch (e) { + const customCollection = getCustomCollection() + const newCollection = produce(customCollection, (draft) => { + draft.schema_type = '' + }) + setCustomCollection(newCollection) + setParamsSchemas([]) + } + })() + }, [debouncedSchema]) + + const [credentialsModalShow, setCredentialsModalShow] = useState(false) + const credential = customCollection.credentials + const setCredential = (credential: Credential) => { + const newCollection = produce(customCollection, (draft) => { + draft.credentials = credential + }) + setCustomCollection(newCollection) + } + + const [currTool, setCurrTool] = useState<CustomParamSchema | null>(null) + const [isShowTestApi, setIsShowTestApi] = useState(false) + + const [labels, setLabels] = useState<string[]>(payload?.labels || []) + const handleLabelSelect = (value: string[]) => { + setLabels(value) + } + + const handleSave = () => { + // const postData = clone(customCollection) + const postData = produce(customCollection, (draft) => { + delete draft.tools + + if (draft.credentials.auth_type === AuthType.none) { + delete draft.credentials.api_key_header + delete draft.credentials.api_key_header_prefix + delete draft.credentials.api_key_value + } + + draft.labels = labels + }) + + let errorMessage = '' + if (!postData.provider) + errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.name') }) + + if (!postData.schema) + errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.schema') }) + + if (errorMessage) { + Toast.notify({ + type: 'error', + message: errorMessage, + }) + return + } + + if (isAdd) { + onAdd?.(postData) + return + } + + onEdit?.({ + ...postData, + original_provider: originalProvider, + }) + } + + const getPath = (url: string) => { + if (!url) + return '' + + try { + const path = decodeURI(new URL(url).pathname) + return path || '' + } + catch (e) { + return url + } + } + + return ( + <> + <Modal + isShow + onClose={onHide} + closable + className='!p-0 !max-w-[630px] !h-[calc(100vh-16px)]' + > + <div className='flex flex-col h-full'> + <div className='ml-6 mt-6 text-base font-semibold text-text-primary'> + {t('tools.createTool.title')} + </div> + <div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'> + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div> + <div className='flex items-center justify-between gap-3'> + <AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} /> + <Input + className='h-10 grow' placeholder={t('tools.createTool.toolNamePlaceHolder')!} + value={customCollection.provider} + onChange={(e) => { + const newCollection = produce(customCollection, (draft) => { + draft.provider = e.target.value + }) + setCustomCollection(newCollection) + }} + /> + </div> + </div> + + {/* Schema */} + <div className='select-none'> + <div className='flex justify-between items-center'> + <div className='flex items-center'> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.schema')}<span className='ml-1 text-red-500'>*</span></div> + <div className='mx-2 w-px h-3 bg-divider-regular'></div> + <a + href="https://swagger.io/specification/" + target='_blank' rel='noopener noreferrer' + className='flex items-center h-[18px] space-x-1 text-text-accent' + > + <div className='text-xs font-normal'>{t('tools.createTool.viewSchemaSpec')}</div> + <LinkExternal02 className='w-3 h-3' /> + </a> + </div> + <GetSchema onChange={setSchema} /> + + </div> + <Textarea + className='h-[240px] resize-none' + value={schema} + onChange={e => setSchema(e.target.value)} + placeholder={t('tools.createTool.schemaPlaceHolder')!} + /> + </div> + + {/* Available Tools */} + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.availableTools.title')}</div> + <div className='rounded-lg border border-divider-regular w-full overflow-x-auto'> + <table className='w-full system-xs-regular text-text-secondary'> + <thead className='text-text-tertiary uppercase'> + <tr className={cn(paramsSchemas.length > 0 && 'border-b', 'border-divider-regular')}> + <th className="p-2 pl-3 font-medium">{t('tools.createTool.availableTools.name')}</th> + <th className="p-2 pl-3 font-medium w-[236px]">{t('tools.createTool.availableTools.description')}</th> + <th className="p-2 pl-3 font-medium">{t('tools.createTool.availableTools.method')}</th> + <th className="p-2 pl-3 font-medium">{t('tools.createTool.availableTools.path')}</th> + <th className="p-2 pl-3 font-medium w-[54px]">{t('tools.createTool.availableTools.action')}</th> + </tr> + </thead> + <tbody> + {paramsSchemas.map((item, index) => ( + <tr key={index} className='border-b last:border-0 border-divider-regular'> + <td className="p-2 pl-3">{item.operation_id}</td> + <td className="p-2 pl-3 w-[236px]">{item.summary}</td> + <td className="p-2 pl-3">{item.method}</td> + <td className="p-2 pl-3">{getPath(item.server_url)}</td> + <td className="p-2 pl-3 w-[62px]"> + <Button + size='small' + onClick={() => { + setCurrTool(item) + setIsShowTestApi(true) + }} + > + {t('tools.createTool.availableTools.test')} + </Button> + </td> + </tr> + ))} + </tbody> + </table> + </div> + </div> + + {/* Authorization method */} + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authMethod.title')}</div> + <div className='flex items-center h-9 justify-between px-2.5 bg-components-input-bg-normal rounded-lg cursor-pointer' onClick={() => setCredentialsModalShow(true)}> + <div className='system-xs-regular text-text-primary'>{t(`tools.createTool.authMethod.types.${credential.auth_type}`)}</div> + <Settings01 className='w-4 h-4 text-text-secondary' /> + </div> + </div> + + {/* Labels */} + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.toolInput.label')}</div> + <LabelSelector value={labels} onChange={handleLabelSelect} /> + </div> + + {/* Privacy Policy */} + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.privacyPolicy')}</div> + <Input + value={customCollection.privacy_policy} + onChange={(e) => { + const newCollection = produce(customCollection, (draft) => { + draft.privacy_policy = e.target.value + }) + setCustomCollection(newCollection) + }} + className='h-10 grow' placeholder={t('tools.createTool.privacyPolicyPlaceholder') || ''} /> + </div> + + <div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.customDisclaimer')}</div> + <Input + value={customCollection.custom_disclaimer} + onChange={(e) => { + const newCollection = produce(customCollection, (draft) => { + draft.custom_disclaimer = e.target.value + }) + setCustomCollection(newCollection) + }} + className='h-10 grow' placeholder={t('tools.createTool.customDisclaimerPlaceholder') || ''} /> + </div> + + </div> + <div className={cn(isEdit ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-background-section-burn border-t border-divider-regular')} > + { + isEdit && ( + <Button variant='warning' onClick={onRemove}>{t('common.operation.delete')}</Button> + ) + } + <div className='flex space-x-2 '> + <Button onClick={onHide}>{t('common.operation.cancel')}</Button> + <Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button> + </div> + </div> + {showEmojiPicker && <EmojiPicker + onSelect={(icon, icon_background) => { + setEmoji({ content: icon, background: icon_background }) + setShowEmojiPicker(false) + }} + onClose={() => { + setShowEmojiPicker(false) + }} + />} + {credentialsModalShow && ( + <ConfigCredentials + positionCenter={isAdd} + credential={credential} + onChange={setCredential} + onHide={() => setCredentialsModalShow(false)} + />) + } + {isShowTestApi && ( + <TestApi + positionCenter={isAdd} + tool={currTool as CustomParamSchema} + customCollection={customCollection} + onHide={() => setIsShowTestApi(false)} + /> + )} + </div> + </Modal> + </> + + ) +} +export default React.memo(EditCustomCollectionModal) diff --git a/web/app/components/tools/edit-custom-collection-modal/test-api.tsx b/web/app/components/tools/edit-custom-collection-modal/test-api.tsx index 80a08d07a9..3172110bf6 100644 --- a/web/app/components/tools/edit-custom-collection-modal/test-api.tsx +++ b/web/app/components/tools/edit-custom-collection-modal/test-api.tsx @@ -3,10 +3,11 @@ import type { FC } from 'react' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' -import { Settings01 } from '../../base/icons/src/vender/line/general' +import { RiSettings2Line } from '@remixicon/react' import ConfigCredentials from './config-credentials' import { AuthType, type Credential, type CustomCollectionBackend, type CustomParamSchema } from '@/app/components/tools/types' import Button from '@/app/components/base/button' +import Input from '@/app/components/base/input' import Drawer from '@/app/components/base/drawer-plus' import I18n from '@/context/i18n' import { testAPIAvailable } from '@/service/tools' @@ -19,8 +20,6 @@ type Props = { onHide: () => void } -const keyClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900' - const TestApi: FC<Props> = ({ positionCenter, customCollection, @@ -65,39 +64,40 @@ const TestApi: FC<Props> = ({ panelClassName='mt-2 !w-[600px]' maxWidthClassName='!max-w-[600px]' height='calc(100vh - 16px)' - headerClassName='!border-b-black/5' + headerClassName='!border-b-divider-regular' body={ <div className='pt-2 px-6 overflow-y-auto'> <div className='space-y-4'> <div> - <div className={keyClassNames}>{t('tools.createTool.authMethod.title')}</div> - <div className='flex items-center h-9 justify-between px-2.5 bg-gray-100 rounded-lg cursor-pointer' onClick={() => setCredentialsModalShow(true)}> - <div className='text-sm font-normal text-gray-900'>{t(`tools.createTool.authMethod.types.${tempCredential.auth_type}`)}</div> - <Settings01 className='w-4 h-4 text-gray-700 opacity-60' /> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.authMethod.title')}</div> + <div className='flex items-center h-9 justify-between px-2.5 bg-components-input-bg-normal rounded-lg cursor-pointer' onClick={() => setCredentialsModalShow(true)}> + <div className='system-xs-regular text-text-primary'>{t(`tools.createTool.authMethod.types.${tempCredential.auth_type}`)}</div> + <RiSettings2Line className='w-4 h-4 text-text-secondary' /> </div> </div> <div> - <div className={keyClassNames}>{t('tools.test.parametersValue')}</div> - <div className='rounded-lg border border-gray-200'> - <table className='w-full leading-[18px] text-xs text-gray-700 font-normal'> - <thead className='text-gray-500 uppercase'> - <tr className='border-b border-gray-200'> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.test.parametersValue')}</div> + <div className='rounded-lg border border-divider-regular'> + <table className='w-full system-xs-regular text-text-secondary font-normal'> + <thead className='text-text-tertiary uppercase'> + <tr className='border-b border-divider-regular'> <th className="p-2 pl-3 font-medium">{t('tools.test.parameters')}</th> <th className="p-2 pl-3 font-medium">{t('tools.test.value')}</th> </tr> </thead> <tbody> {parameters.map((item, index) => ( - <tr key={index} className='border-b last:border-0 border-gray-200'> + <tr key={index} className='border-b last:border-0 border-divider-regular'> <td className="py-2 pl-3 pr-2.5"> {item.label[language]} </td> <td className=""> - <input + <Input value={parametersValue[item.name] || ''} onChange={e => setParametersValue({ ...parametersValue, [item.name]: e.target.value })} - type='text' className='px-3 h-[34px] w-full outline-none focus:bg-gray-100' ></input> + type='text' + className='!bg-transparent !border-transparent !hover:border-transparent !hover:bg-transparent !focus:border-transparent !focus:bg-transparent' /> </td> </tr> ))} @@ -110,11 +110,11 @@ const TestApi: FC<Props> = ({ <Button variant='primary' className=' mt-4 w-full h-10' onClick={handleTest}>{t('tools.test.title')}</Button> <div className='mt-6'> <div className='flex items-center space-x-3'> - <div className='leading-[18px] text-xs font-semibold text-gray-500'>{t('tools.test.testResult')}</div> + <div className='system-xs-semibold text-text-tertiary'>{t('tools.test.testResult')}</div> <div className='grow w-0 h-px bg-[rgb(243, 244, 246)]'></div> </div> - <div className='mt-2 px-3 py-2 h-[200px] overflow-y-auto overflow-x-hidden rounded-lg bg-gray-100 leading-4 text-xs font-normal text-gray-700'> - {result || <span className='text-gray-400'>{t('tools.test.testResultPlaceholder')}</span>} + <div className='mt-2 px-3 py-2 h-[200px] overflow-y-auto overflow-x-hidden rounded-lg bg-components-input-bg-normal system-xs-regular text-text-secondary'> + {result || <span className='text-text-quaternary'>{t('tools.test.testResultPlaceholder')}</span>} </div> </div> </div> diff --git a/web/app/components/tools/labels/constant.ts b/web/app/components/tools/labels/constant.ts index 3f073859d9..ad4836e6a8 100644 --- a/web/app/components/tools/labels/constant.ts +++ b/web/app/components/tools/labels/constant.ts @@ -1,6 +1,4 @@ -import type { TypeWithI18N } from '@/app/components/header/account-setting/model-provider-page/declarations' export type Label = { name: string - icon: string - label: TypeWithI18N + label: string } diff --git a/web/app/components/tools/labels/filter.tsx b/web/app/components/tools/labels/filter.tsx index 20db687e79..87e65b5b4e 100644 --- a/web/app/components/tools/labels/filter.tsx +++ b/web/app/components/tools/labels/filter.tsx @@ -1,10 +1,8 @@ import type { FC } from 'react' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import { useDebounceFn, useMount } from 'ahooks' +import { useDebounceFn } from 'ahooks' import { RiArrowDownSLine } from '@remixicon/react' -import { useStore as useLabelStore } from './store' import cn from '@/utils/classnames' import { PortalToFollowElem, @@ -16,9 +14,7 @@ import { Tag01, Tag03 } from '@/app/components/base/icons/src/vender/line/financ import { Check } from '@/app/components/base/icons/src/vender/line/general' import { XCircle } from '@/app/components/base/icons/src/vender/solid/general' import type { Label } from '@/app/components/tools/labels/constant' -import { fetchLabelList } from '@/service/tools' -import I18n from '@/context/i18n' -import { getLanguage } from '@/i18n/language' +import { useTags } from '@/app/components/plugins/hooks' type LabelFilterProps = { value: string[] @@ -29,12 +25,9 @@ const LabelFilter: FC<LabelFilterProps> = ({ onChange, }) => { const { t } = useTranslation() - const { locale } = useContext(I18n) - const language = getLanguage(locale) const [open, setOpen] = useState(false) - const labelList = useLabelStore(s => s.labelList) - const setLabelList = useLabelStore(s => s.setLabelList) + const { tags: labelList } = useTags() const [keywords, setKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('') @@ -61,12 +54,6 @@ const LabelFilter: FC<LabelFilterProps> = ({ onChange([...value, label.name]) } - useMount(() => { - fetchLabelList().then((res) => { - setLabelList(res) - }) - }) - return ( <PortalToFollowElem open={open} @@ -80,24 +67,23 @@ const LabelFilter: FC<LabelFilterProps> = ({ className='block' > <div className={cn( - 'flex items-center gap-1 px-2 h-8 rounded-lg border-[0.5px] border-transparent bg-gray-200 cursor-pointer hover:bg-gray-300', - open && !value.length && '!bg-gray-300 hover:bg-gray-300', - !open && !!value.length && '!bg-white/80 shadow-xs !border-black/5 hover:!bg-gray-200', - open && !!value.length && '!bg-gray-200 !border-black/5 shadow-xs hover:!bg-gray-200', + 'flex items-center gap-1 px-2 h-8 rounded-lg border-[0.5px] border-transparent bg-components-input-bg-normal cursor-pointer hover:bg-components-input-bg-hover', + !open && !!value.length && 'shadow-xs', + open && !!value.length && 'shadow-xs', )}> <div className='p-[1px]'> - <Tag01 className='h-3.5 w-3.5 text-gray-700' /> + <Tag01 className='h-3.5 w-3.5 text-text-tertiary' /> </div> - <div className='text-[13px] leading-[18px] text-gray-700'> + <div className='text-[13px] leading-[18px] text-text-tertiary'> {!value.length && t('common.tag.placeholder')} - {!!value.length && currentLabel?.label[language]} + {!!value.length && currentLabel?.label} </div> {value.length > 1 && ( - <div className='text-xs font-medium leading-[18px] text-gray-500'>{`+${value.length - 1}`}</div> + <div className='text-xs font-medium leading-[18px] text-text-tertiary'>{`+${value.length - 1}`}</div> )} {!value.length && ( <div className='p-[1px]'> - <RiArrowDownSLine className='h-3.5 w-3.5 text-gray-700' /> + <RiArrowDownSLine className='h-3.5 w-3.5 text-text-tertiary' /> </div> )} {!!value.length && ( @@ -105,14 +91,14 @@ const LabelFilter: FC<LabelFilterProps> = ({ e.stopPropagation() onChange([]) }}> - <XCircle className='h-3.5 w-3.5 text-gray-400 group-hover/clear:text-gray-600' /> + <XCircle className='h-3.5 w-3.5 text-text-tertiary group-hover/clear:text-text-secondary' /> </div> )} </div> </PortalToFollowElemTrigger> <PortalToFollowElemContent className='z-[1002]'> - <div className='relative w-[240px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'> - <div className='p-2 border-b-[0.5px] border-black/5'> + <div className='relative w-[240px] bg-components-panel-bg-blur rounded-lg border-[0.5px] backdrop-blur-[5px] border-components-panel-border shadow-lg'> + <div className='p-2'> <Input showLeftIcon showClearIcon @@ -125,17 +111,17 @@ const LabelFilter: FC<LabelFilterProps> = ({ {filteredLabelList.map(label => ( <div key={label.name} - className='flex items-center gap-2 pl-3 py-[6px] pr-2 rounded-lg cursor-pointer hover:bg-gray-100' + className='flex items-center gap-2 pl-3 py-[6px] pr-2 rounded-lg cursor-pointer hover:bg-state-base-hover' onClick={() => selectLabel(label)} > - <div title={label.label[language]} className='grow text-sm text-gray-700 leading-5 truncate'>{label.label[language]}</div> - {value.includes(label.name) && <Check className='shrink-0 w-4 h-4 text-primary-600' />} + <div title={label.label} className='grow text-sm text-text-secondary leading-5 truncate'>{label.label}</div> + {value.includes(label.name) && <Check className='shrink-0 w-4 h-4 text-text-accent' />} </div> ))} {!filteredLabelList.length && ( <div className='p-3 flex flex-col items-center gap-1'> - <Tag03 className='h-6 w-6 text-gray-300' /> - <div className='text-gray-500 text-xs leading-[14px]'>{t('common.tag.noTag')}</div> + <Tag03 className='h-6 w-6 text-text-quaternary' /> + <div className='text-text-tertiary text-xs leading-[14px]'>{t('common.tag.noTag')}</div> </div> )} </div> diff --git a/web/app/components/tools/labels/selector.tsx b/web/app/components/tools/labels/selector.tsx index 3f33e45b91..26cfc3ad9b 100644 --- a/web/app/components/tools/labels/selector.tsx +++ b/web/app/components/tools/labels/selector.tsx @@ -1,10 +1,8 @@ import type { FC } from 'react' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import { useDebounceFn, useMount } from 'ahooks' +import { useDebounceFn } from 'ahooks' import { RiArrowDownSLine } from '@remixicon/react' -import { useStore as useLabelStore } from './store' import cn from '@/utils/classnames' import { PortalToFollowElem, @@ -15,9 +13,7 @@ import Input from '@/app/components/base/input' import { Tag03 } from '@/app/components/base/icons/src/vender/line/financeAndECommerce' import Checkbox from '@/app/components/base/checkbox' import type { Label } from '@/app/components/tools/labels/constant' -import { fetchLabelList } from '@/service/tools' -import I18n from '@/context/i18n' -import { getLanguage } from '@/i18n/language' +import { useTags } from '@/app/components/plugins/hooks' type LabelSelectorProps = { value: string[] @@ -28,12 +24,9 @@ const LabelSelector: FC<LabelSelectorProps> = ({ onChange, }) => { const { t } = useTranslation() - const { locale } = useContext(I18n) - const language = getLanguage(locale) const [open, setOpen] = useState(false) - const labelList = useLabelStore(s => s.labelList) - const setLabelList = useLabelStore(s => s.setLabelList) + const { tags: labelList } = useTags() const [keywords, setKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('') @@ -50,8 +43,8 @@ const LabelSelector: FC<LabelSelectorProps> = ({ }, [labelList, searchKeywords]) const selectedLabels = useMemo(() => { - return value.map(v => labelList.find(l => l.name === v)?.label[language]).join(', ') - }, [value, labelList, language]) + return value.map(v => labelList.find(l => l.name === v)?.label).join(', ') + }, [value, labelList]) const selectLabel = (label: Label) => { if (value.includes(label.name)) @@ -60,12 +53,6 @@ const LabelSelector: FC<LabelSelectorProps> = ({ onChange([...value, label.name]) } - useMount(() => { - fetchLabelList().then((res) => { - setLabelList(res) - }) - }) - return ( <PortalToFollowElem open={open} @@ -79,21 +66,21 @@ const LabelSelector: FC<LabelSelectorProps> = ({ className='block' > <div className={cn( - 'flex items-center gap-1 px-3 h-10 rounded-lg border-[0.5px] border-transparent bg-gray-100 cursor-pointer hover:bg-gray-200', - open && '!bg-gray-200 hover:bg-gray-200', + 'flex items-center gap-1 px-3 h-10 rounded-lg border-[0.5px] border-transparent bg-components-input-bg-normal cursor-pointer hover:bg-components-input-bg-hover', + open && '!hover:bg-components-input-bg-hover hover:bg-components-input-bg-hover', )}> - <div title={value.length > 0 ? selectedLabels : ''} className={cn('grow text-[13px] leading-[18px] text-gray-700 truncate', !value.length && '!text-gray-400')}> + <div title={value.length > 0 ? selectedLabels : ''} className={cn('grow text-[13px] leading-[18px] text-text-secondary truncate', !value.length && '!text-text-quaternary')}> {!value.length && t('tools.createTool.toolInput.labelPlaceholder')} {!!value.length && selectedLabels} </div> - <div className='shrink-0 ml-1 text-gray-700 opacity-60'> + <div className='shrink-0 ml-1 text-text-secondary opacity-60'> <RiArrowDownSLine className='h-4 w-4' /> </div> </div> </PortalToFollowElemTrigger> <PortalToFollowElemContent className='z-[1040]'> - <div className='relative w-[591px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'> - <div className='p-2 border-b-[0.5px] border-black/5'> + <div className='relative w-[591px] bg-components-panel-bg-blur backdrop-blur-[5px] rounded-lg border-[0.5px] border-components-panel-border shadow-lg'> + <div className='p-2 border-b-[0.5px] border-divider-regular'> <Input showLeftIcon showClearIcon @@ -106,7 +93,7 @@ const LabelSelector: FC<LabelSelectorProps> = ({ {filteredLabelList.map(label => ( <div key={label.name} - className='flex items-center gap-2 pl-3 py-[6px] pr-2 rounded-lg cursor-pointer hover:bg-gray-100' + className='flex items-center gap-2 pl-3 py-[6px] pr-2 rounded-lg cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover' onClick={() => selectLabel(label)} > <Checkbox @@ -114,13 +101,13 @@ const LabelSelector: FC<LabelSelectorProps> = ({ checked={value.includes(label.name)} onCheck={() => { }} /> - <div title={label.label[language]} className='grow text-sm text-gray-700 leading-5 truncate'>{label.label[language]}</div> + <div title={label.label} className='grow text-sm text-text-secondary leading-5 truncate'>{label.label}</div> </div> ))} {!filteredLabelList.length && ( <div className='p-3 flex flex-col items-center gap-1'> - <Tag03 className='h-6 w-6 text-gray-300' /> - <div className='text-gray-500 text-xs leading-[14px]'>{t('common.tag.noTag')}</div> + <Tag03 className='h-6 w-6 text-text-quaternary' /> + <div className='text-text-tertiary text-xs leading-[14px]'>{t('common.tag.noTag')}</div> </div> )} </div> diff --git a/web/app/components/tools/labels/store.ts b/web/app/components/tools/labels/store.ts deleted file mode 100644 index c19991dfd4..0000000000 --- a/web/app/components/tools/labels/store.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { create } from 'zustand' -import type { Label } from './constant' - -type State = { - labelList: Label[] -} - -type Action = { - setLabelList: (labelList?: Label[]) => void -} - -export const useStore = create<State & Action>(set => ({ - labelList: [], - setLabelList: labelList => set(() => ({ labelList })), -})) diff --git a/web/app/components/tools/marketplace/hooks.ts b/web/app/components/tools/marketplace/hooks.ts new file mode 100644 index 0000000000..0790d52721 --- /dev/null +++ b/web/app/components/tools/marketplace/hooks.ts @@ -0,0 +1,117 @@ +import { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react' +import { + useMarketplaceCollectionsAndPlugins, + useMarketplacePlugins, +} from '@/app/components/plugins/marketplace/hooks' +import { PluginType } from '@/app/components/plugins/types' +import { getMarketplaceListCondition } from '@/app/components/plugins/marketplace/utils' +import { useAllToolProviders } from '@/service/use-tools' + +export const useMarketplace = (searchPluginText: string, filterPluginTags: string[]) => { + const { data: toolProvidersData, isSuccess } = useAllToolProviders() + const exclude = useMemo(() => { + if (isSuccess) + return toolProvidersData?.filter(toolProvider => !!toolProvider.plugin_id).map(toolProvider => toolProvider.plugin_id!) + }, [isSuccess, toolProvidersData]) + const { + isLoading, + marketplaceCollections, + marketplaceCollectionPluginsMap, + queryMarketplaceCollectionsAndPlugins, + } = useMarketplaceCollectionsAndPlugins() + const { + plugins, + resetPlugins, + queryPlugins, + queryPluginsWithDebounced, + isLoading: isPluginsLoading, + total: pluginsTotal, + } = useMarketplacePlugins() + const [page, setPage] = useState(1) + const pageRef = useRef(page) + const searchPluginTextRef = useRef(searchPluginText) + const filterPluginTagsRef = useRef(filterPluginTags) + + useEffect(() => { + searchPluginTextRef.current = searchPluginText + filterPluginTagsRef.current = filterPluginTags + }, [searchPluginText, filterPluginTags]) + useEffect(() => { + if ((searchPluginText || filterPluginTags.length) && isSuccess) { + setPage(1) + pageRef.current = 1 + + if (searchPluginText) { + queryPluginsWithDebounced({ + category: PluginType.tool, + query: searchPluginText, + tags: filterPluginTags, + exclude, + type: 'plugin', + page: pageRef.current, + }) + return + } + queryPlugins({ + category: PluginType.tool, + query: searchPluginText, + tags: filterPluginTags, + exclude, + type: 'plugin', + page: pageRef.current, + }) + } + else { + if (isSuccess) { + queryMarketplaceCollectionsAndPlugins({ + category: PluginType.tool, + condition: getMarketplaceListCondition(PluginType.tool), + exclude, + type: 'plugin', + }) + resetPlugins() + } + } + }, [searchPluginText, filterPluginTags, queryPlugins, queryMarketplaceCollectionsAndPlugins, queryPluginsWithDebounced, resetPlugins, exclude, isSuccess]) + + const handleScroll = useCallback((e: Event) => { + const target = e.target as HTMLDivElement + const { + scrollTop, + scrollHeight, + clientHeight, + } = target + if (scrollTop + clientHeight >= scrollHeight - 5 && scrollTop > 0) { + const searchPluginText = searchPluginTextRef.current + const filterPluginTags = filterPluginTagsRef.current + if (pluginsTotal && plugins && pluginsTotal > plugins.length && (!!searchPluginText || !!filterPluginTags.length)) { + setPage(pageRef.current + 1) + pageRef.current++ + + queryPlugins({ + category: PluginType.tool, + query: searchPluginText, + tags: filterPluginTags, + exclude, + type: 'plugin', + page: pageRef.current, + }) + } + } + }, [exclude, plugins, pluginsTotal, queryPlugins]) + + return { + isLoading: isLoading || isPluginsLoading, + marketplaceCollections, + marketplaceCollectionPluginsMap, + plugins, + handleScroll, + page, + } +} diff --git a/web/app/components/tools/marketplace/index.tsx b/web/app/components/tools/marketplace/index.tsx new file mode 100644 index 0000000000..2b560b8a13 --- /dev/null +++ b/web/app/components/tools/marketplace/index.tsx @@ -0,0 +1,117 @@ +import { + useEffect, + useRef, +} from 'react' +import { + RiArrowRightUpLine, + RiArrowUpDoubleLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { useMarketplace } from './hooks' +import List from '@/app/components/plugins/marketplace/list' +import Loading from '@/app/components/base/loading' +import { getLocaleOnClient } from '@/i18n' +import { MARKETPLACE_URL_PREFIX } from '@/config' + +type MarketplaceProps = { + searchPluginText: string + filterPluginTags: string[] + onMarketplaceScroll: () => void +} +const Marketplace = ({ + searchPluginText, + filterPluginTags, + onMarketplaceScroll, +}: MarketplaceProps) => { + const locale = getLocaleOnClient() + const { t } = useTranslation() + + const { + isLoading, + marketplaceCollections, + marketplaceCollectionPluginsMap, + plugins, + handleScroll, + page, + } = useMarketplace(searchPluginText, filterPluginTags) + const containerRef = useRef<HTMLDivElement>(null) + + useEffect(() => { + const container = containerRef.current + if (container) + container.addEventListener('scroll', handleScroll) + + return () => { + if (container) + container.removeEventListener('scroll', handleScroll) + } + }, [handleScroll]) + + return ( + <div + ref={containerRef} + className='grow flex flex-col shrink-0 sticky bottom-[-442px] h-[530px] overflow-y-auto px-12 py-2 pt-0 bg-background-default-subtle' + > + <RiArrowUpDoubleLine + className='absolute top-2 left-1/2 -translate-x-1/2 w-4 h-4 text-text-quaternary cursor-pointer' + onClick={() => onMarketplaceScroll()} + /> + <div className='sticky top-0 pt-5 pb-3 bg-background-default-subtle z-10'> + <div className='title-2xl-semi-bold bg-gradient-to-r from-[rgba(11,165,236,0.95)] to-[rgba(21,90,239,0.95)] bg-clip-text text-transparent'> + {t('plugin.marketplace.moreFrom')} + </div> + <div className='flex items-center text-center body-md-regular text-text-tertiary'> + {t('plugin.marketplace.discover')} + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected"> + {t('plugin.category.models')} + </span> + , + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected"> + {t('plugin.category.tools')} + </span> + , + <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected"> + {t('plugin.category.agents')} + </span> + , + <span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected"> + {t('plugin.category.extensions')} + </span> + {t('plugin.marketplace.and')} + <span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected"> + {t('plugin.category.bundles')} + </span> + {t('common.operation.in')} + <a + href={`${MARKETPLACE_URL_PREFIX}?language=${locale}&q=${searchPluginText}&tags=${filterPluginTags.join(',')}`} + className='flex items-center ml-1 system-sm-medium text-text-accent' + target='_blank' + > + {t('plugin.marketplace.difyMarketplace')} + <RiArrowRightUpLine className='w-4 h-4' /> + </a> + </div> + </div> + { + isLoading && page === 1 && ( + <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'> + <Loading /> + </div> + ) + } + { + (!isLoading || page > 1) && ( + <List + marketplaceCollections={marketplaceCollections || []} + marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}} + plugins={plugins} + showInstallButton + locale={locale} + /> + ) + } + </div> + ) +} + +export default Marketplace diff --git a/web/app/components/tools/provider-list.tsx b/web/app/components/tools/provider-list.tsx index 6f17835589..148612bedc 100644 --- a/web/app/components/tools/provider-list.tsx +++ b/web/app/components/tools/provider-list.tsx @@ -1,33 +1,36 @@ 'use client' -import { useEffect, useMemo, useState } from 'react' +import { useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { RiCloseLine } from '@remixicon/react' import type { Collection } from './types' +import Marketplace from './marketplace' import cn from '@/utils/classnames' import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import TabSliderNew from '@/app/components/base/tab-slider-new' import LabelFilter from '@/app/components/tools/labels/filter' import Input from '@/app/components/base/input' -import { DotsGrid } from '@/app/components/base/icons/src/vender/line/general' -import { Colors } from '@/app/components/base/icons/src/vender/line/others' -import { Route } from '@/app/components/base/icons/src/vender/line/mapsAndTravel' -import CustomCreateCard from '@/app/components/tools/provider/custom-create-card' -import ContributeCard from '@/app/components/tools/provider/contribute' -import ProviderCard from '@/app/components/tools/provider/card' import ProviderDetail from '@/app/components/tools/provider/detail' -import Empty from '@/app/components/tools/add-tool-modal/empty' -import { fetchCollectionList } from '@/service/tools' +import Empty from '@/app/components/plugins/marketplace/empty' +import CustomCreateCard from '@/app/components/tools/provider/custom-create-card' +import WorkflowToolEmpty from '@/app/components/tools/add-tool-modal/empty' +import Card from '@/app/components/plugins/card' +import CardMoreInfo from '@/app/components/plugins/card/card-more-info' +import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import { useAllToolProviders } from '@/service/use-tools' +import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' const ProviderList = () => { const { t } = useTranslation() + const containerRef = useRef<HTMLDivElement>(null) + const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) const [activeTab, setActiveTab] = useTabSearchParams({ defaultTab: 'builtin', }) const options = [ - { value: 'builtin', text: t('tools.type.builtIn'), icon: <DotsGrid className='w-[14px] h-[14px] mr-1' /> }, - { value: 'api', text: t('tools.type.custom'), icon: <Colors className='w-[14px] h-[14px] mr-1' /> }, - { value: 'workflow', text: t('tools.type.workflow'), icon: <Route className='w-[14px] h-[14px] mr-1' /> }, + { value: 'builtin', text: t('tools.type.builtIn') }, + { value: 'api', text: t('tools.type.custom') }, + { value: 'workflow', text: t('tools.type.workflow') }, ] const [tagFilterValue, setTagFilterValue] = useState<string[]>([]) const handleTagsChange = (value: string[]) => { @@ -37,8 +40,7 @@ const ProviderList = () => { const handleKeywordsChange = (value: string) => { setKeywords(value) } - - const [collectionList, setCollectionList] = useState<Collection[]>([]) + const { data: collectionList = [], refetch } = useAllToolProviders() const filteredCollectionList = useMemo(() => { return collectionList.filter((collection) => { if (collection.type !== activeTab) @@ -50,75 +52,108 @@ const ProviderList = () => { return true }) }, [activeTab, tagFilterValue, keywords, collectionList]) - const getProviderList = async () => { - const list = await fetchCollectionList() - setCollectionList([...list]) - } - useEffect(() => { - getProviderList() - }, []) const [currentProvider, setCurrentProvider] = useState<Collection | undefined>() - useEffect(() => { - if (currentProvider && collectionList.length > 0) { - const newCurrentProvider = collectionList.find(collection => collection.id === currentProvider.id) - setCurrentProvider(newCurrentProvider) - } - }, [collectionList, currentProvider]) + const { data: pluginList } = useInstalledPluginList() + const invalidateInstalledPluginList = useInvalidateInstalledPluginList() + const currentPluginDetail = useMemo(() => { + const detail = pluginList?.plugins.find(plugin => plugin.plugin_id === currentProvider?.plugin_id) + return detail + }, [currentProvider?.plugin_id, pluginList?.plugins]) return ( - <div className='relative flex overflow-hidden bg-gray-100 shrink-0 h-0 grow'> - <div className='relative flex flex-col overflow-y-auto bg-gray-100 grow'> - <div className={cn( - 'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] bg-gray-100 z-20 flex-wrap gap-y-2', - currentProvider && 'pr-6', - )}> - <TabSliderNew - value={activeTab} - onChange={(state) => { - setActiveTab(state) - if (state !== activeTab) - setCurrentProvider(undefined) - }} - options={options} - /> - <div className='flex items-center gap-2'> - <LabelFilter value={tagFilterValue} onChange={handleTagsChange} /> - <Input - showLeftIcon - showClearIcon - wrapperClassName='w-[200px]' - value={keywords} - onChange={e => handleKeywordsChange(e.target.value)} - onClear={() => handleKeywordsChange('')} + <> + <div className='relative flex overflow-hidden shrink-0 h-0 grow'> + <div + ref={containerRef} + className='relative flex flex-col overflow-y-auto bg-background-body grow' + > + <div className={cn( + 'sticky top-0 flex justify-between items-center pt-4 px-12 pb-2 leading-[56px] z-20 flex-wrap gap-y-2', + currentProvider && 'pr-6', + )}> + <TabSliderNew + value={activeTab} + onChange={(state) => { + setActiveTab(state) + if (state !== activeTab) + setCurrentProvider(undefined) + }} + options={options} /> + <div className='flex items-center gap-2'> + <LabelFilter value={tagFilterValue} onChange={handleTagsChange} /> + <Input + showLeftIcon + showClearIcon + wrapperClassName='w-[200px]' + value={keywords} + onChange={e => handleKeywordsChange(e.target.value)} + onClear={() => handleKeywordsChange('')} + /> + </div> </div> - </div> - <div className={cn( - 'relative grid content-start grid-cols-1 gap-4 px-12 pt-2 pb-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 grow shrink-0', - currentProvider && 'pr-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3', - )}> - {activeTab === 'builtin' && <ContributeCard />} - {activeTab === 'api' && <CustomCreateCard onRefreshData={getProviderList} />} - {filteredCollectionList.map(collection => ( - <ProviderCard - active={currentProvider?.id === collection.id} - onSelect={() => setCurrentProvider(collection)} - key={collection.id} - collection={collection} - /> - ))} - {!filteredCollectionList.length && <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'><Empty /></div>} + {(filteredCollectionList.length > 0 || activeTab !== 'builtin') && ( + <div className={cn( + 'relative grid content-start grid-cols-1 gap-4 px-12 pt-2 pb-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 shrink-0', + !filteredCollectionList.length && activeTab === 'workflow' && 'grow', + )}> + {activeTab === 'api' && <CustomCreateCard onRefreshData={refetch} />} + {filteredCollectionList.map(collection => ( + <div + key={collection.id} + onClick={() => setCurrentProvider(collection)} + > + <Card + className={cn( + 'border-[1.5px] border-transparent cursor-pointer', + currentProvider?.id === collection.id && 'border-components-option-card-option-selected-border', + )} + hideCornerMark + payload={{ + ...collection, + brief: collection.description, + } as any} + footer={ + <CardMoreInfo + tags={collection.labels} + /> + } + /> + </div> + ))} + {!filteredCollectionList.length && activeTab === 'workflow' && <div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'><WorkflowToolEmpty /></div>} + </div> + )} + {!filteredCollectionList.length && activeTab === 'builtin' && ( + <Empty lightCard text={t('tools.noTools')} className='px-12 h-[224px]' /> + )} + { + enable_marketplace && activeTab === 'builtin' && ( + <Marketplace + onMarketplaceScroll={() => { + containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' }) + }} + searchPluginText={keywords} + filterPluginTags={tagFilterValue} + /> + ) + } </div> </div> - <div className={cn( - 'shrink-0 w-0 border-l-[0.5px] border-black/8 overflow-y-auto transition-all duration-200 ease-in-out', - currentProvider && 'w-[420px]', - )}> - {currentProvider && <ProviderDetail collection={currentProvider} onRefreshData={getProviderList} />} - </div> - <div className='absolute top-5 right-5 p-1 cursor-pointer' onClick={() => setCurrentProvider(undefined)}><RiCloseLine className='w-4 h-4' /></div> - </div> + {currentProvider && !currentProvider.plugin_id && ( + <ProviderDetail + collection={currentProvider} + onHide={() => setCurrentProvider(undefined)} + onRefreshData={refetch} + /> + )} + <PluginDetailPanel + detail={currentPluginDetail} + onUpdate={() => invalidateInstalledPluginList()} + onHide={() => setCurrentProvider(undefined)} + /> + </> ) } ProviderList.displayName = 'ToolProviderList' diff --git a/web/app/components/tools/provider/custom-create-card.tsx b/web/app/components/tools/provider/custom-create-card.tsx index d6aa9ab533..9ae1714a27 100644 --- a/web/app/components/tools/provider/custom-create-card.tsx +++ b/web/app/components/tools/provider/custom-create-card.tsx @@ -45,16 +45,16 @@ const Contribute = ({ onRefreshData }: Props) => { return ( <> {isCurrentWorkspaceManager && ( - <div className='flex flex-col col-span-1 bg-gray-200 border-[0.5px] border-black/5 rounded-xl min-h-[160px] transition-all duration-200 ease-in-out cursor-pointer hover:bg-gray-50 hover:shadow-lg'> - <div className='group grow rounded-t-xl hover:bg-white' onClick={() => setIsShowEditCustomCollectionModal(true)}> + <div className='flex flex-col col-span-1 bg-components-panel-on-panel-item-bg border-[0.5px] border-divider-subtle rounded-xl min-h-[135px] transition-all duration-200 ease-in-out cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover hover:shadow-lg'> + <div className='group grow rounded-t-xl hover:bg-background-body' onClick={() => setIsShowEditCustomCollectionModal(true)}> <div className='shrink-0 flex items-center p-4 pb-3'> - <div className='w-10 h-10 flex items-center justify-center border border-gray-200 bg-gray-100 rounded-lg group-hover:border-primary-100 group-hover:bg-primary-50'> - <RiAddLine className='w-4 h-4 text-gray-500 group-hover:text-primary-600'/> + <div className='w-10 h-10 flex items-center justify-center border border-components-option-card-option-border bg-components-option-card-option-bg rounded-lg group-hover:border-components-option-card-option-border-hover group-hover:bg-components-option-card-option-bg-hover'> + <RiAddLine className='w-4 h-4 text-text-tertiary group-hover:text-text-accent'/> </div> - <div className='ml-3 text-sm font-semibold leading-5 text-gray-800 group-hover:text-primary-600'>{t('tools.createCustomTool')}</div> + <div className='ml-3 text-sm font-semibold leading-5 text-text-primary group-hover:text-text-accent'>{t('tools.createCustomTool')}</div> </div> </div> - <div className='px-4 py-3 rounded-b-xl border-t-[0.5px] border-black/5 text-gray-500 hover:text-[#155EEF] hover:bg-white'> + <div className='px-4 py-3 rounded-b-xl border-t-[0.5px] border-divider-regular text-text-tertiary hover:text-text-accent hover:bg-background-body'> <a href={linkUrl} target='_blank' rel='noopener noreferrer' className='flex items-center space-x-1'> <BookOpen01 className='shrink-0 w-3 h-3' /> <div className='grow leading-[18px] text-xs font-normal truncate' title={t('tools.customToolTip') || ''}>{t('tools.customToolTip')}</div> diff --git a/web/app/components/tools/provider/detail.tsx b/web/app/components/tools/provider/detail.tsx index 566fe4623a..2143ca0b39 100644 --- a/web/app/components/tools/provider/detail.tsx +++ b/web/app/components/tools/provider/detail.tsx @@ -2,6 +2,9 @@ import React, { useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { useContext } from 'use-context-selector' +import { + RiCloseLine, +} from '@remixicon/react' import { AuthHeaderPrefix, AuthType, CollectionType } from '../types' import type { Collection, CustomCollectionBackend, Tool, WorkflowToolProviderRequest, WorkflowToolProviderResponse } from '../types' import ToolItem from './tool-item' @@ -9,14 +12,20 @@ import cn from '@/utils/classnames' import I18n from '@/context/i18n' import { getLanguage } from '@/i18n/language' import Confirm from '@/app/components/base/confirm' -import AppIcon from '@/app/components/base/app-icon' import Button from '@/app/components/base/button' import Indicator from '@/app/components/header/indicator' import { LinkExternal02, Settings01 } from '@/app/components/base/icons/src/vender/line/general' +import Icon from '@/app/components/plugins/card/base/card-icon' +import Title from '@/app/components/plugins/card/base/title' +import OrgInfo from '@/app/components/plugins/card/base/org-info' +import Description from '@/app/components/plugins/card/base/description' import ConfigCredential from '@/app/components/tools/setting/build-in/config-credentials' import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal' import WorkflowToolModal from '@/app/components/tools/workflow-tool' import Toast from '@/app/components/base/toast' +import Drawer from '@/app/components/base/drawer' +import ActionButton from '@/app/components/base/action-button' + import { deleteWorkflowTool, fetchBuiltInToolList, @@ -35,14 +44,17 @@ import { useProviderContext } from '@/context/provider-context' import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' import Loading from '@/app/components/base/loading' import { useAppContext } from '@/context/app-context' +import { useInvalidateAllWorkflowTools } from '@/service/use-tools' type Props = { collection: Collection + onHide: () => void onRefreshData: () => void } const ProviderDetail = ({ collection, + onHide, onRefreshData, }: Props) => { const { t } = useTranslation() @@ -54,7 +66,7 @@ const ProviderDetail = ({ const isBuiltIn = collection.type === CollectionType.builtIn const isModel = collection.type === CollectionType.model const { isCurrentWorkspaceManager } = useAppContext() - + const invalidateAllWorkflowTools = useInvalidateAllWorkflowTools() const [isDetailLoading, setIsDetailLoading] = useState(false) // built in provider @@ -153,6 +165,7 @@ const ProviderDetail = ({ workflow_tool_id: string }>) => { await saveWorkflowToolProvider(data) + invalidateAllWorkflowTools() onRefreshData() getWorkflowToolProvider() Toast.notify({ @@ -213,164 +226,203 @@ const ProviderDetail = ({ }, [collection.name, collection.type, getCustomProvider, getProviderToolList, getWorkflowToolProvider]) return ( - <div className='px-6 py-3'> - <div className='flex items-center py-1 gap-2'> - <div className='relative shrink-0'> - {typeof collection.icon === 'string' && ( - <div className='w-8 h-8 bg-center bg-cover bg-no-repeat rounded-md' style={{ backgroundImage: `url(${collection.icon})` }} /> - )} - {typeof collection.icon !== 'string' && ( - <AppIcon - size='small' - icon={collection.icon.content} - background={collection.icon.background} - /> - )} - </div> - <div className='grow w-0 py-[1px]'> - <div className='flex items-center text-md leading-6 font-semibold text-gray-900'> - <div className='truncate' title={collection.label[language]}>{collection.label[language]}</div> - </div> - </div> - </div> - <div className='mt-2 min-h-[36px] text-gray-500 text-sm leading-[18px]'>{collection.description[language]}</div> - <div className='flex gap-1 border-b-[0.5px] border-black/5'> - {(collection.type === CollectionType.builtIn) && needAuth && ( - <Button - variant={isAuthed ? 'secondary' : 'primary'} - className={cn('shrink-0 my-3 w-full', isAuthed && 'bg-white')} - onClick={() => { - if (collection.type === CollectionType.builtIn || collection.type === CollectionType.model) - showSettingAuthModal() - }} - disabled={!isCurrentWorkspaceManager} - > - {isAuthed && <Indicator className='mr-2' color={'green'} />} - <div className={cn('text-white leading-[18px] text-[13px] font-medium', isAuthed && '!text-gray-700')}> - {isAuthed ? t('tools.auth.authorized') : t('tools.auth.unauthorized')} + <Drawer + isOpen={!!collection} + clickOutsideNotOpen={false} + onClose={onHide} + footer={null} + mask={false} + positionCenter={false} + panelClassname={cn('justify-start mt-[64px] mr-2 mb-2 !w-[420px] !max-w-[420px] !p-0 !bg-components-panel-bg rounded-2xl border-[0.5px] border-components-panel-border shadow-xl')} + > + <div className='p-4'> + <div className='mb-3 flex'> + <Icon src={collection.icon} /> + <div className="ml-3 w-0 grow"> + <div className="flex items-center h-5"> + <Title title={collection.label[language]} /> </div> - </Button> - )} - {collection.type === CollectionType.custom && !isDetailLoading && ( - <Button - className={cn('shrink-0 my-3 w-full')} - onClick={() => setIsShowEditCustomCollectionModal(true)} - > - <Settings01 className='mr-1 w-4 h-4 text-gray-500' /> - <div className='leading-5 text-sm font-medium text-gray-700'>{t('tools.createTool.editAction')}</div> - </Button> - )} - {collection.type === CollectionType.workflow && !isDetailLoading && customCollection && ( - <> - <Button - variant='primary' - className={cn('shrink-0 my-3 w-[183px]')} - > - <a className='flex items-center text-white' href={`/app/${(customCollection as WorkflowToolProviderResponse).workflow_app_id}/workflow`} rel='noreferrer' target='_blank'> - <div className='leading-5 text-sm font-medium'>{t('tools.openInStudio')}</div> - <LinkExternal02 className='ml-1 w-4 h-4' /> - </a> - </Button> - <Button - className={cn('shrink-0 my-3 w-[183px]')} - onClick={() => setIsShowEditWorkflowToolModal(true)} - disabled={!isCurrentWorkspaceManager} - > - <div className='leading-5 text-sm font-medium text-gray-700'>{t('tools.createTool.editAction')}</div> - </Button> - </> - )} - </div> - {/* Tools */} - <div className='pt-3'> - {isDetailLoading && <div className='flex h-[200px]'><Loading type='app' /></div>} - {!isDetailLoading && ( - <div className='text-xs font-medium leading-6 text-gray-500'> - {collection.type === CollectionType.workflow && <span className=''>{t('tools.createTool.toolInput.title').toLocaleUpperCase()}</span>} - {collection.type !== CollectionType.workflow && <span className=''>{t('tools.includeToolNum', { num: toolList.length }).toLocaleUpperCase()}</span>} - {needAuth && (isBuiltIn || isModel) && !isAuthed && ( - <> - <span className='px-1'>·</span> - <span className='text-[#DC6803]'>{t('tools.auth.setup').toLocaleUpperCase()}</span> - </> - )} - </div> - )} - {!isDetailLoading && ( - <div className='mt-1'> - {collection.type !== CollectionType.workflow && toolList.map(tool => ( - <ToolItem - key={tool.name} - disabled={needAuth && (isBuiltIn || isModel) && !isAuthed} - collection={collection} - tool={tool} - isBuiltIn={isBuiltIn} - isModel={isModel} + <div className='mb-1 flex justify-between items-center h-4'> + <OrgInfo + className="mt-0.5" + packageNameClassName='w-auto' + orgName={collection.author} + packageName={collection.name} /> - ))} - {collection.type === CollectionType.workflow && (customCollection as WorkflowToolProviderResponse)?.tool?.parameters.map(item => ( - <div key={item.name} className='mb-2 px-4 py-3 rounded-xl bg-gray-25 border-[0.5px] border-gray-200'> - <div className='flex items-center gap-2'> - <span className='font-medium text-sm text-gray-900'>{item.name}</span> - <span className='text-xs leading-[18px] text-gray-500'>{item.type}</span> - <span className='font-medium text-xs leading-[18px] text-[#ec4a0a]'>{item.required ? t('tools.createTool.toolInput.required') : ''}</span> - </div> - <div className='h-[18px] leading-[18px] text-gray-500 text-xs'>{item.llm_description}</div> - </div> - ))} + </div> </div> + <div className='flex gap-1'> + <ActionButton onClick={onHide}> + <RiCloseLine className='w-4 h-4' /> + </ActionButton> + </div> + </div> + {!!collection.description[language] && ( + <Description text={collection.description[language]} descriptionLineRows={2}></Description> + )} + <div className='flex gap-1 border-b-[0.5px] border-divider-subtle'> + {collection.type === CollectionType.custom && !isDetailLoading && ( + <Button + className={cn('shrink-0 my-3 w-full')} + onClick={() => setIsShowEditCustomCollectionModal(true)} + > + <Settings01 className='mr-1 w-4 h-4 text-text-tertiary' /> + <div className='system-sm-medium text-text-secondary'>{t('tools.createTool.editAction')}</div> + </Button> + )} + {collection.type === CollectionType.workflow && !isDetailLoading && customCollection && ( + <> + <Button + variant='primary' + className={cn('shrink-0 my-3 w-[183px]')} + > + <a className='flex items-center text-text-primary' href={`/app/${(customCollection as WorkflowToolProviderResponse).workflow_app_id}/workflow`} rel='noreferrer' target='_blank'> + <div className='system-sm-medium'>{t('tools.openInStudio')}</div> + <LinkExternal02 className='ml-1 w-4 h-4' /> + </a> + </Button> + <Button + className={cn('shrink-0 my-3 w-[183px]')} + onClick={() => setIsShowEditWorkflowToolModal(true)} + disabled={!isCurrentWorkspaceManager} + > + <div className='system-sm-medium text-text-secondary'>{t('tools.createTool.editAction')}</div> + </Button> + </> + )} + </div> + {/* Tools */} + <div className='pt-3'> + {isDetailLoading && <div className='flex h-[200px]'><Loading type='app' /></div>} + {/* Builtin type */} + {!isDetailLoading && (collection.type === CollectionType.builtIn) && isAuthed && ( + <div className='mb-1 h-6 flex items-center justify-between text-text-secondary system-sm-semibold-uppercase'> + {t('plugin.detailPanel.actionNum', { num: toolList.length, action: toolList.length > 1 ? 'actions' : 'action' })} + {needAuth && ( + <Button + variant='secondary' + size='small' + onClick={() => { + if (collection.type === CollectionType.builtIn || collection.type === CollectionType.model) + showSettingAuthModal() + }} + disabled={!isCurrentWorkspaceManager} + > + <Indicator className='mr-2' color={'green'} /> + {t('tools.auth.authorized')} + </Button> + )} + </div> + )} + {!isDetailLoading && (collection.type === CollectionType.builtIn) && needAuth && !isAuthed && ( + <> + <div className='text-text-secondary system-sm-semibold-uppercase'> + <span className=''>{t('tools.includeToolNum', { num: toolList.length, action: toolList.length > 1 ? 'actions' : 'action' }).toLocaleUpperCase()}</span> + <span className='px-1'>·</span> + <span className='text-util-colors-orange-orange-600'>{t('tools.auth.setup').toLocaleUpperCase()}</span> + </div> + <Button + variant='primary' + className={cn('shrink-0 my-3 w-full')} + onClick={() => { + if (collection.type === CollectionType.builtIn || collection.type === CollectionType.model) + showSettingAuthModal() + }} + disabled={!isCurrentWorkspaceManager} + > + {t('tools.auth.unauthorized')} + </Button> + </> + )} + {/* Custom type */} + {!isDetailLoading && (collection.type === CollectionType.custom) && ( + <div className='text-text-secondary system-sm-semibold-uppercase'> + <span className=''>{t('tools.includeToolNum', { num: toolList.length }).toLocaleUpperCase()}</span> + </div> + )} + {/* Workflow type */} + {!isDetailLoading && (collection.type === CollectionType.workflow) && ( + <div className='text-text-secondary system-sm-semibold-uppercase'> + <span className=''>{t('tools.createTool.toolInput.title').toLocaleUpperCase()}</span> + </div> + )} + {!isDetailLoading && ( + <div className='mt-1 py-2'> + {collection.type !== CollectionType.workflow && toolList.map(tool => ( + <ToolItem + key={tool.name} + disabled={false} + // disabled={needAuth && (isBuiltIn || isModel) && !isAuthed} + collection={collection} + tool={tool} + isBuiltIn={isBuiltIn} + isModel={isModel} + /> + ))} + {collection.type === CollectionType.workflow && (customCollection as WorkflowToolProviderResponse)?.tool?.parameters.map(item => ( + <div key={item.name} className='mb-1 py-1'> + <div className='mb-1 flex items-center gap-2'> + <span className='text-text-secondary code-sm-semibold'>{item.name}</span> + <span className='text-text-tertiary system-xs-regular'>{item.type}</span> + <span className='text-text-warning-secondary system-xs-medium'>{item.required ? t('tools.createTool.toolInput.required') : ''}</span> + </div> + <div className='text-text-tertiary system-xs-regular'>{item.llm_description}</div> + </div> + ))} + </div> + )} + </div> + {showSettingAuth && ( + <ConfigCredential + collection={collection} + onCancel={() => setShowSettingAuth(false)} + onSaved={async (value) => { + await updateBuiltInToolCredential(collection.name, value) + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + await onRefreshData() + setShowSettingAuth(false) + }} + onRemove={async () => { + await removeBuiltInToolCredential(collection.name) + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + await onRefreshData() + setShowSettingAuth(false) + }} + /> + )} + {isShowEditCollectionToolModal && ( + <EditCustomToolModal + payload={customCollection} + onHide={() => setIsShowEditCustomCollectionModal(false)} + onEdit={doUpdateCustomToolCollection} + onRemove={onClickCustomToolDelete} + /> + )} + {isShowEditWorkflowToolModal && ( + <WorkflowToolModal + payload={customCollection} + onHide={() => setIsShowEditWorkflowToolModal(false)} + onRemove={onClickWorkflowToolDelete} + onSave={updateWorkflowToolProvider} + /> + )} + {showConfirmDelete && ( + <Confirm + title={t('tools.createTool.deleteToolConfirmTitle')} + content={t('tools.createTool.deleteToolConfirmContent')} + isShow={showConfirmDelete} + onConfirm={handleConfirmDelete} + onCancel={() => setShowConfirmDelete(false)} + /> )} </div> - {showSettingAuth && ( - <ConfigCredential - collection={collection} - onCancel={() => setShowSettingAuth(false)} - onSaved={async (value) => { - await updateBuiltInToolCredential(collection.name, value) - Toast.notify({ - type: 'success', - message: t('common.api.actionSuccess'), - }) - await onRefreshData() - setShowSettingAuth(false) - }} - onRemove={async () => { - await removeBuiltInToolCredential(collection.name) - Toast.notify({ - type: 'success', - message: t('common.api.actionSuccess'), - }) - await onRefreshData() - setShowSettingAuth(false) - }} - /> - )} - {isShowEditCollectionToolModal && ( - <EditCustomToolModal - payload={customCollection} - onHide={() => setIsShowEditCustomCollectionModal(false)} - onEdit={doUpdateCustomToolCollection} - onRemove={onClickCustomToolDelete} - /> - )} - {isShowEditWorkflowToolModal && ( - <WorkflowToolModal - payload={customCollection} - onHide={() => setIsShowEditWorkflowToolModal(false)} - onRemove={onClickWorkflowToolDelete} - onSave={updateWorkflowToolProvider} - /> - )} - {showConfirmDelete && ( - <Confirm - title={t('tools.createTool.deleteToolConfirmTitle')} - content={t('tools.createTool.deleteToolConfirmContent')} - isShow={showConfirmDelete} - onConfirm={handleConfirmDelete} - onCancel={() => setShowConfirmDelete(false)} - /> - )} - </div> + </Drawer> ) } export default ProviderDetail diff --git a/web/app/components/tools/provider/tool-item.tsx b/web/app/components/tools/provider/tool-item.tsx index 2133f9221a..89bb779f6a 100644 --- a/web/app/components/tools/provider/tool-item.tsx +++ b/web/app/components/tools/provider/tool-item.tsx @@ -29,14 +29,15 @@ const ToolItem = ({ return ( <> <div - className={cn('mb-2 px-4 py-3 rounded-xl bg-gray-25 border-[0.5px] border-gary-200 shadow-xs cursor-pointer', disabled && 'opacity-50 !cursor-not-allowed')} + className={cn('mb-2 px-4 py-3 bg-components-panel-item-bg rounded-xl border-[0.5px] border-components-panel-border-subtle shadow-xs cursor-pointer hover:bg-components-panel-on-panel-item-bg-hover', disabled && 'opacity-50 !cursor-not-allowed')} onClick={() => !disabled && setShowDetail(true)} > - <div className='text-gray-800 font-semibold text-sm leading-5'>{tool.label[language]}</div> - <div className='mt-0.5 text-xs leading-[18px] text-gray-500 line-clamp-2' title={tool.description[language]}>{tool.description[language]}</div> + <div className='pb-0.5 text-text-secondary system-md-semibold'>{tool.label[language]}</div> + <div className='text-text-tertiary system-xs-regular line-clamp-2' title={tool.description[language]}>{tool.description[language]}</div> </div> {showDetail && ( <SettingBuiltInTool + showBackButton collection={collection} toolName={tool.name} readonly diff --git a/web/app/components/tools/setting/build-in/config-credentials.tsx b/web/app/components/tools/setting/build-in/config-credentials.tsx index 23ef867feb..3d083b8d58 100644 --- a/web/app/components/tools/setting/build-in/config-credentials.tsx +++ b/web/app/components/tools/setting/build-in/config-credentials.tsx @@ -20,6 +20,7 @@ type Props = { onSaved: (value: Record<string, any>) => void isHideRemoveBtn?: boolean onRemove?: () => void + isSaving?: boolean } const ConfigCredential: FC<Props> = ({ @@ -28,12 +29,14 @@ const ConfigCredential: FC<Props> = ({ onSaved, isHideRemoveBtn, onRemove = () => { }, + isSaving, }) => { const { t } = useTranslation() const language = useLanguage() const [credentialSchema, setCredentialSchema] = useState<any>(null) const { name: collectionName } = collection const [tempCredential, setTempCredential] = React.useState<any>({}) + const [isLoading, setIsLoading] = React.useState(false) useEffect(() => { fetchBuiltInToolCredentialSchema(collectionName).then(async (res) => { const toolCredentialSchemas = toolCredentialToFormSchemas(res) @@ -45,14 +48,21 @@ const ConfigCredential: FC<Props> = ({ }) }, []) - const handleSave = () => { + const handleSave = async () => { for (const field of credentialSchema) { if (field.required && !tempCredential[field.name]) { Toast.notify({ type: 'error', message: t('common.errorMsg.fieldRequired', { field: field.label[language] || field.label.en_US }) }) return } } - onSaved(tempCredential) + setIsLoading(true) + try { + await onSaved(tempCredential) + setIsLoading(false) + } + finally { + setIsLoading(false) + } } return ( @@ -61,11 +71,11 @@ const ConfigCredential: FC<Props> = ({ onHide={onCancel} title={t('tools.auth.setupModalTitle') as string} titleDescription={t('tools.auth.setupModalTitleDescription') as string} - panelClassName='mt-2 !w-[405px]' - maxWidthClassName='!max-w-[405px]' - height='calc(100vh - 16px)' - contentClassName='!bg-gray-100' - headerClassName='!border-b-black/5' + panelClassName='mt-[64px] mb-2 !w-[420px] border-components-panel-border' + maxWidthClassName='!max-w-[420px]' + height='calc(100vh - 64px)' + contentClassName='!bg-components-panel-bg' + headerClassName='!border-b-divider-subtle' body={ <div className='px-6 py-3 h-full'> @@ -82,12 +92,12 @@ const ConfigCredential: FC<Props> = ({ isEditMode={true} showOnVariableMap={{}} validating={false} - inputClassName='!bg-gray-50' + inputClassName='!bg-components-input-bg-normal' fieldMoreInfo={item => item.url ? (<a href={item.url} target='_blank' rel='noopener noreferrer' - className='inline-flex items-center text-xs text-primary-600' + className='inline-flex items-center text-xs text-text-accent' > {t('tools.howToGet')} <LinkExternal02 className='ml-1 w-3 h-3' /> @@ -102,7 +112,7 @@ const ConfigCredential: FC<Props> = ({ } < div className='flex space-x-2'> <Button onClick={onCancel}>{t('common.operation.cancel')}</Button> - <Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button> + <Button loading={isLoading || isSaving} disabled={isLoading || isSaving} variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button> </div> </div> </> diff --git a/web/app/components/tools/types.ts b/web/app/components/tools/types.ts index f2784e9dfe..32c468cde8 100644 --- a/web/app/components/tools/types.ts +++ b/web/app/components/tools/types.ts @@ -1,4 +1,5 @@ import type { TypeWithI18N } from '../header/account-setting/model-provider-page/declarations' + export enum LOC { tools = 'tools', app = 'app', @@ -16,10 +17,10 @@ export enum AuthHeaderPrefix { } export type Credential = { - 'auth_type': AuthType - 'api_key_header'?: string - 'api_key_value'?: string - 'api_key_header_prefix'?: AuthHeaderPrefix + auth_type: AuthType + api_key_header?: string + api_key_value?: string + api_key_header_prefix?: AuthHeaderPrefix } export enum CollectionType { @@ -47,6 +48,8 @@ export type Collection = { is_team_authorization: boolean allow_delete: boolean labels: string[] + plugin_id?: string + letter?: string } export type ToolParameter = { @@ -66,6 +69,7 @@ export type ToolParameter = { max?: number } +// Action export type Tool = { name: string author: string @@ -73,12 +77,13 @@ export type Tool = { description: any parameters: ToolParameter[] labels: string[] + output_schema: Record<string, any> } export type ToolCredential = { name: string label: TypeWithI18N - help: TypeWithI18N + help: TypeWithI18N | null placeholder: TypeWithI18N type: string required: boolean diff --git a/web/app/components/tools/utils/to-form-schema.ts b/web/app/components/tools/utils/to-form-schema.ts index 4e83248c9b..7086c903d1 100644 --- a/web/app/components/tools/utils/to-form-schema.ts +++ b/web/app/components/tools/utils/to-form-schema.ts @@ -1,5 +1,5 @@ import type { ToolCredential, ToolParameter } from '../types' -const toType = (type: string) => { +export const toType = (type: string) => { switch (type) { case 'string': return 'text-input' diff --git a/web/app/components/tools/workflow-tool/configure-button.tsx b/web/app/components/tools/workflow-tool/configure-button.tsx index 6521410dae..18d1191235 100644 --- a/web/app/components/tools/workflow-tool/configure-button.tsx +++ b/web/app/components/tools/workflow-tool/configure-button.tsx @@ -14,6 +14,7 @@ import { createWorkflowToolProvider, fetchWorkflowToolDetailByAppID, saveWorkflo import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest, WorkflowToolProviderResponse } from '@/app/components/tools/types' import type { InputVar } from '@/app/components/workflow/types' import { useAppContext } from '@/context/app-context' +import { useInvalidateAllWorkflowTools } from '@/service/use-tools' type Props = { disabled: boolean @@ -46,6 +47,7 @@ const WorkflowToolConfigureButton = ({ const [isLoading, setIsLoading] = useState(false) const [detail, setDetail] = useState<WorkflowToolProviderResponse>() const { isCurrentWorkspaceManager } = useAppContext() + const invalidateAllWorkflowTools = useInvalidateAllWorkflowTools() const outdated = useMemo(() => { if (!detail) @@ -135,6 +137,7 @@ const WorkflowToolConfigureButton = ({ const createHandle = async (data: WorkflowToolProviderRequest & { workflow_app_id: string }) => { try { await createWorkflowToolProvider(data) + invalidateAllWorkflowTools() onRefreshData?.() getDetail(workflowAppId) Toast.notify({ @@ -156,6 +159,7 @@ const WorkflowToolConfigureButton = ({ await handlePublish() await saveWorkflowToolProvider(data) onRefreshData?.() + invalidateAllWorkflowTools() getDetail(workflowAppId) Toast.notify({ type: 'success', diff --git a/web/app/components/tools/workflow-tool/confirm-modal/index.tsx b/web/app/components/tools/workflow-tool/confirm-modal/index.tsx index 4c712790a1..21ebe8c119 100644 --- a/web/app/components/tools/workflow-tool/confirm-modal/index.tsx +++ b/web/app/components/tools/workflow-tool/confirm-modal/index.tsx @@ -2,7 +2,6 @@ import { useTranslation } from 'react-i18next' import { RiCloseLine } from '@remixicon/react' -import s from './style.module.css' import cn from '@/utils/classnames' import Button from '@/app/components/base/button' import Modal from '@/app/components/base/modal' @@ -19,24 +18,24 @@ const ConfirmModal = ({ show, onConfirm, onClose }: ConfirmModalProps) => { return ( <Modal - className={cn('p-8 max-w-[600px] w-[600px]', s.bg)} + className={cn('p-8 max-w-[600px] w-[600px]')} isShow={show} onClose={() => { }} > <div className='absolute right-4 top-4 p-2 cursor-pointer' onClick={onClose}> - <RiCloseLine className='w-4 h-4 text-gray-500' /> + <RiCloseLine className='w-4 h-4 text-text-tertiary' /> </div> - <div className='w-12 h-12 p-3 bg-white rounded-xl border-[0.5px] border-gray-100 shadow-xl'> + <div className='w-12 h-12 p-3 bg-background-section rounded-xl border-[0.5px] border-divider-regular shadow-xl'> <AlertTriangle className='w-6 h-6 text-[rgb(247,144,9)]' /> </div> - <div className='relative mt-3 text-xl font-semibold leading-[30px] text-gray-900'>{t('tools.createTool.confirmTitle')}</div> - <div className='my-1 text-gray-500 text-sm leading-5'> + <div className='relative mt-3 text-xl font-semibold leading-[30px] text-text-primary'>{t('tools.createTool.confirmTitle')}</div> + <div className='my-1 text-text-tertiary text-sm leading-5'> {t('tools.createTool.confirmTip')} </div> <div className='pt-6 flex justify-end items-center'> <div className='flex items-center'> <Button className='mr-2' onClick={onClose}>{t('common.operation.cancel')}</Button> - <Button className='border-red-700' variant="warning" onClick={onConfirm}>{t('common.operation.confirm')}</Button> + <Button variant="warning" onClick={onConfirm}>{t('common.operation.confirm')}</Button> </div> </div> </Modal> diff --git a/web/app/components/tools/workflow-tool/confirm-modal/style.module.css b/web/app/components/tools/workflow-tool/confirm-modal/style.module.css deleted file mode 100644 index 14367ec575..0000000000 --- a/web/app/components/tools/workflow-tool/confirm-modal/style.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.bg { - background: linear-gradient(180deg, rgba(247, 144, 9, 0.05) 0%, rgba(247, 144, 9, 0.00) 24.41%), #F9FAFB; -} diff --git a/web/app/components/tools/workflow-tool/index.tsx b/web/app/components/tools/workflow-tool/index.tsx index c4d7424538..c4eb07dfe6 100644 --- a/web/app/components/tools/workflow-tool/index.tsx +++ b/web/app/components/tools/workflow-tool/index.tsx @@ -39,7 +39,7 @@ const WorkflowToolAsModal: FC<Props> = ({ }) => { const { t } = useTranslation() - const [showEmojiPicker, setShowEmojiPicker] = useState<Boolean>(false) + const [showEmojiPicker, setShowEmojiPicker] = useState<boolean>(false) const [emoji, setEmoji] = useState<Emoji>(payload.icon) const [label, setLabel] = useState<string>(payload.label) const [name, setName] = useState(payload.name) @@ -124,13 +124,13 @@ const WorkflowToolAsModal: FC<Props> = ({ panelClassName='mt-2 !w-[640px]' maxWidthClassName='!max-w-[640px]' height='calc(100vh - 16px)' - headerClassName='!border-b-black/5' + headerClassName='!border-b-divider' body={ <div className='flex flex-col h-full'> <div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'> {/* name & icon */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div> <div className='flex items-center justify-between gap-3'> <AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' iconType='emoji' icon={emoji.content} background={emoji.background} /> <Input @@ -143,7 +143,7 @@ const WorkflowToolAsModal: FC<Props> = ({ </div> {/* name for tool call */} <div> - <div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'> + <div className='flex items-center py-2 system-sm-medium text-text-primary'> {t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span> <Tooltip popupContent={ @@ -165,7 +165,7 @@ const WorkflowToolAsModal: FC<Props> = ({ </div> {/* description */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.description')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.description')}</div> <Textarea placeholder={t('tools.createTool.descriptionPlaceholder') || ''} value={description} @@ -174,11 +174,11 @@ const WorkflowToolAsModal: FC<Props> = ({ </div> {/* Tool Input */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.toolInput.title')}</div> - <div className='rounded-lg border border-gray-200 w-full overflow-x-auto'> - <table className='w-full leading-[18px] text-xs text-gray-700 font-normal'> - <thead className='text-gray-500 uppercase'> - <tr className='border-b border-gray-200'> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.toolInput.title')}</div> + <div className='rounded-lg border border-divider-regular w-full overflow-x-auto'> + <table className='w-full leading-[18px] text-xs text-text-secondary font-normal'> + <thead className='text-text-tertiary uppercase'> + <tr className='border-b border-divider-regular'> <th className="p-2 pl-3 font-medium w-[156px]">{t('tools.createTool.toolInput.name')}</th> <th className="p-2 pl-3 font-medium w-[102px]">{t('tools.createTool.toolInput.method')}</th> <th className="p-2 pl-3 font-medium">{t('tools.createTool.toolInput.description')}</th> @@ -186,22 +186,22 @@ const WorkflowToolAsModal: FC<Props> = ({ </thead> <tbody> {parameters.map((item, index) => ( - <tr key={index} className='border-b last:border-0 border-gray-200'> + <tr key={index} className='border-b last:border-0 border-divider-regular'> <td className="p-2 pl-3 max-w-[156px]"> <div className='text-[13px] leading-[18px]'> <div title={item.name} className='flex'> - <span className='font-medium text-gray-900 truncate'>{item.name}</span> + <span className='font-medium text-text-primary truncate'>{item.name}</span> <span className='shrink-0 pl-1 text-[#ec4a0a] text-xs leading-[18px]'>{item.required ? t('tools.createTool.toolInput.required') : ''}</span> </div> - <div className='text-gray-500'>{item.type}</div> + <div className='text-text-tertiary'>{item.type}</div> </div> </td> <td> {item.name === '__image' && ( <div className={cn( - 'flex items-center gap-1 min-h-[56px] px-3 py-2 h-9 bg-white cursor-default', + 'flex items-center gap-1 min-h-[56px] px-3 py-2 h-9 bg-transparent cursor-default', )}> - <div className={cn('grow text-[13px] leading-[18px] text-gray-700 truncate')}> + <div className={cn('grow text-[13px] leading-[18px] text-text-secondary truncate')}> {t('tools.createTool.toolInput.methodParameter')} </div> </div> @@ -210,10 +210,10 @@ const WorkflowToolAsModal: FC<Props> = ({ <MethodSelector value={item.form} onChange={value => handleParameterChange('form', value, index)} /> )} </td> - <td className="p-2 pl-3 text-gray-500 w-[236px]"> + <td className="p-2 pl-3 text-text-tertiary w-[236px]"> <input type='text' - className='grow text-gray-700 text-[13px] leading-[18px] font-normal bg-white outline-none appearance-none caret-primary-600 placeholder:text-gray-300' + className='w-full text-text-secondary text-[13px] leading-[18px] font-normal bg-transparent outline-none appearance-none caret-primary-600 placeholder:text-text-quaternary' placeholder={t('tools.createTool.toolInput.descriptionPlaceholder')!} value={item.description} onChange={e => handleParameterChange('description', e.target.value, index)} @@ -227,12 +227,12 @@ const WorkflowToolAsModal: FC<Props> = ({ </div> {/* Tags */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.toolInput.label')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.toolInput.label')}</div> <LabelSelector value={labels} onChange={handleLabelSelect} /> </div> {/* Privacy Policy */} <div> - <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.privacyPolicy')}</div> + <div className='py-2 system-sm-medium text-text-primary'>{t('tools.createTool.privacyPolicy')}</div> <Input className='h-10' value={privacyPolicy} @@ -240,9 +240,9 @@ const WorkflowToolAsModal: FC<Props> = ({ placeholder={t('tools.createTool.privacyPolicyPlaceholder') || ''} /> </div> </div> - <div className={cn((!isAdd && onRemove) ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-gray-50 border-t border-black/5')} > + <div className={cn((!isAdd && onRemove) ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-background-section-burn border-t border-divider-regular')} > {!isAdd && onRemove && ( - <Button onClick={onRemove} className='text-red-500 border-red-50 hover:border-red-500'>{t('common.operation.delete')}</Button> + <Button variant='warning' onClick={onRemove}>{t('common.operation.delete')}</Button> )} <div className='flex space-x-2 '> <Button onClick={onHide}>{t('common.operation.cancel')}</Button> diff --git a/web/app/components/tools/workflow-tool/method-selector.tsx b/web/app/components/tools/workflow-tool/method-selector.tsx index 1f11430570..895fb18706 100644 --- a/web/app/components/tools/workflow-tool/method-selector.tsx +++ b/web/app/components/tools/workflow-tool/method-selector.tsx @@ -34,37 +34,37 @@ const MethodSelector: FC<MethodSelectorProps> = ({ className='block' > <div className={cn( - 'flex items-center gap-1 min-h-[56px] px-3 py-2 h-9 bg-white cursor-pointer hover:bg-gray-100', - open && '!bg-gray-100 hover:bg-gray-100', + 'flex items-center gap-1 min-h-[56px] px-3 py-2 h-9 bg-transparent cursor-pointer hover:bg-background-section-burn', + open && '!bg-background-section-burn hover:bg-background-section-burn', )}> - <div className={cn('grow text-[13px] leading-[18px] text-gray-700 truncate')}> + <div className={cn('grow text-[13px] leading-[18px] text-text-secondary truncate')}> {value === 'llm' ? t('tools.createTool.toolInput.methodParameter') : t('tools.createTool.toolInput.methodSetting')} </div> - <div className='shrink-0 ml-1 text-gray-700 opacity-60'> + <div className='shrink-0 ml-1 text-text-secondary opacity-60'> <RiArrowDownSLine className='h-4 w-4' /> </div> </div> </PortalToFollowElemTrigger> <PortalToFollowElemContent className='z-[1040]'> - <div className='relative w-[320px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'> + <div className='relative w-[320px] bg-components-panel-bg-blur backdrop-blur-sm rounded-lg border-[0.5px] border-components-panel-border shadow-lg'> <div className='p-1'> - <div className='pl-3 pr-2 py-2.5 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => onChange('llm')}> + <div className='pl-3 pr-2 py-2.5 rounded-lg hover:bg-components-panel-on-panel-item-bg-hover cursor-pointer' onClick={() => onChange('llm')}> <div className='flex item-center gap-1'> <div className='shrink-0 w-4 h-4'> - {value === 'llm' && <Check className='shrink-0 w-4 h-4 text-primary-600' />} + {value === 'llm' && <Check className='shrink-0 w-4 h-4 text-text-accent' />} </div> - <div className='text-[13px] text-gray-700 font-medium leading-[18px]'>{t('tools.createTool.toolInput.methodParameter')}</div> + <div className='text-[13px] text-text-secondary font-medium leading-[18px]'>{t('tools.createTool.toolInput.methodParameter')}</div> </div> - <div className='pl-5 text-gray-500 text-[13px] leading-[18px]'>{t('tools.createTool.toolInput.methodParameterTip')}</div> + <div className='pl-5 text-text-tertiary text-[13px] leading-[18px]'>{t('tools.createTool.toolInput.methodParameterTip')}</div> </div> - <div className='pl-3 pr-2 py-2.5 rounded-lg hover:bg-gray-50 cursor-pointer' onClick={() => onChange('form')}> + <div className='pl-3 pr-2 py-2.5 rounded-lg hover:bg-components-panel-on-panel-item-bg-hover cursor-pointer' onClick={() => onChange('form')}> <div className='flex item-center gap-1'> <div className='shrink-0 w-4 h-4'> - {value === 'form' && <Check className='shrink-0 w-4 h-4 text-primary-600' />} + {value === 'form' && <Check className='shrink-0 w-4 h-4 text-text-accent' />} </div> - <div className='text-[13px] text-gray-700 font-medium leading-[18px]'>{t('tools.createTool.toolInput.methodSetting')}</div> + <div className='text-[13px] text-text-secondary font-medium leading-[18px]'>{t('tools.createTool.toolInput.methodSetting')}</div> </div> - <div className='pl-5 text-gray-500 text-[13px] leading-[18px]'>{t('tools.createTool.toolInput.methodSettingTip')}</div> + <div className='pl-5 text-text-tertiary text-[13px] leading-[18px]'>{t('tools.createTool.toolInput.methodSettingTip')}</div> </div> </div> </div> diff --git a/web/app/components/workflow/block-icon.tsx b/web/app/components/workflow/block-icon.tsx index 1001e981c5..7f7aeca092 100644 --- a/web/app/components/workflow/block-icon.tsx +++ b/web/app/components/workflow/block-icon.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react' import { memo } from 'react' import { BlockEnum } from './types' import { + Agent, Answer, Assigner, Code, @@ -53,6 +54,7 @@ const getIcon = (type: BlockEnum, className: string) => { [BlockEnum.ParameterExtractor]: <ParameterExtractor className={className} />, [BlockEnum.DocExtractor]: <DocsExtractor className={className} />, [BlockEnum.ListFilter]: <ListFilter className={className} />, + [BlockEnum.Agent]: <Agent className={className} />, }[type] } const ICON_CONTAINER_BG_COLOR_MAP: Record<string, string> = { @@ -73,6 +75,7 @@ const ICON_CONTAINER_BG_COLOR_MAP: Record<string, string> = { [BlockEnum.ParameterExtractor]: 'bg-util-colors-blue-blue-500', [BlockEnum.DocExtractor]: 'bg-util-colors-green-green-500', [BlockEnum.ListFilter]: 'bg-util-colors-cyan-cyan-500', + [BlockEnum.Agent]: 'bg-util-colors-indigo-indigo-500', } const BlockIcon: FC<BlockIconProps> = ({ type, diff --git a/web/app/components/workflow/block-selector/all-tools.tsx b/web/app/components/workflow/block-selector/all-tools.tsx index aaa3811251..0100d4ede8 100644 --- a/web/app/components/workflow/block-selector/all-tools.tsx +++ b/web/app/components/workflow/block-selector/all-tools.tsx @@ -1,35 +1,58 @@ import { + useEffect, useMemo, + useRef, useState, } from 'react' import type { OnSelectBlock, ToolWithProvider, } from '../types' -import { useStore } from '../store' import { ToolTypeEnum } from './types' import Tools from './tools' import { useToolTabs } from './hooks' +import ViewTypeSelect, { ViewType } from './view-type-select' import cn from '@/utils/classnames' +import { useGetLanguage } from '@/context/i18n' +import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list' +import ActionButton from '../../base/action-button' +import { RiAddLine } from '@remixicon/react' +import { PluginType } from '../../plugins/types' +import { useMarketplacePlugins } from '../../plugins/marketplace/hooks' type AllToolsProps = { + className?: string + toolContentClassName?: string searchText: string + tags: string[] + buildInTools: ToolWithProvider[] + customTools: ToolWithProvider[] + workflowTools: ToolWithProvider[] onSelect: OnSelectBlock + supportAddCustomTool?: boolean + onAddedCustomTool?: () => void + onShowAddCustomCollectionModal?: () => void } const AllTools = ({ + className, + toolContentClassName, searchText, + tags = [], onSelect, + buildInTools, + workflowTools, + customTools, + supportAddCustomTool, + onShowAddCustomCollectionModal, }: AllToolsProps) => { + const language = useGetLanguage() const tabs = useToolTabs() const [activeTab, setActiveTab] = useState(ToolTypeEnum.All) - const buildInTools = useStore(s => s.buildInTools) - const customTools = useStore(s => s.customTools) - const workflowTools = useStore(s => s.workflowTools) - + const [activeView, setActiveView] = useState<ViewType>(ViewType.flat) + const hasFilter = searchText || tags.length > 0 const isMatchingKeywords = (text: string, keywords: string) => { return text.toLowerCase().includes(keywords.toLowerCase()) } - const tools = useMemo(() => { let mergedTools: ToolWithProvider[] = [] if (activeTab === ToolTypeEnum.All) @@ -41,39 +64,90 @@ const AllTools = ({ if (activeTab === ToolTypeEnum.Workflow) mergedTools = workflowTools + if (!hasFilter) + return mergedTools.filter(toolWithProvider => toolWithProvider.tools.length > 0) + return mergedTools.filter((toolWithProvider) => { - return isMatchingKeywords(toolWithProvider.name, searchText) - || toolWithProvider.tools.some((tool) => { - return Object.values(tool.label).some((label) => { - return isMatchingKeywords(label, searchText) - }) - }) + return isMatchingKeywords(toolWithProvider.name, searchText) || toolWithProvider.tools.some((tool) => { + return tool.label[language].toLowerCase().includes(searchText.toLowerCase()) || tool.name.toLowerCase().includes(searchText.toLowerCase()) + }) }) - }, [activeTab, buildInTools, customTools, workflowTools, searchText]) + }, [activeTab, buildInTools, customTools, workflowTools, searchText, language, hasFilter]) + + const { + queryPluginsWithDebounced: fetchPlugins, + plugins: notInstalledPlugins = [], + } = useMarketplacePlugins() + + useEffect(() => { + if (searchText || tags.length > 0) { + fetchPlugins({ + query: searchText, + tags, + category: PluginType.tool, + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchText, tags]) + + const pluginRef = useRef(null) + const wrapElemRef = useRef<HTMLDivElement>(null) + return ( - <div> - <div className='flex items-center px-3 h-8 space-x-1 bg-background-default-hover border-b-[0.5px] border-divider-subtle shadow-xs'> - { - tabs.map(tab => ( - <div - className={cn( - 'flex items-center px-2 h-6 rounded-md hover:bg-state-base-hover-alt cursor-pointer', - 'system-xs-medium text-text-tertiary', - activeTab === tab.key && 'system-xs-semibold bg-state-base-hover-alt text-text-primary', - )} - key={tab.key} - onClick={() => setActiveTab(tab.key)} + <div className={cn(className)}> + <div className='flex items-center justify-between px-3 bg-background-default-hover border-b-[0.5px] border-black/[0.08] shadow-xs'> + <div className='flex items-center h-8 space-x-1'> + { + tabs.map(tab => ( + <div + className={cn( + 'flex items-center px-2 h-6 rounded-md hover:bg-gray-100 cursor-pointer', + 'text-xs font-medium text-gray-700', + activeTab === tab.key && 'bg-gray-200', + )} + key={tab.key} + onClick={() => setActiveTab(tab.key)} + > + {tab.name} + </div> + )) + } + </div> + <ViewTypeSelect viewType={activeView} onChange={setActiveView} /> + {supportAddCustomTool && ( + <div className='flex items-center'> + <div className='mr-1.5 w-px h-3.5 bg-divider-regular'></div> + <ActionButton + className='bg-components-button-primary-bg hover:bg-components-button-primary-bg text-components-button-primary-text hover:text-components-button-primary-text' + onClick={onShowAddCustomCollectionModal} > - {tab.name} - </div> - )) - } + <RiAddLine className='w-4 h-4' /> + </ActionButton> + </div> + )} + </div> + <div + ref={wrapElemRef} + className='max-h-[464px] overflow-y-auto' + onScroll={(pluginRef.current as any)?.handleScroll} + > + <Tools + className={toolContentClassName} + showWorkflowEmpty={activeTab === ToolTypeEnum.Workflow} + tools={tools} + onSelect={onSelect} + viewType={activeView} + hasSearchText={!!searchText} + /> + {/* Plugins from marketplace */} + <PluginList + wrapElemRef={wrapElemRef} + list={notInstalledPlugins as any} ref={pluginRef} + searchText={searchText} + toolContentClassName={toolContentClassName} + tags={tags} + /> </div> - <Tools - showWorkflowEmpty={activeTab === ToolTypeEnum.Workflow} - tools={tools} - onSelect={onSelect} - /> </div> ) } diff --git a/web/app/components/workflow/block-selector/constants.tsx b/web/app/components/workflow/block-selector/constants.tsx index 2849288404..798e7ae3c5 100644 --- a/web/app/components/workflow/block-selector/constants.tsx +++ b/web/app/components/workflow/block-selector/constants.tsx @@ -84,6 +84,11 @@ export const BLOCKS: Block[] = [ type: BlockEnum.ListFilter, title: 'List Filter', }, + { + classification: BlockClassificationEnum.Default, + type: BlockEnum.Agent, + title: 'Agent', + }, ] export const BLOCK_CLASSIFICATIONS: string[] = [ diff --git a/web/app/components/workflow/block-selector/hooks.ts b/web/app/components/workflow/block-selector/hooks.ts index 592954afa3..a8b1759506 100644 --- a/web/app/components/workflow/block-selector/hooks.ts +++ b/web/app/components/workflow/block-selector/hooks.ts @@ -41,7 +41,7 @@ export const useToolTabs = () => { }, { key: ToolTypeEnum.BuiltIn, - name: t('workflow.tabs.builtInTool'), + name: t('workflow.tabs.plugin'), }, { key: ToolTypeEnum.Custom, diff --git a/web/app/components/workflow/block-selector/index-bar.tsx b/web/app/components/workflow/block-selector/index-bar.tsx index 2a4cbad432..8d4b3de10e 100644 --- a/web/app/components/workflow/block-selector/index-bar.tsx +++ b/web/app/components/workflow/block-selector/index-bar.tsx @@ -1,8 +1,29 @@ import { pinyin } from 'pinyin-pro' import type { FC, RefObject } from 'react' +import type { ToolWithProvider } from '../types' +import { CollectionType } from '../../tools/types' +import classNames from '@/utils/classnames' -export const groupItems = (items: Array<any>, getFirstChar: (item: string) => string) => { - const groups = items.reduce((acc, item) => { +export const CUSTOM_GROUP_NAME = '@@@custom@@@' +export const WORKFLOW_GROUP_NAME = '@@@workflow@@@' +export const AGENT_GROUP_NAME = '@@@agent@@@' +/* +{ + A: { + 'google': [ // plugin organize name + ...tools + ], + 'custom': [ // custom tools + ...tools + ], + 'workflow': [ // workflow as tools + ...tools + ] + } +} +*/ +export const groupItems = (items: ToolWithProvider[], getFirstChar: (item: ToolWithProvider) => string) => { + const groups = items.reduce((acc: Record<string, Record<string, ToolWithProvider[]>>, item) => { const firstChar = getFirstChar(item) if (!firstChar || firstChar.length === 0) return acc @@ -19,9 +40,23 @@ export const groupItems = (items: Array<any>, getFirstChar: (item: string) => st letter = '#' if (!acc[letter]) - acc[letter] = [] + acc[letter] = {} + + let groupName: string = '' + if (item.type === CollectionType.builtIn) + groupName = item.author + else if (item.type === CollectionType.custom) + groupName = CUSTOM_GROUP_NAME + else if (item.type === CollectionType.workflow) + groupName = WORKFLOW_GROUP_NAME + else + groupName = AGENT_GROUP_NAME + + if (!acc[letter][groupName]) + acc[letter][groupName] = [] + + acc[letter][groupName].push(item) - acc[letter].push(item) return acc }, {}) @@ -38,16 +73,18 @@ export const groupItems = (items: Array<any>, getFirstChar: (item: string) => st type IndexBarProps = { letters: string[] itemRefs: RefObject<{ [key: string]: HTMLElement | null }> + className?: string } -const IndexBar: FC<IndexBarProps> = ({ letters, itemRefs }) => { +const IndexBar: FC<IndexBarProps> = ({ letters, itemRefs, className }) => { const handleIndexClick = (letter: string) => { const element = itemRefs.current?.[letter] if (element) element.scrollIntoView({ behavior: 'smooth' }) } return ( - <div className="index-bar fixed right-4 top-36 flex flex-col items-center text-xs font-medium text-text-quaternary"> + <div className={classNames('index-bar absolute right-0 top-36 flex flex-col items-center w-6 justify-center text-xs font-medium text-text-quaternary', className)}> + <div className='absolute left-0 top-0 h-full w-px bg-[linear-gradient(270deg,rgba(255,255,255,0)_0%,rgba(16,24,40,0.08)_30%,rgba(16,24,40,0.08)_50%,rgba(16,24,40,0.08)_70.5%,rgba(255,255,255,0)_100%)]'></div> {letters.map(letter => ( <div className="hover:text-text-secondary cursor-pointer" key={letter} onClick={() => handleIndexClick(letter)}> {letter} diff --git a/web/app/components/workflow/block-selector/index.tsx b/web/app/components/workflow/block-selector/index.tsx index dc93c275f2..659a7694a8 100644 --- a/web/app/components/workflow/block-selector/index.tsx +++ b/web/app/components/workflow/block-selector/index.tsx @@ -22,6 +22,8 @@ import { PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import Input from '@/app/components/base/input' +import SearchBox from '@/app/components/plugins/marketplace/search-box' + import { Plus02, } from '@/app/components/base/icons/src/vender/line/general' @@ -61,6 +63,7 @@ const NodeSelector: FC<NodeSelectorProps> = ({ }) => { const { t } = useTranslation() const [searchText, setSearchText] = useState('') + const [tags, setTags] = useState<string[]>([]) const [localOpen, setLocalOpen] = useState(false) const open = openFromProps === undefined ? localOpen : openFromProps const handleOpenChange = useCallback((newOpen: boolean) => { @@ -126,25 +129,37 @@ const NodeSelector: FC<NodeSelectorProps> = ({ } </PortalToFollowElemTrigger> <PortalToFollowElemContent className='z-[1000]'> - <div className={ - classNames(`rounded-lg border-[0.5px] backdrop-blur-[5px] - border-components-panel-border bg-components-panel-bg-blur shadow-lg`, popupClassName)}> - <div className='p-2 pb-1' onClick={e => e.stopPropagation()}> - <Input - showLeftIcon - showClearIcon - autoFocus - value={searchText} - placeholder={searchPlaceholder} - onChange={e => setSearchText(e.target.value)} - onClear={() => setSearchText('')} - /> + <div className={`rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg ${popupClassName}`}> + <div className='px-2 pt-2' onClick={e => e.stopPropagation()}> + {activeTab === TabsEnum.Blocks && ( + <Input + showLeftIcon + showClearIcon + autoFocus + value={searchText} + placeholder={searchPlaceholder} + onChange={e => setSearchText(e.target.value)} + onClear={() => setSearchText('')} + /> + )} + {activeTab === TabsEnum.Tools && ( + <SearchBox + search={searchText} + onSearchChange={setSearchText} + tags={tags} + onTagsChange={setTags} + size='small' + placeholder={t('plugin.searchTools')!} + /> + )} + </div> <Tabs activeTab={activeTab} onActiveTabChange={handleActiveTabChange} onSelect={handleSelect} searchText={searchText} + tags={tags} availableBlocksTypes={availableBlocksTypes} noBlocks={noBlocks} /> diff --git a/web/app/components/workflow/block-selector/market-place-plugin/action.tsx b/web/app/components/workflow/block-selector/market-place-plugin/action.tsx new file mode 100644 index 0000000000..f4a9668c3e --- /dev/null +++ b/web/app/components/workflow/block-selector/market-place-plugin/action.tsx @@ -0,0 +1,87 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { RiMoreFill } from '@remixicon/react' +import ActionButton from '@/app/components/base/action-button' +// import Button from '@/app/components/base/button' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import cn from '@/utils/classnames' +import { MARKETPLACE_URL_PREFIX } from '@/config' +import { useDownloadPlugin } from '@/service/use-plugins' +import { downloadFile } from '@/utils/format' + +type Props = { + open: boolean + onOpenChange: (v: boolean) => void + author: string + name: string + version: string +} + +const OperationDropdown: FC<Props> = ({ + open, + onOpenChange, + author, + name, + version, +}) => { + const { t } = useTranslation() + const openRef = useRef(open) + const setOpen = useCallback((v: boolean) => { + onOpenChange(v) + openRef.current = v + }, [onOpenChange]) + + const handleTrigger = useCallback(() => { + setOpen(!openRef.current) + }, [setOpen]) + + const [needDownload, setNeedDownload] = useState(false) + const { data: blob, isLoading } = useDownloadPlugin({ + organization: author, + pluginName: name, + version, + }, needDownload) + const handleDownload = useCallback(() => { + if (isLoading) return + setNeedDownload(true) + }, [isLoading]) + + useEffect(() => { + if (blob) { + const fileName = `${author}-${name}_${version}.zip` + downloadFile({ data: blob, fileName }) + setNeedDownload(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [blob]) + return ( + <PortalToFollowElem + open={open} + onOpenChange={setOpen} + placement='bottom-end' + offset={{ + mainAxis: 0, + crossAxis: 0, + }} + > + <PortalToFollowElemTrigger onClick={handleTrigger}> + <ActionButton className={cn(open && 'bg-state-base-hover')}> + <RiMoreFill className='w-4 h-4 text-components-button-secondary-accent-text' /> + </ActionButton> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-[9999]'> + <div className='w-[112px] p-1 bg-components-panel-bg-blur rounded-xl border-[0.5px] border-components-panel-border shadow-lg'> + <div onClick={handleDownload} className='px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover'>{t('common.operation.download')}</div> + <a href={`${MARKETPLACE_URL_PREFIX}/plugins/${author}/${name}`} target='_blank' className='block px-3 py-1.5 rounded-lg text-text-secondary system-md-regular cursor-pointer hover:bg-state-base-hover'>{t('common.operation.viewDetails')}</a> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} +export default React.memo(OperationDropdown) diff --git a/web/app/components/workflow/block-selector/market-place-plugin/item.tsx b/web/app/components/workflow/block-selector/market-place-plugin/item.tsx new file mode 100644 index 0000000000..ebe4da73f8 --- /dev/null +++ b/web/app/components/workflow/block-selector/market-place-plugin/item.tsx @@ -0,0 +1,77 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useContext } from 'use-context-selector' +import { useTranslation } from 'react-i18next' +import Action from './action' +import type { Plugin } from '@/app/components/plugins/types.ts' +import InstallFromMarketplace from '@/app/components/plugins/install-plugin/install-from-marketplace' +import I18n from '@/context/i18n' +import cn from '@/utils/classnames' + +import { formatNumber } from '@/utils/format' +import { useBoolean } from 'ahooks' + +enum ActionType { + install = 'install', + download = 'download', + // viewDetail = 'viewDetail', // wait for marketplace api +} +type Props = { + payload: Plugin + onAction: (type: ActionType) => void +} + +const Item: FC<Props> = ({ + payload, +}) => { + const { t } = useTranslation() + const [open, setOpen] = React.useState(false) + const { locale } = useContext(I18n) + const getLocalizedText = (obj: Record<string, string> | undefined) => + obj?.[locale] || obj?.['en-US'] || obj?.en_US || '' + const [isShowInstallModal, { + setTrue: showInstallModal, + setFalse: hideInstallModal, + }] = useBoolean(false) + + return ( + <div className='group/plugin flex rounded-lg py-1 pr-1 pl-3 hover:bg-state-base-hover'> + <div + className='shrink-0 relative w-6 h-6 border-[0.5px] border-components-panel-border-subtle rounded-md bg-center bg-no-repeat bg-contain' + style={{ backgroundImage: `url(${payload.icon})` }} + /> + <div className='ml-2 w-0 grow flex'> + <div className='w-0 grow'> + <div className='h-4 leading-4 text-text-primary system-sm-medium truncate '>{getLocalizedText(payload.label)}</div> + <div className='h-5 leading-5 text-text-tertiary system-xs-regular truncate'>{getLocalizedText(payload.brief)}</div> + <div className='flex text-text-tertiary system-xs-regular space-x-1'> + <div>{payload.org}</div> + <div>·</div> + <div>{t('plugin.install', { num: formatNumber(payload.install_count || 0) })}</div> + </div> + </div> + {/* Action */} + <div className={cn(!open ? 'hidden' : 'flex', 'group-hover/plugin:flex items-center space-x-1 h-4 text-components-button-secondary-accent-text system-xs-medium')}> + <div className='px-1.5 cursor-pointer' onClick={showInstallModal}>{t('plugin.installAction')}</div> + <Action + open={open} + onOpenChange={setOpen} + author={payload.org} + name={payload.name} + version={payload.latest_version} + /> + </div> + {isShowInstallModal && ( + <InstallFromMarketplace + uniqueIdentifier={payload.latest_package_identifier} + manifest={payload} + onSuccess={hideInstallModal} + onClose={hideInstallModal} + /> + )} + </div> + </div> + ) +} +export default React.memo(Item) diff --git a/web/app/components/workflow/block-selector/market-place-plugin/list.tsx b/web/app/components/workflow/block-selector/market-place-plugin/list.tsx new file mode 100644 index 0000000000..0c381c2a39 --- /dev/null +++ b/web/app/components/workflow/block-selector/market-place-plugin/list.tsx @@ -0,0 +1,129 @@ +'use client' +import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import useStickyScroll, { ScrollPosition } from '../use-sticky-scroll' +import Item from './item' +import type { Plugin } from '@/app/components/plugins/types.ts' +import cn from '@/utils/classnames' +import Link from 'next/link' +import { marketplaceUrlPrefix } from '@/config' +import { RiArrowRightUpLine, RiSearchLine } from '@remixicon/react' +// import { RiArrowRightUpLine } from '@remixicon/react' + +type Props = { + wrapElemRef: React.RefObject<HTMLElement> + list: Plugin[] + searchText: string + tags: string[] + toolContentClassName?: string + disableMaxWidth?: boolean +} + +const List = forwardRef<{ handleScroll: () => void }, Props>(({ + wrapElemRef, + searchText, + tags, + list, + toolContentClassName, + disableMaxWidth = false, +}, ref) => { + const { t } = useTranslation() + const hasFilter = !searchText + const hasRes = list.length > 0 + const urlWithSearchText = `${marketplaceUrlPrefix}/?q=${searchText}&tags=${tags.join(',')}` + const nextToStickyELemRef = useRef<HTMLDivElement>(null) + + const { handleScroll, scrollPosition } = useStickyScroll({ + wrapElemRef, + nextToStickyELemRef, + }) + const stickyClassName = useMemo(() => { + switch (scrollPosition) { + case ScrollPosition.aboveTheWrap: + return 'top-0 h-9 pt-3 pb-2 shadow-xs bg-components-panel-bg-blur cursor-pointer' + case ScrollPosition.showing: + return 'bottom-0 pt-3 pb-1' + case ScrollPosition.belowTheWrap: + return 'bottom-0 items-center rounded-b-xl border-t border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg rounded-b-lg cursor-pointer' + } + }, [scrollPosition]) + + useImperativeHandle(ref, () => ({ + handleScroll, + })) + + useEffect(() => { + handleScroll() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [list]) + + const handleHeadClick = () => { + if (scrollPosition === ScrollPosition.belowTheWrap) { + nextToStickyELemRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }) + return + } + window.open(urlWithSearchText, '_blank') + } + + if (hasFilter) { + return ( + <Link + className='sticky bottom-0 z-10 flex h-8 px-4 py-1 system-sm-medium items-center border-t border-[0.5px] border-components-panel-border bg-components-panel-bg-blur rounded-b-lg shadow-lg text-text-accent-light-mode-only cursor-pointer' + href={`${marketplaceUrlPrefix}/`} + target='_blank' + > + <span>{t('plugin.findMoreInMarketplace')}</span> + <RiArrowRightUpLine className='ml-0.5 w-3 h-3' /> + </Link> + ) + } + + const maxWidthClassName = toolContentClassName || 'max-w-[300px]' + + return ( + <> + {hasRes && ( + <div + className={cn('sticky z-10 flex justify-between h-8 px-4 py-1 text-text-primary system-sm-medium cursor-pointer', stickyClassName, !disableMaxWidth && maxWidthClassName)} + onClick={handleHeadClick} + > + <span>{t('plugin.fromMarketplace')}</span> + <Link + href={urlWithSearchText} + target='_blank' + className='flex items-center text-text-accent-light-mode-only' + onClick={e => e.stopPropagation()} + > + <span>{t('plugin.searchInMarketplace')}</span> + <RiArrowRightUpLine className='ml-0.5 w-3 h-3' /> + </Link> + </div> + )} + <div className={cn('p-1', !disableMaxWidth && maxWidthClassName)} ref={nextToStickyELemRef}> + {list.map((item, index) => ( + <Item + key={index} + payload={item} + onAction={() => { }} + /> + ))} + <div className='mt-2 mb-3 flex items-center justify-center space-x-2'> + <div className="w-[90px] h-[2px] bg-gradient-to-l from-[rgba(16,24,40,0.08)] to-[rgba(255,255,255,0.01)]"></div> + <Link + href={urlWithSearchText} + target='_blank' + className='shrink-0 flex items-center h-4 system-sm-medium text-text-accent-light-mode-only' + > + <RiSearchLine className='mr-0.5 w-3 h-3' /> + <span>{t('plugin.searchInMarketplace')}</span> + </Link> + <div className="w-[90px] h-[2px] bg-gradient-to-l from-[rgba(255,255,255,0.01)] to-[rgba(16,24,40,0.08)]"></div> + </div> + </div> + </> + ) +}) + +List.displayName = 'List' + +export default List diff --git a/web/app/components/workflow/block-selector/tabs.tsx b/web/app/components/workflow/block-selector/tabs.tsx index 12fde56533..bcb54a79dc 100644 --- a/web/app/components/workflow/block-selector/tabs.tsx +++ b/web/app/components/workflow/block-selector/tabs.tsx @@ -1,5 +1,6 @@ import type { FC } from 'react' import { memo } from 'react' +import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools' import type { BlockEnum } from '../types' import { useTabs } from './hooks' import type { ToolDefaultValue } from './types' @@ -12,6 +13,7 @@ export type TabsProps = { activeTab: TabsEnum onActiveTabChange: (activeTab: TabsEnum) => void searchText: string + tags: string[] onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void availableBlocksTypes?: BlockEnum[] noBlocks?: boolean @@ -19,12 +21,16 @@ export type TabsProps = { const Tabs: FC<TabsProps> = ({ activeTab, onActiveTabChange, + tags, searchText, onSelect, availableBlocksTypes, noBlocks, }) => { const tabs = useTabs() + const { data: buildInTools } = useAllBuiltInTools() + const { data: customTools } = useAllCustomTools() + const { data: workflowTools } = useAllWorkflowTools() return ( <div onClick={e => e.stopPropagation()}> @@ -62,8 +68,13 @@ const Tabs: FC<TabsProps> = ({ { activeTab === TabsEnum.Tools && ( <AllTools + className='w-[315px]' searchText={searchText} onSelect={onSelect} + tags={tags} + buildInTools={buildInTools} + customTools={customTools} + workflowTools={workflowTools} /> ) } diff --git a/web/app/components/workflow/block-selector/tool-picker.tsx b/web/app/components/workflow/block-selector/tool-picker.tsx new file mode 100644 index 0000000000..94f36fa0b6 --- /dev/null +++ b/web/app/components/workflow/block-selector/tool-picker.tsx @@ -0,0 +1,170 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import { useMemo, useState } from 'react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import type { + OffsetOptions, + Placement, +} from '@floating-ui/react' +import AllTools from '@/app/components/workflow/block-selector/all-tools' +import type { ToolDefaultValue } from './types' +import type { BlockEnum } from '@/app/components/workflow/types' +import SearchBox from '@/app/components/plugins/marketplace/search-box' +import { useTranslation } from 'react-i18next' +import { useBoolean } from 'ahooks' +import EditCustomToolModal from '@/app/components/tools/edit-custom-collection-modal/modal' +import { + createCustomCollection, +} from '@/service/tools' +import type { CustomCollectionBackend } from '@/app/components/tools/types' +import Toast from '@/app/components/base/toast' +import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools, useInvalidateAllCustomTools } from '@/service/use-tools' + +type Props = { + disabled: boolean + trigger: React.ReactNode + placement?: Placement + offset?: OffsetOptions + isShow: boolean + onShowChange: (isShow: boolean) => void + onSelect: (tool: ToolDefaultValue) => void + supportAddCustomTool?: boolean + scope?: string +} + +const ToolPicker: FC<Props> = ({ + disabled, + trigger, + placement = 'right-start', + offset = 0, + isShow, + onShowChange, + onSelect, + supportAddCustomTool, + scope = 'all', +}) => { + const { t } = useTranslation() + const [searchText, setSearchText] = useState('') + const [tags, setTags] = useState<string[]>([]) + + const { data: buildInTools } = useAllBuiltInTools() + const { data: customTools } = useAllCustomTools() + const invalidateCustomTools = useInvalidateAllCustomTools() + const { data: workflowTools } = useAllWorkflowTools() + + const { builtinToolList, customToolList, workflowToolList } = useMemo(() => { + if (scope === 'plugins') { + return { + builtinToolList: buildInTools, + customToolList: [], + workflowToolList: [], + } + } + if (scope === 'custom') { + return { + builtinToolList: [], + customToolList: customTools, + workflowToolList: [], + } + } + if (scope === 'workflow') { + return { + builtinToolList: [], + customToolList: [], + workflowToolList: workflowTools, + } + } + return { + builtinToolList: buildInTools, + customToolList: customTools, + workflowToolList: workflowTools, + } + }, [scope, buildInTools, customTools, workflowTools]) + + const handleAddedCustomTool = invalidateCustomTools + + const handleTriggerClick = () => { + if (disabled) return + onShowChange(true) + } + + const handleSelect = (_type: BlockEnum, tool?: ToolDefaultValue) => { + onSelect(tool!) + } + + const [isShowEditCollectionToolModal, { + setFalse: hideEditCustomCollectionModal, + setTrue: showEditCustomCollectionModal, + }] = useBoolean(false) + + const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => { + await createCustomCollection(data) + Toast.notify({ + type: 'success', + message: t('common.api.actionSuccess'), + }) + hideEditCustomCollectionModal() + handleAddedCustomTool() + } + + if (isShowEditCollectionToolModal) { + return ( + <EditCustomToolModal + positionLeft + payload={null} + onHide={hideEditCustomCollectionModal} + onAdd={doCreateCustomToolCollection} + /> + ) + } + + return ( + <PortalToFollowElem + placement={placement} + offset={offset} + open={isShow} + onOpenChange={onShowChange} + > + <PortalToFollowElemTrigger + onClick={handleTriggerClick} + > + {trigger} + </PortalToFollowElemTrigger> + + <PortalToFollowElemContent className='z-[1000]'> + <div className="relative w-[356px] min-h-20 rounded-xl bg-components-panel-bg-blur border-[0.5px] border-components-panel-border shadow-lg"> + <div className='p-2 pb-1'> + <SearchBox + search={searchText} + onSearchChange={setSearchText} + tags={tags} + onTagsChange={setTags} + size='small' + placeholder={t('plugin.searchTools')!} + /> + </div> + <AllTools + className='mt-1' + toolContentClassName='max-w-[360px]' + tags={tags} + searchText={searchText} + onSelect={handleSelect} + buildInTools={builtinToolList || []} + customTools={customToolList || []} + workflowTools={workflowToolList || []} + supportAddCustomTool={supportAddCustomTool} + onAddedCustomTool={handleAddedCustomTool} + onShowAddCustomCollectionModal={showEditCustomCollectionModal} + /> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default React.memo(ToolPicker) diff --git a/web/app/components/workflow/block-selector/tool/action-item.tsx b/web/app/components/workflow/block-selector/tool/action-item.tsx new file mode 100644 index 0000000000..f05d7a1c81 --- /dev/null +++ b/web/app/components/workflow/block-selector/tool/action-item.tsx @@ -0,0 +1,72 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { ToolWithProvider } from '../../types' +import { BlockEnum } from '../../types' +import type { ToolDefaultValue } from '../types' +import Tooltip from '@/app/components/base/tooltip' +import type { Tool } from '@/app/components/tools/types' +import { useGetLanguage } from '@/context/i18n' +import BlockIcon from '../../block-icon' + +type Props = { + provider: ToolWithProvider + payload: Tool + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void +} + +const ToolItem: FC<Props> = ({ + provider, + payload, + onSelect, +}) => { + const language = useGetLanguage() + + return ( + <Tooltip + key={payload.name} + position='right' + popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' + popupContent={( + <div> + <BlockIcon + size='md' + className='mb-2' + type={BlockEnum.Tool} + toolIcon={provider.icon} + /> + <div className='mb-1 text-sm leading-5 text-gray-900'>{payload.label[language]}</div> + <div className='text-xs text-gray-700 leading-[18px]'>{payload.description[language]}</div> + </div> + )} + > + <div + key={payload.name} + className='rounded-lg pl-[21px] hover:bg-state-base-hover cursor-pointer' + onClick={() => { + const params: Record<string, string> = {} + if (payload.parameters) { + payload.parameters.forEach((item) => { + params[item.name] = '' + }) + } + onSelect(BlockEnum.Tool, { + provider_id: provider.id, + provider_type: provider.type, + provider_name: provider.name, + tool_name: payload.name, + tool_label: payload.label[language], + title: payload.label[language], + is_team_authorization: provider.is_team_authorization, + output_schema: payload.output_schema, + paramSchemas: payload.parameters, + params, + }) + }} + > + <div className='h-8 leading-8 border-l-2 border-divider-subtle pl-4 truncate text-text-secondary system-sm-medium'>{payload.label[language]}</div> + </div> + </Tooltip > + ) +} +export default React.memo(ToolItem) diff --git a/web/app/components/workflow/block-selector/tool/tool-list-flat-view/list.tsx b/web/app/components/workflow/block-selector/tool/tool-list-flat-view/list.tsx new file mode 100644 index 0000000000..04622cabff --- /dev/null +++ b/web/app/components/workflow/block-selector/tool/tool-list-flat-view/list.tsx @@ -0,0 +1,61 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { ToolWithProvider } from '../../../types' +import type { BlockEnum } from '../../../types' +import type { ToolDefaultValue } from '../../types' +import Tool from '../tool' +import { ViewType } from '../../view-type-select' +import { useMemo } from 'react' + +type Props = { + payload: ToolWithProvider[] + isShowLetterIndex: boolean + hasSearchText: boolean + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void + letters: string[] + toolRefs: any +} + +const ToolViewFlatView: FC<Props> = ({ + letters, + payload, + isShowLetterIndex, + hasSearchText, + onSelect, + toolRefs, +}) => { + const firstLetterToolIds = useMemo(() => { + const res: Record<string, string> = {} + letters.forEach((letter) => { + const firstToolId = payload.find(tool => tool.letter === letter)?.id + if (firstToolId) + res[firstToolId] = letter + }) + return res + }, [payload, letters]) + return ( + <div> + {payload.map(tool => ( + <div + key={tool.id} + ref={(el) => { + const letter = firstLetterToolIds[tool.id] + if (letter) + toolRefs.current[letter] = el + }} + > + <Tool + payload={tool} + viewType={ViewType.flat} + isShowLetterIndex={isShowLetterIndex} + hasSearchText={hasSearchText} + onSelect={onSelect} + /> + </div> + ))} + </div> + ) +} + +export default React.memo(ToolViewFlatView) diff --git a/web/app/components/workflow/block-selector/tool/tool-list-tree-view/item.tsx b/web/app/components/workflow/block-selector/tool/tool-list-tree-view/item.tsx new file mode 100644 index 0000000000..bf90c72aad --- /dev/null +++ b/web/app/components/workflow/block-selector/tool/tool-list-tree-view/item.tsx @@ -0,0 +1,44 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { ToolWithProvider } from '../../../types' +import Tool from '../tool' +import type { BlockEnum } from '../../../types' +import { ViewType } from '../../view-type-select' +import type { ToolDefaultValue } from '../../types' + +type Props = { + groupName: string + toolList: ToolWithProvider[] + hasSearchText: boolean + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void +} + +const Item: FC<Props> = ({ + groupName, + toolList, + hasSearchText, + onSelect, +}) => { + return ( + <div> + <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'> + {groupName} + </div> + <div> + {toolList.map((tool: ToolWithProvider) => ( + <Tool + key={tool.id} + payload={tool} + viewType={ViewType.tree} + isShowLetterIndex={false} + hasSearchText={hasSearchText} + onSelect={onSelect} + /> + ))} + </div> + </div> + ) +} + +export default React.memo(Item) diff --git a/web/app/components/workflow/block-selector/tool/tool-list-tree-view/list.tsx b/web/app/components/workflow/block-selector/tool/tool-list-tree-view/list.tsx new file mode 100644 index 0000000000..a8fd34b98a --- /dev/null +++ b/web/app/components/workflow/block-selector/tool/tool-list-tree-view/list.tsx @@ -0,0 +1,53 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import type { ToolWithProvider } from '../../../types' +import type { BlockEnum } from '../../../types' +import type { ToolDefaultValue } from '../../types' +import Item from './item' +import { useTranslation } from 'react-i18next' +import { AGENT_GROUP_NAME, CUSTOM_GROUP_NAME, WORKFLOW_GROUP_NAME } from '../../index-bar' + +type Props = { + payload: Record<string, ToolWithProvider[]> + hasSearchText: boolean + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void +} + +const ToolListTreeView: FC<Props> = ({ + payload, + hasSearchText, + onSelect, +}) => { + const { t } = useTranslation() + const getI18nGroupName = useCallback((name: string) => { + if (name === CUSTOM_GROUP_NAME) + return t('workflow.tabs.customTool') + + if (name === WORKFLOW_GROUP_NAME) + return t('workflow.tabs.workflowTool') + + if (name === AGENT_GROUP_NAME) + return t('workflow.tabs.agent') + + return name + }, [t]) + + if (!payload) return null + + return ( + <div> + {Object.keys(payload).map(groupName => ( + <Item + key={groupName} + groupName={getI18nGroupName(groupName)} + toolList={payload[groupName]} + hasSearchText={hasSearchText} + onSelect={onSelect} + /> + ))} + </div> + ) +} + +export default React.memo(ToolListTreeView) diff --git a/web/app/components/workflow/block-selector/tool/tool.tsx b/web/app/components/workflow/block-selector/tool/tool.tsx new file mode 100644 index 0000000000..a604f4f211 --- /dev/null +++ b/web/app/components/workflow/block-selector/tool/tool.tsx @@ -0,0 +1,126 @@ +'use client' +import type { FC } from 'react' +import React, { useEffect, useMemo } from 'react' +import cn from '@/utils/classnames' +import { RiArrowDownSLine, RiArrowRightSLine } from '@remixicon/react' +import { useGetLanguage } from '@/context/i18n' +import { CollectionType } from '../../../tools/types' +import type { ToolWithProvider } from '../../types' +import { BlockEnum } from '../../types' +import type { ToolDefaultValue } from '../types' +import { ViewType } from '../view-type-select' +import ActonItem from './action-item' +import BlockIcon from '../../block-icon' +import { useTranslation } from 'react-i18next' + +type Props = { + className?: string + payload: ToolWithProvider + viewType: ViewType + isShowLetterIndex: boolean + hasSearchText: boolean + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void +} + +const Tool: FC<Props> = ({ + className, + payload, + viewType, + isShowLetterIndex, + hasSearchText, + onSelect, +}) => { + const { t } = useTranslation() + const language = useGetLanguage() + const isFlatView = viewType === ViewType.flat + const actions = payload.tools + const hasAction = true // Now always support actions + const [isFold, setFold] = React.useState<boolean>(true) + useEffect(() => { + if (hasSearchText && isFold) { + setFold(false) + return + } + if (!hasSearchText && !isFold) + setFold(true) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hasSearchText]) + + const FoldIcon = isFold ? RiArrowRightSLine : RiArrowDownSLine + + const groupName = useMemo(() => { + if (payload.type === CollectionType.builtIn) + return payload.author + + if (payload.type === CollectionType.custom) + return t('workflow.tabs.customTool') + + if (payload.type === CollectionType.workflow) + return t('workflow.tabs.workflowTool') + + return '' + }, [payload.author, payload.type, t]) + + return ( + <div + key={payload.id} + className={cn('mb-1 last-of-type:mb-0', isShowLetterIndex && 'mr-6')} + > + <div className={cn(className)}> + <div + className='flex items-center justify-between pl-3 pr-1 w-full rounded-lg hover:bg-gray-50 cursor-pointer select-none' + onClick={() => { + if (hasAction) + setFold(!isFold) + + // Now always support actions + // if (payload.parameters) { + // payload.parameters.forEach((item) => { + // params[item.name] = '' + // }) + // } + // onSelect(BlockEnum.Tool, { + // provider_id: payload.id, + // provider_type: payload.type, + // provider_name: payload.name, + // tool_name: payload.name, + // tool_label: payload.label[language], + // title: payload.label[language], + // params: {}, + // }) + }} + > + <div className='flex grow items-center h-8'> + <BlockIcon + className='shrink-0' + type={BlockEnum.Tool} + toolIcon={payload.icon} + /> + <div className='ml-2 text-sm text-gray-900 flex-1 w-0 grow truncate'>{payload.label[language]}</div> + </div> + + <div className='flex items-center'> + {isFlatView && ( + <div className='text-text-tertiary system-xs-regular'>{groupName}</div> + )} + {hasAction && ( + <FoldIcon className={cn('w-4 h-4 text-text-quaternary shrink-0', isFold && 'text-text-tertiary')} /> + )} + </div> + </div> + + {hasAction && !isFold && ( + actions.map(action => ( + <ActonItem + key={action.name} + provider={payload} + payload={action} + onSelect={onSelect} + /> + )) + )} + </div> + </div> + ) +} +export default React.memo(Tool) diff --git a/web/app/components/workflow/block-selector/tools.tsx b/web/app/components/workflow/block-selector/tools.tsx index 394966fb4f..5b5d1da20b 100644 --- a/web/app/components/workflow/block-selector/tools.tsx +++ b/web/app/components/workflow/block-selector/tools.tsx @@ -1,103 +1,91 @@ import { memo, - useCallback, + useMemo, useRef, } from 'react' import { useTranslation } from 'react-i18next' -import BlockIcon from '../block-icon' -import { BlockEnum } from '../types' -import type { ToolWithProvider } from '../types' +import type { BlockEnum, ToolWithProvider } from '../types' import IndexBar, { groupItems } from './index-bar' import type { ToolDefaultValue } from './types' -import Tooltip from '@/app/components/base/tooltip' +import { ViewType } from './view-type-select' import Empty from '@/app/components/tools/add-tool-modal/empty' import { useGetLanguage } from '@/context/i18n' +import ToolListTreeView from './tool/tool-list-tree-view/list' +import ToolListFlatView from './tool/tool-list-flat-view/list' +import classNames from '@/utils/classnames' type ToolsProps = { showWorkflowEmpty: boolean onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void tools: ToolWithProvider[] + viewType: ViewType + hasSearchText: boolean + className?: string + indexBarClassName?: string } const Blocks = ({ showWorkflowEmpty, onSelect, tools, + viewType, + hasSearchText, + className, + indexBarClassName, }: ToolsProps) => { const { t } = useTranslation() const language = useGetLanguage() + const isFlatView = viewType === ViewType.flat + const isShowLetterIndex = isFlatView && tools.length > 10 + + /* + treeViewToolsData: + { + A: { + 'google': [ // plugin organize name + ...tools + ], + 'custom': [ // custom tools + ...tools + ], + 'workflow': [ // workflow as tools + ...tools + ] + } + } + */ + const { letters, groups: withLetterAndGroupViewToolsData } = groupItems(tools, tool => (tool as any).label[language][0]) + const treeViewToolsData = useMemo(() => { + const result: Record<string, ToolWithProvider[]> = {} + Object.keys(withLetterAndGroupViewToolsData).forEach((letter) => { + Object.keys(withLetterAndGroupViewToolsData[letter]).forEach((groupName) => { + if (!result[groupName]) + result[groupName] = [] + result[groupName].push(...withLetterAndGroupViewToolsData[letter][groupName]) + }) + }) + return result + }, [withLetterAndGroupViewToolsData]) + + const listViewToolData = useMemo(() => { + const result: ToolWithProvider[] = [] + letters.forEach((letter) => { + Object.keys(withLetterAndGroupViewToolsData[letter]).forEach((groupName) => { + result.push(...withLetterAndGroupViewToolsData[letter][groupName].map((item) => { + return { + ...item, + letter, + } + })) + }) + }) + + return result + }, [withLetterAndGroupViewToolsData, letters]) - const { letters, groups: groupedTools } = groupItems(tools, tool => tool.label[language][0]) const toolRefs = useRef({}) - const renderGroup = useCallback((toolWithProvider: ToolWithProvider) => { - const list = toolWithProvider.tools - - return ( - <div - key={toolWithProvider.id} - className='mb-1 last-of-type:mb-0' - > - <div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'> - {toolWithProvider.label[language]} - </div> - { - list.map(tool => ( - <Tooltip - key={tool.name} - position='right' - popupClassName='w-[200px]' - popupContent={( - <div> - <BlockIcon - size='md' - className='mb-2' - type={BlockEnum.Tool} - toolIcon={toolWithProvider.icon} - /> - <div className='mb-1 system-md-medium text-text-primary'>{tool.label[language]}</div> - <div className='system-xs-regular text-text-tertiary'>{tool.description[language]}</div> - </div> - )} - > - <div - className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-state-base-hover cursor-pointer' - onClick={() => onSelect(BlockEnum.Tool, { - provider_id: toolWithProvider.id, - provider_type: toolWithProvider.type, - provider_name: toolWithProvider.name, - tool_name: tool.name, - tool_label: tool.label[language], - title: tool.label[language], - })} - > - <BlockIcon - className='mr-2 shrink-0' - type={BlockEnum.Tool} - toolIcon={toolWithProvider.icon} - /> - <div className='text-sm text-text-secondary flex-1 min-w-0 truncate'>{tool.label[language]}</div> - </div> - </Tooltip> - )) - } - </div> - ) - }, [onSelect, language]) - - const renderLetterGroup = (letter) => { - const tools = groupedTools[letter] - return ( - <div - key={letter} - ref={el => (toolRefs.current[letter] = el)} - > - {tools.map(renderGroup)} - </div> - ) - } - return ( - <div className='p-1 max-w-[320px] max-h-[464px] overflow-y-auto'> + <div className={classNames('p-1 max-w-[320px]', className)}> { !tools.length && !showWorkflowEmpty && ( <div className='flex items-center px-3 h-[22px] text-xs font-medium text-text-tertiary'>{t('workflow.tabs.noResult')}</div> @@ -108,8 +96,26 @@ const Blocks = ({ <Empty /> </div> )} - {!!tools.length && letters.map(renderLetterGroup)} - {tools.length > 10 && <IndexBar letters={letters} itemRefs={toolRefs} />} + {!!tools.length && ( + isFlatView ? ( + <ToolListFlatView + toolRefs={toolRefs} + letters={letters} + payload={listViewToolData} + isShowLetterIndex={isShowLetterIndex} + hasSearchText={hasSearchText} + onSelect={onSelect} + /> + ) : ( + <ToolListTreeView + payload={treeViewToolsData} + hasSearchText={hasSearchText} + onSelect={onSelect} + /> + ) + )} + + {isShowLetterIndex && <IndexBar letters={letters} itemRefs={toolRefs} className={indexBarClassName} />} </div> ) } diff --git a/web/app/components/workflow/block-selector/types.ts b/web/app/components/workflow/block-selector/types.ts index affa2488b9..787c3fbff1 100644 --- a/web/app/components/workflow/block-selector/types.ts +++ b/web/app/components/workflow/block-selector/types.ts @@ -25,4 +25,8 @@ export type ToolDefaultValue = { tool_name: string tool_label: string title: string + is_team_authorization: boolean + params: Record<string, any> + paramSchemas: Record<string, any>[] + output_schema: Record<string, any> } diff --git a/web/app/components/workflow/block-selector/use-sticky-scroll.ts b/web/app/components/workflow/block-selector/use-sticky-scroll.ts new file mode 100644 index 0000000000..405ecdba7e --- /dev/null +++ b/web/app/components/workflow/block-selector/use-sticky-scroll.ts @@ -0,0 +1,45 @@ +import React from 'react' +import { useThrottleFn } from 'ahooks' + +export enum ScrollPosition { + belowTheWrap = 'belowTheWrap', + showing = 'showing', + aboveTheWrap = 'aboveTheWrap', +} + +type Params = { + wrapElemRef: React.RefObject<HTMLElement> + nextToStickyELemRef: React.RefObject<HTMLElement> +} +const useStickyScroll = ({ + wrapElemRef, + nextToStickyELemRef, +}: Params) => { + const [scrollPosition, setScrollPosition] = React.useState<ScrollPosition>(ScrollPosition.belowTheWrap) + const { run: handleScroll } = useThrottleFn(() => { + const wrapDom = wrapElemRef.current + const stickyDOM = nextToStickyELemRef.current + if (!wrapDom || !stickyDOM) + return + const { height: wrapHeight, top: wrapTop } = wrapDom.getBoundingClientRect() + const { top: nextToStickyTop } = stickyDOM.getBoundingClientRect() + let scrollPositionNew = ScrollPosition.belowTheWrap + + if (nextToStickyTop - wrapTop >= wrapHeight) + scrollPositionNew = ScrollPosition.belowTheWrap + else if (nextToStickyTop <= wrapTop) + scrollPositionNew = ScrollPosition.aboveTheWrap + else + scrollPositionNew = ScrollPosition.showing + + if (scrollPosition !== scrollPositionNew) + setScrollPosition(scrollPositionNew) + }, { wait: 100 }) + + return { + handleScroll, + scrollPosition, + } +} + +export default useStickyScroll diff --git a/web/app/components/workflow/block-selector/view-type-select.tsx b/web/app/components/workflow/block-selector/view-type-select.tsx new file mode 100644 index 0000000000..d76926e619 --- /dev/null +++ b/web/app/components/workflow/block-selector/view-type-select.tsx @@ -0,0 +1,58 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import { RiNodeTree, RiSortAlphabetAsc } from '@remixicon/react' +import cn from '@/utils/classnames' + +export enum ViewType { + flat = 'flat', + tree = 'tree', +} + +type Props = { + viewType: ViewType + onChange: (viewType: ViewType) => void +} + +const ViewTypeSelect: FC<Props> = ({ + viewType, + onChange, +}) => { + const handleChange = useCallback((nextViewType: ViewType) => { + return () => { + if (nextViewType === viewType) + return + onChange(nextViewType) + } + }, [viewType, onChange]) + + return ( + <div className='flex items-center rounded-lg bg-components-segmented-control-bg-normal p-px'> + <div + className={ + cn('p-[3px] rounded-lg', + viewType === ViewType.flat + ? 'bg-components-segmented-control-item-active-bg shadow-xs text-text-accent-light-mode-only' + : 'text-text-tertiary cursor-pointer', + ) + } + onClick={handleChange(ViewType.flat)} + > + <RiSortAlphabetAsc className='w-4 h-4' /> + </div> + <div + className={ + cn('p-[3px] rounded-lg', + viewType === ViewType.tree + ? 'bg-components-segmented-control-item-active-bg shadow-xs text-text-accent-light-mode-only' + : 'text-text-tertiary cursor-pointer', + ) + } + onClick={handleChange(ViewType.tree)} + > + <RiNodeTree className='w-4 h-4 ' /> + </div> + </div> + ) +} +export default React.memo(ViewTypeSelect) diff --git a/web/app/components/workflow/constants.ts b/web/app/components/workflow/constants.ts index d04163b853..87f1e01f56 100644 --- a/web/app/components/workflow/constants.ts +++ b/web/app/components/workflow/constants.ts @@ -18,6 +18,7 @@ import IterationDefault from './nodes/iteration/default' import DocExtractorDefault from './nodes/document-extractor/default' import ListFilterDefault from './nodes/list-operator/default' import IterationStartDefault from './nodes/iteration-start/default' +import AgentDefault from './nodes/agent/default' type NodesExtraData = { author: string @@ -200,7 +201,15 @@ export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = { getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes, checkValid: ListFilterDefault.checkValid, }, - + [BlockEnum.Agent]: { + author: 'Dify', + about: '', + availablePrevNodes: [], + availableNextNodes: [], + getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes, + getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes, + checkValid: AgentDefault.checkValid, + }, } export const ALL_CHAT_AVAILABLE_BLOCKS = Object.keys(NODES_EXTRA_DATA).filter(key => key !== BlockEnum.End && key !== BlockEnum.Start) as BlockEnum[] @@ -339,6 +348,12 @@ export const NODES_INITIAL_DATA = { desc: '', ...ListFilterDefault.defaultValue, }, + [BlockEnum.Agent]: { + type: BlockEnum.Agent, + title: '', + desc: '', + ...AgentDefault.defaultValue, + }, } export const MAX_ITERATION_PARALLEL_NUM = 10 export const MIN_ITERATION_PARALLEL_NUM = 1 @@ -389,6 +404,7 @@ export const SUPPORT_OUTPUT_VARS_NODE = [ BlockEnum.HttpRequest, BlockEnum.Tool, BlockEnum.VariableAssigner, BlockEnum.VariableAggregator, BlockEnum.QuestionClassifier, BlockEnum.ParameterExtractor, BlockEnum.Iteration, BlockEnum.DocExtractor, BlockEnum.ListFilter, + BlockEnum.Agent, ] export const LLM_OUTPUT_STRUCT: Var[] = [ diff --git a/web/app/components/workflow/hooks/use-checklist.ts b/web/app/components/workflow/hooks/use-checklist.ts index 36201ddfef..b7e717de2b 100644 --- a/web/app/components/workflow/hooks/use-checklist.ts +++ b/web/app/components/workflow/hooks/use-checklist.ts @@ -24,6 +24,8 @@ import { useNodesExtraData } from './use-nodes-data' import { useToastContext } from '@/app/components/base/toast' import { CollectionType } from '@/app/components/tools/types' import { useGetLanguage } from '@/context/i18n' +import type { AgentNodeType } from '../nodes/agent/types' +import { useStrategyProviders } from '@/service/use-strategy' export const useChecklist = (nodes: Node[], edges: Edge[]) => { const { t } = useTranslation() @@ -33,6 +35,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { const buildInTools = useStore(s => s.buildInTools) const customTools = useStore(s => s.customTools) const workflowTools = useStore(s => s.workflowTools) + const { data: strategyProviders } = useStrategyProviders() const needWarningNodes = useMemo(() => { const list = [] @@ -57,6 +60,19 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { toolIcon = workflowTools.find(tool => tool.id === node.data.provider_id)?.icon } + if (node.data.type === BlockEnum.Agent) { + const data = node.data as AgentNodeType + const isReadyForCheckValid = !!strategyProviders + const provider = strategyProviders?.find(provider => provider.declaration.identity.name === data.agent_strategy_provider_name) + const strategy = provider?.declaration.strategies?.find(s => s.identity.name === data.agent_strategy_name) + moreDataForCheckValid = { + provider, + strategy, + language, + isReadyForCheckValid, + } + } + if (node.type === CUSTOM_NODE) { const { errorMessage } = nodesExtraData[node.data.type].checkValid(node.data, t, moreDataForCheckValid) @@ -92,7 +108,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { } return list - }, [t, nodes, edges, nodesExtraData, buildInTools, customTools, workflowTools, language, isChatMode]) + }, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders]) return needWarningNodes } diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/index.ts b/web/app/components/workflow/hooks/use-workflow-run-event/index.ts new file mode 100644 index 0000000000..70528f7e79 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/index.ts @@ -0,0 +1,12 @@ +export * from './use-workflow-started' +export * from './use-workflow-finished' +export * from './use-workflow-failed' +export * from './use-workflow-node-started' +export * from './use-workflow-node-finished' +export * from './use-workflow-node-iteration-started' +export * from './use-workflow-node-iteration-next' +export * from './use-workflow-node-iteration-finished' +export * from './use-workflow-node-retry' +export * from './use-workflow-text-chunk' +export * from './use-workflow-text-replace' +export * from './use-workflow-agent-log' diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-agent-log.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-agent-log.ts new file mode 100644 index 0000000000..9a9fa628c0 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-agent-log.ts @@ -0,0 +1,50 @@ +import { useCallback } from 'react' +import produce from 'immer' +import type { AgentLogResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowAgentLog = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowAgentLog = useCallback((params: AgentLogResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + const currentIndex = draft.tracing!.findIndex(item => item.node_id === data.node_id) + if (currentIndex > -1) { + const current = draft.tracing![currentIndex] + + if (current.execution_metadata) { + if (current.execution_metadata.agent_log) { + const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.id === data.id) + if (currentLogIndex > -1) { + current.execution_metadata.agent_log[currentLogIndex] = { + ...current.execution_metadata.agent_log[currentLogIndex], + ...data, + } + } + else { + current.execution_metadata.agent_log.push(data) + } + } + else { + current.execution_metadata.agent_log = [data] + } + } + else { + current.execution_metadata = { + agent_log: [data], + } as any + } + } + })) + }, [workflowStore]) + + return { + handleWorkflowAgentLog, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-failed.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-failed.ts new file mode 100644 index 0000000000..733f0152a6 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-failed.ts @@ -0,0 +1,26 @@ +import { useCallback } from 'react' +import produce from 'immer' +import { useWorkflowStore } from '@/app/components/workflow/store' +import { WorkflowRunningStatus } from '@/app/components/workflow/types' + +export const useWorkflowFailed = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowFailed = useCallback(() => { + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.result = { + ...draft.result, + status: WorkflowRunningStatus.Failed, + } + })) + }, [workflowStore]) + + return { + handleWorkflowFailed, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-finished.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-finished.ts new file mode 100644 index 0000000000..f447031047 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-finished.ts @@ -0,0 +1,35 @@ +import { useCallback } from 'react' +import produce from 'immer' +import type { WorkflowFinishedResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' +import { getFilesInLogs } from '@/app/components/base/file-uploader/utils' + +export const useWorkflowFinished = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowFinished = useCallback((params: WorkflowFinishedResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + + const isStringOutput = data.outputs && Object.keys(data.outputs).length === 1 && typeof data.outputs[Object.keys(data.outputs)[0]] === 'string' + + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.result = { + ...draft.result, + ...data, + files: getFilesInLogs(data.outputs), + } as any + if (isStringOutput) { + draft.resultTabActive = true + draft.resultText = data.outputs[Object.keys(data.outputs)[0]] + } + })) + }, [workflowStore]) + + return { + handleWorkflowFinished, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-finished.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-finished.ts new file mode 100644 index 0000000000..b8490ff14c --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-finished.ts @@ -0,0 +1,72 @@ +import { useCallback } from 'react' +import { useStoreApi } from 'reactflow' +import produce from 'immer' +import type { NodeFinishedResponse } from '@/types/workflow' +import { + BlockEnum, + NodeRunningStatus, +} from '@/app/components/workflow/types' +import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowNodeFinished = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeFinished = useCallback((params: NodeFinishedResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + const { + getNodes, + setNodes, + edges, + setEdges, + } = store.getState() + const nodes = getNodes() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + const currentIndex = draft.tracing!.findIndex(item => item.id === data.id) + if (currentIndex > -1) { + draft.tracing![currentIndex] = { + ...draft.tracing![currentIndex], + ...data, + } + } + })) + + const newNodes = produce(nodes, (draft) => { + const currentNode = draft.find(node => node.id === data.node_id)! + currentNode.data._runningStatus = data.status + if (data.status === NodeRunningStatus.Exception) { + if (data.execution_metadata?.error_strategy === ErrorHandleTypeEnum.failBranch) + currentNode.data._runningBranchId = ErrorHandleTypeEnum.failBranch + } + else { + if (data.node_type === BlockEnum.IfElse) + currentNode.data._runningBranchId = data?.outputs?.selected_case_id + + if (data.node_type === BlockEnum.QuestionClassifier) + currentNode.data._runningBranchId = data?.outputs?.class_id + } + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + const incomeEdges = draft.filter((edge) => { + return edge.target === data.node_id + }) + incomeEdges.forEach((edge) => { + edge.data = { + ...edge.data, + _targetRunningStatus: data.status as any, + } + }) + }) + setEdges(newEdges) + }, [store, workflowStore]) + + return { + handleWorkflowNodeFinished, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-finished.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-finished.ts new file mode 100644 index 0000000000..fdf9e28587 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-finished.ts @@ -0,0 +1,46 @@ +import { useCallback } from 'react' +import { useStoreApi } from 'reactflow' +import produce from 'immer' +import type { IterationFinishedResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' +import { DEFAULT_ITER_TIMES } from '@/app/components/workflow/constants' + +export const useWorkflowNodeIterationFinished = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeIterationFinished = useCallback((params: IterationFinishedResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + setIterTimes, + } = workflowStore.getState() + const { + getNodes, + setNodes, + } = store.getState() + const nodes = getNodes() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + const currentIndex = draft.tracing!.findIndex(item => item.id === data.id) + + if (currentIndex > -1) { + draft.tracing![currentIndex] = { + ...draft.tracing![currentIndex], + ...data, + } + } + })) + setIterTimes(DEFAULT_ITER_TIMES) + const newNodes = produce(nodes, (draft) => { + const currentNode = draft.find(node => node.id === data.node_id)! + + currentNode.data._runningStatus = data.status + }) + setNodes(newNodes) + }, [workflowStore, store]) + + return { + handleWorkflowNodeIterationFinished, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-next.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-next.ts new file mode 100644 index 0000000000..454f822675 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-next.ts @@ -0,0 +1,35 @@ +import { useCallback } from 'react' +import { useStoreApi } from 'reactflow' +import produce from 'immer' +import type { IterationNextResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowNodeIterationNext = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeIterationNext = useCallback((params: IterationNextResponse) => { + const { + iterTimes, + setIterTimes, + } = workflowStore.getState() + + const { data } = params + const { + getNodes, + setNodes, + } = store.getState() + + const nodes = getNodes() + const newNodes = produce(nodes, (draft) => { + const currentNode = draft.find(node => node.id === data.node_id)! + currentNode.data._iterationIndex = iterTimes + setIterTimes(iterTimes + 1) + }) + setNodes(newNodes) + }, [workflowStore, store]) + + return { + handleWorkflowNodeIterationNext, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-started.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-started.ts new file mode 100644 index 0000000000..0308f62b31 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-iteration-started.ts @@ -0,0 +1,85 @@ +import { useCallback } from 'react' +import { + useReactFlow, + useStoreApi, +} from 'reactflow' +import produce from 'immer' +import { useWorkflowStore } from '@/app/components/workflow/store' +import type { IterationStartedResponse } from '@/types/workflow' +import { NodeRunningStatus } from '@/app/components/workflow/types' +import { DEFAULT_ITER_TIMES } from '@/app/components/workflow/constants' + +export const useWorkflowNodeIterationStarted = () => { + const store = useStoreApi() + const reactflow = useReactFlow() + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeIterationStarted = useCallback(( + params: IterationStartedResponse, + containerParams: { + clientWidth: number, + clientHeight: number, + }, + ) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + setIterTimes, + } = workflowStore.getState() + const { + getNodes, + setNodes, + edges, + setEdges, + transform, + } = store.getState() + const nodes = getNodes() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.tracing!.push({ + ...data, + status: NodeRunningStatus.Running, + }) + })) + setIterTimes(DEFAULT_ITER_TIMES) + + const { + setViewport, + } = reactflow + const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) + const currentNode = nodes[currentNodeIndex] + const position = currentNode.position + const zoom = transform[2] + + if (!currentNode.parentId) { + setViewport({ + x: (containerParams.clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom, + y: (containerParams.clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom, + zoom: transform[2], + }) + } + const newNodes = produce(nodes, (draft) => { + draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running + draft[currentNodeIndex].data._iterationLength = data.metadata.iterator_length + draft[currentNodeIndex].data._waitingRun = false + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + const incomeEdges = draft.filter(edge => edge.target === data.node_id) + + incomeEdges.forEach((edge) => { + edge.data = { + ...edge.data, + _sourceRunningStatus: nodes.find(node => node.id === edge.source)!.data._runningStatus, + _targetRunningStatus: NodeRunningStatus.Running, + _waitingRun: false, + } + }) + }) + setEdges(newEdges) + }, [workflowStore, store, reactflow]) + + return { + handleWorkflowNodeIterationStarted, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-retry.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-retry.ts new file mode 100644 index 0000000000..a57bfbce39 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-retry.ts @@ -0,0 +1,39 @@ +import { useCallback } from 'react' +import { useStoreApi } from 'reactflow' +import produce from 'immer' +import type { + NodeFinishedResponse, +} from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowNodeRetry = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + + const handleWorkflowNodeRetry = useCallback((params: NodeFinishedResponse) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + const { + getNodes, + setNodes, + } = store.getState() + + const nodes = getNodes() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.tracing!.push(data) + })) + const newNodes = produce(nodes, (draft) => { + const currentNode = draft.find(node => node.id === data.node_id)! + + currentNode.data._retryIndex = data.retry_index + }) + setNodes(newNodes) + }, [workflowStore, store]) + + return { + handleWorkflowNodeRetry, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-started.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-started.ts new file mode 100644 index 0000000000..b537ccbb27 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-node-started.ts @@ -0,0 +1,89 @@ +import { useCallback } from 'react' +import { + useReactFlow, + useStoreApi, +} from 'reactflow' +import produce from 'immer' +import type { NodeStartedResponse } from '@/types/workflow' +import { NodeRunningStatus } from '@/app/components/workflow/types' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowNodeStarted = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + const reactflow = useReactFlow() + + const handleWorkflowNodeStarted = useCallback(( + params: NodeStartedResponse, + containerParams: { + clientWidth: number, + clientHeight: number, + }, + ) => { + const { data } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + const { + getNodes, + setNodes, + edges, + setEdges, + transform, + } = store.getState() + const nodes = getNodes() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.tracing!.push({ + ...data, + status: NodeRunningStatus.Running, + }) + })) + + const { + setViewport, + } = reactflow + const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) + const currentNode = nodes[currentNodeIndex] + const position = currentNode.position + const zoom = transform[2] + + if (!currentNode.parentId) { + setViewport({ + x: (containerParams.clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom, + y: (containerParams.clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom, + zoom: transform[2], + }) + } + const newNodes = produce(nodes, (draft) => { + draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running + draft[currentNodeIndex].data._waitingRun = false + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + const incomeEdges = draft.filter((edge) => { + return edge.target === data.node_id + }) + + incomeEdges.forEach((edge) => { + const incomeNode = nodes.find(node => node.id === edge.source)! + if ( + (!incomeNode.data._runningBranchId && edge.sourceHandle === 'source') + || (incomeNode.data._runningBranchId && edge.sourceHandle === incomeNode.data._runningBranchId) + ) { + edge.data = { + ...edge.data, + _sourceRunningStatus: incomeNode.data._runningStatus, + _targetRunningStatus: NodeRunningStatus.Running, + _waitingRun: false, + } + } + }) + }) + setEdges(newEdges) + }, [workflowStore, store, reactflow]) + + return { + handleWorkflowNodeStarted, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts new file mode 100644 index 0000000000..8ba6220818 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-run-event.ts @@ -0,0 +1,44 @@ +import { + useWorkflowAgentLog, + useWorkflowFailed, + useWorkflowFinished, + useWorkflowNodeFinished, + useWorkflowNodeIterationFinished, + useWorkflowNodeIterationNext, + useWorkflowNodeIterationStarted, + useWorkflowNodeRetry, + useWorkflowNodeStarted, + useWorkflowStarted, + useWorkflowTextChunk, + useWorkflowTextReplace, +} from '.' + +export const useWorkflowRunEvent = () => { + const { handleWorkflowStarted } = useWorkflowStarted() + const { handleWorkflowFinished } = useWorkflowFinished() + const { handleWorkflowFailed } = useWorkflowFailed() + const { handleWorkflowNodeStarted } = useWorkflowNodeStarted() + const { handleWorkflowNodeFinished } = useWorkflowNodeFinished() + const { handleWorkflowNodeIterationStarted } = useWorkflowNodeIterationStarted() + const { handleWorkflowNodeIterationNext } = useWorkflowNodeIterationNext() + const { handleWorkflowNodeIterationFinished } = useWorkflowNodeIterationFinished() + const { handleWorkflowNodeRetry } = useWorkflowNodeRetry() + const { handleWorkflowTextChunk } = useWorkflowTextChunk() + const { handleWorkflowTextReplace } = useWorkflowTextReplace() + const { handleWorkflowAgentLog } = useWorkflowAgentLog() + + return { + handleWorkflowStarted, + handleWorkflowFinished, + handleWorkflowFailed, + handleWorkflowNodeStarted, + handleWorkflowNodeFinished, + handleWorkflowNodeIterationStarted, + handleWorkflowNodeIterationNext, + handleWorkflowNodeIterationFinished, + handleWorkflowNodeRetry, + handleWorkflowTextChunk, + handleWorkflowTextReplace, + handleWorkflowAgentLog, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-started.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-started.ts new file mode 100644 index 0000000000..f9911313cc --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-started.ts @@ -0,0 +1,58 @@ +import { useCallback } from 'react' +import { useStoreApi } from 'reactflow' +import produce from 'immer' +import type { WorkflowStartedResponse } from '@/types/workflow' +import { WorkflowRunningStatus } from '@/app/components/workflow/types' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowStarted = () => { + const store = useStoreApi() + const workflowStore = useWorkflowStore() + + const handleWorkflowStarted = useCallback((params: WorkflowStartedResponse) => { + const { task_id, data } = params + const { + workflowRunningData, + setWorkflowRunningData, + setIterParallelLogMap, + } = workflowStore.getState() + const { + getNodes, + setNodes, + edges, + setEdges, + } = store.getState() + setIterParallelLogMap(new Map()) + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.task_id = task_id + draft.result = { + ...draft?.result, + ...data, + status: WorkflowRunningStatus.Running, + } + })) + const nodes = getNodes() + const newNodes = produce(nodes, (draft) => { + draft.forEach((node) => { + node.data._waitingRun = true + node.data._runningBranchId = undefined + }) + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + draft.forEach((edge) => { + edge.data = { + ...edge.data, + _sourceRunningStatus: undefined, + _targetRunningStatus: undefined, + _waitingRun: true, + } + }) + }) + setEdges(newEdges) + }, [workflowStore, store]) + + return { + handleWorkflowStarted, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-chunk.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-chunk.ts new file mode 100644 index 0000000000..c086e57697 --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-chunk.ts @@ -0,0 +1,25 @@ +import { useCallback } from 'react' +import produce from 'immer' +import type { TextChunkResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowTextChunk = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowTextChunk = useCallback((params: TextChunkResponse) => { + const { data: { text } } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.resultTabActive = true + draft.resultText += text + })) + }, [workflowStore]) + + return { + handleWorkflowTextChunk, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-replace.ts b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-replace.ts new file mode 100644 index 0000000000..a00530932d --- /dev/null +++ b/web/app/components/workflow/hooks/use-workflow-run-event/use-workflow-text-replace.ts @@ -0,0 +1,23 @@ +import { useCallback } from 'react' +import produce from 'immer' +import type { TextReplaceResponse } from '@/types/workflow' +import { useWorkflowStore } from '@/app/components/workflow/store' + +export const useWorkflowTextReplace = () => { + const workflowStore = useWorkflowStore() + + const handleWorkflowTextReplace = useCallback((params: TextReplaceResponse) => { + const { data: { text } } = params + const { + workflowRunningData, + setWorkflowRunningData, + } = workflowStore.getState() + setWorkflowRunningData(produce(workflowRunningData!, (draft) => { + draft.resultText = text + })) + }, [workflowStore]) + + return { + handleWorkflowTextReplace, + } +} diff --git a/web/app/components/workflow/hooks/use-workflow-run.ts b/web/app/components/workflow/hooks/use-workflow-run.ts index 11f0a1973f..00e7faeeed 100644 --- a/web/app/components/workflow/hooks/use-workflow-run.ts +++ b/web/app/components/workflow/hooks/use-workflow-run.ts @@ -8,24 +8,16 @@ import { v4 as uuidV4 } from 'uuid' import { usePathname } from 'next/navigation' import { useWorkflowStore } from '../store' import { useNodesSyncDraft } from '../hooks' -import { - BlockEnum, - NodeRunningStatus, - WorkflowRunningStatus, -} from '../types' -import { DEFAULT_ITER_TIMES } from '../constants' +import { WorkflowRunningStatus } from '../types' import { useWorkflowUpdate } from './use-workflow-interactions' +import { useWorkflowRunEvent } from './use-workflow-run-event/use-workflow-run-event' import { useStore as useAppStore } from '@/app/components/app/store' import type { IOtherOptions } from '@/service/base' import { ssePost } from '@/service/base' import { stopWorkflowRun } from '@/service/workflow' import { useFeaturesStore } from '@/app/components/base/features/hooks' import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager' -import { - getFilesInLogs, -} from '@/app/components/base/file-uploader/utils' -import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' -import type { NodeTracing, VersionHistory } from '@/types/workflow' +import type { VersionHistory } from '@/types/workflow' export const useWorkflowRun = () => { const store = useStoreApi() @@ -35,6 +27,20 @@ export const useWorkflowRun = () => { const { doSyncWorkflowDraft } = useNodesSyncDraft() const { handleUpdateWorkflowCanvas } = useWorkflowUpdate() const pathname = usePathname() + const { + handleWorkflowStarted, + handleWorkflowFinished, + handleWorkflowFailed, + handleWorkflowNodeStarted, + handleWorkflowNodeFinished, + handleWorkflowNodeIterationStarted, + handleWorkflowNodeIterationNext, + handleWorkflowNodeIterationFinished, + handleWorkflowNodeRetry, + handleWorkflowAgentLog, + handleWorkflowTextChunk, + handleWorkflowTextReplace, + } = useWorkflowRunEvent() const handleBackupDraft = useCallback(() => { const { @@ -113,6 +119,7 @@ export const useWorkflowRun = () => { onIterationNext, onIterationFinish, onNodeRetry, + onAgentLog, onError, ...restCallback } = callback || {} @@ -132,8 +139,6 @@ export const useWorkflowRun = () => { if (appDetail?.mode === 'workflow') url = `/apps/${appDetail.id}/workflows/draft/run` - let prevNodeId = '' - const { setWorkflowRunningData, } = workflowStore.getState() @@ -166,584 +171,96 @@ export const useWorkflowRun = () => { }, { onWorkflowStarted: (params) => { - const { task_id, data } = params - const { - workflowRunningData, - setWorkflowRunningData, - setIterParallelLogMap, - } = workflowStore.getState() - const { - getNodes, - setNodes, - edges, - setEdges, - } = store.getState() - setIterParallelLogMap(new Map()) - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.task_id = task_id - draft.result = { - ...draft?.result, - ...data, - status: WorkflowRunningStatus.Running, - } - })) - const nodes = getNodes() - const newNodes = produce(nodes, (draft) => { - draft.forEach((node) => { - node.data._waitingRun = true - node.data._runningBranchId = undefined - }) - }) - setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - draft.forEach((edge) => { - edge.data = { - ...edge.data, - _sourceRunningStatus: undefined, - _targetRunningStatus: undefined, - _waitingRun: true, - } - }) - }) - setEdges(newEdges) + handleWorkflowStarted(params) if (onWorkflowStarted) onWorkflowStarted(params) }, onWorkflowFinished: (params) => { - const { data } = params - const { - workflowRunningData, - setWorkflowRunningData, - } = workflowStore.getState() - - const isStringOutput = data.outputs && Object.keys(data.outputs).length === 1 && typeof data.outputs[Object.keys(data.outputs)[0]] === 'string' - - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.result = { - ...draft.result, - ...data, - files: getFilesInLogs(data.outputs), - } as any - if (isStringOutput) { - draft.resultTabActive = true - draft.resultText = data.outputs[Object.keys(data.outputs)[0]] - } - })) - - prevNodeId = '' + handleWorkflowFinished(params) if (onWorkflowFinished) onWorkflowFinished(params) }, onError: (params) => { - const { - workflowRunningData, - setWorkflowRunningData, - } = workflowStore.getState() - - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.result = { - ...draft.result, - status: WorkflowRunningStatus.Failed, - } - })) + handleWorkflowFailed() if (onError) onError(params) }, onNodeStarted: (params) => { - const { data } = params - const { - workflowRunningData, - setWorkflowRunningData, - iterParallelLogMap, - setIterParallelLogMap, - } = workflowStore.getState() - const { - getNodes, - setNodes, - edges, - setEdges, - transform, - } = store.getState() - const nodes = getNodes() - const node = nodes.find(node => node.id === data.node_id) - if (node?.parentId) { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const iterations = tracing.find(trace => trace.node_id === node?.parentId) - const currIteration = iterations?.details![node.data.iteration_index] || iterations?.details![iterations.details!.length - 1] - if (!data.parallel_run_id) { - currIteration?.push({ - ...data, - status: NodeRunningStatus.Running, - } as any) - } - else { - const nodeId = iterations?.node_id as string - if (!iterParallelLogMap.has(nodeId as string)) - iterParallelLogMap.set(iterations?.node_id as string, new Map()) + handleWorkflowNodeStarted( + params, + { + clientWidth, + clientHeight, + }, + ) - const currentIterLogMap = iterParallelLogMap.get(nodeId)! - if (!currentIterLogMap.has(data.parallel_run_id)) - currentIterLogMap.set(data.parallel_run_id, [{ ...data, status: NodeRunningStatus.Running } as any]) - else - currentIterLogMap.get(data.parallel_run_id)!.push({ ...data, status: NodeRunningStatus.Running } as any) - setIterParallelLogMap(iterParallelLogMap) - if (iterations) - iterations.details = Array.from(currentIterLogMap.values()) - } - })) - } - else { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.tracing!.push({ - ...data, - status: NodeRunningStatus.Running, - } as any) - })) - - const { - setViewport, - } = reactflow - const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) - const currentNode = nodes[currentNodeIndex] - const position = currentNode.position - const zoom = transform[2] - - if (!currentNode.parentId) { - setViewport({ - x: (clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom, - y: (clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom, - zoom: transform[2], - }) - } - const newNodes = produce(nodes, (draft) => { - draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running - draft[currentNodeIndex].data._waitingRun = false - }) - setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - const incomeEdges = draft.filter((edge) => { - return edge.target === data.node_id - }) - - incomeEdges.forEach((edge) => { - const incomeNode = nodes.find(node => node.id === edge.source)! - if ( - (!incomeNode.data._runningBranchId && edge.sourceHandle === 'source') - || (incomeNode.data._runningBranchId && edge.sourceHandle === incomeNode.data._runningBranchId) - ) { - edge.data = { - ...edge.data, - _sourceRunningStatus: incomeNode.data._runningStatus, - _targetRunningStatus: NodeRunningStatus.Running, - _waitingRun: false, - } - } - }) - }) - setEdges(newEdges) - } if (onNodeStarted) onNodeStarted(params) }, onNodeFinished: (params) => { - const { data } = params - const { - workflowRunningData, - setWorkflowRunningData, - iterParallelLogMap, - setIterParallelLogMap, - } = workflowStore.getState() - const { - getNodes, - setNodes, - edges, - setEdges, - } = store.getState() - const nodes = getNodes() - const nodeParentId = nodes.find(node => node.id === data.node_id)!.parentId - if (nodeParentId) { - if (!data.execution_metadata.parallel_mode_run_id) { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const iterations = tracing.find(trace => trace.node_id === nodeParentId) // the iteration node - - if (iterations && iterations.details) { - const iterationIndex = data.execution_metadata?.iteration_index || 0 - if (!iterations.details[iterationIndex]) - iterations.details[iterationIndex] = [] - - const currIteration = iterations.details[iterationIndex] - const nodeIndex = currIteration.findIndex(node => - node.node_id === data.node_id && ( - node.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || node.parallel_id === data.execution_metadata?.parallel_id), - ) - if (nodeIndex !== -1) { - currIteration[nodeIndex] = { - ...currIteration[nodeIndex], - ...(currIteration[nodeIndex].retryDetail - ? { retryDetail: currIteration[nodeIndex].retryDetail } - : {}), - ...data, - } as any - } - else { - currIteration.push({ - ...data, - } as any) - } - } - })) - } - else { - // open parallel mode - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const iterations = tracing.find(trace => trace.node_id === nodeParentId) // the iteration node - - if (iterations && iterations.details) { - const iterRunID = data.execution_metadata?.parallel_mode_run_id - - const currIteration = iterParallelLogMap.get(iterations.node_id)?.get(iterRunID) - const nodeIndex = currIteration?.findIndex(node => - node.node_id === data.node_id && ( - node?.parallel_run_id === data.execution_metadata?.parallel_mode_run_id), - ) - if (currIteration) { - if (nodeIndex !== undefined && nodeIndex !== -1) { - currIteration[nodeIndex] = { - ...currIteration[nodeIndex], - ...data, - } as any - } - else { - currIteration.push({ - ...data, - } as any) - } - } - setIterParallelLogMap(iterParallelLogMap) - const iterLogMap = iterParallelLogMap.get(iterations.node_id) - if (iterLogMap) - iterations.details = Array.from(iterLogMap.values()) - } - })) - } - } - else { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const currentIndex = draft.tracing!.findIndex((trace) => { - if (!trace.execution_metadata?.parallel_id) - return trace.node_id === data.node_id - return trace.node_id === data.node_id && trace.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id - }) - if (currentIndex > -1 && draft.tracing) { - draft.tracing[currentIndex] = { - ...data, - ...(draft.tracing[currentIndex].extras - ? { extras: draft.tracing[currentIndex].extras } - : {}), - ...(draft.tracing[currentIndex].retryDetail - ? { retryDetail: draft.tracing[currentIndex].retryDetail } - : {}), - } as any - } - })) - const newNodes = produce(nodes, (draft) => { - const currentNode = draft.find(node => node.id === data.node_id)! - currentNode.data._runningStatus = data.status as any - if (data.status === NodeRunningStatus.Exception) { - if (data.execution_metadata.error_strategy === ErrorHandleTypeEnum.failBranch) - currentNode.data._runningBranchId = ErrorHandleTypeEnum.failBranch - } - else { - if (data.node_type === BlockEnum.IfElse) - currentNode.data._runningBranchId = data?.outputs?.selected_case_id - - if (data.node_type === BlockEnum.QuestionClassifier) - currentNode.data._runningBranchId = data?.outputs?.class_id - } - }) - setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - const incomeEdges = draft.filter((edge) => { - return edge.target === data.node_id - }) - incomeEdges.forEach((edge) => { - edge.data = { - ...edge.data, - _targetRunningStatus: data.status as any, - } - }) - }) - setEdges(newEdges) - prevNodeId = data.node_id - } + handleWorkflowNodeFinished(params) if (onNodeFinished) onNodeFinished(params) }, onIterationStart: (params) => { - const { data } = params - const { - workflowRunningData, - setWorkflowRunningData, - setIterTimes, - } = workflowStore.getState() - const { - getNodes, - setNodes, - edges, - setEdges, - transform, - } = store.getState() - const nodes = getNodes() - setIterTimes(DEFAULT_ITER_TIMES) - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.tracing!.push({ - ...data, - status: NodeRunningStatus.Running, - details: [], - iterDurationMap: {}, - } as any) - })) - - const { - setViewport, - } = reactflow - const currentNodeIndex = nodes.findIndex(node => node.id === data.node_id) - const currentNode = nodes[currentNodeIndex] - const position = currentNode.position - const zoom = transform[2] - - if (!currentNode.parentId) { - setViewport({ - x: (clientWidth - 400 - currentNode.width! * zoom) / 2 - position.x * zoom, - y: (clientHeight - currentNode.height! * zoom) / 2 - position.y * zoom, - zoom: transform[2], - }) - } - const newNodes = produce(nodes, (draft) => { - draft[currentNodeIndex].data._runningStatus = NodeRunningStatus.Running - draft[currentNodeIndex].data._iterationLength = data.metadata.iterator_length - draft[currentNodeIndex].data._waitingRun = false - }) - setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - const incomeEdges = draft.filter(edge => edge.target === data.node_id) - - incomeEdges.forEach((edge) => { - edge.data = { - ...edge.data, - _sourceRunningStatus: nodes.find(node => node.id === edge.source)!.data._runningStatus, - _targetRunningStatus: NodeRunningStatus.Running, - _waitingRun: false, - } - }) - }) - setEdges(newEdges) + handleWorkflowNodeIterationStarted( + params, + { + clientWidth, + clientHeight, + }, + ) if (onIterationStart) onIterationStart(params) }, onIterationNext: (params) => { - const { - workflowRunningData, - setWorkflowRunningData, - iterTimes, - setIterTimes, - } = workflowStore.getState() - - const { data } = params - const { - getNodes, - setNodes, - } = store.getState() - - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const iteration = draft.tracing!.find(trace => trace.node_id === data.node_id) - if (iteration) { - if (iteration.iterDurationMap && data.duration) - iteration.iterDurationMap[data.parallel_mode_run_id ?? `${data.index - 1}`] = data.duration - if (iteration.details!.length >= iteration.metadata.iterator_length!) - return - } - if (!data.parallel_mode_run_id) - iteration?.details!.push([]) - })) - const nodes = getNodes() - const newNodes = produce(nodes, (draft) => { - const currentNode = draft.find(node => node.id === data.node_id)! - currentNode.data._iterationIndex = iterTimes - setIterTimes(iterTimes + 1) - }) - setNodes(newNodes) + handleWorkflowNodeIterationNext(params) if (onIterationNext) onIterationNext(params) }, onIterationFinish: (params) => { - const { data } = params - - const { - workflowRunningData, - setWorkflowRunningData, - setIterTimes, - } = workflowStore.getState() - const { - getNodes, - setNodes, - } = store.getState() - const nodes = getNodes() - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const currIterationNode = tracing.find(trace => trace.node_id === data.node_id) - if (currIterationNode) { - Object.assign(currIterationNode, { - ...data, - status: NodeRunningStatus.Succeeded, - }) - } - })) - setIterTimes(DEFAULT_ITER_TIMES) - const newNodes = produce(nodes, (draft) => { - const currentNode = draft.find(node => node.id === data.node_id)! - - currentNode.data._runningStatus = data.status - }) - setNodes(newNodes) - - prevNodeId = data.node_id + handleWorkflowNodeIterationFinished(params) if (onIterationFinish) onIterationFinish(params) }, onNodeRetry: (params) => { - const { data } = params - const { - workflowRunningData, - setWorkflowRunningData, - iterParallelLogMap, - setIterParallelLogMap, - } = workflowStore.getState() - const { - getNodes, - setNodes, - } = store.getState() - - const nodes = getNodes() - const currentNode = nodes.find(node => node.id === data.node_id)! - const nodeParent = nodes.find(node => node.id === currentNode.parentId) - if (nodeParent) { - if (!data.execution_metadata.parallel_mode_run_id) { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const iteration = tracing.find(trace => trace.node_id === nodeParent.id) - - if (iteration && iteration.details?.length) { - const currentNodeRetry = iteration.details[nodeParent.data._iterationIndex - 1]?.find(item => item.node_id === data.node_id) - - if (currentNodeRetry) { - if (currentNodeRetry?.retryDetail) - currentNodeRetry?.retryDetail.push(data as NodeTracing) - else - currentNodeRetry.retryDetail = [data as NodeTracing] - } - } - })) - } - else { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const iteration = tracing.find(trace => trace.node_id === nodeParent.id) - - if (iteration && iteration.details?.length) { - const iterRunID = data.execution_metadata?.parallel_mode_run_id - - const currIteration = iterParallelLogMap.get(iteration.node_id)?.get(iterRunID) - const currentNodeRetry = currIteration?.find(item => item.node_id === data.node_id) - - if (currentNodeRetry) { - if (currentNodeRetry?.retryDetail) - currentNodeRetry?.retryDetail.push(data as NodeTracing) - else - currentNodeRetry.retryDetail = [data as NodeTracing] - } - setIterParallelLogMap(iterParallelLogMap) - const iterLogMap = iterParallelLogMap.get(iteration.node_id) - if (iterLogMap) - iteration.details = Array.from(iterLogMap.values()) - } - })) - } - } - else { - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - const tracing = draft.tracing! - const currentRetryNodeIndex = tracing.findIndex(trace => trace.node_id === data.node_id) - - if (currentRetryNodeIndex > -1) { - const currentRetryNode = tracing[currentRetryNodeIndex] - if (currentRetryNode.retryDetail) - draft.tracing![currentRetryNodeIndex].retryDetail!.push(data as NodeTracing) - else - draft.tracing![currentRetryNodeIndex].retryDetail = [data as NodeTracing] - } - })) - } - const newNodes = produce(nodes, (draft) => { - const currentNode = draft.find(node => node.id === data.node_id)! - - currentNode.data._retryIndex = data.retry_index - }) - setNodes(newNodes) + handleWorkflowNodeRetry(params) if (onNodeRetry) onNodeRetry(params) }, - onParallelBranchStarted: (params) => { - // console.log(params, 'parallel start') - }, - onParallelBranchFinished: (params) => { - // console.log(params, 'finished') + onAgentLog: (params) => { + handleWorkflowAgentLog(params) + + if (onAgentLog) + onAgentLog(params) }, onTextChunk: (params) => { - const { data: { text } } = params - const { - workflowRunningData, - setWorkflowRunningData, - } = workflowStore.getState() - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.resultTabActive = true - draft.resultText += text - })) + handleWorkflowTextChunk(params) }, onTextReplace: (params) => { - const { data: { text } } = params - const { - workflowRunningData, - setWorkflowRunningData, - } = workflowStore.getState() - setWorkflowRunningData(produce(workflowRunningData!, (draft) => { - draft.resultText = text - })) + handleWorkflowTextReplace(params) }, - onTTSChunk: (messageId: string, audio: string, audioType?: string) => { + onTTSChunk: (messageId: string, audio: string) => { if (!audio || audio === '') return player.playAudioWithAudio(audio, true) AudioPlayerManager.getInstance().resetMsgId(messageId) }, - onTTSEnd: (messageId: string, audio: string, audioType?: string) => { + onTTSEnd: (messageId: string, audio: string) => { player.playAudioWithAudio(audio, false) }, ...restCallback, }, ) - }, [store, reactflow, workflowStore, doSyncWorkflowDraft]) + }, [store, workflowStore, doSyncWorkflowDraft, handleWorkflowStarted, handleWorkflowFinished, handleWorkflowFailed, handleWorkflowNodeStarted, handleWorkflowNodeFinished, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, handleWorkflowNodeRetry, handleWorkflowTextChunk, handleWorkflowTextReplace, handleWorkflowAgentLog, pathname]) const handleStopRun = useCallback((taskId: string) => { const appId = useAppStore.getState().appDetail?.id diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts index 2eafb4ad40..0f6ae59b6e 100644 --- a/web/app/components/workflow/hooks/use-workflow.ts +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -484,7 +484,6 @@ export const useWorkflowInit = () => { return acc }, {} as Record<string, string>), environmentVariables: res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [], - // #TODO chatVar sync# conversationVariables: res.conversation_variables || [], }) setSyncWorkflowDraftHash(res.hash) diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 2a0572becc..0510109b39 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -72,6 +72,7 @@ import SyncingDataModal from './syncing-data-modal' import UpdateDSLModal from './update-dsl-modal' import DSLExportConfirmModal from './dsl-export-confirm-modal' import LimitTips from './limit-tips' +import PluginDependency from './plugin-dependency' import { useStore, useWorkflowStore, @@ -327,6 +328,7 @@ const Workflow: FC<WorkflowProps> = memo(({ ) } <LimitTips /> + <PluginDependency /> <ReactFlow nodeTypes={nodeTypes} edgeTypes={edgeTypes} diff --git a/web/app/components/workflow/nodes/_base/components/add-button.tsx b/web/app/components/workflow/nodes/_base/components/add-button.tsx index 1e7323c8d7..c7fdcaa009 100644 --- a/web/app/components/workflow/nodes/_base/components/add-button.tsx +++ b/web/app/components/workflow/nodes/_base/components/add-button.tsx @@ -7,7 +7,7 @@ import { import cn from '@/utils/classnames' import Button from '@/app/components/base/button' -type Props = { +interface Props { className?: string text: string onClick: () => void diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx new file mode 100644 index 0000000000..a96654c4d9 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx @@ -0,0 +1,228 @@ +import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' +import type { ReactNode } from 'react' +import { memo, useEffect, useMemo, useRef, useState } from 'react' +import type { Strategy } from './agent-strategy' +import classNames from '@/utils/classnames' +import { RiArrowDownSLine, RiErrorWarningFill } from '@remixicon/react' +import Tooltip from '@/app/components/base/tooltip' +import Link from 'next/link' +import { InstallPluginButton } from './install-plugin-button' +import ViewTypeSelect, { ViewType } from '../../../block-selector/view-type-select' +import SearchInput from '@/app/components/base/search-input' +import Tools from '../../../block-selector/tools' +import { useTranslation } from 'react-i18next' +import { useStrategyProviders } from '@/service/use-strategy' +import { PluginType, type StrategyPluginDetail } from '@/app/components/plugins/types' +import type { ToolWithProvider } from '../../../types' +import { CollectionType } from '@/app/components/tools/types' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import { useStrategyInfo } from '../../agent/use-config' +import { SwitchPluginVersion } from './switch-plugin-version' +import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list' +import { useMarketplacePlugins } from '@/app/components/plugins/marketplace/hooks' +import { ToolTipContent } from '@/app/components/base/tooltip/content' + +const NotFoundWarn = (props: { + title: ReactNode, + description: ReactNode +}) => { + const { title, description } = props + + const { t } = useTranslation() + return <Tooltip + popupContent={ + <div className='space-y-1 text-xs'> + <h3 className='text-text-primary font-semibold'> + {title} + </h3> + <p className='text-text-secondary tracking-tight'> + {description} + </p> + <p> + <Link href={'/plugins'} className='text-text-accent tracking-tight'> + {t('workflow.nodes.agent.linkToPlugin')} + </Link> + </p> + </div> + } + needsDelay + > + <div> + <RiErrorWarningFill className='text-text-destructive size-4' /> + </div> + </Tooltip> +} + +function formatStrategy(input: StrategyPluginDetail[], getIcon: (i: string) => string): ToolWithProvider[] { + return input.map((item) => { + const res: ToolWithProvider = { + id: item.plugin_unique_identifier, + author: item.declaration.identity.author, + name: item.declaration.identity.name, + description: item.declaration.identity.description as any, + plugin_id: item.plugin_id, + icon: getIcon(item.declaration.identity.icon), + label: item.declaration.identity.label as any, + type: CollectionType.all, + tools: item.declaration.strategies.map(strategy => ({ + name: strategy.identity.name, + author: strategy.identity.author, + label: strategy.identity.label as any, + description: strategy.description, + parameters: strategy.parameters as any, + output_schema: strategy.output_schema, + labels: [], + })), + team_credentials: {}, + is_team_authorization: true, + allow_delete: false, + labels: [], + } + return res + }) +} + +export type AgentStrategySelectorProps = { + value?: Strategy, + onChange: (value?: Strategy) => void, +} + +export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) => { + const { value, onChange } = props + const [open, setOpen] = useState(false) + const [viewType, setViewType] = useState<ViewType>(ViewType.flat) + const [query, setQuery] = useState('') + const stra = useStrategyProviders() + const { getIconUrl } = useGetIcon() + const list = stra.data ? formatStrategy(stra.data, getIconUrl) : undefined + const filteredTools = useMemo(() => { + if (!list) return [] + return list.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase())) + }, [query, list]) + const { strategyStatus, refetch: refetchStrategyInfo } = useStrategyInfo( + value?.agent_strategy_provider_name, + value?.agent_strategy_name, + ) + + const showPluginNotInstalledWarn = strategyStatus?.plugin?.source === 'external' + && !strategyStatus.plugin.installed && !!value + + const showUnsupportedStrategy = strategyStatus?.plugin.source === 'external' + && !strategyStatus?.isExistInPlugin && !!value + + const showSwitchVersion = !strategyStatus?.isExistInPlugin + && strategyStatus?.plugin.source === 'marketplace' && strategyStatus.plugin.installed && !!value + + const showInstallButton = !strategyStatus?.isExistInPlugin + && strategyStatus?.plugin.source === 'marketplace' && !strategyStatus.plugin.installed && !!value + + const icon = list?.find( + coll => coll.tools?.find(tool => tool.name === value?.agent_strategy_name), + )?.icon as string | undefined + const { t } = useTranslation() + + const wrapElemRef = useRef<HTMLDivElement>(null) + + const { + queryPluginsWithDebounced: fetchPlugins, + plugins: notInstalledPlugins = [], + } = useMarketplacePlugins() + + useEffect(() => { + if (query) { + fetchPlugins({ + query, + category: PluginType.agent, + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [query]) + + const pluginRef = useRef(null) + + return <PortalToFollowElem open={open} onOpenChange={setOpen} placement='bottom'> + <PortalToFollowElemTrigger className='w-full'> + <div + className='h-8 p-1 gap-0.5 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none' + onClick={() => setOpen(o => !o)} + > + {/* eslint-disable-next-line @next/next/no-img-element */} + {icon && <div className='flex items-center justify-center w-6 h-6'><img + src={icon} + width={20} + height={20} + className='rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge' + alt='icon' + /></div>} + <p + className={classNames(value ? 'text-components-input-text-filled' : 'text-components-input-text-placeholder', 'text-xs px-1')} + > + {value?.agent_strategy_label || t('workflow.nodes.agent.strategy.selectTip')} + </p> + <div className='ml-auto flex items-center gap-1'> + {showInstallButton && value && <InstallPluginButton + onClick={e => e.stopPropagation()} + size={'small'} + uniqueIdentifier={value.plugin_unique_identifier} + />} + {showPluginNotInstalledWarn + ? <NotFoundWarn + title={t('workflow.nodes.agent.pluginNotInstalled')} + description={t('workflow.nodes.agent.pluginNotInstalledDesc')} + /> + : showUnsupportedStrategy + ? <NotFoundWarn + title={t('workflow.nodes.agent.unsupportedStrategy')} + description={t('workflow.nodes.agent.strategyNotFoundDesc')} + /> + : <RiArrowDownSLine className='size-4 text-text-tertiary' /> + } + {showSwitchVersion && <SwitchPluginVersion + uniqueIdentifier={value.plugin_unique_identifier} + tooltip={<ToolTipContent + title={t('workflow.nodes.agent.unsupportedStrategy')}> + {t('workflow.nodes.agent.strategyNotFoundDescAndSwitchVersion')} + </ToolTipContent>} + onChange={() => { + refetchStrategyInfo() + }} + />} + </div> + </div> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent className='z-10'> + <div className='bg-components-panel-bg-blur border-components-panel-border border-[0.5px] rounded-md shadow overflow-hidden w-[388px]'> + <header className='p-2 gap-1 flex'> + <SearchInput placeholder={t('workflow.nodes.agent.strategy.searchPlaceholder')} value={query} onChange={setQuery} className={'w-full'} /> + <ViewTypeSelect viewType={viewType} onChange={setViewType} /> + </header> + <main className="md:max-h-[300px] xl:max-h-[400px] 2xl:max-h-[564px] relative overflow-hidden flex flex-col w-full" ref={wrapElemRef}> + <Tools + tools={filteredTools} + viewType={viewType} + onSelect={(_, tool) => { + onChange({ + agent_strategy_name: tool!.tool_name, + agent_strategy_provider_name: tool!.provider_name, + agent_strategy_label: tool!.tool_label, + agent_output_schema: tool!.output_schema, + plugin_unique_identifier: tool!.provider_id, + }) + setOpen(false) + } } + className='max-w-none max-h-full h-full overflow-y-auto' + indexBarClassName='top-0 xl:top-36' showWorkflowEmpty={false} hasSearchText={false} /> + <PluginList + wrapElemRef={wrapElemRef} + list={notInstalledPlugins as any} ref={pluginRef} + searchText={query} + tags={[]} + disableMaxWidth + /> + </main> + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> +}) + +AgentStrategySelector.displayName = 'AgentStrategySelector' diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx new file mode 100644 index 0000000000..01a1aba24e --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx @@ -0,0 +1,218 @@ +import type { CredentialFormSchemaNumberInput, CredentialFormSchemaTextInput } from '@/app/components/header/account-setting/model-provider-page/declarations' +import { type CredentialFormSchema, FormTypeEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' +import type { ToolVarInputs } from '../../tool/types' +import ListEmpty from '@/app/components/base/list-empty' +import { AgentStrategySelector } from './agent-strategy-selector' +import Link from 'next/link' +import { useTranslation } from 'react-i18next' +import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +import { Agent } from '@/app/components/base/icons/src/vender/workflow' +import { InputNumber } from '@/app/components/base/input-number' +import Slider from '@/app/components/base/slider' +import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector' +import Field from './field' +import { type ComponentProps, memo } from 'react' +import { useDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks' +import Editor from './prompt/editor' +import { useWorkflowStore } from '../../../store' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import type { NodeOutPutVar } from '../../../types' +import type { Node } from 'reactflow' + +export type Strategy = { + agent_strategy_provider_name: string + agent_strategy_name: string + agent_strategy_label: string + agent_output_schema: Record<string, any> + plugin_unique_identifier: string +} + +export type AgentStrategyProps = { + strategy?: Strategy + onStrategyChange: (strategy?: Strategy) => void + formSchema: CredentialFormSchema[] + formValue: ToolVarInputs + onFormValueChange: (value: ToolVarInputs) => void + nodeOutputVars?: NodeOutPutVar[], + availableNodes?: Node[], +} + +type CustomSchema<Type, Field = {}> = Omit<CredentialFormSchema, 'type'> & { type: Type } & Field + +type ToolSelectorSchema = CustomSchema<'tool-selector'> +type MultipleToolSelectorSchema = CustomSchema<'array[tools]'> + +type CustomField = ToolSelectorSchema | MultipleToolSelectorSchema + +export const AgentStrategy = memo((props: AgentStrategyProps) => { + const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes } = props + const { t } = useTranslation() + const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration) + const renderI18nObject = useRenderI18nObject() + const workflowStore = useWorkflowStore() + const { + setControlPromptEditorRerenderKey, + } = workflowStore.getState() + const override: ComponentProps<typeof Form<CustomField>>['override'] = [ + [FormTypeEnum.textNumber, FormTypeEnum.textInput], + (schema, props) => { + switch (schema.type) { + case FormTypeEnum.textInput: { + const def = schema as CredentialFormSchemaTextInput + const value = props.value[schema.variable] + const onChange = (value: string) => { + props.onChange({ ...props.value, [schema.variable]: value }) + } + const handleGenerated = (value: string) => { + onChange(value) + setControlPromptEditorRerenderKey(Math.random()) + } + return <Editor + value={value} + onChange={onChange} + onGenerated={handleGenerated} + title={renderI18nObject(schema.label)} + headerClassName='bg-transparent px-0 text-text-secondary system-sm-semibold-uppercase' + containerBackgroundClassName='bg-transparent' + gradientBorder={false} + isSupportPromptGenerator={!!def.auto_generate?.type} + titleTooltip={schema.tooltip && renderI18nObject(schema.tooltip)} + editorContainerClassName='px-0' + availableNodes={availableNodes} + nodesOutputVars={nodeOutputVars} + isSupportJinja={def.template?.enabled} + required={def.required} + varList={[]} + modelConfig={ + defaultModel.data + ? { + mode: 'chat', + name: defaultModel.data.model, + provider: defaultModel.data.provider.provider, + completion_params: {}, + } : undefined + } + placeholderClassName='px-2 py-1' + titleClassName='system-sm-semibold-uppercase text-text-secondary text-[13px]' + inputClassName='px-2 py-1 bg-components-input-bg-normal focus:bg-components-input-bg-active focus:border-components-input-border-active focus:border rounded-lg' + /> + } + case FormTypeEnum.textNumber: { + const def = schema as CredentialFormSchemaNumberInput + if (!def.max || !def.min) + return false + + const defaultValue = schema.default ? Number.parseInt(schema.default) : 1 + const value = props.value[schema.variable] || defaultValue + const onChange = (value: number) => { + props.onChange({ ...props.value, [schema.variable]: value }) + } + return <Field + title={<> + {renderI18nObject(def.label)} {def.required && <span className='text-red-500'>*</span>} + </>} + tooltip={def.tooltip && renderI18nObject(def.tooltip)} + inline + > + <div className='flex w-[200px] items-center gap-3'> + <Slider + value={value} + onChange={onChange} + className='w-full' + min={def.min} + max={def.max} + /> + <InputNumber + value={value} + // TODO: maybe empty, handle this + onChange={onChange as any} + defaultValue={defaultValue} + size='sm' + min={def.min} + max={def.max} + className='w-12' + /> + </div> + </Field> + } + } + }, + ] + const renderField: ComponentProps<typeof Form<CustomField>>['customRenderField'] = (schema, props) => { + switch (schema.type) { + case 'tool-selector': { + const value = props.value[schema.variable] + const onChange = (value: any) => { + props.onChange({ ...props.value, [schema.variable]: value }) + } + return ( + <Field + title={<> + {renderI18nObject(schema.label)} {schema.required && <span className='text-red-500'>*</span>} + </>} + tooltip={schema.tooltip && renderI18nObject(schema.tooltip)} + > + <ToolSelector + scope={schema.scope} + value={value} + onSelect={item => onChange(item)} + onDelete={() => onChange(null)} + /> + </Field> + ) + } + case 'array[tools]': { + const value = props.value[schema.variable] + const onChange = (value: any) => { + props.onChange({ ...props.value, [schema.variable]: value }) + } + return ( + <MultipleToolSelector + scope={schema.scope} + value={value || []} + label={renderI18nObject(schema.label)} + tooltip={schema.tooltip && renderI18nObject(schema.tooltip)} + onChange={onChange} + supportCollapse + required={schema.required} + /> + ) + } + } + } + return <div className='space-y-2'> + <AgentStrategySelector value={strategy} onChange={onStrategyChange} /> + { + strategy + ? <div> + <Form<CustomField> + formSchemas={[ + ...formSchema, + ]} + value={formValue} + onChange={onFormValueChange} + validating={false} + showOnVariableMap={{}} + isEditMode={true} + isAgentStrategy={true} + fieldLabelClassName='uppercase' + customRenderField={renderField} + override={override} + /> + </div> + : <ListEmpty + icon={<Agent className='w-5 h-5 shrink-0 text-text-accent' />} + title={t('workflow.nodes.agent.strategy.configureTip')} + description={<div className='text-text-tertiary text-xs'> + {t('workflow.nodes.agent.strategy.configureTipDesc')} <br /> + <Link href={'/'} className='text-text-accent-secondary'> + {t('workflow.nodes.agent.learnMore')} + </Link> + </div>} + /> + } + </div> +}) + +AgentStrategy.displayName = 'AgentStrategy' diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx index e2ca592a62..a4885759c4 100644 --- a/web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx @@ -25,7 +25,7 @@ import { BubbleX } from '@/app/components/base/icons/src/vender/line/others' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' import cn from '@/utils/classnames' -type Props = { +interface Props { payload: InputVar value: any onChange: (value: any) => void diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx index 967e796373..e9ac442680 100644 --- a/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/form.tsx @@ -9,7 +9,7 @@ import { InputVarType } from '@/app/components/workflow/types' import AddButton from '@/app/components/base/button/add-button' import { RETRIEVAL_OUTPUT_STRUCT } from '@/app/components/workflow/constants' -export type Props = { +export interface Props { className?: string label?: string inputs: InputVar[] diff --git a/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx index d7e2a953da..2fb873e604 100644 --- a/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/before-run-form/index.tsx @@ -17,10 +17,10 @@ import ResultPanel from '@/app/components/workflow/run/result-panel' import Toast from '@/app/components/base/toast' import { TransferMethod } from '@/types/app' import { getProcessedFiles } from '@/app/components/base/file-uploader/utils' -import type { NodeTracing } from '@/types/workflow' -import RetryResultPanel from '@/app/components/workflow/run/retry-result-panel' import type { BlockEnum } from '@/app/components/workflow/types' import type { Emoji } from '@/app/components/tools/types' +import type { SpecialResultPanelProps } from '@/app/components/workflow/run/special-result-panel' +import SpecialResultPanel from '@/app/components/workflow/run/special-result-panel' const i18nPrefix = 'workflow.singleRun' @@ -34,13 +34,12 @@ type BeforeRunFormProps = { runningStatus: NodeRunningStatus result?: JSX.Element forms: FormProps[] - retryDetails?: NodeTracing[] - onRetryDetailBack?: any -} + showSpecialResultPanel?: boolean +} & Partial<SpecialResultPanelProps> function formatValue(value: string | any, type: InputVarType) { if (type === InputVarType.number) - return parseFloat(value) + return Number.parseFloat(value) if (type === InputVarType.json) return JSON.parse(value) if (type === InputVarType.contexts) { @@ -66,8 +65,8 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({ runningStatus, result, forms, - retryDetails, - onRetryDetailBack = () => { }, + showSpecialResultPanel, + ...restResultPanelParams }) => { const { t } = useTranslation() @@ -141,24 +140,14 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({ </div> </div> { - retryDetails?.length && ( + showSpecialResultPanel && ( <div className='h-0 grow overflow-y-auto pb-4'> - <RetryResultPanel - list={retryDetails.map((item, index) => ({ - ...item, - title: `${t('workflow.nodes.common.retry.retry')} ${index + 1}`, - node_type: nodeType!, - extras: { - icon: toolIcon!, - }, - }))} - onBack={onRetryDetailBack} - /> + <SpecialResultPanel {...restResultPanelParams} /> </div> ) } { - !retryDetails?.length && ( + !showSpecialResultPanel && ( <div className='h-0 grow overflow-y-auto pb-4'> <div className='mt-3 px-4 space-y-4'> {forms.map((form, index) => ( diff --git a/web/app/components/workflow/nodes/_base/components/collapse/field-collapse.tsx b/web/app/components/workflow/nodes/_base/components/collapse/field-collapse.tsx index 7d2698a6d0..71ca0d28ea 100644 --- a/web/app/components/workflow/nodes/_base/components/collapse/field-collapse.tsx +++ b/web/app/components/workflow/nodes/_base/components/collapse/field-collapse.tsx @@ -1,8 +1,9 @@ +import type { ReactNode } from 'react' import Collapse from '.' type FieldCollapseProps = { title: string - children: JSX.Element + children: ReactNode } const FieldCollapse = ({ title, diff --git a/web/app/components/workflow/nodes/_base/components/editor/base.tsx b/web/app/components/workflow/nodes/_base/components/editor/base.tsx index ead88b86dd..9e20a3857f 100644 --- a/web/app/components/workflow/nodes/_base/components/editor/base.tsx +++ b/web/app/components/workflow/nodes/_base/components/editor/base.tsx @@ -16,7 +16,7 @@ import useToggleExpend from '@/app/components/workflow/nodes/_base/hooks/use-tog import type { FileEntity } from '@/app/components/base/file-uploader/types' import FileListInLog from '@/app/components/base/file-uploader/file-list-in-log' -type Props = { +interface Props { className?: string title: JSX.Element | string headerRight?: JSX.Element diff --git a/web/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx b/web/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx index db2425c958..3d667ac700 100644 --- a/web/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx +++ b/web/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars.tsx @@ -88,7 +88,7 @@ const CodeEditor: FC<Props> = ({ const index = (() => { if (match) - return parseInt(match[1]!) + 1 + return Number.parseInt(match[1]!) + 1 return 1 })() diff --git a/web/app/components/workflow/nodes/_base/components/field.tsx b/web/app/components/workflow/nodes/_base/components/field.tsx index e284e91cfc..d5d5ed7394 100644 --- a/web/app/components/workflow/nodes/_base/components/field.tsx +++ b/web/app/components/workflow/nodes/_base/components/field.tsx @@ -1,18 +1,17 @@ 'use client' -import type { FC } from 'react' +import type { FC, ReactNode } from 'react' import React from 'react' import { RiArrowDownSLine, } from '@remixicon/react' import { useBoolean } from 'ahooks' -import type { DefaultTFuncReturn } from 'i18next' import cn from '@/utils/classnames' import Tooltip from '@/app/components/base/tooltip' type Props = { className?: string - title: JSX.Element | string | DefaultTFuncReturn - tooltip?: React.ReactNode + title: ReactNode + tooltip?: ReactNode isSubTitle?: boolean supportFold?: boolean children?: JSX.Element | string | null @@ -51,7 +50,7 @@ const Field: FC<Props> = ({ <div className='flex'> {operations && <div>{operations}</div>} {supportFold && ( - <RiArrowDownSLine className='w-4 h-4 text-text-tertiary cursor-pointer transform transition-transform' style={{ transform: fold ? 'rotate(-90deg)' : 'rotate(0deg)' }} /> + <RiArrowDownSLine className='w-4 h-4 text-text-tertiary cursor-pointer transition-transform' style={{ transform: fold ? 'rotate(-90deg)' : 'rotate(0deg)' }} /> )} </div> </div> diff --git a/web/app/components/workflow/nodes/_base/components/group.tsx b/web/app/components/workflow/nodes/_base/components/group.tsx new file mode 100644 index 0000000000..ad2e3f0596 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/group.tsx @@ -0,0 +1,25 @@ +import classNames from '@/utils/classnames' +import type { ComponentProps, FC, PropsWithChildren, ReactNode } from 'react' + +export type GroupLabelProps = ComponentProps<'div'> + +export const GroupLabel: FC<GroupLabelProps> = (props) => { + const { children, className, ...rest } = props + return <div {...rest} className={classNames('mb-1 system-2xs-medium-uppercase text-text-tertiary', className)}> + {children} + </div> +} + +export type Group = PropsWithChildren<{ + label: ReactNode +}> + +export const Group: FC<Group> = (props) => { + const { children, label } = props + return <div className={classNames('py-1')}> + {label} + <div className='space-y-0.5'> + {children} + </div> + </div> +} diff --git a/web/app/components/workflow/nodes/_base/components/info-panel.tsx b/web/app/components/workflow/nodes/_base/components/info-panel.tsx index 983cb9bd0c..e960931d49 100644 --- a/web/app/components/workflow/nodes/_base/components/info-panel.tsx +++ b/web/app/components/workflow/nodes/_base/components/info-panel.tsx @@ -1,10 +1,10 @@ 'use client' -import type { FC } from 'react' +import type { FC, ReactNode } from 'react' import React from 'react' type Props = { title: string - content: string | JSX.Element + content: ReactNode } const InfoPanel: FC<Props> = ({ diff --git a/web/app/components/workflow/nodes/_base/components/input-number-with-slider.tsx b/web/app/components/workflow/nodes/_base/components/input-number-with-slider.tsx index c64f98093a..0210db2f8e 100644 --- a/web/app/components/workflow/nodes/_base/components/input-number-with-slider.tsx +++ b/web/app/components/workflow/nodes/_base/components/input-number-with-slider.tsx @@ -34,7 +34,7 @@ const InputNumberWithSlider: FC<Props> = ({ }, [defaultValue, max, min, onChange, value]) const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { - onChange(parseFloat(e.target.value)) + onChange(Number.parseFloat(e.target.value)) }, [onChange]) return ( diff --git a/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx b/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx index d3cc1dbc78..178adc5ea3 100644 --- a/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx +++ b/web/app/components/workflow/nodes/_base/components/input-var-type-icon.tsx @@ -4,7 +4,7 @@ import React from 'react' import { RiAlignLeft, RiCheckboxMultipleLine, RiFileCopy2Line, RiFileList2Line, RiHashtag, RiTextSnippet } from '@remixicon/react' import { InputVarType } from '../../../types' -type Props = { +interface Props { className?: string type: InputVarType } diff --git a/web/app/components/workflow/nodes/_base/components/install-plugin-button.tsx b/web/app/components/workflow/nodes/_base/components/install-plugin-button.tsx new file mode 100644 index 0000000000..dc5930e15b --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/install-plugin-button.tsx @@ -0,0 +1,45 @@ +import Button from '@/app/components/base/button' +import { RiInstallLine, RiLoader2Line } from '@remixicon/react' +import type { ComponentProps, MouseEventHandler } from 'react' +import classNames from '@/utils/classnames' +import { useTranslation } from 'react-i18next' +import { useCheckInstalled, useInstallPackageFromMarketPlace } from '@/service/use-plugins' + +type InstallPluginButtonProps = Omit<ComponentProps<typeof Button>, 'children' | 'loading'> & { + uniqueIdentifier: string + onSuccess?: () => void +} + +export const InstallPluginButton = (props: InstallPluginButtonProps) => { + const { className, uniqueIdentifier, onSuccess, ...rest } = props + const { t } = useTranslation() + const manifest = useCheckInstalled({ + pluginIds: [uniqueIdentifier], + enabled: !!uniqueIdentifier, + }) + const install = useInstallPackageFromMarketPlace() + const isLoading = manifest.isLoading || install.isPending + // await for refetch to get the new installed plugin, when manifest refetch, this component will unmount + || install.isSuccess + const handleInstall: MouseEventHandler = (e) => { + e.stopPropagation() + install.mutate(uniqueIdentifier, { + onSuccess: async () => { + await manifest.refetch() + onSuccess?.() + }, + }) + } + if (!manifest.data) return null + if (manifest.data.plugins.some(plugin => plugin.id === uniqueIdentifier)) return null + return <Button + variant={'secondary'} + disabled={isLoading} + {...rest} + onClick={handleInstall} + className={classNames('flex items-center', className)} + > + {!isLoading ? t('workflow.nodes.agent.pluginInstaller.install') : t('workflow.nodes.agent.pluginInstaller.installing')} + {!isLoading ? <RiInstallLine className='size-3.5 ml-1' /> : <RiLoader2Line className='size-3.5 ml-1 animate-spin' />} + </Button> +} diff --git a/web/app/components/workflow/nodes/_base/components/memory-config.tsx b/web/app/components/workflow/nodes/_base/components/memory-config.tsx index 476f5b738c..1e436c28e7 100644 --- a/web/app/components/workflow/nodes/_base/components/memory-config.tsx +++ b/web/app/components/workflow/nodes/_base/components/memory-config.tsx @@ -88,7 +88,7 @@ const MemoryConfig: FC<Props> = ({ limitedSize = null } else { - limitedSize = parseInt(limitedSize as string, 10) + limitedSize = Number.parseInt(limitedSize as string, 10) if (isNaN(limitedSize)) limitedSize = WINDOW_SIZE_DEFAULT diff --git a/web/app/components/workflow/nodes/_base/components/node-status-icon.tsx b/web/app/components/workflow/nodes/_base/components/node-status-icon.tsx new file mode 100644 index 0000000000..99d70f474f --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/node-status-icon.tsx @@ -0,0 +1,43 @@ +import { + RiAlertFill, + RiCheckboxCircleFill, + RiErrorWarningLine, + RiLoader2Line, +} from '@remixicon/react' +import cn from '@/utils/classnames' + +type NodeStatusIconProps = { + status: string + className?: string +} +const NodeStatusIcon = ({ + status, + className, +}: NodeStatusIconProps) => { + return ( + <> + { + status === 'succeeded' && ( + <RiCheckboxCircleFill className={cn('shrink-0 w-4 h-4 text-text-success', className)} /> + ) + } + { + status === 'failed' && ( + <RiErrorWarningLine className={cn('shrink-0 w-4 h-4 text-text-warning', className)} /> + ) + } + { + (status === 'stopped' || status === 'exception') && ( + <RiAlertFill className={cn('shrink-0 w-4 h-4 text-text-warning-secondary', className)} /> + ) + } + { + status === 'running' && ( + <RiLoader2Line className={cn('shrink-0 w-4 h-4 text-text-accent animate-spin', className)} /> + ) + } + </> + ) +} + +export default NodeStatusIcon diff --git a/web/app/components/workflow/nodes/_base/components/output-vars.tsx b/web/app/components/workflow/nodes/_base/components/output-vars.tsx index a0d7a25c07..4a265a5a5b 100644 --- a/web/app/components/workflow/nodes/_base/components/output-vars.tsx +++ b/web/app/components/workflow/nodes/_base/components/output-vars.tsx @@ -1,5 +1,5 @@ 'use client' -import type { FC } from 'react' +import type { FC, ReactNode } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse' @@ -7,7 +7,7 @@ import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/ type Props = { className?: string title?: string - children: JSX.Element + children: ReactNode } const OutputVars: FC<Props> = ({ diff --git a/web/app/components/workflow/nodes/_base/components/prompt/editor.tsx b/web/app/components/workflow/nodes/_base/components/prompt/editor.tsx index 66923fbe1f..9b7c63d862 100644 --- a/web/app/components/workflow/nodes/_base/components/prompt/editor.tsx +++ b/web/app/components/workflow/nodes/_base/components/prompt/editor.tsx @@ -1,5 +1,5 @@ 'use client' -import type { FC } from 'react' +import type { FC, ReactNode } from 'react' import React, { useCallback, useRef } from 'react' import { RiDeleteBinLine, @@ -68,6 +68,14 @@ type Props = { onEditionTypeChange?: (editionType: EditionType) => void varList?: Variable[] handleAddVariable?: (payload: any) => void + containerBackgroundClassName?: string + gradientBorder?: boolean + titleTooltip?: ReactNode + inputClassName?: string + editorContainerClassName?: string + placeholderClassName?: string + titleClassName?: string + required?: boolean } const Editor: FC<Props> = ({ @@ -96,6 +104,14 @@ const Editor: FC<Props> = ({ handleAddVariable, onGenerated, modelConfig, + containerBackgroundClassName: containerClassName, + gradientBorder = true, + titleTooltip, + inputClassName, + placeholderClassName, + titleClassName, + editorContainerClassName, + required, }) => { const { t } = useTranslation() const { eventEmitter } = useEventEmitterContextContext() @@ -129,10 +145,13 @@ const Editor: FC<Props> = ({ return ( <Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}> - <div ref={ref} className={cn(isFocus ? s.gradientBorder : 'bg-gray-100', isExpand && 'h-full', '!rounded-[9px] p-0.5')}> - <div className={cn(isFocus ? 'bg-gray-50' : 'bg-gray-100', isExpand && 'h-full flex flex-col', 'rounded-lg')}> - <div className={cn(headerClassName, 'pt-1 pl-3 pr-2 flex justify-between items-center')}> - <div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div> + <div ref={ref} className={cn(isFocus ? (gradientBorder && s.gradientBorder) : 'bg-gray-100', isExpand && 'h-full', '!rounded-[9px] p-0.5', containerClassName)}> + <div className={cn(isFocus ? 'bg-gray-50' : 'bg-gray-100', isExpand && 'h-full flex flex-col', 'rounded-lg', containerClassName)}> + <div className={cn('pt-1 pl-3 pr-2 flex justify-between items-center', headerClassName)}> + <div className='flex gap-2'> + <div className={cn('leading-4 text-xs font-semibold text-gray-700 uppercase', titleClassName)}>{title} {required && <span className='text-red-500'>*</span>}</div> + {titleTooltip && <Tooltip popupContent={titleTooltip} />} + </div> <div className='flex items-center'> <div className='leading-[18px] text-xs font-medium text-gray-500'>{value?.length || 0}</div> {isSupportPromptGenerator && ( @@ -201,12 +220,13 @@ const Editor: FC<Props> = ({ <div className={cn('pb-2', isExpand && 'flex flex-col grow')}> {!(isSupportJinja && editionType === EditionType.jinja2) ? ( - <div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto')}> + <div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto', editorContainerClassName)}> <PromptEditor key={controlPromptEditorRerenderKey} + placeholderClassName={placeholderClassName} instanceId={instanceId} compact - className='min-h-[56px]' + className={cn('min-h-[56px]', inputClassName)} style={isExpand ? { height: editorExpandHeight - 5 } : {}} value={value} contextBlock={{ @@ -254,7 +274,7 @@ const Editor: FC<Props> = ({ </div> ) : ( - <div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto')}> + <div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto', editorContainerClassName)}> <CodeEditor availableVars={nodesOutputVars || []} varList={varList} @@ -266,6 +286,7 @@ const Editor: FC<Props> = ({ onChange={onChange} noWrapper isExpand={isExpand} + className={inputClassName} /> </div> )} diff --git a/web/app/components/workflow/nodes/_base/components/setting-item.tsx b/web/app/components/workflow/nodes/_base/components/setting-item.tsx new file mode 100644 index 0000000000..ca074ffbb7 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/setting-item.tsx @@ -0,0 +1,28 @@ +import Tooltip from '@/app/components/base/tooltip' +import Indicator from '@/app/components/header/indicator' +import classNames from '@/utils/classnames' +import { type ComponentProps, type PropsWithChildren, type ReactNode, memo } from 'react' + +export type SettingItemProps = PropsWithChildren<{ + label: string + status?: 'error' | 'warning' + tooltip?: ReactNode +}> + +export const SettingItem = memo(({ label, children, status, tooltip }: SettingItemProps) => { + const indicator: ComponentProps<typeof Indicator>['color'] = status === 'error' ? 'red' : status === 'warning' ? 'yellow' : undefined + const needTooltip = ['error', 'warning'].includes(status as any) + return <div className='flex items-center justify-between bg-workflow-block-parma-bg rounded-md py-1 px-1.5 space-x-1 text-xs font-normal relative'> + <div className={classNames('shrink-0 truncate text-text-tertiary system-xs-medium-uppercase', !!children && 'max-w-[100px]')}> + {label} + </div> + <Tooltip popupContent={tooltip} disabled={!needTooltip}> + <div className='truncate text-right system-xs-medium text-text-secondary'> + {children} + </div> + </Tooltip> + {indicator && <Indicator color={indicator} className='absolute -right-0.5 -top-0.5' />} + </div> +}) + +SettingItem.displayName = 'SettingItem' diff --git a/web/app/components/workflow/nodes/_base/components/split.tsx b/web/app/components/workflow/nodes/_base/components/split.tsx index 28cd05f6da..9f773ba960 100644 --- a/web/app/components/workflow/nodes/_base/components/split.tsx +++ b/web/app/components/workflow/nodes/_base/components/split.tsx @@ -3,7 +3,7 @@ import type { FC } from 'react' import React from 'react' import cn from '@/utils/classnames' -type Props = { +interface Props { className?: string } diff --git a/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx b/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx new file mode 100644 index 0000000000..ea35c8492f --- /dev/null +++ b/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx @@ -0,0 +1,126 @@ +'use client' + +import Badge from '@/app/components/base/badge' +import Tooltip from '@/app/components/base/tooltip' +import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker' +import { RiArrowLeftRightLine, RiExternalLinkLine } from '@remixicon/react' +import type { ReactNode } from 'react' +import { type FC, useCallback, useState } from 'react' +import { useBoolean } from 'ahooks' +import { useCheckInstalled, useUpdatePackageFromMarketPlace } from '@/service/use-plugins' +import cn from '@/utils/classnames' +import PluginMutationModel from '@/app/components/plugins/plugin-mutation-model' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' +import { pluginManifestToCardPluginProps } from '@/app/components/plugins/install-plugin/utils' +import { Badge as Badge2, BadgeState } from '@/app/components/base/badge/index' +import Link from 'next/link' +import { useTranslation } from 'react-i18next' +import { marketplaceUrlPrefix } from '@/config' + +export type SwitchPluginVersionProps = { + uniqueIdentifier: string + tooltip?: ReactNode + onChange?: (version: string) => void + className?: string +} + +export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => { + const { uniqueIdentifier, tooltip, onChange, className } = props + const [pluginId] = uniqueIdentifier.split(':') + const [isShow, setIsShow] = useState(false) + const [isShowUpdateModal, { setTrue: showUpdateModal, setFalse: hideUpdateModal }] = useBoolean(false) + const [target, setTarget] = useState<{ + version: string, + pluginUniqueIden: string; + }>() + const pluginDetails = useCheckInstalled({ + pluginIds: [pluginId], + enabled: true, + }) + const pluginDetail = pluginDetails.data?.plugins.at(0) + + const handleUpdatedFromMarketplace = useCallback(() => { + hideUpdateModal() + pluginDetails.refetch() + onChange?.(target!.version) + }, [hideUpdateModal, onChange, pluginDetails, target]) + const { getIconUrl } = useGetIcon() + const icon = pluginDetail?.declaration.icon ? getIconUrl(pluginDetail.declaration.icon) : undefined + const mutation = useUpdatePackageFromMarketPlace() + const install = () => { + mutation.mutate( + { + new_plugin_unique_identifier: target!.pluginUniqueIden, + original_plugin_unique_identifier: uniqueIdentifier, + }, + { + onSuccess() { + handleUpdatedFromMarketplace() + }, + }) + } + const { t } = useTranslation() + return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'> + <div className={cn('w-fit flex items-center justify-center', className)} onClick={e => e.stopPropagation()}> + {isShowUpdateModal && pluginDetail && <PluginMutationModel + onCancel={hideUpdateModal} + plugin={pluginManifestToCardPluginProps({ + ...pluginDetail.declaration, + icon: icon!, + })} + mutation={mutation} + mutate={install} + confirmButtonText={t('workflow.nodes.agent.installPlugin.install')} + cancelButtonText={t('workflow.nodes.agent.installPlugin.cancel')} + modelTitle={t('workflow.nodes.agent.installPlugin.title')} + description={t('workflow.nodes.agent.installPlugin.desc')} + cardTitleLeft={<> + <Badge2 className='mx-1' size="s" state={BadgeState.Warning}> + {`${pluginDetail.version} -> ${target!.version}`} + </Badge2> + </>} + modalBottomLeft={ + <Link + className='flex justify-center items-center gap-1' + href={`${marketplaceUrlPrefix}/plugins/${pluginDetail.declaration.author}/${pluginDetail.declaration.name}`} + target='_blank' + > + <span className='text-text-accent system-xs-regular text-xs'> + {t('workflow.nodes.agent.installPlugin.changelog')} + </span> + <RiExternalLinkLine className='text-text-accent size-3' /> + </Link> + } + />} + {pluginDetail && <PluginVersionPicker + isShow={isShow} + onShowChange={setIsShow} + pluginID={pluginId} + currentVersion={pluginDetail.version} + onSelect={(state) => { + setTarget({ + pluginUniqueIden: state.unique_identifier, + version: state.version, + }) + showUpdateModal() + }} + trigger={ + <Badge + className={cn( + 'mx-1 hover:bg-state-base-hover flex', + isShow && 'bg-state-base-hover', + )} + uppercase={true} + text={ + <> + <div>{pluginDetail.version}</div> + <RiArrowLeftRightLine className='ml-1 w-3 h-3 text-text-tertiary' /> + </> + } + hasRedCornerMark={true} + /> + } + />} + </div> + </Tooltip> +} diff --git a/web/app/components/workflow/nodes/_base/components/variable-tag.tsx b/web/app/components/workflow/nodes/_base/components/variable-tag.tsx index 0c5c3bde4b..67c8bb57df 100644 --- a/web/app/components/workflow/nodes/_base/components/variable-tag.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable-tag.tsx @@ -19,7 +19,7 @@ import Tooltip from '@/app/components/base/tooltip' import cn from '@/utils/classnames' import { isExceptionVariable } from '@/app/components/workflow/utils' -type VariableTagProps = { +interface VariableTagProps { valueSelector: ValueSelector varType: VarType isShort?: boolean diff --git a/web/app/components/workflow/nodes/_base/components/variable/output-var-list.tsx b/web/app/components/workflow/nodes/_base/components/variable/output-var-list.tsx index 1c07461b42..17c0061f0e 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/output-var-list.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable/output-var-list.tsx @@ -11,7 +11,7 @@ import type { VarType } from '@/app/components/workflow/types' import { checkKeys } from '@/utils/var' import Toast from '@/app/components/base/toast' -type Props = { +interface Props { readonly: boolean outputs: OutputVar outputKeyOrders: string[] diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index 715ad1c7b1..482bb7acf7 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -32,6 +32,7 @@ import { } from '@/app/components/workflow/constants' import type { PromptItem } from '@/models/debug' import { VAR_REGEX } from '@/config' +import type { AgentNodeType } from '../../../agent/types' export const isSystemVar = (valueSelector: ValueSelector) => { return valueSelector[0] === 'sys' || valueSelector[1] === 'sys' @@ -235,7 +236,29 @@ const formatItem = ( } case BlockEnum.Tool: { - res.vars = TOOL_OUTPUT_STRUCT + const { + output_schema, + } = data as ToolNodeType + if (!output_schema) { + res.vars = TOOL_OUTPUT_STRUCT + } + else { + const outputSchema: any[] = [] + Object.keys(output_schema.properties).forEach((outputKey) => { + const output = output_schema.properties[outputKey] + outputSchema.push({ + variable: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`, + description: output.description, + }) + }) + res.vars = [ + ...TOOL_OUTPUT_STRUCT, + ...outputSchema, + ] + } break } @@ -293,6 +316,25 @@ const formatItem = ( break } + case BlockEnum.Agent: { + const payload = data as AgentNodeType + const outputs: Var[] = [] + Object.keys(payload.output_schema?.properties || {}).forEach((outputKey) => { + const output = payload.output_schema.properties[outputKey] + outputs.push({ + variable: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` as VarType + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}` as VarType, + }) + }) + res.vars = [ + ...outputs, + ...TOOL_OUTPUT_STRUCT, + ] + break + } + case 'env': { res.vars = data.envList.map((env: EnvironmentVariable) => { return { @@ -678,7 +720,7 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => { break } case BlockEnum.LLM: { - const payload = (data as LLMNodeType) + const payload = data as LLMNodeType const isChatModel = payload.model?.mode === 'chat' let prompts: string[] = [] if (isChatModel) { @@ -716,19 +758,19 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => { break } case BlockEnum.QuestionClassifier: { - const payload = (data as QuestionClassifierNodeType) + const payload = data as QuestionClassifierNodeType res = [payload.query_variable_selector] const varInInstructions = matchNotSystemVars([payload.instruction || '']) res.push(...varInInstructions) break } case BlockEnum.HttpRequest: { - const payload = (data as HttpNodeType) + const payload = data as HttpNodeType res = matchNotSystemVars([payload.url, payload.headers, payload.params, typeof payload.body.data === 'string' ? payload.body.data : payload.body.data.map(d => d.value).join('')]) break } case BlockEnum.Tool: { - const payload = (data as ToolNodeType) + const payload = data as ToolNodeType const mixVars = matchNotSystemVars(Object.keys(payload.tool_parameters)?.filter(key => payload.tool_parameters[key].type === ToolVarType.mixed).map(key => payload.tool_parameters[key].value) as string[]) const vars = Object.keys(payload.tool_parameters).filter(key => payload.tool_parameters[key].type === ToolVarType.variable).map(key => payload.tool_parameters[key].value as string) || [] res = [...(mixVars as ValueSelector[]), ...(vars as any)] @@ -746,7 +788,7 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => { } case BlockEnum.ParameterExtractor: { - const payload = (data as ParameterExtractorNodeType) + const payload = data as ParameterExtractorNodeType res = [payload.query] const varInInstructions = matchNotSystemVars([payload.instruction || '']) res.push(...varInInstructions) @@ -762,6 +804,21 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => { res = [(data as ListFilterNodeType).variable] break } + + case BlockEnum.Agent: { + const payload = data as AgentNodeType + const valueSelectors: ValueSelector[] = [] + if (!payload.agent_parameters) + break + + Object.keys(payload.agent_parameters || {}).forEach((key) => { + const { value } = payload.agent_parameters![key] + if (typeof value === 'string') + valueSelectors.push(...matchNotSystemVars([value])) + }) + res = valueSelectors + break + } } return res || [] } @@ -773,7 +830,7 @@ export const getNodeUsedVarPassToServerKey = (node: Node, valueSelector: ValueSe let res: string | string[] = '' switch (type) { case BlockEnum.LLM: { - const payload = (data as LLMNodeType) + const payload = data as LLMNodeType res = [`#${valueSelector.join('.')}#`] if (payload.context?.variable_selector.join('.') === valueSelector.join('.')) res.push('#context#') diff --git a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx index 9ac5e4a4e4..3b7845003a 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx +++ b/web/app/components/workflow/nodes/_base/components/variable/var-reference-vars.tsx @@ -17,7 +17,7 @@ import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others import { checkKeys } from '@/utils/var' import { FILE_STRUCT } from '@/app/components/workflow/constants' -type ObjectChildrenProps = { +interface ObjectChildrenProps { nodeId: string title: string data: Var[] @@ -28,7 +28,7 @@ type ObjectChildrenProps = { isSupportFileVar?: boolean } -type ItemProps = { +interface ItemProps { nodeId: string title: string objPath: string[] @@ -134,7 +134,7 @@ const Item: FC<ItemProps> = ({ zIndex: 100, }}> {(isObj && !isFile) && ( - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define <ObjectChildren nodeId={nodeId} title={title} @@ -147,7 +147,7 @@ const Item: FC<ItemProps> = ({ /> )} {isFile && ( - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define <ObjectChildren nodeId={nodeId} title={title} @@ -226,7 +226,7 @@ const ObjectChildren: FC<ObjectChildrenProps> = ({ ) } -type Props = { +interface Props { hideSearch?: boolean searchBoxClassName?: string vars: NodeOutPutVar[] diff --git a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts index 05481b4c8c..443ba1bbd2 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-one-step-run.ts @@ -46,6 +46,7 @@ const { checkValid: checkParameterExtractorValid } = ParameterExtractorDefault const { checkValid: checkIterationValid } = IterationDefault const { checkValid: checkDocumentExtractorValid } = DocumentExtractorDefault +// eslint-disable-next-line ts/no-unsafe-function-type const checkValidFns: Record<BlockEnum, Function> = { [BlockEnum.LLM]: checkLLMValid, [BlockEnum.KnowledgeRetrieval]: checkKnowledgeRetrievalValid, @@ -144,7 +145,7 @@ const useOneStepRun = <T>({ const { handleNodeDataUpdate }: { handleNodeDataUpdate: (data: any) => void } = useNodeDataUpdate() const [canShowSingleRun, setCanShowSingleRun] = useState(false) const isShowSingleRun = data._isSingleRun && canShowSingleRun - const [iterationRunResult, setIterationRunResult] = useState<NodeTracing[][]>([]) + const [iterationRunResult, setIterationRunResult] = useState<NodeTracing[]>([]) useEffect(() => { if (!checkValid) { @@ -175,7 +176,7 @@ const useOneStepRun = <T>({ const workflowStore = useWorkflowStore() useEffect(() => { workflowStore.getState().setShowSingleRunPanel(!!isShowSingleRun) - }, [isShowSingleRun]) + }, [isShowSingleRun, workflowStore]) const hideSingleRun = () => { handleNodeDataUpdate({ @@ -213,7 +214,7 @@ const useOneStepRun = <T>({ } else { setIterationRunResult([]) - let _iterationResult: NodeTracing[][] = [] + let _iterationResult: NodeTracing[] = [] let _runResult: any = null ssePost( getIterationSingleNodeRunUrl(isChatMode, appId!, id), @@ -233,27 +234,43 @@ const useOneStepRun = <T>({ _runResult.created_by = iterationData.created_by.name setRunResult(_runResult) }, - onIterationNext: () => { - // iteration next trigger time is triggered one more time than iterationTimes - if (_iterationResult.length >= iterationTimes!) - return - + onIterationStart: (params) => { const newIterationRunResult = produce(_iterationResult, (draft) => { - draft.push([]) + draft.push({ + ...params.data, + status: NodeRunningStatus.Running, + }) }) _iterationResult = newIterationRunResult setIterationRunResult(newIterationRunResult) }, + onIterationNext: () => { + // iteration next trigger time is triggered one more time than iterationTimes + if (_iterationResult.length >= iterationTimes!) + return _iterationResult.length >= iterationTimes! + }, onIterationFinish: (params) => { _runResult = params.data setRunResult(_runResult) + const iterationRunResult = _iterationResult + const currentIndex = iterationRunResult.findIndex(trace => trace.id === params.data.id) + const newIterationRunResult = produce(iterationRunResult, (draft) => { + if (currentIndex > -1) { + draft[currentIndex] = { + ...draft[currentIndex], + ...data, + } + } + }) + _iterationResult = newIterationRunResult + setIterationRunResult(newIterationRunResult) }, onNodeStarted: (params) => { const newIterationRunResult = produce(_iterationResult, (draft) => { - draft[draft.length - 1].push({ + draft.push({ ...params.data, status: NodeRunningStatus.Running, - } as NodeTracing) + }) }) _iterationResult = newIterationRunResult setIterationRunResult(newIterationRunResult) @@ -262,18 +279,25 @@ const useOneStepRun = <T>({ const iterationRunResult = _iterationResult const { data } = params - const currentIndex = iterationRunResult[iterationRunResult.length - 1].findIndex(trace => trace.node_id === data.node_id) + const currentIndex = iterationRunResult.findIndex(trace => trace.id === data.id) const newIterationRunResult = produce(iterationRunResult, (draft) => { if (currentIndex > -1) { - draft[draft.length - 1][currentIndex] = { + draft[currentIndex] = { + ...draft[currentIndex], ...data, - status: NodeRunningStatus.Succeeded, - } as NodeTracing + } } }) _iterationResult = newIterationRunResult setIterationRunResult(newIterationRunResult) }, + onNodeRetry: (params) => { + const newIterationRunResult = produce(_iterationResult, (draft) => { + draft.push(params.data) + }) + _iterationResult = newIterationRunResult + setIterationRunResult(newIterationRunResult) + }, onError: () => { handleNodeDataUpdate({ id, diff --git a/web/app/components/workflow/nodes/agent/components/model-bar.tsx b/web/app/components/workflow/nodes/agent/components/model-bar.tsx new file mode 100644 index 0000000000..1b2007070f --- /dev/null +++ b/web/app/components/workflow/nodes/agent/components/model-bar.tsx @@ -0,0 +1,75 @@ +import Tooltip from '@/app/components/base/tooltip' +import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' +import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks' +import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' +import Indicator from '@/app/components/header/indicator' +import { type FC, useMemo } from 'react' +import { useTranslation } from 'react-i18next' + +export type ModelBarProps = { + provider: string + model: string +} | {} + +const useAllModel = () => { + const { data: textGeneration } = useModelList(ModelTypeEnum.textGeneration) + const { data: moderation } = useModelList(ModelTypeEnum.moderation) + const { data: rerank } = useModelList(ModelTypeEnum.rerank) + const { data: speech2text } = useModelList(ModelTypeEnum.speech2text) + const { data: textEmbedding } = useModelList(ModelTypeEnum.textEmbedding) + const { data: tts } = useModelList(ModelTypeEnum.tts) + const models = useMemo(() => { + return textGeneration + .concat(moderation) + .concat(rerank) + .concat(speech2text) + .concat(textEmbedding) + .concat(tts) + }, [textGeneration, moderation, rerank, speech2text, textEmbedding, tts]) + if (!textGeneration || !moderation || !rerank || !speech2text || !textEmbedding || !tts) + return undefined + return models +} + +export const ModelBar: FC<ModelBarProps> = (props) => { + const { t } = useTranslation() + const modelList = useAllModel() + if (!('provider' in props)) { + return <Tooltip + popupContent={t('workflow.nodes.agent.modelNotSelected')} + triggerMethod='hover' + > + <div className='relative'> + <ModelSelector + modelList={[]} + triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md' + defaultModel={undefined} + showDeprecatedWarnIcon={false} + readonly + deprecatedClassName='opacity-50' + /> + <Indicator color={'red'} className='absolute -right-0.5 -top-0.5' /> + </div> + </Tooltip> + } + const modelInstalled = modelList?.some( + provider => provider.provider === props.provider && provider.models.some(model => model.model === props.model)) + const showWarn = modelList && !modelInstalled + return modelList && <Tooltip + popupContent={t('workflow.nodes.agent.modelNotInstallTooltip')} + triggerMethod='hover' + disabled={!modelList || modelInstalled} + > + <div className='relative'> + <ModelSelector + modelList={modelList} + triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md' + defaultModel={props} + showDeprecatedWarnIcon={false} + readonly + deprecatedClassName='opacity-50' + /> + {showWarn && <Indicator color={'red'} className='absolute -right-0.5 -top-0.5' />} + </div> + </Tooltip> +} diff --git a/web/app/components/workflow/nodes/agent/components/tool-icon.tsx b/web/app/components/workflow/nodes/agent/components/tool-icon.tsx new file mode 100644 index 0000000000..07c20e0f80 --- /dev/null +++ b/web/app/components/workflow/nodes/agent/components/tool-icon.tsx @@ -0,0 +1,81 @@ +import Tooltip from '@/app/components/base/tooltip' +import Indicator from '@/app/components/header/indicator' +import classNames from '@/utils/classnames' +import { memo, useMemo, useRef, useState } from 'react' +import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools' +import { getIconFromMarketPlace } from '@/utils/get-icon' +import { useTranslation } from 'react-i18next' +import { Group } from '@/app/components/base/icons/src/vender/other' + +type Status = 'not-installed' | 'not-authorized' | undefined + +export type ToolIconProps = { + providerName: string +} + +export const ToolIcon = memo(({ providerName }: ToolIconProps) => { + const containerRef = useRef<HTMLDivElement>(null) + const { data: buildInTools } = useAllBuiltInTools() + const { data: customTools } = useAllCustomTools() + const { data: workflowTools } = useAllWorkflowTools() + const isDataReady = !!buildInTools && !!customTools && !!workflowTools + const currentProvider = useMemo(() => { + const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])] + return mergedTools.find((toolWithProvider) => { + return toolWithProvider.name === providerName + }) + }, [buildInTools, customTools, providerName, workflowTools]) + const providerNameParts = providerName.split('/') + const author = providerNameParts[0] + const name = providerNameParts[1] + const icon = useMemo(() => { + if (currentProvider) return currentProvider.icon as string + const iconFromMarketPlace = getIconFromMarketPlace(`${author}/${name}`) + return iconFromMarketPlace + }, [author, currentProvider, name]) + const status: Status = useMemo(() => { + if (!isDataReady) return undefined + if (!currentProvider) return 'not-installed' + if (currentProvider.is_team_authorization === false) return 'not-authorized' + return undefined + }, [currentProvider, isDataReady]) + const indicator = status === 'not-installed' ? 'red' : status === 'not-authorized' ? 'yellow' : undefined + const notSuccess = (['not-installed', 'not-authorized'] as Array<Status>).includes(status) + const { t } = useTranslation() + const tooltip = useMemo(() => { + if (!notSuccess) return undefined + if (status === 'not-installed') return t('workflow.nodes.agent.toolNotInstallTooltip', { tool: name }) + if (status === 'not-authorized') return t('workflow.nodes.agent.toolNotAuthorizedTooltip', { tool: name }) + throw new Error('Unknown status') + }, [name, notSuccess, status, t]) + const [iconFetchError, setIconFetchError] = useState(false) + return <Tooltip + triggerMethod='hover' + popupContent={tooltip} + disabled={!notSuccess} + > + <div + className={classNames( + 'size-5 border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge relative flex items-center justify-center rounded-[6px]', + )} + ref={containerRef} + > + {!iconFetchError + // eslint-disable-next-line @next/next/no-img-element + ? <img + src={icon} + alt='tool icon' + className={classNames( + 'w-full h-full size-3.5 object-cover', + notSuccess && 'opacity-50', + )} + onError={() => setIconFetchError(true)} + /> + : <Group className="w-3 h-3 opacity-35" /> + } + {indicator && <Indicator color={indicator} className="absolute right-[-1px] top-[-1px]" />} + </div> + </Tooltip> +}) + +ToolIcon.displayName = 'ToolIcon' diff --git a/web/app/components/workflow/nodes/agent/default.ts b/web/app/components/workflow/nodes/agent/default.ts new file mode 100644 index 0000000000..3ece9d44bc --- /dev/null +++ b/web/app/components/workflow/nodes/agent/default.ts @@ -0,0 +1,54 @@ +import type { StrategyDetail, StrategyPluginDetail } from '@/app/components/plugins/types' +import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '../../constants' +import type { NodeDefault } from '../../types' +import type { AgentNodeType } from './types' +import { renderI18nObject } from '@/hooks/use-i18n' + +const nodeDefault: NodeDefault<AgentNodeType> = { + defaultValue: { + }, + getAvailablePrevNodes(isChatMode) { + return isChatMode + ? ALL_CHAT_AVAILABLE_BLOCKS + : ALL_COMPLETION_AVAILABLE_BLOCKS + }, + getAvailableNextNodes(isChatMode) { + return isChatMode + ? ALL_CHAT_AVAILABLE_BLOCKS + : ALL_COMPLETION_AVAILABLE_BLOCKS + }, + checkValid(payload, t, moreDataForCheckValid: { + strategyProvider?: StrategyPluginDetail, + strategy?: StrategyDetail + language: string + isReadyForCheckValid: boolean + }) { + const { strategy, language, isReadyForCheckValid } = moreDataForCheckValid + if (!isReadyForCheckValid) { + return { + isValid: true, + errorMessage: '', + } + } + if (!strategy) { + return { + isValid: false, + errorMessage: t('workflow.nodes.agent.checkList.strategyNotSelected'), + } + } + for (const param of strategy.parameters) { + if (param.required && !payload.agent_parameters?.[param.name]?.value) { + return { + isValid: false, + errorMessage: t('workflow.errorMsg.fieldRequired', { field: renderI18nObject(param.label, language) }), + } + } + } + return { + isValid: true, + errorMessage: '', + } + }, +} + +export default nodeDefault diff --git a/web/app/components/workflow/nodes/agent/node.tsx b/web/app/components/workflow/nodes/agent/node.tsx new file mode 100644 index 0000000000..b3101c3d88 --- /dev/null +++ b/web/app/components/workflow/nodes/agent/node.tsx @@ -0,0 +1,113 @@ +import { type FC, memo, useMemo } from 'react' +import type { NodeProps } from '../../types' +import type { AgentNodeType } from './types' +import { SettingItem } from '../_base/components/setting-item' +import { Group, GroupLabel } from '../_base/components/group' +import type { ToolIconProps } from './components/tool-icon' +import { ToolIcon } from './components/tool-icon' +import useConfig from './use-config' +import { useTranslation } from 'react-i18next' +import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' +import { useRenderI18nObject } from '@/hooks/use-i18n' +import { ModelBar } from './components/model-bar' + +const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => { + const { inputs, currentStrategy, currentStrategyStatus, pluginDetail } = useConfig(props.id, props.data) + const renderI18nObject = useRenderI18nObject() + const { t } = useTranslation() + const models = useMemo(() => { + if (!inputs) return [] + // if selected, show in node + // if required and not selected, show empty selector + // if not required and not selected, show nothing + const models = currentStrategy?.parameters + .filter(param => param.type === FormTypeEnum.modelSelector) + .reduce((acc, param) => { + const item = inputs.agent_parameters?.[param.name]?.value + if (!item) { + if (param.required) { + acc.push({ param: param.name }) + return acc + } + else { return acc } + } + acc.push({ provider: item.provider, model: item.model, param: param.name }) + return acc + }, [] as Array<{ param: string } | { provider: string, model: string, param: string }>) || [] + return models + }, [currentStrategy, inputs]) + + const tools = useMemo(() => { + const tools: Array<ToolIconProps> = [] + currentStrategy?.parameters.forEach((param) => { + if (param.type === FormTypeEnum.toolSelector) { + const field = param.name + const value = inputs.agent_parameters?.[field]?.value + if (value) { + tools.push({ + providerName: value.provider_name as any, + }) + } + } + if (param.type === FormTypeEnum.multiToolSelector) { + const field = param.name + const value = inputs.agent_parameters?.[field]?.value + if (value) { + (value as unknown as any[]).forEach((item) => { + tools.push({ + providerName: item.provider_name, + }) + }) + } + } + }) + return tools + }, [currentStrategy?.parameters, inputs.agent_parameters]) + return <div className='mb-1 px-3 py-1 space-y-1'> + {inputs.agent_strategy_name + ? <SettingItem + label={t('workflow.nodes.agent.strategy.shortLabel')} + status={ + currentStrategyStatus && !currentStrategyStatus.isExistInPlugin + ? 'error' + : undefined + } + tooltip={ + (currentStrategyStatus && !currentStrategyStatus.isExistInPlugin) + ? t('workflow.nodes.agent.strategyNotInstallTooltip', { + plugin: pluginDetail?.declaration.label + ? renderI18nObject(pluginDetail?.declaration.label) + : undefined, + strategy: inputs.agent_strategy_label, + }) + : undefined + } + > + {inputs.agent_strategy_label} + </SettingItem> + : <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />} + {models.length > 0 && <Group + label={<GroupLabel className='mt-1'> + {t('workflow.nodes.agent.model')} + </GroupLabel>} + > + {models.map((model) => { + return <ModelBar + {...model} + key={model.param} + /> + })} + </Group>} + {tools.length > 0 && <Group label={<GroupLabel className='mt-1'> + {t('workflow.nodes.agent.toolbox')} + </GroupLabel>}> + <div className='grid grid-cols-10 gap-0.5'> + {tools.map(tool => <ToolIcon {...tool} key={Math.random()} />)} + </div> + </Group>} + </div> +} + +AgentNode.displayName = 'AgentNode' + +export default memo(AgentNode) diff --git a/web/app/components/workflow/nodes/agent/panel.tsx b/web/app/components/workflow/nodes/agent/panel.tsx new file mode 100644 index 0000000000..50eadf9b3e --- /dev/null +++ b/web/app/components/workflow/nodes/agent/panel.tsx @@ -0,0 +1,154 @@ +import type { FC } from 'react' +import { memo, useMemo } from 'react' +import type { NodePanelProps } from '../../types' +import type { AgentNodeType } from './types' +import Field from '../_base/components/field' +import { AgentStrategy } from '../_base/components/agent-strategy' +import useConfig from './use-config' +import { useTranslation } from 'react-i18next' +import OutputVars, { VarItem } from '../_base/components/output-vars' +import type { StrategyParamItem } from '@/app/components/plugins/types' +import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations' +import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' +import ResultPanel from '@/app/components/workflow/run/result-panel' +import formatTracing from '@/app/components/workflow/run/utils/format-log' +import { useLogs } from '@/app/components/workflow/run/hooks' +import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' +import { toType } from '@/app/components/tools/utils/to-form-schema' +import { useStore } from '../../store' + +const i18nPrefix = 'workflow.nodes.agent' + +export function strategyParamToCredientialForm(param: StrategyParamItem): CredentialFormSchema { + return { + ...param as any, + variable: param.name, + show_on: [], + type: toType(param.type), + } +} + +const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => { + const { + inputs, + setInputs, + currentStrategy, + formData, + onFormChange, + + availableNodesWithParent, + availableVars, + + isShowSingleRun, + hideSingleRun, + runningStatus, + handleRun, + handleStop, + runResult, + runInputData, + setRunInputData, + varInputs, + } = useConfig(props.id, props.data) + const { t } = useTranslation() + const nodeInfo = useMemo(() => { + if (!runResult) + return + return formatTracing([runResult], t)[0] + }, [runResult, t]) + const logsParams = useLogs() + const singleRunForms = (() => { + const forms: FormProps[] = [] + + if (varInputs.length > 0) { + forms.push( + { + label: t(`${i18nPrefix}.singleRun.variable`)!, + inputs: varInputs, + values: runInputData, + onChange: setRunInputData, + }, + ) + } + + return forms + })() + + const resetEditor = useStore(s => s.setControlPromptEditorRerenderKey) + + return <div className='my-2'> + <Field title={t('workflow.nodes.agent.strategy.label')} className='px-4 py-2' tooltip={t('workflow.nodes.agent.strategy.tooltip')} > + <AgentStrategy + strategy={inputs.agent_strategy_name ? { + agent_strategy_provider_name: inputs.agent_strategy_provider_name!, + agent_strategy_name: inputs.agent_strategy_name!, + agent_strategy_label: inputs.agent_strategy_label!, + agent_output_schema: inputs.output_schema, + plugin_unique_identifier: inputs.plugin_unique_identifier!, + } : undefined} + onStrategyChange={(strategy) => { + setInputs({ + ...inputs, + agent_strategy_provider_name: strategy?.agent_strategy_provider_name, + agent_strategy_name: strategy?.agent_strategy_name, + agent_strategy_label: strategy?.agent_strategy_label, + output_schema: strategy!.agent_output_schema, + plugin_unique_identifier: strategy!.plugin_unique_identifier, + agent_parameters: {}, + }) + resetEditor(Date.now()) + }} + formSchema={currentStrategy?.parameters?.map(strategyParamToCredientialForm) || []} + formValue={formData} + onFormValueChange={onFormChange} + nodeOutputVars={availableVars} + availableNodes={availableNodesWithParent} + /> + </Field> + <div> + <OutputVars> + <VarItem + name='text' + type='String' + description={t(`${i18nPrefix}.outputVars.text`)} + /> + <VarItem + name='files' + type='Array[File]' + description={t(`${i18nPrefix}.outputVars.files.title`)} + /> + <VarItem + name='json' + type='Array[Object]' + description={t(`${i18nPrefix}.outputVars.json`)} + /> + {inputs.output_schema && Object.entries(inputs.output_schema).map(([name, schema]) => ( + <VarItem + key={name} + name={name} + type={schema.type} + description={schema.description} + /> + ))} + </OutputVars> + </div> + { + isShowSingleRun && ( + <BeforeRunForm + nodeName={inputs.title} + nodeType={inputs.type} + onHide={hideSingleRun} + forms={singleRunForms} + runningStatus={runningStatus} + onRun={handleRun} + onStop={handleStop} + {...logsParams} + result={<ResultPanel {...runResult} nodeInfo={nodeInfo} showSteps={false} {...logsParams} />} + /> + ) + } + </div> +} + +AgentPanel.displayName = 'AgentPanel' + +export default memo(AgentPanel) diff --git a/web/app/components/workflow/nodes/agent/types.ts b/web/app/components/workflow/nodes/agent/types.ts new file mode 100644 index 0000000000..1b5c96364f --- /dev/null +++ b/web/app/components/workflow/nodes/agent/types.ts @@ -0,0 +1,11 @@ +import type { CommonNodeType } from '@/app/components/workflow/types' +import type { ToolVarInputs } from '../tool/types' + +export type AgentNodeType = CommonNodeType & { + agent_strategy_provider_name?: string + agent_strategy_name?: string + agent_strategy_label?: string + agent_parameters?: ToolVarInputs + output_schema: Record<string, any> + plugin_unique_identifier?: string +} diff --git a/web/app/components/workflow/nodes/agent/use-config.ts b/web/app/components/workflow/nodes/agent/use-config.ts new file mode 100644 index 0000000000..88c793723f --- /dev/null +++ b/web/app/components/workflow/nodes/agent/use-config.ts @@ -0,0 +1,190 @@ +import { useStrategyProviderDetail } from '@/service/use-strategy' +import useNodeCrud from '../_base/hooks/use-node-crud' +import useVarList from '../_base/hooks/use-var-list' +import useOneStepRun from '../_base/hooks/use-one-step-run' +import type { AgentNodeType } from './types' +import { + useNodesReadOnly, +} from '@/app/components/workflow/hooks' +import { useCallback, useMemo } from 'react' +import { type ToolVarInputs, VarType } from '../tool/types' +import { useCheckInstalled, useFetchPluginsInMarketPlaceByIds } from '@/service/use-plugins' +import type { Var } from '../../types' +import { VarType as VarKindType } from '../../types' +import useAvailableVarList from '../_base/hooks/use-available-var-list' + +export type StrategyStatus = { + plugin: { + source: 'external' | 'marketplace' + installed: boolean + } + isExistInPlugin: boolean +} + +export const useStrategyInfo = ( + strategyProviderName?: string, + strategyName?: string, +) => { + const strategyProvider = useStrategyProviderDetail( + strategyProviderName || '', + { retry: false }, + ) + const strategy = strategyProvider.data?.declaration.strategies.find( + str => str.identity.name === strategyName, + ) + const marketplace = useFetchPluginsInMarketPlaceByIds([strategyProviderName!], { + retry: false, + }) + const strategyStatus: StrategyStatus | undefined = useMemo(() => { + if (strategyProvider.isLoading || marketplace.isLoading) + return undefined + const strategyExist = !!strategy + const isPluginInstalled = !strategyProvider.isError + const isInMarketplace = !!marketplace.data?.data.plugins.at(0) + return { + plugin: { + source: isInMarketplace ? 'marketplace' : 'external', + installed: isPluginInstalled, + }, + isExistInPlugin: strategyExist, + } + }, [strategy, marketplace, strategyProvider.isError, strategyProvider.isLoading]) + const refetch = useCallback(() => { + strategyProvider.refetch() + marketplace.refetch() + }, [marketplace, strategyProvider]) + return { + strategyProvider, + strategy, + strategyStatus, + refetch, + } +} + +const useConfig = (id: string, payload: AgentNodeType) => { + const { nodesReadOnly: readOnly } = useNodesReadOnly() + const { inputs, setInputs } = useNodeCrud<AgentNodeType>(id, payload) + // variables + const { handleVarListChange, handleAddVariable } = useVarList<AgentNodeType>({ + inputs, + setInputs, + }) + const { + strategyStatus: currentStrategyStatus, + strategy: currentStrategy, + strategyProvider, + } = useStrategyInfo( + inputs.agent_strategy_provider_name, + inputs.agent_strategy_name, + ) + const pluginId = inputs.agent_strategy_provider_name?.split('/').splice(0, 2).join('/') + const pluginDetail = useCheckInstalled({ + pluginIds: [pluginId!], + enabled: Boolean(pluginId), + }) + const formData = useMemo(() => { + return Object.fromEntries( + Object.entries(inputs.agent_parameters || {}).map(([key, value]) => { + return [key, value.value] + }), + ) + }, [inputs.agent_parameters]) + const onFormChange = (value: Record<string, any>) => { + const res: ToolVarInputs = {} + Object.entries(value).forEach(([key, val]) => { + res[key] = { + type: VarType.constant, + value: val, + } + }) + setInputs({ + ...inputs, + agent_parameters: res, + }) + } + + // vars + + const filterMemoryPromptVar = useCallback((varPayload: Var) => { + return [ + VarKindType.arrayObject, + VarKindType.array, + VarKindType.number, + VarKindType.string, + VarKindType.secret, + VarKindType.arrayString, + VarKindType.arrayNumber, + VarKindType.file, + VarKindType.arrayFile, + ].includes(varPayload.type) + }, []) + + const { + availableVars, + availableNodesWithParent, + } = useAvailableVarList(id, { + onlyLeafNodeVar: false, + filterVar: filterMemoryPromptVar, + }) + + // single run + const { + isShowSingleRun, + showSingleRun, + hideSingleRun, + toVarInputs, + runningStatus, + handleRun, + handleStop, + runInputData, + setRunInputData, + runResult, + getInputVars, + } = useOneStepRun<AgentNodeType>({ + id, + data: inputs, + defaultRunInputData: {}, + }) + const allVarStrArr = (() => { + const arr = currentStrategy?.parameters.filter(item => item.type === 'string').map((item) => { + return formData[item.name] + }) || [] + + return arr + })() + const varInputs = (() => { + const vars = getInputVars(allVarStrArr) + + return vars + })() + + return { + readOnly, + inputs, + setInputs, + handleVarListChange, + handleAddVariable, + currentStrategy, + formData, + onFormChange, + currentStrategyStatus, + strategyProvider: strategyProvider.data, + pluginDetail: pluginDetail.data?.plugins.at(0), + availableVars, + availableNodesWithParent, + + isShowSingleRun, + showSingleRun, + hideSingleRun, + toVarInputs, + runningStatus, + handleRun, + handleStop, + runInputData, + setRunInputData, + runResult, + varInputs, + } +} + +export default useConfig diff --git a/web/app/components/workflow/nodes/assigner/components/operation-selector.tsx b/web/app/components/workflow/nodes/assigner/components/operation-selector.tsx index 8542bb4829..b2f8e8cb5b 100644 --- a/web/app/components/workflow/nodes/assigner/components/operation-selector.tsx +++ b/web/app/components/workflow/nodes/assigner/components/operation-selector.tsx @@ -108,7 +108,7 @@ const OperationSelector: FC<OperationSelectorProps> = ({ }} > <div className='flex min-h-5 px-1 items-center gap-1 grow'> - <span className={'flex flex-grow text-text-secondary system-sm-medium'}>{t(`${i18nPrefix}.operations.${item.name}`)}</span> + <span className={'flex grow text-text-secondary system-sm-medium'}>{t(`${i18nPrefix}.operations.${item.name}`)}</span> </div> {item.value === value && ( <div className='flex justify-center items-center'> diff --git a/web/app/components/workflow/nodes/assigner/components/var-list/index.tsx b/web/app/components/workflow/nodes/assigner/components/var-list/index.tsx index 42ee9845dd..52d076624d 100644 --- a/web/app/components/workflow/nodes/assigner/components/var-list/index.tsx +++ b/web/app/components/workflow/nodes/assigner/components/var-list/index.tsx @@ -128,7 +128,7 @@ const VarList: FC<Props> = ({ return ( <div className='flex items-start gap-1 self-stretch' key={index}> - <div className='flex flex-col items-start gap-1 flex-grow'> + <div className='flex flex-col items-start gap-1 grow'> <div className='flex items-center gap-1 self-stretch'> <VarReferencePicker readonly={readonly} @@ -212,7 +212,7 @@ const VarList: FC<Props> = ({ </div> <ActionButton size='l' - className='flex-shrink-0 group hover:!bg-state-destructive-hover' + className='shrink-0 group hover:!bg-state-destructive-hover' onClick={handleVarRemove(index)} > <RiDeleteBinLine className='text-text-tertiary w-4 h-4 group-hover:text-text-destructive' /> diff --git a/web/app/components/workflow/nodes/assigner/node.tsx b/web/app/components/workflow/nodes/assigner/node.tsx index 516cfbcb16..23dcf04aae 100644 --- a/web/app/components/workflow/nodes/assigner/node.tsx +++ b/web/app/components/workflow/nodes/assigner/node.tsx @@ -3,7 +3,7 @@ import React from 'react' import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import NodeVariableItem from '../variable-assigner/components/node-variable-item' -import { type AssignerNodeType } from './types' +import type { AssignerNodeType } from './types' import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' diff --git a/web/app/components/workflow/nodes/assigner/panel.tsx b/web/app/components/workflow/nodes/assigner/panel.tsx index a470d94929..6b151a7cb0 100644 --- a/web/app/components/workflow/nodes/assigner/panel.tsx +++ b/web/app/components/workflow/nodes/assigner/panel.tsx @@ -7,9 +7,9 @@ import { import VarList from './components/var-list' import useConfig from './use-config' import type { AssignerNodeType } from './types' +import type { NodePanelProps } from '@/app/components/workflow/types' import { useHandleAddOperationItem } from './hooks' import ActionButton from '@/app/components/base/action-button' -import { type NodePanelProps } from '@/app/components/workflow/types' const i18nPrefix = 'workflow.nodes.assigner' @@ -40,7 +40,7 @@ const Panel: FC<NodePanelProps<AssignerNodeType>> = ({ <div className='flex py-2 flex-col items-start self-stretch'> <div className='flex flex-col justify-center items-start gap-1 px-4 py-2 w-full self-stretch'> <div className='flex items-start gap-2 self-stretch'> - <div className='flex flex-col justify-center items-start flex-grow text-text-secondary system-sm-semibold-uppercase'>{t(`${i18nPrefix}.variables`)}</div> + <div className='flex flex-col justify-center items-start grow text-text-secondary system-sm-semibold-uppercase'>{t(`${i18nPrefix}.variables`)}</div> <ActionButton onClick={handleAddOperation}> <RiAddLine className='w-4 h-4 shrink-0 text-text-tertiary' /> </ActionButton> diff --git a/web/app/components/workflow/nodes/code/panel.tsx b/web/app/components/workflow/nodes/code/panel.tsx index a0027daf53..f20a9c60d6 100644 --- a/web/app/components/workflow/nodes/code/panel.tsx +++ b/web/app/components/workflow/nodes/code/panel.tsx @@ -13,7 +13,7 @@ import Field from '@/app/components/workflow/nodes/_base/components/field' import Split from '@/app/components/workflow/nodes/_base/components/split' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector' -import { type NodePanelProps } from '@/app/components/workflow/types' +import type { NodePanelProps } from '@/app/components/workflow/types' import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' import ResultPanel from '@/app/components/workflow/run/result-panel' const i18nPrefix = 'workflow.nodes.code' diff --git a/web/app/components/workflow/nodes/constants.ts b/web/app/components/workflow/nodes/constants.ts index 82a21d9a58..dc202acc28 100644 --- a/web/app/components/workflow/nodes/constants.ts +++ b/web/app/components/workflow/nodes/constants.ts @@ -34,6 +34,8 @@ import DocExtractorNode from './document-extractor/node' import DocExtractorPanel from './document-extractor/panel' import ListFilterNode from './list-operator/node' import ListFilterPanel from './list-operator/panel' +import AgentNode from './agent/node' +import AgentPanel from './agent/panel' export const NodeComponentMap: Record<string, ComponentType<any>> = { [BlockEnum.Start]: StartNode, @@ -54,6 +56,7 @@ export const NodeComponentMap: Record<string, ComponentType<any>> = { [BlockEnum.Iteration]: IterationNode, [BlockEnum.DocExtractor]: DocExtractorNode, [BlockEnum.ListFilter]: ListFilterNode, + [BlockEnum.Agent]: AgentNode, } export const PanelComponentMap: Record<string, ComponentType<any>> = { @@ -75,6 +78,7 @@ export const PanelComponentMap: Record<string, ComponentType<any>> = { [BlockEnum.Iteration]: IterationPanel, [BlockEnum.DocExtractor]: DocExtractorPanel, [BlockEnum.ListFilter]: ListFilterPanel, + [BlockEnum.Agent]: AgentPanel, } export const CUSTOM_NODE_TYPE = 'custom' diff --git a/web/app/components/workflow/nodes/document-extractor/default.ts b/web/app/components/workflow/nodes/document-extractor/default.ts index 54045cc52e..26eddff62b 100644 --- a/web/app/components/workflow/nodes/document-extractor/default.ts +++ b/web/app/components/workflow/nodes/document-extractor/default.ts @@ -1,6 +1,6 @@ import { BlockEnum } from '../../types' import type { NodeDefault } from '../../types' -import { type DocExtractorNodeType } from './types' +import type { DocExtractorNodeType } from './types' import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants' const i18nPrefix = 'workflow.errorMsg' diff --git a/web/app/components/workflow/nodes/document-extractor/node.tsx b/web/app/components/workflow/nodes/document-extractor/node.tsx index 6324961051..becf9fda95 100644 --- a/web/app/components/workflow/nodes/document-extractor/node.tsx +++ b/web/app/components/workflow/nodes/document-extractor/node.tsx @@ -3,7 +3,7 @@ import React from 'react' import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import NodeVariableItem from '../variable-assigner/components/node-variable-item' -import { type DocExtractorNodeType } from './types' +import type { DocExtractorNodeType } from './types' import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' diff --git a/web/app/components/workflow/nodes/document-extractor/use-config.ts b/web/app/components/workflow/nodes/document-extractor/use-config.ts index 9d720d7b63..95ac9fe7a7 100644 --- a/web/app/components/workflow/nodes/document-extractor/use-config.ts +++ b/web/app/components/workflow/nodes/document-extractor/use-config.ts @@ -4,7 +4,7 @@ import { useStoreApi } from 'reactflow' import type { ValueSelector, Var } from '../../types' import { InputVarType, VarType } from '../../types' -import { type DocExtractorNodeType } from './types' +import type { DocExtractorNodeType } from './types' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' import { diff --git a/web/app/components/workflow/nodes/end/default.ts b/web/app/components/workflow/nodes/end/default.ts index ceeda5b43b..d144a079cf 100644 --- a/web/app/components/workflow/nodes/end/default.ts +++ b/web/app/components/workflow/nodes/end/default.ts @@ -1,6 +1,6 @@ import { BlockEnum } from '../../types' import type { NodeDefault } from '../../types' -import { type EndNodeType } from './types' +import type { EndNodeType } from './types' import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants' const nodeDefault: NodeDefault<EndNodeType> = { diff --git a/web/app/components/workflow/nodes/end/panel.tsx b/web/app/components/workflow/nodes/end/panel.tsx index a74ba51b6d..fc5e498d13 100644 --- a/web/app/components/workflow/nodes/end/panel.tsx +++ b/web/app/components/workflow/nodes/end/panel.tsx @@ -1,4 +1,4 @@ -import { type FC } from 'react' +import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' import useConfig from './use-config' @@ -6,7 +6,7 @@ import type { EndNodeType } from './types' import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list' import Field from '@/app/components/workflow/nodes/_base/components/field' import AddButton from '@/app/components/base/button/add-button' -import { type NodePanelProps } from '@/app/components/workflow/types' +import type { NodePanelProps } from '@/app/components/workflow/types' const i18nPrefix = 'workflow.nodes.end' diff --git a/web/app/components/workflow/nodes/http/components/authorization/index.tsx b/web/app/components/workflow/nodes/http/components/authorization/index.tsx index 7110188dbe..5f0cf8d888 100644 --- a/web/app/components/workflow/nodes/http/components/authorization/index.tsx +++ b/web/app/components/workflow/nodes/http/components/authorization/index.tsx @@ -17,7 +17,7 @@ import cn from '@/utils/classnames' const i18nPrefix = 'workflow.nodes.http.authorization' -type Props = { +interface Props { nodeId: string payload: AuthorizationPayloadType onChange: (payload: AuthorizationPayloadType) => void diff --git a/web/app/components/workflow/nodes/http/components/edit-body/index.tsx b/web/app/components/workflow/nodes/http/components/edit-body/index.tsx index b58cc68064..0297d3102e 100644 --- a/web/app/components/workflow/nodes/http/components/edit-body/index.tsx +++ b/web/app/components/workflow/nodes/http/components/edit-body/index.tsx @@ -15,7 +15,7 @@ import { VarType } from '@/app/components/workflow/types' const UNIQUE_ID_PREFIX = 'key-value-' -type Props = { +interface Props { readonly: boolean nodeId: string payload: Body diff --git a/web/app/components/workflow/nodes/http/components/key-value/index.tsx b/web/app/components/workflow/nodes/http/components/key-value/index.tsx index e930114f32..97f69ff2db 100644 --- a/web/app/components/workflow/nodes/http/components/key-value/index.tsx +++ b/web/app/components/workflow/nodes/http/components/key-value/index.tsx @@ -4,7 +4,7 @@ import React from 'react' import type { KeyValue } from '../../types' import KeyValueEdit from './key-value-edit' -type Props = { +interface Props { readonly: boolean nodeId: string list: KeyValue[] diff --git a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsx b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsx index adf7f966e0..dac2c1c17c 100644 --- a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsx +++ b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/index.tsx @@ -9,7 +9,7 @@ import cn from '@/utils/classnames' const i18nPrefix = 'workflow.nodes.http' -type Props = { +interface Props { readonly: boolean nodeId: string list: KeyValue[] diff --git a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/input-item.tsx b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/input-item.tsx index b6d2904d64..fdaeefbc4a 100644 --- a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/input-item.tsx +++ b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/input-item.tsx @@ -8,7 +8,7 @@ import RemoveButton from '@/app/components/workflow/nodes/_base/components/remov import Input from '@/app/components/workflow/nodes/_base/components/input-support-select-var' import type { Var } from '@/app/components/workflow/types' import { VarType } from '@/app/components/workflow/types' -type Props = { +interface Props { className?: string instanceId?: string nodeId: string diff --git a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/item.tsx b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/item.tsx index 75c6a77873..9c64f9f764 100644 --- a/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/item.tsx +++ b/web/app/components/workflow/nodes/http/components/key-value/key-value-edit/item.tsx @@ -14,7 +14,7 @@ import { VarType } from '@/app/components/workflow/types' const i18nPrefix = 'workflow.nodes.http' -type Props = { +interface Props { instanceId: string className?: string nodeId: string diff --git a/web/app/components/workflow/nodes/http/components/timeout/index.tsx b/web/app/components/workflow/nodes/http/components/timeout/index.tsx index f20a91dba5..2de3bd443c 100644 --- a/web/app/components/workflow/nodes/http/components/timeout/index.tsx +++ b/web/app/components/workflow/nodes/http/components/timeout/index.tsx @@ -6,7 +6,7 @@ import type { Timeout as TimeoutPayloadType } from '../../types' import Input from '@/app/components/base/input' import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse' -type Props = { +interface Props { readonly: boolean nodeId: string payload: TimeoutPayloadType @@ -35,7 +35,7 @@ const InputField: FC<{ type='number' value={value} onChange={(e) => { - const value = Math.max(min, Math.min(max, parseInt(e.target.value, 10))) + const value = Math.max(min, Math.min(max, Number.parseInt(e.target.value, 10))) onChange(value) }} placeholder={placeholder} diff --git a/web/app/components/workflow/nodes/http/panel.tsx b/web/app/components/workflow/nodes/http/panel.tsx index 91b3a6140d..8f2b901a84 100644 --- a/web/app/components/workflow/nodes/http/panel.tsx +++ b/web/app/components/workflow/nodes/http/panel.tsx @@ -18,7 +18,6 @@ import { FileArrow01 } from '@/app/components/base/icons/src/vender/line/files' import type { NodePanelProps } from '@/app/components/workflow/types' import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' import ResultPanel from '@/app/components/workflow/run/result-panel' -import { useRetryDetailShowInSingleRun } from '@/app/components/workflow/nodes/_base/components/retry/hooks' const i18nPrefix = 'workflow.nodes.http' @@ -61,10 +60,6 @@ const Panel: FC<NodePanelProps<HttpNodeType>> = ({ hideCurlPanel, handleCurlImport, } = useConfig(id, data) - const { - retryDetails, - handleRetryDetailsChange, - } = useRetryDetailShowInSingleRun() // To prevent prompt editor in body not update data. if (!isDataReady) return null @@ -198,9 +193,7 @@ const Panel: FC<NodePanelProps<HttpNodeType>> = ({ runningStatus={runningStatus} onRun={handleRun} onStop={handleStop} - retryDetails={retryDetails} - onRetryDetailBack={handleRetryDetailsChange} - result={<ResultPanel {...runResult} showSteps={false} onShowRetryDetail={handleRetryDetailsChange} />} + result={<ResultPanel {...runResult} showSteps={false} />} /> )} {(isShowCurlPanel && !readOnly) && ( diff --git a/web/app/components/workflow/nodes/http/types.ts b/web/app/components/workflow/nodes/http/types.ts index f1937ec5bd..775d621eea 100644 --- a/web/app/components/workflow/nodes/http/types.ts +++ b/web/app/components/workflow/nodes/http/types.ts @@ -18,7 +18,7 @@ export enum BodyType { binary = 'binary', } -export type KeyValue = { +export interface KeyValue { id?: string key: string value: string @@ -38,7 +38,7 @@ export type BodyPayload = { file?: ValueSelector // when type is file value?: string // when type is text }[] -export type Body = { +export interface Body { type: BodyType data: string | BodyPayload // string is deprecated, it would convert to BodyPayload after loaded } @@ -54,7 +54,7 @@ export enum APIType { custom = 'custom', } -export type Authorization = { +export interface Authorization { type: AuthorizationType config?: { type: APIType @@ -63,7 +63,7 @@ export type Authorization = { } | null } -export type Timeout = { +export interface Timeout { connect?: number read?: number write?: number diff --git a/web/app/components/workflow/nodes/if-else/components/condition-add.tsx b/web/app/components/workflow/nodes/if-else/components/condition-add.tsx index 344e986305..8b14a59dcc 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-add.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-add.tsx @@ -18,7 +18,7 @@ import type { Var, } from '@/app/components/workflow/types' -type ConditionAddProps = { +interface ConditionAddProps { className?: string caseId: string variables: NodeOutPutVar[] diff --git a/web/app/components/workflow/nodes/if-else/components/condition-list/condition-item.tsx b/web/app/components/workflow/nodes/if-else/components/condition-list/condition-item.tsx index 818383c750..2e89c73074 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-list/condition-item.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-list/condition-item.tsx @@ -39,7 +39,7 @@ import { SimpleSelect as Select } from '@/app/components/base/select' import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' const optionNameI18NPrefix = 'workflow.nodes.ifElse.optionName' -type ConditionItemProps = { +interface ConditionItemProps { className?: string disabled?: boolean caseId: string diff --git a/web/app/components/workflow/nodes/if-else/components/condition-list/condition-operator.tsx b/web/app/components/workflow/nodes/if-else/components/condition-list/condition-operator.tsx index ecbe53f689..afd9b1bccd 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-list/condition-operator.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-list/condition-operator.tsx @@ -16,7 +16,7 @@ import type { VarType } from '@/app/components/workflow/types' import cn from '@/utils/classnames' const i18nPrefix = 'workflow.nodes.ifElse' -type ConditionOperatorProps = { +interface ConditionOperatorProps { className?: string disabled?: boolean varType: VarType diff --git a/web/app/components/workflow/nodes/if-else/components/condition-list/index.tsx b/web/app/components/workflow/nodes/if-else/components/condition-list/index.tsx index 05b5df4f4a..7417cd1077 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-list/index.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-list/index.tsx @@ -19,7 +19,7 @@ import type { } from '@/app/components/workflow/types' import cn from '@/utils/classnames' -type ConditionListProps = { +interface ConditionListProps { isSubVariable?: boolean disabled?: boolean caseId: string diff --git a/web/app/components/workflow/nodes/if-else/components/condition-number-input.tsx b/web/app/components/workflow/nodes/if-else/components/condition-number-input.tsx index 5dabd967cd..95b0aa0c02 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-number-input.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-number-input.tsx @@ -30,7 +30,7 @@ const options = [ NumberVarType.constant, ] -type ConditionNumberInputProps = { +interface ConditionNumberInputProps { numberVarType?: NumberVarType onNumberVarTypeChange: (v: NumberVarType) => void value: string diff --git a/web/app/components/workflow/nodes/if-else/components/condition-value.tsx b/web/app/components/workflow/nodes/if-else/components/condition-value.tsx index e997c2cbd2..3a71b85a0e 100644 --- a/web/app/components/workflow/nodes/if-else/components/condition-value.tsx +++ b/web/app/components/workflow/nodes/if-else/components/condition-value.tsx @@ -20,7 +20,7 @@ import type { Node, } from '@/app/components/workflow/types' -type ConditionValueProps = { +interface ConditionValueProps { variableSelector: string[] labelName?: string operator: ComparisonOperator diff --git a/web/app/components/workflow/nodes/if-else/types.ts b/web/app/components/workflow/nodes/if-else/types.ts index 56952de25a..22238b3389 100644 --- a/web/app/components/workflow/nodes/if-else/types.ts +++ b/web/app/components/workflow/nodes/if-else/types.ts @@ -35,7 +35,7 @@ export enum ComparisonOperator { notExists = 'not exists', } -export type Condition = { +export interface Condition { id: string varType: VarType variable_selector?: ValueSelector @@ -46,7 +46,7 @@ export type Condition = { sub_variable_condition?: CaseItem } -export type CaseItem = { +export interface CaseItem { case_id: string logical_operator: LogicalOperator conditions: Condition[] diff --git a/web/app/components/workflow/nodes/iteration/panel.tsx b/web/app/components/workflow/nodes/iteration/panel.tsx index 9b6b3d3790..5dcd3e0c92 100644 --- a/web/app/components/workflow/nodes/iteration/panel.tsx +++ b/web/app/components/workflow/nodes/iteration/panel.tsx @@ -1,13 +1,9 @@ import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' -import { - RiArrowRightSLine, -} from '@remixicon/react' import VarReferencePicker from '../_base/components/variable/var-reference-picker' import Split from '../_base/components/split' import ResultPanel from '../../run/result-panel' -import IterationResultPanel from '../../run/iteration-result-panel' import { MAX_ITERATION_PARALLEL_NUM, MIN_ITERATION_PARALLEL_NUM } from '../../constants' import type { IterationNodeType } from './types' import useConfig from './use-config' @@ -18,6 +14,9 @@ import Switch from '@/app/components/base/switch' import Select from '@/app/components/base/select' import Slider from '@/app/components/base/slider' import Input from '@/app/components/base/input' +import formatTracing from '@/app/components/workflow/run/utils/format-log' + +import { useLogs } from '@/app/components/workflow/run/hooks' const i18nPrefix = 'workflow.nodes.iteration' @@ -50,10 +49,6 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({ handleOutputVarChange, isShowSingleRun, hideSingleRun, - isShowIterationDetail, - backToSingleRun, - showIterationDetail, - hideIterationDetail, runningStatus, handleRun, handleStop, @@ -70,6 +65,9 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({ changeParallelNums, } = useConfig(id, data) + const nodeInfo = formatTracing(iterationRunResult, t)[0] + const logsParams = useLogs() + return ( <div className='pt-2 pb-2'> <div className='px-4 pb-4 space-y-4'> @@ -123,7 +121,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({ onChange={changeParallelNums} max={MAX_ITERATION_PARALLEL_NUM} min={MIN_ITERATION_PARALLEL_NUM} - className=' flex-shrink-0 flex-1 mt-4' + className=' shrink-0 flex-1 mt-4' /> </div> @@ -164,27 +162,12 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({ runningStatus={runningStatus} onRun={handleRun} onStop={handleStop} + {...logsParams} result={ - <div className='mt-3'> - <div className='px-4'> - <div className='flex items-center h-[34px] justify-between px-3 bg-gray-100 border-[0.5px] border-gray-200 rounded-lg cursor-pointer' onClick={showIterationDetail}> - <div className='leading-[18px] text-[13px] font-medium text-gray-700'>{t(`${i18nPrefix}.iteration`, { count: iterationRunResult.length })}</div> - <RiArrowRightSLine className='w-3.5 h-3.5 text-gray-500' /> - </div> - <Split className='mt-3' /> - </div> - <ResultPanel {...runResult} showSteps={false} /> - </div> + <ResultPanel {...runResult} showSteps={false} nodeInfo={nodeInfo} {...logsParams} /> } /> )} - {isShowIterationDetail && ( - <IterationResultPanel - onBack={backToSingleRun} - onHide={hideIterationDetail} - list={iterationRunResult} - /> - )} </div> ) } diff --git a/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx b/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx index 3e9be6485b..b0d992fcf2 100644 --- a/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx +++ b/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx @@ -18,7 +18,7 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import Badge from '@/app/components/base/badge' import { useKnowledge } from '@/hooks/use-knowledge' -type Props = { +interface Props { payload: DataSet onRemove: () => void onChange: (dataSet: DataSet) => void diff --git a/web/app/components/workflow/nodes/list-operator/components/limit-config.tsx b/web/app/components/workflow/nodes/list-operator/components/limit-config.tsx index f245e07c12..b8812d3473 100644 --- a/web/app/components/workflow/nodes/list-operator/components/limit-config.tsx +++ b/web/app/components/workflow/nodes/list-operator/components/limit-config.tsx @@ -45,7 +45,7 @@ const LimitConfig: FC<Props> = ({ const handleLimitSizeChange = useCallback((size: number | string) => { onChange({ ...config, - size: parseInt(size as string), + size: Number.parseInt(size as string), }) }, [onChange, config]) diff --git a/web/app/components/workflow/nodes/list-operator/node.tsx b/web/app/components/workflow/nodes/list-operator/node.tsx index 721e13b2d2..5c498369c7 100644 --- a/web/app/components/workflow/nodes/list-operator/node.tsx +++ b/web/app/components/workflow/nodes/list-operator/node.tsx @@ -3,7 +3,7 @@ import React from 'react' import { useNodes } from 'reactflow' import { useTranslation } from 'react-i18next' import NodeVariableItem from '../variable-assigner/components/node-variable-item' -import { type ListFilterNodeType } from './types' +import type { ListFilterNodeType } from './types' import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types' diff --git a/web/app/components/workflow/nodes/list-operator/panel.tsx b/web/app/components/workflow/nodes/list-operator/panel.tsx index 3075c1dec7..4212305c8c 100644 --- a/web/app/components/workflow/nodes/list-operator/panel.tsx +++ b/web/app/components/workflow/nodes/list-operator/panel.tsx @@ -11,7 +11,7 @@ import { type ListFilterNodeType, OrderBy } from './types' import LimitConfig from './components/limit-config' import FilterCondition from './components/filter-condition' import Field from '@/app/components/workflow/nodes/_base/components/field' -import { type NodePanelProps } from '@/app/components/workflow/types' +import type { NodePanelProps } from '@/app/components/workflow/types' import Switch from '@/app/components/base/switch' import ExtractInput from '@/app/components/workflow/nodes/list-operator/components/extract-input' diff --git a/web/app/components/workflow/nodes/llm/node.tsx b/web/app/components/workflow/nodes/llm/node.tsx index 3d81c172be..ce676ba984 100644 --- a/web/app/components/workflow/nodes/llm/node.tsx +++ b/web/app/components/workflow/nodes/llm/node.tsx @@ -25,6 +25,7 @@ const Node: FC<NodeProps<LLMNodeType>> = ({ <ModelSelector defaultModel={{ provider, model: modelId }} modelList={textGenerationModelList} + triggerClassName='!h-6 !rounded-md' readonly /> )} diff --git a/web/app/components/workflow/nodes/llm/panel.tsx b/web/app/components/workflow/nodes/llm/panel.tsx index 60f68d93e2..cc0f1c18f4 100644 --- a/web/app/components/workflow/nodes/llm/panel.tsx +++ b/web/app/components/workflow/nodes/llm/panel.tsx @@ -19,7 +19,6 @@ import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/c import ResultPanel from '@/app/components/workflow/run/result-panel' import Tooltip from '@/app/components/base/tooltip' import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor' -import { useRetryDetailShowInSingleRun } from '@/app/components/workflow/nodes/_base/components/retry/hooks' const i18nPrefix = 'workflow.nodes.llm' @@ -70,10 +69,6 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({ runResult, filterJinjia2InputVar, } = useConfig(id, data) - const { - retryDetails, - handleRetryDetailsChange, - } = useRetryDetailShowInSingleRun() const model = inputs.model @@ -293,9 +288,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({ runningStatus={runningStatus} onRun={handleRun} onStop={handleStop} - retryDetails={retryDetails} - onRetryDetailBack={handleRetryDetailsChange} - result={<ResultPanel {...runResult} showSteps={false} onShowRetryDetail={handleRetryDetailsChange} />} + result={<ResultPanel {...runResult} showSteps={false} />} /> )} </div> diff --git a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/update.tsx b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/update.tsx index f7cf7bddad..dbf0839ebf 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/update.tsx +++ b/web/app/components/workflow/nodes/parameter-extractor/components/extract-parameter/update.tsx @@ -28,7 +28,7 @@ const DEFAULT_PARAM: Param = { required: false, } -type Props = { +interface Props { type: 'add' | 'edit' payload?: Param onSave: (payload: Param, moreInfo?: MoreInfo) => void diff --git a/web/app/components/workflow/nodes/parameter-extractor/components/reasoning-mode-picker.tsx b/web/app/components/workflow/nodes/parameter-extractor/components/reasoning-mode-picker.tsx index f4fd6e85a6..8612e8954f 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/components/reasoning-mode-picker.tsx +++ b/web/app/components/workflow/nodes/parameter-extractor/components/reasoning-mode-picker.tsx @@ -8,7 +8,7 @@ import OptionCard from '../../_base/components/option-card' const i18nPrefix = 'workflow.nodes.parameterExtractor' -type Props = { +interface Props { type: ReasoningModeType onChange: (type: ReasoningModeType) => void } diff --git a/web/app/components/workflow/nodes/parameter-extractor/node.tsx b/web/app/components/workflow/nodes/parameter-extractor/node.tsx index 8a1b08e924..d79ae717d9 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/node.tsx +++ b/web/app/components/workflow/nodes/parameter-extractor/node.tsx @@ -21,6 +21,7 @@ const Node: FC<NodeProps<ParameterExtractorNodeType>> = ({ <ModelSelector defaultModel={{ provider, model: modelId }} modelList={textGenerationModelList} + triggerClassName='!h-6 !rounded-md' readonly /> )} diff --git a/web/app/components/workflow/nodes/parameter-extractor/types.ts b/web/app/components/workflow/nodes/parameter-extractor/types.ts index f5ba717be8..f96d26a7af 100644 --- a/web/app/components/workflow/nodes/parameter-extractor/types.ts +++ b/web/app/components/workflow/nodes/parameter-extractor/types.ts @@ -10,7 +10,7 @@ export enum ParamType { arrayObject = 'array[object]', } -export type Param = { +export interface Param { name: string type: ParamType options?: string[] diff --git a/web/app/components/workflow/nodes/question-classifier/node.tsx b/web/app/components/workflow/nodes/question-classifier/node.tsx index 8ca721fbef..8316c3b259 100644 --- a/web/app/components/workflow/nodes/question-classifier/node.tsx +++ b/web/app/components/workflow/nodes/question-classifier/node.tsx @@ -32,6 +32,7 @@ const Node: FC<NodeProps<QuestionClassifierNodeType>> = (props) => { {hasSetModel && ( <ModelSelector defaultModel={{ provider, model: modelId }} + triggerClassName='!h-6 !rounded-md' modelList={textGenerationModelList} readonly /> diff --git a/web/app/components/workflow/nodes/question-classifier/types.ts b/web/app/components/workflow/nodes/question-classifier/types.ts index ddc16b4501..ca102b083e 100644 --- a/web/app/components/workflow/nodes/question-classifier/types.ts +++ b/web/app/components/workflow/nodes/question-classifier/types.ts @@ -1,6 +1,6 @@ import type { CommonNodeType, Memory, ModelConfig, ValueSelector, VisionSetting } from '@/app/components/workflow/types' -export type Topic = { +export interface Topic { id: string name: string } diff --git a/web/app/components/workflow/nodes/start/components/var-item.tsx b/web/app/components/workflow/nodes/start/components/var-item.tsx index 8a94161999..2ccb1edb56 100644 --- a/web/app/components/workflow/nodes/start/components/var-item.tsx +++ b/web/app/components/workflow/nodes/start/components/var-item.tsx @@ -13,7 +13,7 @@ import { Edit03 } from '@/app/components/base/icons/src/vender/solid/general' import Badge from '@/app/components/base/badge' import ConfigVarModal from '@/app/components/app/configuration/config-var/config-modal' -type Props = { +interface Props { readonly: boolean payload: InputVar onChange?: (item: InputVar, moreInfo?: MoreInfo) => void diff --git a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx b/web/app/components/workflow/nodes/tool/components/input-var-list.tsx index bab7c20d5b..d4cef82c43 100644 --- a/web/app/components/workflow/nodes/tool/components/input-var-list.tsx +++ b/web/app/components/workflow/nodes/tool/components/input-var-list.tsx @@ -14,6 +14,9 @@ import VarReferencePicker from '@/app/components/workflow/nodes/_base/components import Input from '@/app/components/workflow/nodes/_base/components/input-support-select-var' import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list' import { VarType } from '@/app/components/workflow/types' +import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector' +import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector' + type Props = { readOnly: boolean nodeId: string @@ -46,12 +49,14 @@ const InputVarList: FC<Props> = ({ const paramType = (type: string) => { if (type === FormTypeEnum.textNumber) return 'Number' - else if (type === FormTypeEnum.file) - return 'File' - else if (type === FormTypeEnum.files) + else if (type === FormTypeEnum.file || type === FormTypeEnum.files) return 'Files' - else if (type === FormTypeEnum.select) - return 'Options' + else if (type === FormTypeEnum.appSelector) + return 'AppSelector' + else if (type === FormTypeEnum.modelSelector) + return 'ModelSelector' + else if (type === FormTypeEnum.toolSelector) + return 'ToolSelector' else return 'String' } @@ -73,7 +78,7 @@ const InputVarList: FC<Props> = ({ }) onChange(newValue) } - }, [value, onChange, isSupportConstantValue]) + }, [value, onChange]) const handleMixedTypeChange = useCallback((variable: string) => { return (itemValue: string) => { @@ -105,6 +110,30 @@ const InputVarList: FC<Props> = ({ } }, [value, onChange]) + const handleAppChange = useCallback((variable: string) => { + return (app: { + app_id: string + inputs: Record<string, any> + files?: any[] + }) => { + const newValue = produce(value, (draft: ToolVarInputs) => { + draft[variable] = app as any + }) + onChange(newValue) + } + }, [onChange, value]) + const handleModelChange = useCallback((variable: string) => { + return (model: any) => { + const newValue = produce(value, (draft: ToolVarInputs) => { + draft[variable] = { + ...draft[variable], + ...model, + } as any + }) + onChange(newValue) + } + }, [onChange, value]) + const [inputsIsFocus, setInputsIsFocus] = useState<Record<string, boolean>>({}) const handleInputFocus = useCallback((variable: string) => { return (value: boolean) => { @@ -129,13 +158,16 @@ const InputVarList: FC<Props> = ({ type, required, tooltip, + scope, } = schema const varInput = value[variable] const isNumber = type === FormTypeEnum.textNumber const isSelect = type === FormTypeEnum.select - const isFile = type === FormTypeEnum.file - const isFileArray = type === FormTypeEnum.files - const isString = !isNumber && !isSelect && !isFile && !isFileArray + const isFile = type === FormTypeEnum.file || type === FormTypeEnum.files + const isAppSelector = type === FormTypeEnum.appSelector + const isModelSelector = type === FormTypeEnum.modelSelector + // const isToolSelector = type === FormTypeEnum.toolSelector + const isString = !isNumber && !isSelect && !isFile && !isAppSelector && !isModelSelector return ( <div key={variable} className='space-y-1'> @@ -181,19 +213,26 @@ const InputVarList: FC<Props> = ({ onChange={handleFileChange(variable)} onOpen={handleOpen(index)} defaultVarKindType={VarKindType.variable} - filterVar={(varPayload: Var) => varPayload.type === VarType.file} + filterVar={(varPayload: Var) => varPayload.type === VarType.file || varPayload.type === VarType.arrayFile} /> )} - {isFileArray && ( - <VarReferencePicker + {isAppSelector && ( + <AppSelector + disabled={readOnly} + scope={scope || 'all'} + value={varInput as any} + onSelect={handleAppChange(variable)} + /> + )} + {isModelSelector && ( + <ModelParameterModal + popupClassName='!w-[387px]' + isAdvancedMode + isInWorkflow + value={varInput as any} + setModel={handleModelChange(variable)} readonly={readOnly} - isShowNodeName - nodeId={nodeId} - value={varInput?.value || []} - onChange={handleFileChange(variable)} - onOpen={handleOpen(index)} - defaultVarKindType={VarKindType.variable} - filterVar={(varPayload: Var) => varPayload.type === VarType.arrayFile} + scope={scope} /> )} {tooltip && <div className='text-text-tertiary body-xs-regular'>{tooltip[language] || tooltip.en_US}</div>} diff --git a/web/app/components/workflow/nodes/tool/node.tsx b/web/app/components/workflow/nodes/tool/node.tsx index 4de03394c3..d7ed993aab 100644 --- a/web/app/components/workflow/nodes/tool/node.tsx +++ b/web/app/components/workflow/nodes/tool/node.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react' import React from 'react' import type { ToolNodeType } from './types' import type { NodeProps } from '@/app/components/workflow/types' +import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations' const Node: FC<NodeProps<ToolNodeType>> = ({ data, @@ -20,9 +21,21 @@ const Node: FC<NodeProps<ToolNodeType>> = ({ <div title={key} className='max-w-[100px] shrink-0 truncate text-xs font-medium text-gray-500 uppercase'> {key} </div> - <div title={tool_configurations[key]} className='grow w-0 shrink-0 truncate text-right text-xs font-normal text-gray-700'> - {tool_configurations[key]} - </div> + {typeof tool_configurations[key] === 'string' && ( + <div title={tool_configurations[key]} className='grow w-0 shrink-0 truncate text-right text-xs font-normal text-gray-700'> + {tool_configurations[key]} + </div> + )} + {typeof tool_configurations[key] !== 'string' && tool_configurations[key]?.type === FormTypeEnum.modelSelector && ( + <div title={tool_configurations[key].model} className='grow w-0 shrink-0 truncate text-right text-xs font-normal text-gray-700'> + {tool_configurations[key].model} + </div> + )} + {/* {typeof tool_configurations[key] !== 'string' && tool_configurations[key]?.type === FormTypeEnum.appSelector && ( + <div title={tool_configurations[key].app_id} className='grow w-0 shrink-0 truncate text-right text-xs font-normal text-gray-700'> + {tool_configurations[key].app_id} + </div> + )} */} </div> ))} diff --git a/web/app/components/workflow/nodes/tool/panel.tsx b/web/app/components/workflow/nodes/tool/panel.tsx index d0d4c3a839..93e2e9130f 100644 --- a/web/app/components/workflow/nodes/tool/panel.tsx +++ b/web/app/components/workflow/nodes/tool/panel.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react' -import React from 'react' +import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' import Split from '../_base/components/split' import type { ToolNodeType } from './types' @@ -14,8 +14,9 @@ import Loading from '@/app/components/base/loading' import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form' import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars' import ResultPanel from '@/app/components/workflow/run/result-panel' -import { useRetryDetailShowInSingleRun } from '@/app/components/workflow/nodes/_base/components/retry/hooks' import { useToolIcon } from '@/app/components/workflow/hooks' +import { useLogs } from '@/app/components/workflow/run/hooks' +import formatToTracingNodeList from '@/app/components/workflow/run/utils/format-log' const i18nPrefix = 'workflow.nodes.tool' @@ -49,12 +50,15 @@ const Panel: FC<NodePanelProps<ToolNodeType>> = ({ handleRun, handleStop, runResult, + outputSchema, } = useConfig(id, data) const toolIcon = useToolIcon(data) - const { - retryDetails, - handleRetryDetailsChange, - } = useRetryDetailShowInSingleRun() + const logsParams = useLogs() + const nodeInfo = useMemo(() => { + if (!runResult) + return null + return formatToTracingNodeList([runResult], t)[0] + }, [runResult, t]) if (isLoading) { return <div className='flex h-[200px] items-center justify-center'> @@ -143,6 +147,14 @@ const Panel: FC<NodePanelProps<ToolNodeType>> = ({ type='Array[Object]' description={t(`${i18nPrefix}.outputVars.json`)} /> + {outputSchema.map(outputItem => ( + <VarItem + key={outputItem.name} + name={outputItem.name} + type={outputItem.type} + description={outputItem.description} + /> + ))} </> </OutputVars> </div> @@ -157,9 +169,8 @@ const Panel: FC<NodePanelProps<ToolNodeType>> = ({ runningStatus={runningStatus} onRun={handleRun} onStop={handleStop} - retryDetails={retryDetails} - onRetryDetailBack={handleRetryDetailsChange} - result={<ResultPanel {...runResult} showSteps={false} onShowRetryDetail={handleRetryDetailsChange} />} + {...logsParams} + result={<ResultPanel {...runResult} showSteps={false} {...logsParams} nodeInfo={nodeInfo} />} /> )} </div> diff --git a/web/app/components/workflow/nodes/tool/types.ts b/web/app/components/workflow/nodes/tool/types.ts index 1ed6f9c373..4fbd945710 100644 --- a/web/app/components/workflow/nodes/tool/types.ts +++ b/web/app/components/workflow/nodes/tool/types.ts @@ -9,7 +9,7 @@ export enum VarType { export type ToolVarInputs = Record<string, { type: VarType - value?: string | ValueSelector + value?: string | ValueSelector | any }> export type ToolNodeType = CommonNodeType & { @@ -20,4 +20,5 @@ export type ToolNodeType = CommonNodeType & { tool_label: string tool_parameters: ToolVarInputs tool_configurations: Record<string, any> + output_schema: Record<string, any> } diff --git a/web/app/components/workflow/nodes/tool/use-config.ts b/web/app/components/workflow/nodes/tool/use-config.ts index 94046ba4fa..acc20ec7ea 100644 --- a/web/app/components/workflow/nodes/tool/use-config.ts +++ b/web/app/components/workflow/nodes/tool/use-config.ts @@ -29,8 +29,9 @@ const useConfig = (id: string, payload: ToolNodeType) => { /* * tool_configurations: tool setting, not dynamic setting * tool_parameters: tool dynamic setting(by user) + * output_schema: tool dynamic output */ - const { provider_id, provider_type, tool_name, tool_configurations } = inputs + const { provider_id, provider_type, tool_name, tool_configurations, output_schema } = inputs const isBuiltIn = provider_type === CollectionType.builtIn const buildInTools = useStore(s => s.buildInTools) const customTools = useStore(s => s.customTools) @@ -91,7 +92,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { const value = newConfig[key] if (schema?.type === 'boolean') { if (typeof value === 'string') - newConfig[key] = parseInt(value, 10) + newConfig[key] = Number.parseInt(value, 10) if (typeof value === 'boolean') newConfig[key] = value ? 1 : 0 @@ -99,7 +100,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { if (schema?.type === 'number-input') { if (typeof value === 'string' && value !== '') - newConfig[key] = parseFloat(value) + newConfig[key] = Number.parseFloat(value) } }) draft.tool_configurations = newConfig @@ -162,7 +163,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { const [inputVarValues, doSetInputVarValues] = useState<Record<string, any>>({}) const setInputVarValues = (value: Record<string, any>) => { doSetInputVarValues(value) - // eslint-disable-next-line @typescript-eslint/no-use-before-define + // eslint-disable-next-line ts/no-use-before-define setRunInputData(value) } // fill single run form variable with constant value first time @@ -254,6 +255,23 @@ const useConfig = (id: string, payload: ToolNodeType) => { doHandleRun(addMissedVarData) } + const outputSchema = useMemo(() => { + const res: any[] = [] + if (!output_schema) + return [] + Object.keys(output_schema.properties).forEach((outputKey) => { + const output = output_schema.properties[outputKey] + res.push({ + name: outputKey, + type: output.type === 'array' + ? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` + : `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}`, + description: output.description, + }) + }) + return res + }, [output_schema]) + return { readOnly, inputs, @@ -282,6 +300,7 @@ const useConfig = (id: string, payload: ToolNodeType) => { handleRun, handleStop, runResult, + outputSchema, } } diff --git a/web/app/components/workflow/nodes/variable-assigner/components/var-group-item.tsx b/web/app/components/workflow/nodes/variable-assigner/components/var-group-item.tsx index eb5a8f8e51..e18327a472 100644 --- a/web/app/components/workflow/nodes/variable-assigner/components/var-group-item.tsx +++ b/web/app/components/workflow/nodes/variable-assigner/components/var-group-item.tsx @@ -24,7 +24,7 @@ type Payload = VarGroupItemType & { group_name?: string } -type Props = { +interface Props { readOnly: boolean nodeId: string payload: Payload diff --git a/web/app/components/workflow/nodes/variable-assigner/panel.tsx b/web/app/components/workflow/nodes/variable-assigner/panel.tsx index 6152e0f5b8..b25e2656ed 100644 --- a/web/app/components/workflow/nodes/variable-assigner/panel.tsx +++ b/web/app/components/workflow/nodes/variable-assigner/panel.tsx @@ -7,7 +7,7 @@ import useConfig from './use-config' import type { VariableAssignerNodeType } from './types' import VarGroupItem from './components/var-group-item' import cn from '@/utils/classnames' -import { type NodePanelProps } from '@/app/components/workflow/types' +import type { NodePanelProps } from '@/app/components/workflow/types' import Split from '@/app/components/workflow/nodes/_base/components/split' import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars' import Switch from '@/app/components/base/switch' diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/array-value-list.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/array-value-list.tsx index 8206f02049..b2bfd2a218 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/components/array-value-list.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/components/array-value-list.tsx @@ -8,7 +8,7 @@ import RemoveButton from '@/app/components/workflow/nodes/_base/components/remov import Button from '@/app/components/base/button' import Input from '@/app/components/base/input' -type Props = { +interface Props { isString: boolean list: any[] onChange: (list: any[]) => void diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx index baa42eef24..3c983cd364 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx @@ -18,13 +18,13 @@ import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel import cn from '@/utils/classnames' import { checkKeys } from '@/utils/var' -export type ModalPropsType = { +export interface ModalPropsType { chatVar?: ConversationVariable onClose: () => void onSave: (chatVar: ConversationVariable) => void } -type ObjectValueItem = { +interface ObjectValueItem { key: string type: ChatVarType value: string | number | undefined diff --git a/web/app/components/workflow/panel/debug-and-preview/conversation-variable-modal.tsx b/web/app/components/workflow/panel/debug-and-preview/conversation-variable-modal.tsx index 5991414baf..e60c8afac9 100644 --- a/web/app/components/workflow/panel/debug-and-preview/conversation-variable-modal.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/conversation-variable-modal.tsx @@ -22,7 +22,7 @@ import useTimestamp from '@/hooks/use-timestamp' import { fetchCurrentValueOfConversationVariable } from '@/service/workflow' import cn from '@/utils/classnames' -export type Props = { +export interface Props { conversationID: string onHide: () => void } diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index ebd5e7a99d..81cccd9cc7 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -27,7 +27,6 @@ import { getProcessedFilesFromResponse, } from '@/app/components/base/file-uploader/utils' import type { FileEntity } from '@/app/components/base/file-uploader/types' -import type { NodeTracing } from '@/types/workflow' type GetAbortController = (abortController: AbortController) => void type SendCallback = { @@ -276,6 +275,7 @@ export const useChat = ( ) setSuggestQuestions(data) } + // eslint-disable-next-line unused-imports/no-unused-vars catch (error) { setSuggestQuestions([]) } @@ -331,8 +331,7 @@ export const useChat = ( responseItem.workflowProcess!.tracing!.push({ ...data, status: NodeRunningStatus.Running, - details: [], - } as any) + }) handleUpdateChatList(produce(chatListRef.current, (draft) => { const currentIndex = draft.findIndex(item => item.id === responseItem.id) draft[currentIndex] = { @@ -341,30 +340,21 @@ export const useChat = ( } })) }, - onIterationNext: ({ data }) => { - const tracing = responseItem.workflowProcess!.tracing! - const iterations = tracing.find(item => item.node_id === data.node_id - && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))! - iterations.details!.push([]) - - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.length - 1 - draft[currentIndex] = responseItem - })) - }, onIterationFinish: ({ data }) => { - const tracing = responseItem.workflowProcess!.tracing! - const iterationsIndex = tracing.findIndex(item => item.node_id === data.node_id - && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))! - tracing[iterationsIndex] = { - ...tracing[iterationsIndex], - ...data, - status: NodeRunningStatus.Succeeded, - } as any - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.length - 1 - draft[currentIndex] = responseItem - })) + const currentTracingIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.id === data.id) + if (currentTracingIndex > -1) { + responseItem.workflowProcess!.tracing[currentTracingIndex] = { + ...responseItem.workflowProcess!.tracing[currentTracingIndex], + ...data, + } + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) + } }, onNodeStarted: ({ data }) => { if (data.iteration_id) @@ -386,16 +376,7 @@ export const useChat = ( if (data.iteration_id) return - const currentIndex = responseItem.workflowProcess!.tracing!.findIndex((item) => { - if (!item.execution_metadata?.parallel_id) - return item.node_id === data.node_id - return item.node_id === data.node_id && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id) - }) - if (responseItem.workflowProcess!.tracing[currentIndex].retryDetail) - responseItem.workflowProcess!.tracing[currentIndex].retryDetail?.push(data as NodeTracing) - else - responseItem.workflowProcess!.tracing[currentIndex].retryDetail = [data as NodeTracing] - + responseItem.workflowProcess!.tracing!.push(data) handleUpdateChatList(produce(chatListRef.current, (draft) => { const currentIndex = draft.findIndex(item => item.id === responseItem.id) draft[currentIndex] = { @@ -408,27 +389,77 @@ export const useChat = ( if (data.iteration_id) return - const currentIndex = responseItem.workflowProcess!.tracing!.findIndex((item) => { - if (!item.execution_metadata?.parallel_id) - return item.node_id === data.node_id - return item.node_id === data.node_id && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id) - }) - responseItem.workflowProcess!.tracing[currentIndex] = { - ...(responseItem.workflowProcess!.tracing[currentIndex]?.extras - ? { extras: responseItem.workflowProcess!.tracing[currentIndex].extras } - : {}), - ...(responseItem.workflowProcess!.tracing[currentIndex]?.retryDetail - ? { retryDetail: responseItem.workflowProcess!.tracing[currentIndex].retryDetail } - : {}), - ...data, - } as any - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.findIndex(item => item.id === responseItem.id) - draft[currentIndex] = { - ...draft[currentIndex], - ...responseItem, + const currentTracingIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.id === data.id) + if (currentTracingIndex > -1) { + responseItem.workflowProcess!.tracing[currentTracingIndex] = { + ...responseItem.workflowProcess!.tracing[currentTracingIndex], + ...data, } - })) + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) + } + }, + onAgentLog: ({ data }) => { + const currentNodeIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.node_id === data.node_id) + if (currentNodeIndex > -1) { + const current = responseItem.workflowProcess!.tracing![currentNodeIndex] + + if (current.execution_metadata) { + if (current.execution_metadata.agent_log) { + const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.id === data.id) + if (currentLogIndex > -1) { + current.execution_metadata.agent_log[currentLogIndex] = { + ...current.execution_metadata.agent_log[currentLogIndex], + ...data, + } + } + else { + current.execution_metadata.agent_log.push(data) + } + } + else { + current.execution_metadata.agent_log = [data] + } + } + else { + current.execution_metadata = { + agent_log: [data], + } as any + } + // if (current.agentLog) { + // const currentLogIndex = current.agentLog.findIndex(log => log.id === data.id) + + // if (currentLogIndex > -1) { + // current.agentLog[currentLogIndex] = { + // ...current.agentLog[currentLogIndex], + // ...data, + // } + // } + // else { + // current.agentLog.push(data) + // } + // } + // else { + // current.agentLog = [data] + // } + + responseItem.workflowProcess!.tracing[currentNodeIndex] = { + ...current, + } + + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) + } }, }, ) diff --git a/web/app/components/workflow/panel/env-panel/variable-modal.tsx b/web/app/components/workflow/panel/env-panel/variable-modal.tsx index feabd5a422..da59670a5b 100644 --- a/web/app/components/workflow/panel/env-panel/variable-modal.tsx +++ b/web/app/components/workflow/panel/env-panel/variable-modal.tsx @@ -12,7 +12,7 @@ import type { EnvironmentVariable } from '@/app/components/workflow/types' import cn from '@/utils/classnames' import { checkKeys } from '@/utils/var' -export type ModalPropsType = { +export interface ModalPropsType { env?: EnvironmentVariable onClose: () => void onSave: (env: EnvironmentVariable) => void diff --git a/web/app/components/workflow/panel/inputs-panel.tsx b/web/app/components/workflow/panel/inputs-panel.tsx index 47fec40e60..d7d7f7c5cc 100644 --- a/web/app/components/workflow/panel/inputs-panel.tsx +++ b/web/app/components/workflow/panel/inputs-panel.tsx @@ -25,7 +25,7 @@ import { } from '@/app/components/base/chat/chat/utils' import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks' -type Props = { +interface Props { onRun: () => void } diff --git a/web/app/components/workflow/panel/workflow-preview.tsx b/web/app/components/workflow/panel/workflow-preview.tsx index 210a95f1f8..b4e4d4c5d1 100644 --- a/web/app/components/workflow/panel/workflow-preview.tsx +++ b/web/app/components/workflow/panel/workflow-preview.tsx @@ -1,8 +1,6 @@ import { memo, - useCallback, useEffect, - // useRef, useState, } from 'react' import { @@ -11,7 +9,6 @@ import { } from '@remixicon/react' import { useTranslation } from 'react-i18next' import copy from 'copy-to-clipboard' -import { useBoolean } from 'ahooks' import ResultText from '../run/result-text' import ResultPanel from '../run/result-panel' import TracingPanel from '../run/tracing-panel' @@ -24,12 +21,9 @@ import { } from '../types' import { SimpleBtn } from '../../app/text-generate/item' import Toast from '../../base/toast' -import IterationResultPanel from '../run/iteration-result-panel' -import RetryResultPanel from '../run/retry-result-panel' import InputsPanel from './inputs-panel' import cn from '@/utils/classnames' import Loading from '@/app/components/base/loading' -import type { IterationDurationMap, NodeTracing } from '@/types/workflow' const WorkflowPreview = () => { const { t } = useTranslation() @@ -53,44 +47,6 @@ const WorkflowPreview = () => { switchTab('DETAIL') }, [workflowRunningData]) - const [iterationRunResult, setIterationRunResult] = useState<NodeTracing[][]>([]) - const [retryRunResult, setRetryRunResult] = useState<NodeTracing[]>([]) - const [iterDurationMap, setIterDurationMap] = useState<IterationDurationMap>({}) - const [isShowIterationDetail, { - setTrue: doShowIterationDetail, - setFalse: doHideIterationDetail, - }] = useBoolean(false) - const [isShowRetryDetail, { - setTrue: doShowRetryDetail, - setFalse: doHideRetryDetail, - }] = useBoolean(false) - - const handleShowIterationDetail = useCallback((detail: NodeTracing[][], iterationDurationMap: IterationDurationMap) => { - setIterDurationMap(iterationDurationMap) - setIterationRunResult(detail) - doShowIterationDetail() - }, [doShowIterationDetail]) - - const handleRetryDetail = useCallback((detail: NodeTracing[]) => { - setRetryRunResult(detail) - doShowRetryDetail() - }, [doShowRetryDetail]) - - if (isShowIterationDetail) { - return ( - <div className={` - flex flex-col w-[420px] h-full rounded-l-2xl border-[0.5px] border-gray-200 shadow-xl bg-white - `}> - <IterationResultPanel - list={iterationRunResult} - onHide={doHideIterationDetail} - onBack={doHideIterationDetail} - iterDurationMap={iterDurationMap} - /> - </div> - ) - } - return ( <div className={` flex flex-col w-[420px] h-full rounded-l-2xl border-[0.5px] border-gray-200 shadow-xl bg-white @@ -102,141 +58,117 @@ const WorkflowPreview = () => { </div> </div> <div className='grow relative flex flex-col'> - {isShowIterationDetail - ? ( - <IterationResultPanel - list={iterationRunResult} - onHide={doHideIterationDetail} - onBack={doHideIterationDetail} - iterDurationMap={iterDurationMap} - /> - ) - : ( + <div className='shrink-0 flex items-center px-4 border-b-[0.5px] border-[rgba(0,0,0,0.05)]'> + {showInputsPanel && ( + <div + className={cn( + 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', + currentTab === 'INPUT' && '!border-[rgb(21,94,239)] text-gray-700', + )} + onClick={() => switchTab('INPUT')} + >{t('runLog.input')}</div> + )} + <div + className={cn( + 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', + currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-gray-700', + !workflowRunningData && 'opacity-30 !cursor-not-allowed', + )} + onClick={() => { + if (!workflowRunningData) + return + switchTab('RESULT') + }} + >{t('runLog.result')}</div> + <div + className={cn( + 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', + currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-gray-700', + !workflowRunningData && 'opacity-30 !cursor-not-allowed', + )} + onClick={() => { + if (!workflowRunningData) + return + switchTab('DETAIL') + }} + >{t('runLog.detail')}</div> + <div + className={cn( + 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', + currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700', + !workflowRunningData && 'opacity-30 !cursor-not-allowed', + )} + onClick={() => { + if (!workflowRunningData) + return + switchTab('TRACING') + }} + >{t('runLog.tracing')}</div> + </div> + <div className={cn( + 'grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl', + (currentTab === 'RESULT' || currentTab === 'TRACING') && '!bg-background-section-burn', + )}> + {currentTab === 'INPUT' && showInputsPanel && ( + <InputsPanel onRun={() => switchTab('RESULT')} /> + )} + {currentTab === 'RESULT' && ( <> - <div className='shrink-0 flex items-center px-4 border-b-[0.5px] border-[rgba(0,0,0,0.05)]'> - {showInputsPanel && ( - <div - className={cn( - 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', - currentTab === 'INPUT' && '!border-[rgb(21,94,239)] text-gray-700', - )} - onClick={() => switchTab('INPUT')} - >{t('runLog.input')}</div> - )} - <div - className={cn( - 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', - currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-gray-700', - !workflowRunningData && 'opacity-30 !cursor-not-allowed', - )} + <ResultText + isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result} + outputs={workflowRunningData?.resultText} + allFiles={workflowRunningData?.result?.files as any} + error={workflowRunningData?.result?.error} + onClick={() => switchTab('DETAIL')} + /> + {(workflowRunningData?.result.status === WorkflowRunningStatus.Succeeded && workflowRunningData?.resultText && typeof workflowRunningData?.resultText === 'string') && ( + <SimpleBtn + className={cn('ml-4 mb-4 inline-flex space-x-1')} onClick={() => { - if (!workflowRunningData) - return - switchTab('RESULT') - }} - >{t('runLog.result')}</div> - <div - className={cn( - 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', - currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-gray-700', - !workflowRunningData && 'opacity-30 !cursor-not-allowed', - )} - onClick={() => { - if (!workflowRunningData) - return - switchTab('DETAIL') - }} - >{t('runLog.detail')}</div> - <div - className={cn( - 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer', - currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700', - !workflowRunningData && 'opacity-30 !cursor-not-allowed', - )} - onClick={() => { - if (!workflowRunningData) - return - switchTab('TRACING') - }} - >{t('runLog.tracing')}</div> - </div> - <div className={cn( - 'grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl', - (currentTab === 'RESULT' || currentTab === 'TRACING') && '!bg-background-section-burn', - )}> - {currentTab === 'INPUT' && showInputsPanel && ( - <InputsPanel onRun={() => switchTab('RESULT')} /> - )} - {currentTab === 'RESULT' && ( - <> - <ResultText - isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result} - outputs={workflowRunningData?.resultText} - allFiles={workflowRunningData?.result?.files as any} - error={workflowRunningData?.result?.error} - onClick={() => switchTab('DETAIL')} - /> - {(workflowRunningData?.result.status === WorkflowRunningStatus.Succeeded && workflowRunningData?.resultText && typeof workflowRunningData?.resultText === 'string') && ( - <SimpleBtn - className={cn('ml-4 mb-4 inline-flex space-x-1')} - onClick={() => { - const content = workflowRunningData?.resultText - if (typeof content === 'string') - copy(content) - else - copy(JSON.stringify(content)) - Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') }) - }}> - <RiClipboardLine className='w-3.5 h-3.5' /> - <div>{t('common.operation.copy')}</div> - </SimpleBtn> - )} - </> - )} - {currentTab === 'DETAIL' && ( - <ResultPanel - inputs={workflowRunningData?.result?.inputs} - outputs={workflowRunningData?.result?.outputs} - status={workflowRunningData?.result?.status || ''} - error={workflowRunningData?.result?.error} - elapsed_time={workflowRunningData?.result?.elapsed_time} - total_tokens={workflowRunningData?.result?.total_tokens} - created_at={workflowRunningData?.result?.created_at} - created_by={(workflowRunningData?.result?.created_by as any)?.name} - steps={workflowRunningData?.result?.total_steps} - exceptionCounts={workflowRunningData?.result?.exceptions_count} - /> - )} - {currentTab === 'DETAIL' && !workflowRunningData?.result && ( - <div className='flex h-full items-center justify-center bg-components-panel-bg'> - <Loading /> - </div> - )} - {currentTab === 'TRACING' && !isShowRetryDetail && ( - <TracingPanel - className='bg-background-section-burn' - list={workflowRunningData?.tracing || []} - onShowIterationDetail={handleShowIterationDetail} - onShowRetryDetail={handleRetryDetail} - /> - )} - {currentTab === 'TRACING' && !workflowRunningData?.tracing?.length && ( - <div className='flex h-full items-center justify-center !bg-background-section-burn'> - <Loading /> - </div> - )} - { - currentTab === 'TRACING' && isShowRetryDetail && ( - <RetryResultPanel - list={retryRunResult} - onBack={doHideRetryDetail} - /> - ) - } - </div> + const content = workflowRunningData?.resultText + if (typeof content === 'string') + copy(content) + else + copy(JSON.stringify(content)) + Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') }) + }}> + <RiClipboardLine className='w-3.5 h-3.5' /> + <div>{t('common.operation.copy')}</div> + </SimpleBtn> + )} </> )} - + {currentTab === 'DETAIL' && ( + <ResultPanel + inputs={workflowRunningData?.result?.inputs} + outputs={workflowRunningData?.result?.outputs} + status={workflowRunningData?.result?.status || ''} + error={workflowRunningData?.result?.error} + elapsed_time={workflowRunningData?.result?.elapsed_time} + total_tokens={workflowRunningData?.result?.total_tokens} + created_at={workflowRunningData?.result?.created_at} + created_by={(workflowRunningData?.result?.created_by as any)?.name} + steps={workflowRunningData?.result?.total_steps} + exceptionCounts={workflowRunningData?.result?.exceptions_count} + /> + )} + {currentTab === 'DETAIL' && !workflowRunningData?.result && ( + <div className='flex h-full items-center justify-center bg-components-panel-bg'> + <Loading /> + </div> + )} + {currentTab === 'TRACING' && ( + <TracingPanel + className='bg-background-section-burn' + list={workflowRunningData?.tracing || []} + /> + )} + {currentTab === 'TRACING' && !workflowRunningData?.tracing?.length && ( + <div className='flex h-full items-center justify-center !bg-background-section-burn'> + <Loading /> + </div> + )} + </div> </div> </div> ) diff --git a/web/app/components/workflow/plugin-dependency/hooks.ts b/web/app/components/workflow/plugin-dependency/hooks.ts new file mode 100644 index 0000000000..1aa52cf028 --- /dev/null +++ b/web/app/components/workflow/plugin-dependency/hooks.ts @@ -0,0 +1,17 @@ +import { useCallback } from 'react' +import { useStore as usePluginDependenciesStore } from './store' +import { useMutationCheckDependencies } from '@/service/use-plugins' + +export const usePluginDependencies = () => { + const { mutateAsync } = useMutationCheckDependencies() + + const handleCheckPluginDependencies = useCallback(async (appId: string) => { + const { leaked_dependencies } = await mutateAsync(appId) + const { setDependencies } = usePluginDependenciesStore.getState() + setDependencies(leaked_dependencies) + }, [mutateAsync]) + + return { + handleCheckPluginDependencies, + } +} diff --git a/web/app/components/workflow/plugin-dependency/index.tsx b/web/app/components/workflow/plugin-dependency/index.tsx new file mode 100644 index 0000000000..185722e1b7 --- /dev/null +++ b/web/app/components/workflow/plugin-dependency/index.tsx @@ -0,0 +1,24 @@ +import { useCallback } from 'react' +import { useStore } from './store' +import InstallBundle from '@/app/components/plugins/install-plugin/install-bundle' + +const PluginDependency = () => { + const dependencies = useStore(s => s.dependencies) + + const handleCancelInstallBundle = useCallback(() => { + const { setDependencies } = useStore.getState() + setDependencies([]) + }, []) + + if (!dependencies.length) + return null + + return ( + <InstallBundle + fromDSLPayload={dependencies} + onClose={handleCancelInstallBundle} + /> + ) +} + +export default PluginDependency diff --git a/web/app/components/workflow/plugin-dependency/store.ts b/web/app/components/workflow/plugin-dependency/store.ts new file mode 100644 index 0000000000..a8e1d8171a --- /dev/null +++ b/web/app/components/workflow/plugin-dependency/store.ts @@ -0,0 +1,11 @@ +import { create } from 'zustand' +import type { Dependency } from '@/app/components/plugins/types' + +type Shape = { + dependencies: Dependency[] + setDependencies: (dependencies: Dependency[]) => void +} +export const useStore = create<Shape>(set => ({ + dependencies: [], + setDependencies: dependencies => set({ dependencies }), +})) diff --git a/web/app/components/workflow/run/agent-log/agent-log-item.tsx b/web/app/components/workflow/run/agent-log/agent-log-item.tsx new file mode 100644 index 0000000000..0b84827500 --- /dev/null +++ b/web/app/components/workflow/run/agent-log/agent-log-item.tsx @@ -0,0 +1,126 @@ +import { + useMemo, + useState, +} from 'react' +import { + RiArrowRightSLine, + RiListView, +} from '@remixicon/react' +import cn from '@/utils/classnames' +import Button from '@/app/components/base/button' +import type { AgentLogItemWithChildren } from '@/types/workflow' +import NodeStatusIcon from '@/app/components/workflow/nodes/_base/components/node-status-icon' +import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' +import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' +import BlockIcon from '@/app/components/workflow/block-icon' +import { BlockEnum } from '@/app/components/workflow/types' +import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' + +type AgentLogItemProps = { + item: AgentLogItemWithChildren + onShowAgentOrToolLog: (detail: AgentLogItemWithChildren) => void +} +const AgentLogItem = ({ + item, + onShowAgentOrToolLog, +}: AgentLogItemProps) => { + const { + label, + status, + children, + data, + metadata, + } = item + const [expanded, setExpanded] = useState(false) + const { getIconUrl } = useGetIcon() + const toolIcon = useMemo(() => { + const icon = metadata?.icon + + if (icon) { + if (icon.includes('http')) + return icon + + return getIconUrl(icon) + } + + return '' + }, [getIconUrl, metadata?.icon]) + + const mergeStatus = useMemo(() => { + if (status === 'start') + return 'running' + + return status + }, [status]) + + return ( + <div className='bg-background-default border-[0.5px] border-components-panel-border rounded-[10px]'> + <div + className={cn( + 'flex items-center pl-1.5 pt-2 pr-3 pb-2 cursor-pointer', + expanded && 'pb-1', + )} + onClick={() => setExpanded(!expanded)} + > + { + expanded + ? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90 text-text-quaternary' /> + : <RiArrowRightSLine className='shrink-0 w-4 h-4 text-text-quaternary' /> + } + <BlockIcon + className='shrink-0 mr-1.5' + type={toolIcon ? BlockEnum.Tool : BlockEnum.Agent} + toolIcon={toolIcon} + /> + <div + className='grow system-sm-semibold-uppercase text-text-secondary truncate' + title={label} + > + {label} + </div> + { + metadata?.elapsed_time && ( + <div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>{metadata?.elapsed_time?.toFixed(3)}s</div> + ) + } + <NodeStatusIcon status={mergeStatus} /> + </div> + { + expanded && ( + <div className='p-1 pt-0'> + { + !!children?.length && ( + <Button + className='flex items-center justify-between mb-1 w-full' + variant='tertiary' + onClick={() => onShowAgentOrToolLog(item)} + > + <div className='flex items-center'> + <RiListView className='mr-1 w-4 h-4 text-components-button-tertiary-text shrink-0' /> + {`${children.length} Action Logs`} + </div> + <div className='flex'> + <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' /> + </div> + </Button> + ) + } + { + data && ( + <CodeEditor + readOnly + title={<div>{'data'.toLocaleUpperCase()}</div>} + language={CodeLanguage.json} + value={data} + isJSONStringifyBeauty + /> + ) + } + </div> + ) + } + </div> + ) +} + +export default AgentLogItem diff --git a/web/app/components/workflow/run/agent-log/agent-log-nav-more.tsx b/web/app/components/workflow/run/agent-log/agent-log-nav-more.tsx new file mode 100644 index 0000000000..f965a86f31 --- /dev/null +++ b/web/app/components/workflow/run/agent-log/agent-log-nav-more.tsx @@ -0,0 +1,61 @@ +import { useState } from 'react' +import { RiMoreLine } from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Button from '@/app/components/base/button' +import type { AgentLogItemWithChildren } from '@/types/workflow' + +type AgentLogNavMoreProps = { + options: { id: string; label: string }[] + onShowAgentOrToolLog: (detail?: AgentLogItemWithChildren) => void +} +const AgentLogNavMore = ({ + options, + onShowAgentOrToolLog, +}: AgentLogNavMoreProps) => { + const [open, setOpen] = useState(false) + + return ( + <PortalToFollowElem + placement='bottom-start' + offset={{ + mainAxis: 2, + crossAxis: -54, + }} + open={open} + onOpenChange={setOpen} + > + <PortalToFollowElemTrigger> + <Button + className='w-6 h-6' + variant='ghost-accent' + > + <RiMoreLine className='w-4 h-4' /> + </Button> + </PortalToFollowElemTrigger> + <PortalToFollowElemContent> + <div className='p-1 w-[136px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl shadow-lg'> + { + options.map(option => ( + <div + key={option.id} + className='flex items-center px-2 h-8 rounded-lg system-md-regular text-text-secondary hover:bg-state-base-hover cursor-pointer' + onClick={() => { + onShowAgentOrToolLog(option as AgentLogItemWithChildren) + setOpen(false) + }} + > + {option.label} + </div> + )) + } + </div> + </PortalToFollowElemContent> + </PortalToFollowElem> + ) +} + +export default AgentLogNavMore diff --git a/web/app/components/workflow/run/agent-log/agent-log-nav.tsx b/web/app/components/workflow/run/agent-log/agent-log-nav.tsx new file mode 100644 index 0000000000..ccfc6da8cf --- /dev/null +++ b/web/app/components/workflow/run/agent-log/agent-log-nav.tsx @@ -0,0 +1,78 @@ +import { RiArrowLeftLine } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import AgentLogNavMore from './agent-log-nav-more' +import Button from '@/app/components/base/button' +import type { AgentLogItemWithChildren } from '@/types/workflow' + +type AgentLogNavProps = { + agentOrToolLogItemStack: AgentLogItemWithChildren[] + onShowAgentOrToolLog: (detail?: AgentLogItemWithChildren) => void +} +const AgentLogNav = ({ + agentOrToolLogItemStack, + onShowAgentOrToolLog, +}: AgentLogNavProps) => { + const { t } = useTranslation() + const agentOrToolLogItemStackLength = agentOrToolLogItemStack.length + const first = agentOrToolLogItemStack[0] + const mid = agentOrToolLogItemStack.slice(1, -1) + const end = agentOrToolLogItemStack.at(-1) + + return ( + <div className='flex items-center p-1 pr-3 h-8 bg-components-panel-bg'> + <Button + className='shrink-0 px-[5px]' + size='small' + variant='ghost-accent' + onClick={() => { + onShowAgentOrToolLog() + }} + > + <RiArrowLeftLine className='mr-1 w-3.5 h-3.5' /> + AGENT + </Button> + <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> + { + agentOrToolLogItemStackLength > 1 + ? ( + <Button + className='shrink-0 px-[5px]' + size='small' + variant='ghost-accent' + onClick={() => onShowAgentOrToolLog(first)} + > + {t('workflow.nodes.agent.strategy.label')} + </Button> + ) + : ( + <div className='flex items-center px-[5px] system-xs-medium-uppercase text-text-tertiary'> + {t('workflow.nodes.agent.strategy.label')} + </div> + ) + } + { + !!mid.length && ( + <> + <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> + <AgentLogNavMore + options={mid} + onShowAgentOrToolLog={onShowAgentOrToolLog} + /> + </> + ) + } + { + !!end && agentOrToolLogItemStackLength > 1 && ( + <> + <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> + <div className='flex items-center px-[5px] system-xs-medium-uppercase text-text-tertiary'> + {end.label} + </div> + </> + ) + } + </div> + ) +} + +export default AgentLogNav diff --git a/web/app/components/workflow/run/agent-log/agent-log-trigger.tsx b/web/app/components/workflow/run/agent-log/agent-log-trigger.tsx new file mode 100644 index 0000000000..86418a1c69 --- /dev/null +++ b/web/app/components/workflow/run/agent-log/agent-log-trigger.tsx @@ -0,0 +1,49 @@ +import { RiArrowRightLine } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import type { + AgentLogItemWithChildren, + NodeTracing, +} from '@/types/workflow' + +type AgentLogTriggerProps = { + nodeInfo: NodeTracing + onShowAgentOrToolLog: (detail?: AgentLogItemWithChildren) => void +} +const AgentLogTrigger = ({ + nodeInfo, + onShowAgentOrToolLog, +}: AgentLogTriggerProps) => { + const { t } = useTranslation() + const { agentLog, execution_metadata } = nodeInfo + const agentStrategy = execution_metadata?.tool_info?.agent_strategy + + return ( + <div + className='bg-components-button-tertiary-bg rounded-[10px] cursor-pointer' + onClick={() => { + onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren) + }} + > + <div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'> + {t('workflow.nodes.agent.strategy.label')} + </div> + <div className='flex items-center pl-3 pt-1 pr-2 pb-1.5'> + { + agentStrategy && ( + <div className='grow system-xs-medium text-text-secondary'> + {agentStrategy} + </div> + ) + } + <div + className='shrink-0 flex items-center px-[1px] system-xs-regular-uppercase text-text-tertiary cursor-pointer' + > + {t('runLog.detail')} + <RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' /> + </div> + </div> + </div> + ) +} + +export default AgentLogTrigger diff --git a/web/app/components/workflow/run/agent-log/agent-result-panel.tsx b/web/app/components/workflow/run/agent-log/agent-result-panel.tsx new file mode 100644 index 0000000000..e2d2b24966 --- /dev/null +++ b/web/app/components/workflow/run/agent-log/agent-result-panel.tsx @@ -0,0 +1,60 @@ +import { RiAlertFill } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import AgentLogItem from './agent-log-item' +import AgentLogNav from './agent-log-nav' +import type { AgentLogItemWithChildren } from '@/types/workflow' + +type AgentResultPanelProps = { + agentOrToolLogItemStack: AgentLogItemWithChildren[] + agentOrToolLogListMap: Record<string, AgentLogItemWithChildren[]> + onShowAgentOrToolLog: (detail?: AgentLogItemWithChildren) => void +} +const AgentResultPanel = ({ + agentOrToolLogItemStack, + agentOrToolLogListMap, + onShowAgentOrToolLog, +}: AgentResultPanelProps) => { + const { t } = useTranslation() + const top = agentOrToolLogItemStack[agentOrToolLogItemStack.length - 1] + const list = agentOrToolLogListMap[top.id] + + return ( + <div className='bg-background-section overflow-y-auto'> + <AgentLogNav + agentOrToolLogItemStack={agentOrToolLogItemStack} + onShowAgentOrToolLog={onShowAgentOrToolLog} + /> + { + <div className='p-2 space-y-1'> + { + list.map(item => ( + <AgentLogItem + key={item.id} + item={item} + onShowAgentOrToolLog={onShowAgentOrToolLog} + /> + )) + } + </div> + } + { + top.hasCircle && ( + <div className='flex items-center mt-1 rounded-xl px-3 pr-2 border border-components-panel-border bg-components-panel-bg-blur shadow-md'> + <div + className='absolute inset-0 opacity-[0.4] rounded-xl' + style={{ + background: 'linear-gradient(92deg, rgba(247, 144, 9, 0.25) 0%, rgba(255, 255, 255, 0.00) 100%)', + }} + ></div> + <RiAlertFill className='mr-1.5 w-4 h-4 text-text-warning-secondary' /> + <div className='system-xs-medium text-text-primary'> + {t('runLog.circularInvocationTip')} + </div> + </div> + ) + } + </div> + ) +} + +export default AgentResultPanel diff --git a/web/app/components/workflow/run/agent-log/index.tsx b/web/app/components/workflow/run/agent-log/index.tsx new file mode 100644 index 0000000000..a39f5416bb --- /dev/null +++ b/web/app/components/workflow/run/agent-log/index.tsx @@ -0,0 +1,2 @@ +export { default as AgentLogTrigger } from './agent-log-trigger' +export { default as AgentResultPanel } from './agent-result-panel' diff --git a/web/app/components/workflow/run/hooks.ts b/web/app/components/workflow/run/hooks.ts new file mode 100644 index 0000000000..55ddc4cbfc --- /dev/null +++ b/web/app/components/workflow/run/hooks.ts @@ -0,0 +1,88 @@ +import { + useCallback, + useRef, + useState, +} from 'react' +import { useBoolean } from 'ahooks' +import type { + AgentLogItemWithChildren, + IterationDurationMap, + NodeTracing, +} from '@/types/workflow' + +export const useLogs = () => { + const [showRetryDetail, { + setTrue: setShowRetryDetailTrue, + setFalse: setShowRetryDetailFalse, + }] = useBoolean(false) + const [retryResultList, setRetryResultList] = useState<NodeTracing[]>([]) + const handleShowRetryResultList = useCallback((detail: NodeTracing[]) => { + setShowRetryDetailTrue() + setRetryResultList(detail) + }, [setShowRetryDetailTrue, setRetryResultList]) + + const [showIteratingDetail, { + setTrue: setShowIteratingDetailTrue, + setFalse: setShowIteratingDetailFalse, + }] = useBoolean(false) + const [iterationResultList, setIterationResultList] = useState<NodeTracing[][]>([]) + const [iterationResultDurationMap, setIterationResultDurationMap] = useState<IterationDurationMap>({}) + const handleShowIterationResultList = useCallback((detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => { + setShowIteratingDetailTrue() + setIterationResultList(detail) + setIterationResultDurationMap(iterDurationMap) + }, [setShowIteratingDetailTrue, setIterationResultList, setIterationResultDurationMap]) + + const [agentOrToolLogItemStack, setAgentOrToolLogItemStack] = useState<AgentLogItemWithChildren[]>([]) + const agentOrToolLogItemStackRef = useRef(agentOrToolLogItemStack) + const [agentOrToolLogListMap, setAgentOrToolLogListMap] = useState<Record<string, AgentLogItemWithChildren[]>>({}) + const agentOrToolLogListMapRef = useRef(agentOrToolLogListMap) + const handleShowAgentOrToolLog = useCallback((detail?: AgentLogItemWithChildren) => { + if (!detail) { + setAgentOrToolLogItemStack([]) + agentOrToolLogItemStackRef.current = [] + return + } + const { id, children } = detail + let currentAgentOrToolLogItemStack = agentOrToolLogItemStackRef.current.slice() + const index = currentAgentOrToolLogItemStack.findIndex(logItem => logItem.id === id) + + if (index > -1) + currentAgentOrToolLogItemStack = currentAgentOrToolLogItemStack.slice(0, index + 1) + else + currentAgentOrToolLogItemStack = [...currentAgentOrToolLogItemStack.slice(), detail] + + setAgentOrToolLogItemStack(currentAgentOrToolLogItemStack) + agentOrToolLogItemStackRef.current = currentAgentOrToolLogItemStack + + if (children) { + setAgentOrToolLogListMap({ + ...agentOrToolLogListMapRef.current, + [id]: children, + }) + } + }, [setAgentOrToolLogItemStack, setAgentOrToolLogListMap]) + + return { + showSpecialResultPanel: showRetryDetail || showIteratingDetail || !!agentOrToolLogItemStack.length, + showRetryDetail, + setShowRetryDetailTrue, + setShowRetryDetailFalse, + retryResultList, + setRetryResultList, + handleShowRetryResultList, + + showIteratingDetail, + setShowIteratingDetailTrue, + setShowIteratingDetailFalse, + iterationResultList, + setIterationResultList, + iterationResultDurationMap, + setIterationResultDurationMap, + handleShowIterationResultList, + + agentOrToolLogItemStack, + agentOrToolLogListMap, + handleShowAgentOrToolLog, + } +} diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx index 8b0319cabe..eaa88d2df8 100644 --- a/web/app/components/workflow/run/index.tsx +++ b/web/app/components/workflow/run/index.tsx @@ -3,21 +3,16 @@ import type { FC } from 'react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' -import { BlockEnum } from '../types' import OutputPanel from './output-panel' import ResultPanel from './result-panel' import TracingPanel from './tracing-panel' -import IterationResultPanel from './iteration-result-panel' -import RetryResultPanel from './retry-result-panel' import cn from '@/utils/classnames' import { ToastContext } from '@/app/components/base/toast' import Loading from '@/app/components/base/loading' import { fetchRunDetail, fetchTracingList } from '@/service/log' -import type { IterationDurationMap, NodeTracing } from '@/types/workflow' +import type { NodeTracing } from '@/types/workflow' import type { WorkflowRunDetailResponse } from '@/models/log' import { useStore as useAppStore } from '@/app/components/app/store' - export type RunProps = { hideResult?: boolean activeTab?: 'RESULT' | 'DETAIL' | 'TRACING' @@ -60,124 +55,12 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe } }, [notify, getResultCallback]) - const formatNodeList = useCallback((list: NodeTracing[]) => { - const allItems = [...list].reverse() - const result: NodeTracing[] = [] - const nodeGroupMap = new Map<string, Map<string, NodeTracing[]>>() - - const processIterationNode = (item: NodeTracing) => { - result.push({ - ...item, - details: [], - }) - } - - const updateParallelModeGroup = (runId: string, item: NodeTracing, iterationNode: NodeTracing) => { - if (!nodeGroupMap.has(iterationNode.node_id)) - nodeGroupMap.set(iterationNode.node_id, new Map()) - - const groupMap = nodeGroupMap.get(iterationNode.node_id)! - - if (!groupMap.has(runId)) { - groupMap.set(runId, [item]) - } - else { - if (item.status === 'retry') { - const retryNode = groupMap.get(runId)!.find(node => node.node_id === item.node_id) - - if (retryNode) { - if (retryNode?.retryDetail) - retryNode.retryDetail.push(item) - else - retryNode.retryDetail = [item] - } - } - else { - groupMap.get(runId)!.push(item) - } - } - - if (item.status === 'failed') { - iterationNode.status = 'failed' - iterationNode.error = item.error - } - - iterationNode.details = Array.from(groupMap.values()) - } - const updateSequentialModeGroup = (index: number, item: NodeTracing, iterationNode: NodeTracing) => { - const { details } = iterationNode - if (details) { - if (!details[index]) { - details[index] = [item] - } - else { - if (item.status === 'retry') { - const retryNode = details[index].find(node => node.node_id === item.node_id) - - if (retryNode) { - if (retryNode?.retryDetail) - retryNode.retryDetail.push(item) - else - retryNode.retryDetail = [item] - } - } - else { - details[index].push(item) - } - } - } - - if (item.status === 'failed') { - iterationNode.status = 'failed' - iterationNode.error = item.error - } - } - const processNonIterationNode = (item: NodeTracing) => { - const { execution_metadata } = item - if (!execution_metadata?.iteration_id) { - if (item.status === 'retry') { - const retryNode = result.find(node => node.node_id === item.node_id) - - if (retryNode) { - if (retryNode?.retryDetail) - retryNode.retryDetail.push(item) - else - retryNode.retryDetail = [item] - } - - return - } - result.push(item) - return - } - - const iterationNode = result.find(node => node.node_id === execution_metadata.iteration_id) - if (!iterationNode || !Array.isArray(iterationNode.details)) - return - - const { parallel_mode_run_id, iteration_index = 0 } = execution_metadata - - if (parallel_mode_run_id) - updateParallelModeGroup(parallel_mode_run_id, item, iterationNode) - else - updateSequentialModeGroup(iteration_index, item, iterationNode) - } - - allItems.forEach((item) => { - item.node_type === BlockEnum.Iteration - ? processIterationNode(item) - : processNonIterationNode(item) - }) - - return result - }, []) - const getTracingList = useCallback(async (appID: string, runID: string) => { try { const { data: nodeList } = await fetchTracingList({ url: `/apps/${appID}/workflow-runs/${runID}/node-executions`, }) - setList(formatNodeList(nodeList)) + setList(nodeList) } catch (err) { notify({ @@ -219,42 +102,6 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe adjustResultHeight() }, [loading]) - const [iterationRunResult, setIterationRunResult] = useState<NodeTracing[][]>([]) - const [iterDurationMap, setIterDurationMap] = useState<IterationDurationMap>({}) - const [retryRunResult, setRetryRunResult] = useState<NodeTracing[]>([]) - const [isShowIterationDetail, { - setTrue: doShowIterationDetail, - setFalse: doHideIterationDetail, - }] = useBoolean(false) - const [isShowRetryDetail, { - setTrue: doShowRetryDetail, - setFalse: doHideRetryDetail, - }] = useBoolean(false) - - const handleShowIterationDetail = useCallback((detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => { - setIterationRunResult(detail) - doShowIterationDetail() - setIterDurationMap(iterDurationMap) - }, [doShowIterationDetail, setIterationRunResult, setIterDurationMap]) - - const handleShowRetryDetail = useCallback((detail: NodeTracing[]) => { - setRetryRunResult(detail) - doShowRetryDetail() - }, [doShowRetryDetail, setRetryRunResult]) - - if (isShowIterationDetail) { - return ( - <div className='grow relative flex flex-col'> - <IterationResultPanel - list={iterationRunResult} - onHide={doHideIterationDetail} - onBack={doHideIterationDetail} - iterDurationMap={iterDurationMap} - /> - </div> - ) - } - return ( <div className='grow relative flex flex-col'> {/* tab */} @@ -284,7 +131,7 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe >{t('runLog.tracing')}</div> </div> {/* panel detail */} - <div ref={ref} className={cn('grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl', currentTab !== 'DETAIL' && '!bg-background-section-burn')}> + <div ref={ref} className={cn('relative grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl')}> {loading && ( <div className='flex h-full items-center justify-center bg-components-panel-bg'> <Loading /> @@ -311,22 +158,12 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe exceptionCounts={runDetail.exceptions_count} /> )} - {!loading && currentTab === 'TRACING' && !isShowRetryDetail && ( + {!loading && currentTab === 'TRACING' && ( <TracingPanel className='bg-background-section-burn' list={list} - onShowIterationDetail={handleShowIterationDetail} - onShowRetryDetail={handleShowRetryDetail} /> )} - { - !loading && currentTab === 'TRACING' && isShowRetryDetail && ( - <RetryResultPanel - list={retryRunResult} - onBack={doHideRetryDetail} - /> - ) - } </div> </div> ) diff --git a/web/app/components/workflow/run/iteration-log/index.tsx b/web/app/components/workflow/run/iteration-log/index.tsx new file mode 100644 index 0000000000..5cbe70fece --- /dev/null +++ b/web/app/components/workflow/run/iteration-log/index.tsx @@ -0,0 +1,2 @@ +export { default as IterationLogTrigger } from './iteration-log-trigger' +export { default as IterationResultPanel } from './iteration-result-panel' diff --git a/web/app/components/workflow/run/iteration-log/iteration-log-trigger.tsx b/web/app/components/workflow/run/iteration-log/iteration-log-trigger.tsx new file mode 100644 index 0000000000..93c6495216 --- /dev/null +++ b/web/app/components/workflow/run/iteration-log/iteration-log-trigger.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from 'react-i18next' +import { RiArrowRightSLine } from '@remixicon/react' +import Button from '@/app/components/base/button' +import type { + IterationDurationMap, + NodeTracing, +} from '@/types/workflow' +import { Iteration } from '@/app/components/base/icons/src/vender/workflow' + +type IterationLogTriggerProps = { + nodeInfo: NodeTracing + onShowIterationResultList: (iterationResultList: NodeTracing[][], iterationResultDurationMap: IterationDurationMap) => void +} +const IterationLogTrigger = ({ + nodeInfo, + onShowIterationResultList, +}: IterationLogTriggerProps) => { + const { t } = useTranslation() + const getErrorCount = (details: NodeTracing[][] | undefined) => { + if (!details || details.length === 0) + return 0 + + return details.reduce((acc, iteration) => { + if (iteration.some(item => item.status === 'failed')) + acc++ + return acc + }, 0) + } + const getCount = (iteration_curr_length: number | undefined, iteration_length: number) => { + if ((iteration_curr_length && iteration_curr_length < iteration_length) || !iteration_length) + return iteration_curr_length + + return iteration_length + } + const handleOnShowIterationDetail = (e: React.MouseEvent<HTMLButtonElement>) => { + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + onShowIterationResultList(nodeInfo.details || [], nodeInfo?.iterDurationMap || nodeInfo.execution_metadata?.iteration_duration_map || {}) + } + return ( + <Button + className='flex items-center w-full self-stretch gap-2 px-3 py-2 bg-components-button-tertiary-bg-hover hover:bg-components-button-tertiary-bg-hover rounded-lg cursor-pointer border-none' + onClick={handleOnShowIterationDetail} + > + <Iteration className='w-4 h-4 text-components-button-tertiary-text shrink-0' /> + <div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && ( + <> + {t('workflow.nodes.iteration.comma')} + {t('workflow.nodes.iteration.error', { count: getErrorCount(nodeInfo.details) })} + </> + )}</div> + <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' /> + </Button> + ) +} + +export default IterationLogTrigger diff --git a/web/app/components/workflow/run/iteration-result-panel.tsx b/web/app/components/workflow/run/iteration-log/iteration-result-panel.tsx similarity index 56% rename from web/app/components/workflow/run/iteration-result-panel.tsx rename to web/app/components/workflow/run/iteration-log/iteration-result-panel.tsx index b809e1e669..19f79feb13 100644 --- a/web/app/components/workflow/run/iteration-result-panel.tsx +++ b/web/app/components/workflow/run/iteration-log/iteration-result-panel.tsx @@ -3,15 +3,13 @@ import type { FC } from 'react' import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { + RiArrowLeftLine, RiArrowRightSLine, - RiCloseLine, RiErrorWarningLine, RiLoader2Line, } from '@remixicon/react' -import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows' -import { NodeRunningStatus } from '../types' -import TracingPanel from './tracing-panel' -import RetryResultPanel from './retry-result-panel' +import { NodeRunningStatus } from '@/app/components/workflow/types' +import TracingPanel from '@/app/components/workflow/run/tracing-panel' import { Iteration } from '@/app/components/base/icons/src/vender/workflow' import cn from '@/utils/classnames' import type { IterationDurationMap, NodeTracing } from '@/types/workflow' @@ -19,17 +17,13 @@ const i18nPrefix = 'workflow.singleRun' type Props = { list: NodeTracing[][] - onHide: () => void onBack: () => void - noWrap?: boolean iterDurationMap?: IterationDurationMap } const IterationResultPanel: FC<Props> = ({ list, - onHide, onBack, - noWrap, iterDurationMap, }) => { const { t } = useTranslation() @@ -75,29 +69,22 @@ const IterationResultPanel: FC<Props> = ({ </> ) } - const [retryRunResult, setRetryRunResult] = useState<Record<string, NodeTracing[]> | undefined>() - const handleRetryDetail = (v: number, detail?: NodeTracing[]) => { - setRetryRunResult({ ...retryRunResult, [v]: detail }) - } - const main = ( - <> - <div className={cn(!noWrap && 'shrink-0 ', 'px-4 pt-3')}> - <div className='shrink-0 flex justify-between items-center h-8'> - <div className='system-xl-semibold text-text-primary truncate'> - {t(`${i18nPrefix}.testRunIteration`)} - </div> - <div className='ml-2 shrink-0 p-1 cursor-pointer' onClick={onHide}> - <RiCloseLine className='w-4 h-4 text-text-tertiary' /> - </div> - </div> - <div className='flex items-center py-2 space-x-1 text-text-accent-secondary cursor-pointer' onClick={onBack}> - <ArrowNarrowLeft className='w-4 h-4' /> - <div className='system-sm-medium'>{t(`${i18nPrefix}.back`)}</div> - </div> + return ( + <div className='bg-components-panel-bg'> + <div + className='flex items-center px-4 h-8 text-text-accent-secondary cursor-pointer border-b-[0.5px] border-b-divider-regular' + onClick={(e) => { + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + onBack() + }} + > + <RiArrowLeftLine className='mr-1 w-4 h-4' /> + <div className='system-sm-medium'>{t(`${i18nPrefix}.back`)}</div> </div> {/* List */} - <div className={cn(!noWrap ? 'flex-grow overflow-auto' : 'max-h-full', 'p-2 bg-components-panel-bg')}> + <div className='p-2 bg-components-panel-bg'> {list.map((iteration, index) => ( <div key={index} className={cn('mb-1 overflow-hidden rounded-xl bg-background-section-burn border-none')}> <div @@ -109,66 +96,31 @@ const IterationResultPanel: FC<Props> = ({ onClick={() => toggleIteration(index)} > <div className={cn('flex items-center gap-2 flex-grow')}> - <div className='flex items-center justify-center w-4 h-4 rounded-[5px] border-divider-subtle bg-util-colors-cyan-cyan-500 flex-shrink-0'> + <div className='flex items-center justify-center w-4 h-4 rounded-[5px] border-divider-subtle bg-util-colors-cyan-cyan-500 shrink-0'> <Iteration className='w-3 h-3 text-text-primary-on-surface' /> </div> - <span className='system-sm-semibold-uppercase text-text-primary flex-grow'> + <span className='system-sm-semibold-uppercase text-text-primary grow'> {t(`${i18nPrefix}.iteration`)} {index + 1} </span> {iterationStatusShow(index, iteration, iterDurationMap)} </div> </div> {expandedIterations[index] && <div - className="flex-grow h-px bg-divider-subtle" + className="grow h-px bg-divider-subtle" ></div>} - { - !retryRunResult?.[index] && ( - <div className={cn( - 'overflow-hidden transition-all duration-200', - expandedIterations[index] ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0', - )}> - <TracingPanel - list={iteration} - className='bg-background-section-burn' - onShowRetryDetail={v => handleRetryDetail(index, v)} - /> - </div> - ) - } - { - retryRunResult?.[index] && ( - <RetryResultPanel - list={retryRunResult[index]} - onBack={() => handleRetryDetail(index, undefined)} - /> - ) - } + <div className={cn( + 'overflow-hidden transition-all duration-200', + expandedIterations[index] ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0', + )}> + <TracingPanel + list={iteration} + className='bg-background-section-burn' + /> + </div> </div> ))} </div> - </> - ) - const handleNotBubble = useCallback((e: React.MouseEvent) => { - // if not do this, it will trigger the message log modal disappear(useClickAway) - e.stopPropagation() - e.nativeEvent.stopImmediatePropagation() - }, []) - - if (noWrap) - return main - - return ( - <div - className='absolute inset-0 z-10 rounded-2xl pt-10' - style={{ - backgroundColor: 'rgba(16, 24, 40, 0.20)', - }} - onClick={handleNotBubble} - > - <div className='h-full rounded-2xl bg-components-panel-bg flex flex-col'> - {main} - </div> - </div > + </div> ) } export default React.memo(IterationResultPanel) diff --git a/web/app/components/workflow/run/node.tsx b/web/app/components/workflow/run/node.tsx index d2da319a02..33ed05e891 100644 --- a/web/app/components/workflow/run/node.tsx +++ b/web/app/components/workflow/run/node.tsx @@ -8,18 +8,21 @@ import { RiCheckboxCircleFill, RiErrorWarningLine, RiLoader2Line, - RiRestartFill, } from '@remixicon/react' import BlockIcon from '../block-icon' import { BlockEnum } from '../types' -import Split from '../nodes/_base/components/split' -import { Iteration } from '@/app/components/base/icons/src/vender/workflow' +import { RetryLogTrigger } from './retry-log' +import { IterationLogTrigger } from './iteration-log' +import { AgentLogTrigger } from './agent-log' import cn from '@/utils/classnames' import StatusContainer from '@/app/components/workflow/run/status-container' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' -import Button from '@/app/components/base/button' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' -import type { IterationDurationMap, NodeTracing } from '@/types/workflow' +import type { + AgentLogItemWithChildren, + IterationDurationMap, + NodeTracing, +} from '@/types/workflow' import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip' import { hasRetryNode } from '@/app/components/workflow/utils' @@ -31,9 +34,8 @@ type Props = { hideProcessDetail?: boolean onShowIterationDetail?: (detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => void onShowRetryDetail?: (detail: NodeTracing[]) => void + onShowAgentOrToolLog?: (detail?: AgentLogItemWithChildren) => void notShowIterationNav?: boolean - justShowIterationNavArrow?: boolean - justShowRetryNavArrow?: boolean } const NodePanel: FC<Props> = ({ @@ -44,8 +46,8 @@ const NodePanel: FC<Props> = ({ hideProcessDetail, onShowIterationDetail, onShowRetryDetail, + onShowAgentOrToolLog, notShowIterationNav, - justShowIterationNavArrow, }) => { const [collapseState, doSetCollapseState] = useState<boolean>(true) const setCollapseState = useCallback((state: boolean) => { @@ -59,7 +61,7 @@ const NodePanel: FC<Props> = ({ if (time < 1) return `${(time * 1000).toFixed(3)} ms` if (time > 60) - return `${parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s` + return `${Number.parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s` return `${time.toFixed(3)} s` } @@ -67,43 +69,20 @@ const NodePanel: FC<Props> = ({ if (tokens < 1000) return tokens if (tokens >= 1000 && tokens < 1000000) - return `${parseFloat((tokens / 1000).toFixed(3))}K` + return `${Number.parseFloat((tokens / 1000).toFixed(3))}K` if (tokens >= 1000000) - return `${parseFloat((tokens / 1000000).toFixed(3))}M` + return `${Number.parseFloat((tokens / 1000000).toFixed(3))}M` } - const getCount = (iteration_curr_length: number | undefined, iteration_length: number) => { - if ((iteration_curr_length && iteration_curr_length < iteration_length) || !iteration_length) - return iteration_curr_length - - return iteration_length - } - const getErrorCount = (details: NodeTracing[][] | undefined) => { - if (!details || details.length === 0) - return 0 - - return details.reduce((acc, iteration) => { - if (iteration.some(item => item.status === 'failed')) - acc++ - return acc - }, 0) - } useEffect(() => { setCollapseState(!nodeInfo.expand) }, [nodeInfo.expand, setCollapseState]) - const isIterationNode = nodeInfo.node_type === BlockEnum.Iteration - const isRetryNode = hasRetryNode(nodeInfo.node_type) && nodeInfo.retryDetail - const handleOnShowIterationDetail = (e: React.MouseEvent<HTMLButtonElement>) => { - e.stopPropagation() - e.nativeEvent.stopImmediatePropagation() - onShowIterationDetail?.(nodeInfo.details || [], nodeInfo?.iterDurationMap || nodeInfo.execution_metadata?.iteration_duration_map || {}) - } - const handleOnShowRetryDetail = (e: React.MouseEvent<HTMLButtonElement>) => { - e.stopPropagation() - e.nativeEvent.stopImmediatePropagation() - onShowRetryDetail?.(nodeInfo.retryDetail || []) - } + const isIterationNode = nodeInfo.node_type === BlockEnum.Iteration && !!nodeInfo.details?.length + const isRetryNode = hasRetryNode(nodeInfo.node_type) && !!nodeInfo.retryDetail?.length + const isAgentNode = nodeInfo.node_type === BlockEnum.Agent && !!nodeInfo.agentLog?.length + const isToolNode = nodeInfo.node_type === BlockEnum.Tool && !!nodeInfo.agentLog?.length + return ( <div className={cn('px-2 py-1', className)}> <div className='group transition-all bg-background-default border border-components-panel-border rounded-[10px] shadow-xs hover:shadow-md'> @@ -153,46 +132,26 @@ const NodePanel: FC<Props> = ({ {!collapseState && !hideProcessDetail && ( <div className='px-1 pb-1'> {/* The nav to the iteration detail */} - {isIterationNode && !notShowIterationNav && ( - <div className='mt-2 mb-1 !px-2'> - <Button - className='flex items-center w-full self-stretch gap-2 px-3 py-2 bg-components-button-tertiary-bg-hover hover:bg-components-button-tertiary-bg-hover rounded-lg cursor-pointer border-none' - onClick={handleOnShowIterationDetail} - > - <Iteration className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - <div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && ( - <> - {t('workflow.nodes.iteration.comma')} - {t('workflow.nodes.iteration.error', { count: getErrorCount(nodeInfo.details) })} - </> - )}</div> - {justShowIterationNavArrow - ? ( - <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - ) - : ( - <div className='flex items-center space-x-1 text-[#155EEF]'> - <div className='text-[13px] font-normal '>{t('workflow.common.viewDetailInTracingPanel')}</div> - <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - </div> - )} - </Button> - <Split className='mt-2' /> - </div> + {isIterationNode && !notShowIterationNav && onShowIterationDetail && ( + <IterationLogTrigger + nodeInfo={nodeInfo} + onShowIterationResultList={onShowIterationDetail} + /> )} - {isRetryNode && ( - <Button - className='flex items-center justify-between mb-1 w-full' - variant='tertiary' - onClick={handleOnShowRetryDetail} - > - <div className='flex items-center'> - <RiRestartFill className='mr-0.5 w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - {t('workflow.nodes.common.retry.retries', { num: nodeInfo.retryDetail?.length })} - </div> - <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - </Button> + {isRetryNode && onShowRetryDetail && ( + <RetryLogTrigger + nodeInfo={nodeInfo} + onShowRetryResultList={onShowRetryDetail} + /> )} + { + (isAgentNode || isToolNode) && onShowAgentOrToolLog && ( + <AgentLogTrigger + nodeInfo={nodeInfo} + onShowAgentOrToolLog={onShowAgentOrToolLog} + /> + ) + } <div className={cn('mb-1', hideInfo && '!px-2 !py-0.5')}> {(nodeInfo.status === 'stopped') && ( <StatusContainer status='stopped'> diff --git a/web/app/components/workflow/run/output-panel.tsx b/web/app/components/workflow/run/output-panel.tsx index a1667d9b45..6a2a359483 100644 --- a/web/app/components/workflow/run/output-panel.tsx +++ b/web/app/components/workflow/run/output-panel.tsx @@ -47,7 +47,7 @@ const OutputPanel: FC<OutputPanelProps> = ({ return getProcessedFilesFromResponse(fileList) }, [outputs]) return ( - <div className='py-2'> + <div className='p-2'> {isRunning && ( <div className='pt-4 pl-[26px]'> <LoadingAnim type='text' /> diff --git a/web/app/components/workflow/run/result-panel.tsx b/web/app/components/workflow/run/result-panel.tsx index bbe740ad48..b05e5cb888 100644 --- a/web/app/components/workflow/run/result-panel.tsx +++ b/web/app/components/workflow/run/result-panel.tsx @@ -1,19 +1,23 @@ 'use client' import type { FC } from 'react' import { useTranslation } from 'react-i18next' -import { - RiArrowRightSLine, - RiRestartFill, -} from '@remixicon/react' import StatusPanel from './status' import MetaData from './meta' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip' -import type { NodeTracing } from '@/types/workflow' -import Button from '@/app/components/base/button' +import type { + AgentLogItemWithChildren, + NodeTracing, +} from '@/types/workflow' +import { BlockEnum } from '@/app/components/workflow/types' +import { hasRetryNode } from '@/app/components/workflow/utils' +import { IterationLogTrigger } from '@/app/components/workflow/run/iteration-log' +import { RetryLogTrigger } from '@/app/components/workflow/run/retry-log' +import { AgentLogTrigger } from '@/app/components/workflow/run/agent-log' type ResultPanelProps = { + nodeInfo?: NodeTracing inputs?: string process_data?: string outputs?: string @@ -28,11 +32,13 @@ type ResultPanelProps = { showSteps?: boolean exceptionCounts?: number execution_metadata?: any - retry_events?: NodeTracing[] - onShowRetryDetail?: (retries: NodeTracing[]) => void + handleShowIterationResultList?: (detail: NodeTracing[][], iterDurationMap: any) => void + onShowRetryDetail?: (detail: NodeTracing[]) => void + handleShowAgentOrToolLog?: (detail?: AgentLogItemWithChildren) => void } const ResultPanel: FC<ResultPanelProps> = ({ + nodeInfo, inputs, process_data, outputs, @@ -46,10 +52,15 @@ const ResultPanel: FC<ResultPanelProps> = ({ showSteps, exceptionCounts, execution_metadata, - retry_events, + handleShowIterationResultList, onShowRetryDetail, + handleShowAgentOrToolLog, }) => { const { t } = useTranslation() + const isIterationNode = nodeInfo?.node_type === BlockEnum.Iteration && !!nodeInfo?.details?.length + const isRetryNode = hasRetryNode(nodeInfo?.node_type) && !!nodeInfo?.retryDetail?.length + const isAgentNode = nodeInfo?.node_type === BlockEnum.Agent && !!nodeInfo?.agentLog?.length + const isToolNode = nodeInfo?.node_type === BlockEnum.Tool && !!nodeInfo?.agentLog?.length return ( <div className='bg-components-panel-bg py-2'> @@ -62,23 +73,32 @@ const ResultPanel: FC<ResultPanelProps> = ({ exceptionCounts={exceptionCounts} /> </div> - { - retry_events?.length && onShowRetryDetail && ( - <div className='px-4'> - <Button - className='flex items-center justify-between w-full' - variant='tertiary' - onClick={() => onShowRetryDetail(retry_events)} - > - <div className='flex items-center'> - <RiRestartFill className='mr-0.5 w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - {t('workflow.nodes.common.retry.retries', { num: retry_events?.length })} - </div> - <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text flex-shrink-0' /> - </Button> - </div> - ) - } + <div className='px-4'> + { + isIterationNode && handleShowIterationResultList && ( + <IterationLogTrigger + nodeInfo={nodeInfo} + onShowIterationResultList={handleShowIterationResultList} + /> + ) + } + { + isRetryNode && onShowRetryDetail && ( + <RetryLogTrigger + nodeInfo={nodeInfo} + onShowRetryResultList={onShowRetryDetail} + /> + ) + } + { + (isAgentNode || isToolNode) && handleShowAgentOrToolLog && ( + <AgentLogTrigger + nodeInfo={nodeInfo} + onShowAgentOrToolLog={handleShowAgentOrToolLog} + /> + ) + } + </div> <div className='px-4 py-2 flex flex-col gap-2'> <CodeEditor readOnly diff --git a/web/app/components/workflow/run/result-text.tsx b/web/app/components/workflow/run/result-text.tsx index 27b1f2cd8c..9183226b60 100644 --- a/web/app/components/workflow/run/result-text.tsx +++ b/web/app/components/workflow/run/result-text.tsx @@ -7,7 +7,7 @@ import LoadingAnim from '@/app/components/base/chat/chat/loading-anim' import StatusContainer from '@/app/components/workflow/run/status-container' import { FileList } from '@/app/components/base/file-uploader' -type ResultTextProps = { +interface ResultTextProps { isRunning?: boolean outputs?: any error?: string diff --git a/web/app/components/workflow/run/retry-log/index.tsx b/web/app/components/workflow/run/retry-log/index.tsx new file mode 100644 index 0000000000..ee83f1a151 --- /dev/null +++ b/web/app/components/workflow/run/retry-log/index.tsx @@ -0,0 +1,2 @@ +export { default as RetryLogTrigger } from './retry-log-trigger' +export { default as RetryResultPanel } from './retry-result-panel' diff --git a/web/app/components/workflow/run/retry-log/retry-log-trigger.tsx b/web/app/components/workflow/run/retry-log/retry-log-trigger.tsx new file mode 100644 index 0000000000..9c4a987c42 --- /dev/null +++ b/web/app/components/workflow/run/retry-log/retry-log-trigger.tsx @@ -0,0 +1,41 @@ +import { useTranslation } from 'react-i18next' +import { + RiArrowRightSLine, + RiRestartFill, +} from '@remixicon/react' +import Button from '@/app/components/base/button' +import type { NodeTracing } from '@/types/workflow' + +type RetryLogTriggerProps = { + nodeInfo: NodeTracing + onShowRetryResultList: (detail: NodeTracing[]) => void +} +const RetryLogTrigger = ({ + nodeInfo, + onShowRetryResultList, +}: RetryLogTriggerProps) => { + const { t } = useTranslation() + const { retryDetail } = nodeInfo + + const handleShowRetryResultList = (e: React.MouseEvent<HTMLButtonElement>) => { + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + onShowRetryResultList(retryDetail || []) + } + + return ( + <Button + className='flex items-center justify-between mb-1 w-full' + variant='tertiary' + onClick={handleShowRetryResultList} + > + <div className='flex items-center'> + <RiRestartFill className='mr-0.5 w-4 h-4 text-components-button-tertiary-text shrink-0' /> + {t('workflow.nodes.common.retry.retries', { num: retryDetail?.length })} + </div> + <RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' /> + </Button> + ) +} + +export default RetryLogTrigger diff --git a/web/app/components/workflow/run/retry-result-panel.tsx b/web/app/components/workflow/run/retry-log/retry-result-panel.tsx similarity index 96% rename from web/app/components/workflow/run/retry-result-panel.tsx rename to web/app/components/workflow/run/retry-log/retry-result-panel.tsx index 3b177b1623..a8d171a4fc 100644 --- a/web/app/components/workflow/run/retry-result-panel.tsx +++ b/web/app/components/workflow/run/retry-log/retry-result-panel.tsx @@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next' import { RiArrowLeftLine, } from '@remixicon/react' -import TracingPanel from './tracing-panel' +import TracingPanel from '../tracing-panel' import type { NodeTracing } from '@/types/workflow' type Props = { diff --git a/web/app/components/workflow/run/special-result-panel.tsx b/web/app/components/workflow/run/special-result-panel.tsx new file mode 100644 index 0000000000..cdd77894f5 --- /dev/null +++ b/web/app/components/workflow/run/special-result-panel.tsx @@ -0,0 +1,73 @@ +import { RetryResultPanel } from './retry-log' +import { IterationResultPanel } from './iteration-log' +import { AgentResultPanel } from './agent-log' +import type { + AgentLogItemWithChildren, + IterationDurationMap, + NodeTracing, +} from '@/types/workflow' + +export type SpecialResultPanelProps = { + showRetryDetail?: boolean + setShowRetryDetailFalse?: () => void + retryResultList?: NodeTracing[] + + showIteratingDetail?: boolean + setShowIteratingDetailFalse?: () => void + iterationResultList?: NodeTracing[][] + iterationResultDurationMap?: IterationDurationMap + + agentOrToolLogItemStack?: AgentLogItemWithChildren[] + agentOrToolLogListMap?: Record<string, AgentLogItemWithChildren[]> + handleShowAgentOrToolLog?: (detail?: AgentLogItemWithChildren) => void +} +const SpecialResultPanel = ({ + showRetryDetail, + setShowRetryDetailFalse, + retryResultList, + + showIteratingDetail, + setShowIteratingDetailFalse, + iterationResultList, + iterationResultDurationMap, + + agentOrToolLogItemStack, + agentOrToolLogListMap, + handleShowAgentOrToolLog, +}: SpecialResultPanelProps) => { + return ( + <div onClick={(e) => { + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + }}> + { + !!showRetryDetail && !!retryResultList?.length && setShowRetryDetailFalse && ( + <RetryResultPanel + list={retryResultList} + onBack={setShowRetryDetailFalse} + /> + ) + } + { + showIteratingDetail && !!iterationResultList?.length && setShowIteratingDetailFalse && ( + <IterationResultPanel + list={iterationResultList} + onBack={setShowIteratingDetailFalse} + iterDurationMap={iterationResultDurationMap} + /> + ) + } + { + !!agentOrToolLogItemStack?.length && agentOrToolLogListMap && handleShowAgentOrToolLog && ( + <AgentResultPanel + agentOrToolLogItemStack={agentOrToolLogItemStack} + agentOrToolLogListMap={agentOrToolLogListMap} + onShowAgentOrToolLog={handleShowAgentOrToolLog} + /> + ) + } + </div> + ) +} + +export default SpecialResultPanel diff --git a/web/app/components/workflow/run/status.tsx b/web/app/components/workflow/run/status.tsx index ef67cb5467..26fc053446 100644 --- a/web/app/components/workflow/run/status.tsx +++ b/web/app/components/workflow/run/status.tsx @@ -5,7 +5,7 @@ import cn from '@/utils/classnames' import Indicator from '@/app/components/header/indicator' import StatusContainer from '@/app/components/workflow/run/status-container' -type ResultProps = { +interface ResultProps { status: string time?: number tokens?: number diff --git a/web/app/components/workflow/run/tracing-panel.tsx b/web/app/components/workflow/run/tracing-panel.tsx index ad78971895..7739c8f836 100644 --- a/web/app/components/workflow/run/tracing-panel.tsx +++ b/web/app/components/workflow/run/tracing-panel.tsx @@ -12,162 +12,27 @@ import { RiMenu4Line, } from '@remixicon/react' import { useTranslation } from 'react-i18next' +import { useLogs } from './hooks' import NodePanel from './node' -import { - BlockEnum, -} from '@/app/components/workflow/types' -import type { IterationDurationMap, NodeTracing } from '@/types/workflow' +import SpecialResultPanel from './special-result-panel' +import type { NodeTracing } from '@/types/workflow' +import formatNodeList from '@/app/components/workflow/run/utils/format-log' type TracingPanelProps = { list: NodeTracing[] - onShowIterationDetail?: (detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => void - onShowRetryDetail?: (detail: NodeTracing[]) => void className?: string hideNodeInfo?: boolean hideNodeProcessDetail?: boolean } -type TracingNodeProps = { - id: string - uniqueId: string - isParallel: boolean - data: NodeTracing | null - children: TracingNodeProps[] - parallelTitle?: string - branchTitle?: string - hideNodeInfo?: boolean - hideNodeProcessDetail?: boolean -} - -function buildLogTree(nodes: NodeTracing[], t: (key: string) => string): TracingNodeProps[] { - const rootNodes: TracingNodeProps[] = [] - const parallelStacks: { [key: string]: TracingNodeProps } = {} - const levelCounts: { [key: string]: number } = {} - const parallelChildCounts: { [key: string]: Set<string> } = {} - let uniqueIdCounter = 0 - const getUniqueId = () => { - uniqueIdCounter++ - return `unique-${uniqueIdCounter}` - } - - const getParallelTitle = (parentId: string | null): string => { - const levelKey = parentId || 'root' - if (!levelCounts[levelKey]) - levelCounts[levelKey] = 0 - - levelCounts[levelKey]++ - - const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : '' - const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1 - const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : '' - return `${t('workflow.common.parallel')}-${levelNumber}${letter}` - } - - const getBranchTitle = (parentId: string | null, branchNum: number): string => { - const levelKey = parentId || 'root' - const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : '' - const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1 - const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : '' - const branchLetter = String.fromCharCode(64 + branchNum) - return `${t('workflow.common.branch')}-${levelNumber}${letter}-${branchLetter}` - } - - // Count parallel children (for figuring out if we need to use letters) - for (const node of nodes) { - const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null - const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null - - if (parallel_id) { - const parentKey = parent_parallel_id || 'root' - if (!parallelChildCounts[parentKey]) - parallelChildCounts[parentKey] = new Set() - - parallelChildCounts[parentKey].add(parallel_id) - } - } - - for (const node of nodes) { - const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null - const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null - const parallel_start_node_id = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null - const parent_parallel_start_node_id = node.parent_parallel_start_node_id ?? node.execution_metadata?.parent_parallel_start_node_id ?? null - - if (!parallel_id || node.node_type === BlockEnum.End) { - rootNodes.push({ - id: node.id, - uniqueId: getUniqueId(), - isParallel: false, - data: node, - children: [], - }) - } - else { - if (!parallelStacks[parallel_id]) { - const newParallelGroup: TracingNodeProps = { - id: parallel_id, - uniqueId: getUniqueId(), - isParallel: true, - data: null, - children: [], - parallelTitle: '', - } - parallelStacks[parallel_id] = newParallelGroup - - if (parent_parallel_id && parallelStacks[parent_parallel_id]) { - const sameBranchIndex = parallelStacks[parent_parallel_id].children.findLastIndex(c => - c.data?.execution_metadata?.parallel_start_node_id === parent_parallel_start_node_id || c.data?.parallel_start_node_id === parent_parallel_start_node_id, - ) - parallelStacks[parent_parallel_id].children.splice(sameBranchIndex + 1, 0, newParallelGroup) - newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id) - } - else { - newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id) - rootNodes.push(newParallelGroup) - } - } - const branchTitle = parallel_start_node_id === node.node_id ? getBranchTitle(parent_parallel_id, parallelStacks[parallel_id].children.length + 1) : '' - if (branchTitle) { - parallelStacks[parallel_id].children.push({ - id: node.id, - uniqueId: getUniqueId(), - isParallel: false, - data: node, - children: [], - branchTitle, - }) - } - else { - let sameBranchIndex = parallelStacks[parallel_id].children.findLastIndex(c => - c.data?.execution_metadata?.parallel_start_node_id === parallel_start_node_id || c.data?.parallel_start_node_id === parallel_start_node_id, - ) - if (parallelStacks[parallel_id].children[sameBranchIndex + 1]?.isParallel) - sameBranchIndex++ - - parallelStacks[parallel_id].children.splice(sameBranchIndex + 1, 0, { - id: node.id, - uniqueId: getUniqueId(), - isParallel: false, - data: node, - children: [], - branchTitle, - }) - } - } - } - - return rootNodes -} - const TracingPanel: FC<TracingPanelProps> = ({ list, - onShowIterationDetail, - onShowRetryDetail, className, hideNodeInfo = false, hideNodeProcessDetail = false, }) => { const { t } = useTranslation() - const treeNodes = buildLogTree(list, t) + const treeNodes = formatNodeList(list, t) const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(new Set()) const [hoveredParallel, setHoveredParallel] = useState<string | null>(null) @@ -203,13 +68,34 @@ const TracingPanel: FC<TracingPanelProps> = ({ } }, []) - const renderNode = (node: TracingNodeProps) => { - if (node.isParallel) { + const { + showSpecialResultPanel, + + showRetryDetail, + setShowRetryDetailFalse, + retryResultList, + handleShowRetryResultList, + + showIteratingDetail, + setShowIteratingDetailFalse, + iterationResultList, + iterationResultDurationMap, + handleShowIterationResultList, + + agentOrToolLogItemStack, + agentOrToolLogListMap, + handleShowAgentOrToolLog, + } = useLogs() + + const renderNode = (node: NodeTracing) => { + const isParallelFirstNode = !!node.parallelDetail?.isParallelStartNode + if (isParallelFirstNode) { + const parallelDetail = node.parallelDetail! const isCollapsed = collapsedNodes.has(node.id) const isHovered = hoveredParallel === node.id return ( <div - key={node.uniqueId} + key={node.id} className="ml-4 mb-2 relative" data-parallel-id={node.id} onMouseEnter={() => handleParallelMouseEnter(node.id)} @@ -226,10 +112,10 @@ const TracingPanel: FC<TracingPanelProps> = ({ {isHovered ? <RiArrowDownSLine className="w-3 h-3" /> : <RiMenu4Line className="w-3 h-3 text-text-tertiary" />} </button> <div className="system-xs-semibold-uppercase text-text-secondary flex items-center"> - <span>{node.parallelTitle}</span> + <span>{parallelDetail.parallelTitle}</span> </div> <div - className="mx-2 flex-grow h-px bg-divider-subtle" + className="mx-2 grow h-px bg-divider-subtle" style={{ background: 'linear-gradient(to right, rgba(16, 24, 40, 0.08), rgba(255, 255, 255, 0)' }} ></div> </div> @@ -238,7 +124,7 @@ const TracingPanel: FC<TracingPanelProps> = ({ 'absolute top-0 bottom-0 left-[5px] w-[2px]', isHovered ? 'bg-text-accent-secondary' : 'bg-divider-subtle', )}></div> - {node.children.map(renderNode)} + {parallelDetail.children!.map(renderNode)} </div> </div> ) @@ -246,16 +132,15 @@ const TracingPanel: FC<TracingPanelProps> = ({ else { const isHovered = hoveredParallel === node.id return ( - <div key={node.uniqueId}> + <div key={node.id}> <div className={cn('pl-4 -mb-1.5 system-2xs-medium-uppercase', isHovered ? 'text-text-tertiary' : 'text-text-quaternary')}> - {node.branchTitle} + {node?.parallelDetail?.branchTitle} </div> <NodePanel - nodeInfo={node.data!} - onShowIterationDetail={onShowIterationDetail} - onShowRetryDetail={onShowRetryDetail} - justShowIterationNavArrow={true} - justShowRetryNavArrow={true} + nodeInfo={node!} + onShowIterationDetail={handleShowIterationResultList} + onShowRetryDetail={handleShowRetryResultList} + onShowAgentOrToolLog={handleShowAgentOrToolLog} hideInfo={hideNodeInfo} hideProcessDetail={hideNodeProcessDetail} /> @@ -264,8 +149,33 @@ const TracingPanel: FC<TracingPanelProps> = ({ } } + if (showSpecialResultPanel) { + return ( + <SpecialResultPanel + showRetryDetail={showRetryDetail} + setShowRetryDetailFalse={setShowRetryDetailFalse} + retryResultList={retryResultList} + + showIteratingDetail={showIteratingDetail} + setShowIteratingDetailFalse={setShowIteratingDetailFalse} + iterationResultList={iterationResultList} + iterationResultDurationMap={iterationResultDurationMap} + + agentOrToolLogItemStack={agentOrToolLogItemStack} + agentOrToolLogListMap={agentOrToolLogListMap} + handleShowAgentOrToolLog={handleShowAgentOrToolLog} + /> + ) + } + return ( - <div className={cn(className || 'bg-components-panel-bg', 'py-2')}> + <div + className={cn(className || 'bg-components-panel-bg', 'py-2')} + onClick={(e) => { + e.stopPropagation() + e.nativeEvent.stopImmediatePropagation() + }} + > {treeNodes.map(renderNode)} </div> ) diff --git a/web/app/components/workflow/run/utils/format-log/agent/data.ts b/web/app/components/workflow/run/utils/format-log/agent/data.ts new file mode 100644 index 0000000000..a1e06bf63b --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/agent/data.ts @@ -0,0 +1,182 @@ +import { BlockEnum } from '@/app/components/workflow/types' + +export const agentNodeData = (() => { + const node = { + node_type: BlockEnum.Agent, + execution_metadata: { + agent_log: [ + { id: '1', label: 'Root 1' }, + { id: '2', parent_id: '1', label: 'Child 1.2' }, + { id: '3', parent_id: '1', label: 'Child 1.3' }, + { id: '4', parent_id: '2', label: 'Child 2.4' }, + { id: '5', parent_id: '2', label: 'Child 2.5' }, + { id: '6', parent_id: '3', label: 'Child 3.6' }, + { id: '7', parent_id: '4', label: 'Child 4.7' }, + { id: '8', parent_id: '4', label: 'Child 4.8' }, + { id: '9', parent_id: '5', label: 'Child 5.9' }, + { id: '10', parent_id: '5', label: 'Child 5.10' }, + { id: '11', parent_id: '7', label: 'Child 7.11' }, + { id: '12', parent_id: '7', label: 'Child 7.12' }, + { id: '13', parent_id: '9', label: 'Child 9.13' }, + { id: '14', parent_id: '9', label: 'Child 9.14' }, + { id: '15', parent_id: '9', label: 'Child 9.15' }, + ], + }, + } + + return { + in: [node], + expect: [{ + ...node, + agentLog: [ + { + id: '1', + label: 'Root 1', + children: [ + { + id: '2', + parent_id: '1', + label: 'Child 1.2', + children: [ + { + id: '4', + parent_id: '2', + label: 'Child 2.4', + children: [ + { + id: '7', + parent_id: '4', + label: 'Child 4.7', + children: [ + { id: '11', parent_id: '7', label: 'Child 7.11' }, + { id: '12', parent_id: '7', label: 'Child 7.12' }, + ], + }, + { id: '8', parent_id: '4', label: 'Child 4.8' }, + ], + }, + { + id: '5', + parent_id: '2', + label: 'Child 2.5', + children: [ + { + id: '9', + parent_id: '5', + label: 'Child 5.9', + children: [ + { id: '13', parent_id: '9', label: 'Child 9.13' }, + { id: '14', parent_id: '9', label: 'Child 9.14' }, + { id: '15', parent_id: '9', label: 'Child 9.15' }, + ], + }, + { id: '10', parent_id: '5', label: 'Child 5.10' }, + ], + }, + ], + }, + { + id: '3', + parent_id: '1', + label: 'Child 1.3', + children: [ + { id: '6', parent_id: '3', label: 'Child 3.6' }, + ], + }, + ], + }, + ], + }], + } +})() + +export const oneStepCircle = (() => { + const node = { + node_type: BlockEnum.Agent, + execution_metadata: { + agent_log: [ + { id: '1', label: 'Node 1' }, + { id: '1', parent_id: '1', label: 'Node 1' }, + { id: '1', parent_id: '1', label: 'Node 1' }, + { id: '1', parent_id: '1', label: 'Node 1' }, + { id: '1', parent_id: '1', label: 'Node 1' }, + { id: '1', parent_id: '1', label: 'Node 1' }, + ], + }, + } + + return { + in: [node], + expect: [{ + ...node, + agentLog: [ + { + id: '1', + label: 'Node 1', + hasCircle: true, + children: [], + }, + ], + }], + } +})() + +export const multiStepsCircle = (() => { + const node = { + node_type: BlockEnum.Agent, + execution_metadata: { + agent_log: [ + // 1 -> [2 -> 4 -> 1, 3] + { id: '1', label: 'Node 1' }, + { id: '2', parent_id: '1', label: 'Node 2' }, + { id: '3', parent_id: '1', label: 'Node 3' }, + { id: '4', parent_id: '2', label: 'Node 4' }, + + // Loop + { id: '1', parent_id: '4', label: 'Node 1' }, + { id: '2', parent_id: '1', label: 'Node 2' }, + { id: '4', parent_id: '2', label: 'Node 4' }, + { id: '1', parent_id: '4', label: 'Node 1' }, + { id: '2', parent_id: '1', label: 'Node 2' }, + { id: '4', parent_id: '2', label: 'Node 4' }, + ], + }, + } + // 1 -> [2(4(1(2(4...)))), 3] + return { + in: [node], + expect: [{ + ...node, + agentLog: [ + { + id: '1', + label: 'Node 1', + children: [ + { + id: '2', + parent_id: '1', + label: 'Node 2', + children: [ + { + id: '4', + parent_id: '2', + label: 'Node 4', + children: [], + hasCircle: true, + }, + ], + }, + { + id: '3', + parent_id: '1', + label: 'Node 3', + }, + ], + }, + ], + }], + } +})() + +export const CircleNestCircle = (() => { +})() diff --git a/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts b/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts new file mode 100644 index 0000000000..2cd61e99e4 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts @@ -0,0 +1,16 @@ +import exp from 'constants' +import format from '.' +import { agentNodeData, oneStepCircle, multiStepsCircle } from './data' + +describe('agent', () => { + test('list should transform to tree', () => { + // console.log(format(agentNodeData.in as any)) + expect(format(agentNodeData.in as any)).toEqual(agentNodeData.expect) + }) + + test('list should remove circle log item', () => { + // format(oneStepCircle.in as any) + expect(format(oneStepCircle.in as any)).toEqual(oneStepCircle.expect) + expect(format(multiStepsCircle.in as any)).toEqual(multiStepsCircle.expect) + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/agent/index.ts b/web/app/components/workflow/run/utils/format-log/agent/index.ts new file mode 100644 index 0000000000..c1f3afc20a --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/agent/index.ts @@ -0,0 +1,99 @@ +import { BlockEnum } from '@/app/components/workflow/types' +import type { AgentLogItem, AgentLogItemWithChildren, NodeTracing } from '@/types/workflow' +import { cloneDeep } from 'lodash-es' + +const supportedAgentLogNodes = [BlockEnum.Agent, BlockEnum.Tool] + +const remove = (node: AgentLogItemWithChildren, removeId: string) => { + let { children } = node + if (!children || children.length === 0) + return + + const hasCircle = !!children.find(c => c.id === removeId) + if (hasCircle) { + node.hasCircle = true + node.children = node.children.filter(c => c.id !== removeId) + children = node.children + } + + children.forEach((child) => { + remove(child, removeId) + }) +} + +const removeRepeatedSiblings = (list: AgentLogItemWithChildren[]) => { + if (!list || list.length === 0) + return [] + + const result: AgentLogItemWithChildren[] = [] + const addedItemIds: string[] = [] + list.forEach((item) => { + if (!addedItemIds.includes(item.id)) { + result.push(item) + addedItemIds.push(item.id) + } + }) + return result +} + +const removeCircleLogItem = (log: AgentLogItemWithChildren) => { + const newLog = cloneDeep(log) + newLog.children = removeRepeatedSiblings(newLog.children) + let { id, children } = newLog + if (!children || children.length === 0) + return log + + // check one step circle + const hasOneStepCircle = !!children.find(c => c.id === id) + if (hasOneStepCircle) { + newLog.hasCircle = true + newLog.children = newLog.children.filter(c => c.id !== id) + children = newLog.children + } + + children.forEach((child, index) => { + remove(child, id) // check multi steps circle + children[index] = removeCircleLogItem(child) + }) + return newLog +} + +const listToTree = (logs: AgentLogItem[]) => { + if (!logs || logs.length === 0) + return [] + + const tree: AgentLogItemWithChildren[] = [] + logs.forEach((log) => { + const hasParent = !!log.parent_id + if (hasParent) { + const parent = logs.find(item => item.id === log.parent_id) as AgentLogItemWithChildren + if (parent) { + if (!parent.children) + parent.children = [] + parent.children.push(log as AgentLogItemWithChildren) + } + } + else { + tree.push(log as AgentLogItemWithChildren) + } + }) + return tree +} + +const format = (list: NodeTracing[]): NodeTracing[] => { + const result: NodeTracing[] = list.map((item) => { + let treeList: AgentLogItemWithChildren[] = [] + let removedCircleTree: AgentLogItemWithChildren[] = [] + if (supportedAgentLogNodes.includes(item.node_type) && item.execution_metadata?.agent_log && item.execution_metadata?.agent_log.length > 0) + treeList = listToTree(item.execution_metadata.agent_log) + // console.log(JSON.stringify(treeList)) + removedCircleTree = treeList.length > 0 ? treeList.map(t => removeCircleLogItem(t)) : [] + item.agentLog = removedCircleTree + + return item + }) + + return result +} + +export default format diff --git a/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.spec.ts b/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.spec.ts new file mode 100644 index 0000000000..18758404ff --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.spec.ts @@ -0,0 +1,128 @@ +import parseDSL from './graph-to-log-struct' + +describe('parseDSL', () => { + it('should parse plain nodes correctly', () => { + const dsl = 'plainNode1 -> plainNode2' + const result = parseDSL(dsl) + expect(result).toEqual([ + { id: 'plainNode1', node_id: 'plainNode1', title: 'plainNode1', execution_metadata: {}, status: 'succeeded' }, + { id: 'plainNode2', node_id: 'plainNode2', title: 'plainNode2', execution_metadata: {}, status: 'succeeded' }, + ]) + }) + + it('should parse retry nodes correctly', () => { + const dsl = '(retry, retryNode, 3)' + const result = parseDSL(dsl) + expect(result).toEqual([ + { id: 'retryNode', node_id: 'retryNode', title: 'retryNode', execution_metadata: {}, status: 'succeeded' }, + { id: 'retryNode', node_id: 'retryNode', title: 'retryNode', execution_metadata: {}, status: 'retry' }, + { id: 'retryNode', node_id: 'retryNode', title: 'retryNode', execution_metadata: {}, status: 'retry' }, + { id: 'retryNode', node_id: 'retryNode', title: 'retryNode', execution_metadata: {}, status: 'retry' }, + ]) + }) + + it('should parse iteration nodes correctly', () => { + const dsl = '(iteration, iterationNode, plainNode1 -> plainNode2)' + const result = parseDSL(dsl) + expect(result).toEqual([ + { id: 'iterationNode', node_id: 'iterationNode', title: 'iterationNode', node_type: 'iteration', execution_metadata: {}, status: 'succeeded' }, + { id: 'plainNode1', node_id: 'plainNode1', title: 'plainNode1', execution_metadata: { iteration_id: 'iterationNode', iteration_index: 0 }, status: 'succeeded' }, + { id: 'plainNode2', node_id: 'plainNode2', title: 'plainNode2', execution_metadata: { iteration_id: 'iterationNode', iteration_index: 0 }, status: 'succeeded' }, + ]) + }) + + it('should parse parallel nodes correctly', () => { + const dsl = '(parallel, parallelNode, nodeA, nodeB -> nodeC)' + const result = parseDSL(dsl) + expect(result).toEqual([ + { id: 'parallelNode', node_id: 'parallelNode', title: 'parallelNode', execution_metadata: { parallel_id: 'parallelNode' }, status: 'succeeded' }, + { id: 'nodeA', node_id: 'nodeA', title: 'nodeA', execution_metadata: { parallel_id: 'parallelNode', parallel_start_node_id: 'nodeA' }, status: 'succeeded' }, + { id: 'nodeB', node_id: 'nodeB', title: 'nodeB', execution_metadata: { parallel_id: 'parallelNode', parallel_start_node_id: 'nodeB' }, status: 'succeeded' }, + { id: 'nodeC', node_id: 'nodeC', title: 'nodeC', execution_metadata: { parallel_id: 'parallelNode', parallel_start_node_id: 'nodeB' }, status: 'succeeded' }, + ]) + }) + + // TODO + it('should handle nested parallel nodes', () => { + const dsl = '(parallel, outerParallel, (parallel, innerParallel, plainNode1 -> plainNode2) -> plainNode3)' + const result = parseDSL(dsl) + expect(result).toEqual([ + { + id: 'outerParallel', + node_id: 'outerParallel', + title: 'outerParallel', + execution_metadata: { parallel_id: 'outerParallel' }, + status: 'succeeded', + }, + { + id: 'innerParallel', + node_id: 'innerParallel', + title: 'innerParallel', + execution_metadata: { parallel_id: 'outerParallel', parallel_start_node_id: 'innerParallel' }, + status: 'succeeded', + }, + { + id: 'plainNode1', + node_id: 'plainNode1', + title: 'plainNode1', + execution_metadata: { + parallel_id: 'innerParallel', + parallel_start_node_id: 'plainNode1', + parent_parallel_id: 'outerParallel', + parent_parallel_start_node_id: 'innerParallel', + }, + status: 'succeeded', + }, + { + id: 'plainNode2', + node_id: 'plainNode2', + title: 'plainNode2', + execution_metadata: { + parallel_id: 'innerParallel', + parallel_start_node_id: 'plainNode1', + parent_parallel_id: 'outerParallel', + parent_parallel_start_node_id: 'innerParallel', + }, + status: 'succeeded', + }, + { + id: 'plainNode3', + node_id: 'plainNode3', + title: 'plainNode3', + execution_metadata: { + parallel_id: 'outerParallel', + parallel_start_node_id: 'plainNode3', + }, + status: 'succeeded', + }, + ]) + }) + + // iterations not support nested iterations + // it('should handle nested iterations', () => { + // const dsl = '(iteration, outerIteration, (iteration, innerIteration -> plainNode1 -> plainNode2))' + // const result = parseDSL(dsl) + // expect(result).toEqual([ + // { id: 'outerIteration', node_id: 'outerIteration', title: 'outerIteration', node_type: 'iteration', execution_metadata: {}, status: 'succeeded' }, + // { id: 'innerIteration', node_id: 'innerIteration', title: 'innerIteration', node_type: 'iteration', execution_metadata: { iteration_id: 'outerIteration', iteration_index: 0 }, status: 'succeeded' }, + // { id: 'plainNode1', node_id: 'plainNode1', title: 'plainNode1', execution_metadata: { iteration_id: 'innerIteration', iteration_index: 0 }, status: 'succeeded' }, + // { id: 'plainNode2', node_id: 'plainNode2', title: 'plainNode2', execution_metadata: { iteration_id: 'innerIteration', iteration_index: 0 }, status: 'succeeded' }, + // ]) + // }) + + it('should handle nested iterations within parallel nodes', () => { + const dsl = '(parallel, parallelNode, (iteration, iterationNode, plainNode1, plainNode2))' + const result = parseDSL(dsl) + expect(result).toEqual([ + { id: 'parallelNode', node_id: 'parallelNode', title: 'parallelNode', execution_metadata: { parallel_id: 'parallelNode' }, status: 'succeeded' }, + { id: 'iterationNode', node_id: 'iterationNode', title: 'iterationNode', node_type: 'iteration', execution_metadata: { parallel_id: 'parallelNode', parallel_start_node_id: 'iterationNode' }, status: 'succeeded' }, + { id: 'plainNode1', node_id: 'plainNode1', title: 'plainNode1', execution_metadata: { iteration_id: 'iterationNode', iteration_index: 0, parallel_id: 'parallelNode', parallel_start_node_id: 'iterationNode' }, status: 'succeeded' }, + { id: 'plainNode2', node_id: 'plainNode2', title: 'plainNode2', execution_metadata: { iteration_id: 'iterationNode', iteration_index: 0, parallel_id: 'parallelNode', parallel_start_node_id: 'iterationNode' }, status: 'succeeded' }, + ]) + }) + + it('should throw an error for unknown node types', () => { + const dsl = '(unknown, nodeId)' + expect(() => parseDSL(dsl)).toThrowError('Unknown nodeType: unknown') + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.ts b/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.ts new file mode 100644 index 0000000000..a6b20b0565 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/graph-to-log-struct.ts @@ -0,0 +1,304 @@ +type IterationInfo = { iterationId: string; iterationIndex: number } +type NodePlain = { nodeType: 'plain'; nodeId: string; } & Partial<IterationInfo> +type NodeComplex = { nodeType: string; nodeId: string; params: (NodePlain | (NodeComplex & Partial<IterationInfo>) | Node[] | number)[] } & Partial<IterationInfo> +type Node = NodePlain | NodeComplex + +/** + * Parses a DSL string into an array of node objects. + * @param dsl - The input DSL string. + * @returns An array of parsed nodes. + */ +function parseDSL(dsl: string): NodeData[] { + return convertToNodeData(parseTopLevelFlow(dsl).map(nodeStr => parseNode(nodeStr))) +} + +/** + * Splits a top-level flow string by "->", respecting nested structures. + * @param dsl - The DSL string to split. + * @returns An array of top-level segments. + */ +function parseTopLevelFlow(dsl: string): string[] { + const segments: string[] = [] + let buffer = '' + let nested = 0 + + for (let i = 0; i < dsl.length; i++) { + const char = dsl[i] + if (char === '(') nested++ + if (char === ')') nested-- + if (char === '-' && dsl[i + 1] === '>' && nested === 0) { + segments.push(buffer.trim()) + buffer = '' + i++ // Skip the ">" character + } + else { + buffer += char + } + } + if (buffer.trim()) + segments.push(buffer.trim()) + + return segments +} + +/** + * Parses a single node string. + * If the node is complex (e.g., has parentheses), it extracts the node type, node ID, and parameters. + * @param nodeStr - The node string to parse. + * @param parentIterationId - The ID of the parent iteration node (if applicable). + * @returns A parsed node object. + */ +function parseNode(nodeStr: string, parentIterationId?: string): Node { + // Check if the node is a complex node + if (nodeStr.startsWith('(') && nodeStr.endsWith(')')) { + const innerContent = nodeStr.slice(1, -1).trim() // Remove outer parentheses + let nested = 0 + let buffer = '' + const parts: string[] = [] + + // Split the inner content by commas, respecting nested parentheses + for (let i = 0; i < innerContent.length; i++) { + const char = innerContent[i] + if (char === '(') nested++ + if (char === ')') nested-- + + if (char === ',' && nested === 0) { + parts.push(buffer.trim()) + buffer = '' + } + else { + buffer += char + } + } + parts.push(buffer.trim()) + + // Extract nodeType, nodeId, and params + const [nodeType, nodeId, ...paramsRaw] = parts + const params = parseParams(paramsRaw, nodeType === 'iteration' ? nodeId.trim() : parentIterationId) + const complexNode = { + nodeType: nodeType.trim(), + nodeId: nodeId.trim(), + params, + } + if (parentIterationId) { + (complexNode as any).iterationId = parentIterationId; + (complexNode as any).iterationIndex = 0 // Fixed as 0 + } + return complexNode + } + + // If it's not a complex node, treat it as a plain node + const plainNode: NodePlain = { nodeType: 'plain', nodeId: nodeStr.trim() } + if (parentIterationId) { + plainNode.iterationId = parentIterationId + plainNode.iterationIndex = 0 // Fixed as 0 + } + return plainNode +} + +/** + * Parses parameters of a complex node. + * Supports nested flows and complex sub-nodes. + * Adds iteration-specific metadata recursively. + * @param paramParts - The parameters string split by commas. + * @param iterationId - The ID of the iteration node, if applicable. + * @returns An array of parsed parameters (plain nodes, nested nodes, or flows). + */ +function parseParams(paramParts: string[], iterationId?: string): (Node | Node[] | number)[] { + return paramParts.map((part) => { + if (part.includes('->')) { + // Parse as a flow and return an array of nodes + return parseTopLevelFlow(part).map(node => parseNode(node, iterationId)) + } + else if (part.startsWith('(')) { + // Parse as a nested complex node + return parseNode(part, iterationId) + } + else if (!Number.isNaN(Number(part.trim()))) { + // Parse as a numeric parameter + return Number(part.trim()) + } + else { + // Parse as a plain node + return parseNode(part, iterationId) + } + }) +} + +type NodeData = { + id: string; + node_id: string; + title: string; + node_type?: string; + execution_metadata: Record<string, any>; + status: string; +} + +/** + * Converts a plain node to node data. + */ +function convertPlainNode(node: Node): NodeData[] { + return [ + { + id: node.nodeId, + node_id: node.nodeId, + title: node.nodeId, + execution_metadata: {}, + status: 'succeeded', + }, + ] +} + +/** + * Converts a retry node to node data. + */ +function convertRetryNode(node: Node): NodeData[] { + const { nodeId, iterationId, iterationIndex, params } = node as NodeComplex + const retryCount = params ? Number.parseInt(params[0] as unknown as string, 10) : 0 + const result: NodeData[] = [ + { + id: nodeId, + node_id: nodeId, + title: nodeId, + execution_metadata: {}, + status: 'succeeded', + }, + ] + + for (let i = 0; i < retryCount; i++) { + result.push({ + id: nodeId, + node_id: nodeId, + title: nodeId, + execution_metadata: iterationId ? { + iteration_id: iterationId, + iteration_index: iterationIndex || 0, + } : {}, + status: 'retry', + }) + } + + return result +} + +/** + * Converts an iteration node to node data. + */ +function convertIterationNode(node: Node): NodeData[] { + const { nodeId, params } = node as NodeComplex + const result: NodeData[] = [ + { + id: nodeId, + node_id: nodeId, + title: nodeId, + node_type: 'iteration', + status: 'succeeded', + execution_metadata: {}, + }, + ] + + params?.forEach((param: any) => { + if (Array.isArray(param)) { + param.forEach((childNode: Node) => { + const childData = convertToNodeData([childNode]) + childData.forEach((data) => { + data.execution_metadata = { + ...data.execution_metadata, + iteration_id: nodeId, + iteration_index: 0, + } + }) + result.push(...childData) + }) + } + }) + + return result +} + +/** + * Converts a parallel node to node data. + */ +function convertParallelNode(node: Node, parentParallelId?: string, parentStartNodeId?: string): NodeData[] { + const { nodeId, params } = node as NodeComplex + const result: NodeData[] = [ + { + id: nodeId, + node_id: nodeId, + title: nodeId, + execution_metadata: { + parallel_id: nodeId, + }, + status: 'succeeded', + }, + ] + + params?.forEach((param) => { + if (Array.isArray(param)) { + const startNodeId = param[0]?.nodeId + param.forEach((childNode: Node) => { + const childData = convertToNodeData([childNode]) + childData.forEach((data) => { + data.execution_metadata = { + ...data.execution_metadata, + parallel_id: nodeId, + parallel_start_node_id: startNodeId, + ...(parentParallelId && { + parent_parallel_id: parentParallelId, + parent_parallel_start_node_id: parentStartNodeId, + }), + } + }) + result.push(...childData) + }) + } + else if (param && typeof param === 'object') { + const startNodeId = param.nodeId + const childData = convertToNodeData([param]) + childData.forEach((data) => { + data.execution_metadata = { + ...data.execution_metadata, + parallel_id: nodeId, + parallel_start_node_id: startNodeId, + ...(parentParallelId && { + parent_parallel_id: parentParallelId, + parent_parallel_start_node_id: parentStartNodeId, + }), + } + }) + result.push(...childData) + } + }) + + return result +} + +/** + * Main function to convert nodes to node data. + */ +function convertToNodeData(nodes: Node[], parentParallelId?: string, parentStartNodeId?: string): NodeData[] { + const result: NodeData[] = [] + + nodes.forEach((node) => { + switch (node.nodeType) { + case 'plain': + result.push(...convertPlainNode(node)) + break + case 'retry': + result.push(...convertRetryNode(node)) + break + case 'iteration': + result.push(...convertIterationNode(node)) + break + case 'parallel': + result.push(...convertParallelNode(node, parentParallelId, parentStartNodeId)) + break + default: + throw new Error(`Unknown nodeType: ${node.nodeType}`) + } + }) + + return result +} + +export default parseDSL diff --git a/web/app/components/workflow/run/utils/format-log/index.spec.ts b/web/app/components/workflow/run/utils/format-log/index.spec.ts new file mode 100644 index 0000000000..5ebaf8c20a --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/index.spec.ts @@ -0,0 +1,10 @@ +import formatToTracingNodeList from '.' +import { simpleIterationData } from './iteration/data' +import { simpleRetryData } from './retry/data' + +describe('format api data to tracing panel data', () => { + test('integration', () => { + expect(formatToTracingNodeList(simpleIterationData.in.reverse() as any)).toEqual(simpleIterationData.expect) + expect(formatToTracingNodeList(simpleRetryData.in.reverse() as any)).toEqual(simpleRetryData.expect) + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/index.ts b/web/app/components/workflow/run/utils/format-log/index.ts new file mode 100644 index 0000000000..4e8f6c33c2 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/index.ts @@ -0,0 +1,27 @@ +import type { NodeTracing } from '@/types/workflow' +import formatIterationNode from './iteration' +import formatParallelNode from './parallel' +import formatRetryNode from './retry' +import formatAgentNode from './agent' +import { cloneDeep } from 'lodash-es' + +const formatToTracingNodeList = (list: NodeTracing[], t: any) => { + const allItems = cloneDeep([...list]).sort((a, b) => a.index - b.index) + /* + * First handle not change list structure node + * Because Handle struct node will put the node in different + */ + const formattedAgentList = formatAgentNode(allItems) + const formattedRetryList = formatRetryNode(formattedAgentList) // retry one node + // would change the structure of the list. Iteration and parallel can include each other. + const formattedIterationList = formatIterationNode(formattedRetryList, t) + const formattedParallelList = formatParallelNode(formattedIterationList, t) + + const result = formattedParallelList + // console.log(allItems) + // console.log(result) + + return result +} + +export default formatToTracingNodeList diff --git a/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts b/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts new file mode 100644 index 0000000000..ca23c4d9ee --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts @@ -0,0 +1,22 @@ +import format from '.' +import graphToLogStruct from '../graph-to-log-struct' + +describe('iteration', () => { + const list = graphToLogStruct('start -> (iteration, iterationNode, plainNode1 -> plainNode2)') + const [startNode, iterationNode, ...iterations] = list + const result = format(list as any, () => { }) + test('result should have no nodes in iteration node', () => { + expect((result as any).find((item: any) => !!item.execution_metadata?.iteration_id)).toBeUndefined() + }) + test('iteration should put nodes in details', () => { + expect(result as any).toEqual([ + startNode, + { + ...iterationNode, + details: [ + [iterations[0], iterations[1]], + ], + }, + ]) + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/iteration/index.ts b/web/app/components/workflow/run/utils/format-log/iteration/index.ts new file mode 100644 index 0000000000..ca3dad7fb0 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/iteration/index.ts @@ -0,0 +1,55 @@ +import { BlockEnum } from '@/app/components/workflow/types' +import type { NodeTracing } from '@/types/workflow' +import formatParallelNode from '../parallel' +function addChildrenToIterationNode(iterationNode: NodeTracing, childrenNodes: NodeTracing[]): NodeTracing { + const details: NodeTracing[][] = [] + childrenNodes.forEach((item) => { + if (!item.execution_metadata) return + const { parallel_mode_run_id, iteration_index = 0 } = item.execution_metadata + const runIndex: number = (parallel_mode_run_id || iteration_index) as number + if (!details[runIndex]) + details[runIndex] = [] + + details[runIndex].push(item) + }) + return { + ...iterationNode, + details, + } +} + +const format = (list: NodeTracing[], t: any): NodeTracing[] => { + const iterationNodeIds = list + .filter(item => item.node_type === BlockEnum.Iteration) + .map(item => item.node_id) + const iterationChildrenNodeIds = list + .filter(item => item.execution_metadata?.iteration_id && iterationNodeIds.includes(item.execution_metadata.iteration_id)) + .map(item => item.node_id) + // move iteration children nodes to iteration node's details field + const result = list + .filter(item => !iterationChildrenNodeIds.includes(item.node_id)) + .map((item) => { + if (item.node_type === BlockEnum.Iteration) { + const childrenNodes = list.filter(child => child.execution_metadata?.iteration_id === item.node_id) + const error = childrenNodes.find(child => child.status === 'failed') + if (error) { + item.status = 'failed' + item.error = error.error + } + const addedChildrenList = addChildrenToIterationNode(item, childrenNodes) + // handle parallel node in iteration node + if (addedChildrenList.details && addedChildrenList.details.length > 0) { + addedChildrenList.details = addedChildrenList.details.map((row) => { + return formatParallelNode(row, t) + }) + } + return addedChildrenList + } + + return item + }) + + return result +} + +export default format diff --git a/web/app/components/workflow/run/utils/format-log/parallel/index.spec.ts b/web/app/components/workflow/run/utils/format-log/parallel/index.spec.ts new file mode 100644 index 0000000000..d1ce052ee8 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/parallel/index.spec.ts @@ -0,0 +1,39 @@ +import { cloneDeep } from 'lodash-es' +import format from '.' +import graphToLogStruct from '../graph-to-log-struct' + +describe('parallel', () => { + const list = graphToLogStruct('(parallel, parallelNode, nodeA, nodeB -> nodeC)') + const [parallelNode, ...parallelDetail] = list + const parallelI18n = 'PARALLEL' + // format will change the list... + const result = format(cloneDeep(list) as any, () => parallelI18n) + + test('parallel should put nodes in details', () => { + expect(result as any).toEqual([ + { + ...parallelNode, + parallelDetail: { + isParallelStartNode: true, + parallelTitle: `${parallelI18n}-1`, + children: [ + parallelNode, + { + ...parallelDetail[0], + parallelDetail: { + branchTitle: `${parallelI18n}-1-A`, + }, + }, + { + ...parallelDetail[1], + parallelDetail: { + branchTitle: `${parallelI18n}-1-B`, + }, + }, + parallelDetail[2], + ], + }, + }, + ]) + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/parallel/index.ts b/web/app/components/workflow/run/utils/format-log/parallel/index.ts new file mode 100644 index 0000000000..245337dc0c --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/parallel/index.ts @@ -0,0 +1,175 @@ +import { BlockEnum } from '@/app/components/workflow/types' +import type { NodeTracing } from '@/types/workflow' + +function printNodeStructure(node: NodeTracing, depth: number) { + const indent = ' '.repeat(depth) + console.log(`${indent}${node.title}`) + if (node.parallelDetail?.children) { + node.parallelDetail.children.forEach((child) => { + printNodeStructure(child, depth + 1) + }) + } +} + +function addTitle({ + list, depth, belongParallelIndexInfo, +}: { + list: NodeTracing[], + depth: number, + belongParallelIndexInfo?: string, +}, t: any) { + let branchIndex = 0 + const hasMoreThanOneParallel = list.filter(node => node.parallelDetail?.isParallelStartNode).length > 1 + list.forEach((node) => { + const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null + const parallel_start_node_id = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null + + const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End + if (isNotInParallel) + return + + const isParallelStartNode = node.parallelDetail?.isParallelStartNode + + const parallelIndexLetter = (() => { + if (!isParallelStartNode || !hasMoreThanOneParallel) + return '' + + const index = 1 + list.filter(node => node.parallelDetail?.isParallelStartNode).findIndex(item => item.node_id === node.node_id) + return String.fromCharCode(64 + index) + })() + + const parallelIndexInfo = `${depth}${parallelIndexLetter}` + + if (isParallelStartNode) { + node.parallelDetail!.isParallelStartNode = true + node.parallelDetail!.parallelTitle = `${t('workflow.common.parallel')}-${parallelIndexInfo}` + } + + const isBrachStartNode = parallel_start_node_id === node.node_id + if (isBrachStartNode) { + branchIndex++ + const branchLetter = String.fromCharCode(64 + branchIndex) + if (!node.parallelDetail) { + node.parallelDetail = { + branchTitle: '', + } + } + + node.parallelDetail!.branchTitle = `${t('workflow.common.branch')}-${belongParallelIndexInfo}-${branchLetter}` + } + + if (node.parallelDetail?.children && node.parallelDetail.children.length > 0) { + addTitle({ + list: node.parallelDetail.children, + depth: depth + 1, + belongParallelIndexInfo: parallelIndexInfo, + }, t) + } + }) +} + +// list => group by parallel_id(parallel tree). +const format = (list: NodeTracing[], t: any, isPrint?: boolean): NodeTracing[] => { + if (isPrint) + console.log(list) + + const result: NodeTracing[] = [...list] + const parallelFirstNodeMap: Record<string, string> = {} + // list to tree by parent_parallel_start_node_id and branch by parallel_start_node_id. Each parallel may has more than one branch. + result.forEach((node) => { + const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null + const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null + const branchStartNodeId = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null + const parentParallelBranchStartNodeId = node.parent_parallel_start_node_id ?? node.execution_metadata?.parent_parallel_start_node_id ?? null + const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End + if (isNotInParallel) + return + + const isParallelStartNode = !parallelFirstNodeMap[parallel_id] + if (isParallelStartNode) { + const selfNode = { ...node, parallelDetail: undefined } + node.parallelDetail = { + isParallelStartNode: true, + children: [selfNode], + } + parallelFirstNodeMap[parallel_id] = node.node_id + const isRootLevel = !parent_parallel_id + if (isRootLevel) + return + + const parentParallelStartNode = result.find(item => item.node_id === parentParallelBranchStartNodeId) + // append to parent parallel start node and after the same branch + if (parentParallelStartNode) { + if (!parentParallelStartNode?.parallelDetail) { + parentParallelStartNode!.parallelDetail = { + children: [], + } + } + if (parentParallelStartNode!.parallelDetail.children) { + const sameBranchNodesLastIndex = parentParallelStartNode.parallelDetail.children.findLastIndex((node) => { + const currStartNodeId = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null + return currStartNodeId === parentParallelBranchStartNodeId + }) + if (sameBranchNodesLastIndex !== -1) + parentParallelStartNode!.parallelDetail.children.splice(sameBranchNodesLastIndex + 1, 0, node) + else + parentParallelStartNode!.parallelDetail.children.push(node) + } + } + return + } + + // append to parallel start node and after the same branch + const parallelStartNode = result.find(item => item.node_id === parallelFirstNodeMap[parallel_id]) + + if (parallelStartNode && parallelStartNode.parallelDetail && parallelStartNode!.parallelDetail!.children) { + const sameBranchNodesLastIndex = parallelStartNode.parallelDetail.children.findLastIndex((node) => { + const currStartNodeId = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null + return currStartNodeId === branchStartNodeId + }) + if (sameBranchNodesLastIndex !== -1) { + parallelStartNode.parallelDetail.children.splice(sameBranchNodesLastIndex + 1, 0, node) + } + else { // new branch + parallelStartNode.parallelDetail.children.push(node) + } + } + // parallelStartNode!.parallelDetail!.children.push(node) + }) + + const filteredInParallelSubNodes = result.filter((node) => { + const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null + const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End + if (isNotInParallel) + return true + + const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null + + if (parent_parallel_id) + return false + + const isParallelStartNode = node.parallelDetail?.isParallelStartNode + if (!isParallelStartNode) + return false + + return true + }) + + // print node structure for debug + if (isPrint) { + filteredInParallelSubNodes.forEach((node) => { + const now = Date.now() + console.log(`----- p: ${now} start -----`) + printNodeStructure(node, 0) + console.log(`----- p: ${now} end -----`) + }) + } + + addTitle({ + list: filteredInParallelSubNodes, + depth: 1, + }, t) + + return filteredInParallelSubNodes +} +export default format diff --git a/web/app/components/workflow/run/utils/format-log/retry/index.spec.ts b/web/app/components/workflow/run/utils/format-log/retry/index.spec.ts new file mode 100644 index 0000000000..a8f46e96b1 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/retry/index.spec.ts @@ -0,0 +1,21 @@ +import format from '.' +import graphToLogStruct from '../graph-to-log-struct' + +describe('retry', () => { + // retry nodeId:1 3 times. + const steps = graphToLogStruct('start -> (retry, retryNode, 3)') + const [startNode, retryNode, ...retryDetail] = steps + const result = format(steps as any) + test('should have no retry status nodes', () => { + expect(result.find(item => (item as any).status === 'retry')).toBeUndefined() + }) + test('should put retry nodes in retryDetail', () => { + expect(result).toEqual([ + startNode, + { + ...retryNode, + retryDetail, + }, + ]) + }) +}) diff --git a/web/app/components/workflow/run/utils/format-log/retry/index.ts b/web/app/components/workflow/run/utils/format-log/retry/index.ts new file mode 100644 index 0000000000..b8dd0bfa80 --- /dev/null +++ b/web/app/components/workflow/run/utils/format-log/retry/index.ts @@ -0,0 +1,35 @@ +import type { NodeTracing } from '@/types/workflow' + +const format = (list: NodeTracing[]): NodeTracing[] => { + const retryNodes = list.filter((item) => { + return item.status === 'retry' + }) + + const retryNodeIds = retryNodes.map(item => item.node_id) + // move retry nodes to retryDetail + const result = list.filter((item) => { + return item.status !== 'retry' + }).map((item) => { + const { execution_metadata } = item + const isInIteration = !!execution_metadata?.iteration_id + const nodeId = item.node_id + const isRetryBelongNode = retryNodeIds.includes(nodeId) + + if (isRetryBelongNode) { + return { + ...item, + retryDetail: retryNodes.filter((node) => { + if (!isInIteration) + return node.node_id === nodeId + + // retry node in iteration + return node.node_id === nodeId && node.execution_metadata?.iteration_index === execution_metadata?.iteration_index + }), + } + } + return item + }) + return result +} + +export default format diff --git a/web/app/components/workflow/store.ts b/web/app/components/workflow/store.ts index 8e9cdbfc45..6bd47eaa01 100644 --- a/web/app/components/workflow/store.ts +++ b/web/app/components/workflow/store.ts @@ -184,7 +184,7 @@ export const createWorkflowStore = () => { } return createStore<Shape>(set => ({ appId: '', - panelWidth: localStorage.getItem('workflow-node-panel-width') ? parseFloat(localStorage.getItem('workflow-node-panel-width')!) : 420, + panelWidth: localStorage.getItem('workflow-node-panel-width') ? Number.parseFloat(localStorage.getItem('workflow-node-panel-width')!) : 420, showSingleRunPanel: false, setShowSingleRunPanel: showSingleRunPanel => set(() => ({ showSingleRunPanel })), workflowRunningData: undefined, diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 7c61ca98fe..10df1b02b9 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -35,6 +35,7 @@ export enum BlockEnum { ListFilter = 'list-operator', IterationStart = 'iteration-start', Assigner = 'assigner', // is now named as VariableAssigner + Agent = 'agent', } export enum ControlMode { diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx index 3eb65e68f8..fc65806487 100644 --- a/web/app/components/workflow/update-dsl-modal.tsx +++ b/web/app/components/workflow/update-dsl-modal.tsx @@ -38,6 +38,7 @@ import { ToastContext } from '@/app/components/base/toast' import { useEventEmitterContextContext } from '@/context/event-emitter' import { useStore as useAppStore } from '@/app/components/app/store' import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants' +import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' type UpdateDSLModalProps = { onCancel: () => void @@ -61,6 +62,7 @@ const UpdateDSLModal = ({ const [showErrorModal, setShowErrorModal] = useState(false) const [versions, setVersions] = useState<{ importedVersion: string; systemVersion: string }>() const [importId, setImportId] = useState<string>() + const { handleCheckPluginDependencies } = usePluginDependencies() const readFile = (file: File) => { const reader = new FileReader() @@ -79,7 +81,7 @@ const UpdateDSLModal = ({ setFileContent('') } - const handleWorkflowUpdate = async (app_id: string) => { + const handleWorkflowUpdate = useCallback(async (app_id: string) => { const { graph, features, @@ -122,7 +124,7 @@ const UpdateDSLModal = ({ hash, }, } as any) - } + }, [eventEmitter]) const isCreatingRef = useRef(false) const handleImport: MouseEventHandler = useCallback(async () => { @@ -136,6 +138,7 @@ const UpdateDSLModal = ({ setLoading(true) const response = await importDSL({ mode: DSLImportMode.YAML_CONTENT, yaml_content: fileContent, app_id: appDetail.id }) const { id, status, app_id, imported_dsl_version, current_dsl_version } = response + if (status === DSLImportStatus.COMPLETED || status === DSLImportStatus.COMPLETED_WITH_WARNINGS) { if (!app_id) { notify({ type: 'error', message: t('workflow.common.importFailure') }) @@ -149,6 +152,7 @@ const UpdateDSLModal = ({ message: t(status === DSLImportStatus.COMPLETED ? 'workflow.common.importSuccess' : 'workflow.common.importWarning'), children: status === DSLImportStatus.COMPLETED_WITH_WARNINGS && t('workflow.common.importWarningDetails'), }) + await handleCheckPluginDependencies(app_id) setLoading(false) onCancel() } @@ -169,12 +173,13 @@ const UpdateDSLModal = ({ } } } + // eslint-disable-next-line unused-imports/no-unused-vars catch (e) { setLoading(false) notify({ type: 'error', message: t('workflow.common.importFailure') }) } isCreatingRef.current = false - }, [currentFile, fileContent, onCancel, notify, t, eventEmitter, appDetail, onImport]) + }, [currentFile, fileContent, onCancel, notify, t, appDetail, onImport, handleWorkflowUpdate, handleCheckPluginDependencies]) const onUpdateDSLConfirm: MouseEventHandler = async () => { try { @@ -192,6 +197,7 @@ const UpdateDSLModal = ({ return } handleWorkflowUpdate(app_id) + await handleCheckPluginDependencies(app_id) if (onImport) onImport() notify({ type: 'success', message: t('workflow.common.importSuccess') }) @@ -203,6 +209,7 @@ const UpdateDSLModal = ({ notify({ type: 'error', message: t('workflow.common.importFailure') }) } } + // eslint-disable-next-line unused-imports/no-unused-vars catch (e) { setLoading(false) notify({ type: 'error', message: t('workflow.common.importFailure') }) @@ -222,12 +229,12 @@ const UpdateDSLModal = ({ <RiCloseLine className='w-[18px] h-[18px] text-text-tertiary' /> </div> </div> - <div className='flex relative p-2 mb-2 gap-0.5 flex-grow rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-xs overflow-hidden'> - <div className='absolute top-0 left-0 w-full h-full opacity-40 bg-[linear-gradient(92deg,rgba(247,144,9,0.25)_0%,rgba(255,255,255,0.00)_100%)]' /> + <div className='flex relative p-2 mb-2 gap-0.5 grow rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-xs overflow-hidden'> + <div className='absolute top-0 left-0 w-full h-full opacity-40 bg-toast-warning-bg' /> <div className='flex p-1 justify-center items-start'> - <RiAlertFill className='w-4 h-4 flex-shrink-0 text-text-warning-secondary' /> + <RiAlertFill className='w-4 h-4 shrink-0 text-text-warning-secondary' /> </div> - <div className='flex py-1 flex-col items-start gap-0.5 flex-grow'> + <div className='flex py-1 flex-col items-start gap-0.5 grow'> <div className='text-text-primary system-xs-medium whitespace-pre-line'>{t('workflow.common.importDSLTip')}</div> <div className='flex pt-1 pb-0.5 items-start gap-1 self-stretch'> <Button @@ -275,7 +282,7 @@ const UpdateDSLModal = ({ > <div className='flex pb-4 flex-col items-start gap-2 self-stretch'> <div className='text-text-primary title-2xl-semi-bold'>{t('app.newApp.appCreateDSLErrorTitle')}</div> - <div className='flex flex-grow flex-col text-text-secondary system-md-regular'> + <div className='flex grow flex-col text-text-secondary system-md-regular'> <div>{t('app.newApp.appCreateDSLErrorPart1')}</div> <div>{t('app.newApp.appCreateDSLErrorPart2')}</div> <br /> diff --git a/web/app/components/workflow/utils.ts b/web/app/components/workflow/utils.ts index da2848277f..9a24c4fce0 100644 --- a/web/app/components/workflow/utils.ts +++ b/web/app/components/workflow/utils.ts @@ -41,6 +41,7 @@ import type { ToolNodeType } from './nodes/tool/types' import type { IterationNodeType } from './nodes/iteration/types' import { CollectionType } from '@/app/components/tools/types' import { toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' +import { correctProvider } from '@/utils' const WHITE = 'WHITE' const GRAY = 'GRAY' @@ -281,6 +282,18 @@ export const initialNodes = (originNodes: Node[], originEdges: Edge[]) => { iterationNodeData.error_handle_mode = iterationNodeData.error_handle_mode || ErrorHandleMode.Terminated } + // legacy provider handle + if (node.data.type === BlockEnum.LLM) + (node as any).data.model.provider = correctProvider((node as any).data.model.provider) + + if (node.data.type === BlockEnum.KnowledgeRetrieval && (node as any).data.multiple_retrieval_config.reranking_model) + (node as any).data.multiple_retrieval_config.reranking_model.provider = correctProvider((node as any).data.multiple_retrieval_config.reranking_model.provider) + + if (node.data.type === BlockEnum.QuestionClassifier) + (node as any).data.model.provider = correctProvider((node as any).data.model.provider) + + if (node.data.type === BlockEnum.ParameterExtractor) + (node as any).data.model.provider = correctProvider((node as any).data.model.provider) if (node.data.type === BlockEnum.HttpRequest && !node.data.retry_config) { node.data.retry_config = { retry_enabled: true, @@ -382,6 +395,7 @@ export const canRunBySingle = (nodeType: BlockEnum) => { || nodeType === BlockEnum.Tool || nodeType === BlockEnum.ParameterExtractor || nodeType === BlockEnum.Iteration + || nodeType === BlockEnum.Agent || nodeType === BlockEnum.DocExtractor } @@ -443,7 +457,7 @@ export const genNewNodeTitleFromOld = (oldTitle: string) => { if (match) { const title = match[1] - const num = parseInt(match[2], 10) + const num = Number.parseInt(match[2], 10) return `${title} (${num + 1})` } else { diff --git a/web/app/dev-preview/page.tsx b/web/app/dev-preview/page.tsx new file mode 100644 index 0000000000..24631aa28e --- /dev/null +++ b/web/app/dev-preview/page.tsx @@ -0,0 +1,19 @@ +'use client' + +import { ToolTipContent } from '../components/base/tooltip/content' +import { SwitchPluginVersion } from '../components/workflow/nodes/_base/components/switch-plugin-version' +import { useTranslation } from 'react-i18next' + +export default function Page() { + const { t } = useTranslation() + return <div className="p-20"> + <SwitchPluginVersion + uniqueIdentifier={'langgenius/openai:12'} + tooltip={<ToolTipContent + title={t('workflow.nodes.agent.unsupportedStrategy')} + > + {t('workflow.nodes.agent.strategyNotFoundDescAndSwitchVersion')} + </ToolTipContent>} + /> + </div> +} diff --git a/web/app/layout.tsx b/web/app/layout.tsx index b52c904561..0dfa0609f9 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -38,6 +38,8 @@ const LocaleLayout = ({ className="h-full select-auto color-scheme" data-api-prefix={process.env.NEXT_PUBLIC_API_PREFIX} data-pubic-api-prefix={process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX} + data-marketplace-api-prefix={process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX} + data-marketplace-url-prefix={process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX} data-public-edition={process.env.NEXT_PUBLIC_EDITION} data-public-support-mail-login={process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN} data-public-sentry-dsn={process.env.NEXT_PUBLIC_SENTRY_DSN} diff --git a/web/app/repos/[owner]/[repo]/releases/route.ts b/web/app/repos/[owner]/[repo]/releases/route.ts new file mode 100644 index 0000000000..29b604d94b --- /dev/null +++ b/web/app/repos/[owner]/[repo]/releases/route.ts @@ -0,0 +1,36 @@ +import { type NextRequest, NextResponse } from 'next/server' +import { Octokit } from '@octokit/core' +import { RequestError } from '@octokit/request-error' +import { GITHUB_ACCESS_TOKEN } from '@/config' + +type Params = { + owner: string, + repo: string, +} + +const octokit = new Octokit({ + auth: GITHUB_ACCESS_TOKEN, +}) + +export async function GET( + request: NextRequest, + { params }: { params: Promise<Params> }, +) { + const { owner, repo } = (await params) + try { + const releasesRes = await octokit.request('GET /repos/{owner}/{repo}/releases', { + owner, + repo, + headers: { + 'X-GitHub-Api-Version': '2022-11-28', + }, + }) + return NextResponse.json(releasesRes) + } + catch (error) { + if (error instanceof RequestError) + return NextResponse.json(error.response) + else + throw error + } +} diff --git a/web/app/signin/_header.tsx b/web/app/signin/_header.tsx index a9479a3fe4..9d03f18ac4 100644 --- a/web/app/signin/_header.tsx +++ b/web/app/signin/_header.tsx @@ -3,7 +3,7 @@ import React from 'react' import { useContext } from 'use-context-selector' import Select from '@/app/components/base/select/locale' import { languages } from '@/i18n/language' -import { type Locale } from '@/i18n' +import type { Locale } from '@/i18n' import I18n from '@/context/i18n' import LogoSite from '@/app/components/base/logo/logo-site' diff --git a/web/app/signin/oneMoreStep.tsx b/web/app/signin/oneMoreStep.tsx index 8554b364c0..dfb8a04781 100644 --- a/web/app/signin/oneMoreStep.tsx +++ b/web/app/signin/oneMoreStep.tsx @@ -13,7 +13,7 @@ import { LanguagesSupported, languages } from '@/i18n/language' import { oneMoreStep } from '@/service/common' import Toast from '@/app/components/base/toast' -type IState = { +interface IState { formState: 'processing' | 'error' | 'success' | 'initial' invitation_code: string interface_language: string diff --git a/web/app/styles/globals.css b/web/app/styles/globals.css index f2aadc5820..573523fd48 100644 --- a/web/app/styles/globals.css +++ b/web/app/styles/globals.css @@ -292,7 +292,7 @@ button:focus-within { line-height: 24px; } -[class*='code-'] { +[class*="code-"] { @apply font-mono; } @@ -654,7 +654,7 @@ button:focus-within { } .text-gradient { - background: linear-gradient(91.58deg, #2250F2 -29.55%, #0EBCF3 75.22%); + background: linear-gradient(91.58deg, #2250f2 -29.55%, #0ebcf3 75.22%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; @@ -662,7 +662,7 @@ button:focus-within { } /* overwrite paging active dark model style */ -[class*=style_paginatio] li .text-primary-600 { +[class*="style_paginatio"] li .text-primary-600 { color: rgb(28 100 242); background-color: rgb(235 245 255); } @@ -675,8 +675,13 @@ button:focus-within { bottom: 0; } -@import '../components/base/button/index.css'; -@import '../components/base/action-button/index.css'; -@import '../components/base/modal/index.css'; +[data-theme="dark"] [data-hide-on-theme="dark"], +[data-theme="light"] [data-hide-on-theme="light"] { + display: none; +} + +@import "../components/base/button/index.css"; +@import "../components/base/action-button/index.css"; +@import "../components/base/modal/index.css"; @tailwind utilities; \ No newline at end of file diff --git a/web/config/index.ts b/web/config/index.ts index b87c027de1..5600022ba1 100644 --- a/web/config/index.ts +++ b/web/config/index.ts @@ -1,10 +1,11 @@ -/* eslint-disable import/no-mutable-exports */ import { InputVarType } from '@/app/components/workflow/types' import { AgentStrategy } from '@/types/app' import { PromptRole } from '@/models/debug' export let apiPrefix = '' export let publicApiPrefix = '' +export let marketplaceApiPrefix = '' +export let marketplaceUrlPrefix = '' // NEXT_PUBLIC_API_PREFIX=/console/api NEXT_PUBLIC_PUBLIC_API_PREFIX=/api npm run start if (process.env.NEXT_PUBLIC_API_PREFIX && process.env.NEXT_PUBLIC_PUBLIC_API_PREFIX) { @@ -25,10 +26,22 @@ else { // const env = domainParts.length === 2 ? 'ai' : domainParts?.[0]; apiPrefix = 'http://localhost:5001/console/api' publicApiPrefix = 'http://localhost:5001/api' // avoid browser private mode api cross origin + marketplaceApiPrefix = 'http://localhost:5002/api' +} + +if (process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX && process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX) { + marketplaceApiPrefix = process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX + marketplaceUrlPrefix = process.env.NEXT_PUBLIC_MARKETPLACE_URL_PREFIX +} +else { + marketplaceApiPrefix = globalThis.document?.body?.getAttribute('data-marketplace-api-prefix') || '' + marketplaceUrlPrefix = globalThis.document?.body?.getAttribute('data-marketplace-url-prefix') || '' } export const API_PREFIX: string = apiPrefix export const PUBLIC_API_PREFIX: string = publicApiPrefix +export const MARKETPLACE_API_PREFIX: string = marketplaceApiPrefix +export const MARKETPLACE_URL_PREFIX: string = marketplaceUrlPrefix const EDITION = process.env.NEXT_PUBLIC_EDITION || globalThis.document?.body?.getAttribute('data-public-edition') || 'SELF_HOSTED' export const IS_CE_EDITION = EDITION === 'SELF_HOSTED' @@ -251,12 +264,15 @@ export const resetReg = () => VAR_REGEX.lastIndex = 0 export let textGenerationTimeoutMs = 60000 if (process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS && process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS !== '') - textGenerationTimeoutMs = parseInt(process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS) + textGenerationTimeoutMs = Number.parseInt(process.env.NEXT_PUBLIC_TEXT_GENERATION_TIMEOUT_MS) else if (globalThis.document?.body?.getAttribute('data-public-text-generation-timeout-ms') && globalThis.document.body.getAttribute('data-public-text-generation-timeout-ms') !== '') - textGenerationTimeoutMs = parseInt(globalThis.document.body.getAttribute('data-public-text-generation-timeout-ms') as string) + textGenerationTimeoutMs = Number.parseInt(globalThis.document.body.getAttribute('data-public-text-generation-timeout-ms') as string) export const TEXT_GENERATION_TIMEOUT_MS = textGenerationTimeoutMs export const DISABLE_UPLOAD_IMAGE_AS_ICON = process.env.NEXT_PUBLIC_DISABLE_UPLOAD_IMAGE_AS_ICON === 'true' +export const GITHUB_ACCESS_TOKEN = process.env.NEXT_PUBLIC_GITHUB_ACCESS_TOKEN || '' + +export const SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS = '.difypkg,.difybndl' export const FULL_DOC_PREVIEW_LENGTH = 50 diff --git a/web/context/modal-context.tsx b/web/context/modal-context.tsx index 2dfc08cf88..622077ee91 100644 --- a/web/context/modal-context.tsx +++ b/web/context/modal-context.tsx @@ -31,6 +31,8 @@ import ModelLoadBalancingModal from '@/app/components/header/account-setting/mod import OpeningSettingModal from '@/app/components/base/features/new-feature-panel/conversation-opener/modal' import type { OpeningStatement } from '@/app/components/base/features/types' import type { InputVar } from '@/app/components/workflow/types' +import type { UpdatePluginPayload } from '@/app/components/plugins/types' +import UpdatePlugin from '@/app/components/plugins/update-plugin' export type ModalState<T> = { payload: T @@ -52,6 +54,7 @@ export type LoadBalancingEntryModalType = ModelModalType & { entry?: ModelLoadBalancingConfigEntry index?: number } + export type ModalContextState = { setShowAccountSettingModal: Dispatch<SetStateAction<ModalState<string> | null>> setShowApiBasedExtensionModal: Dispatch<SetStateAction<ModalState<ApiBasedExtension> | null>> @@ -68,6 +71,7 @@ export type ModalContextState = { workflowVariables?: InputVar[] onAutoAddPromptVariable?: (variable: PromptVariable[]) => void }> | null>> + setShowUpdatePluginModal: Dispatch<SetStateAction<ModalState<UpdatePluginPayload> | null>> } const ModalContext = createContext<ModalContextState>({ setShowAccountSettingModal: () => { }, @@ -81,13 +85,13 @@ const ModalContext = createContext<ModalContextState>({ setShowModelLoadBalancingModal: () => { }, setShowModelLoadBalancingEntryModal: () => { }, setShowOpeningModal: () => { }, + setShowUpdatePluginModal: () => { }, }) export const useModalContext = () => useContext(ModalContext) // Adding a dangling comma to avoid the generic parsing issue in tsx, see: // https://github.com/microsoft/TypeScript/issues/15713 -// eslint-disable-next-line @typescript-eslint/comma-dangle export const useModalContextSelector = <T,>(selector: (state: ModalContextState) => T): T => useContextSelector(ModalContext, selector) @@ -110,6 +114,8 @@ export const ModalContextProvider = ({ workflowVariables?: InputVar[] onAutoAddPromptVariable?: (variable: PromptVariable[]) => void }> | null>(null) + const [showUpdatePluginModal, setShowUpdatePluginModal] = useState<ModalState<UpdatePluginPayload> | null>(null) + const searchParams = useSearchParams() const router = useRouter() const [showPricingModal, setShowPricingModal] = useState(searchParams.get('show-pricing') === '1') @@ -229,6 +235,7 @@ export const ModalContextProvider = ({ setShowModelLoadBalancingModal, setShowModelLoadBalancingEntryModal, setShowOpeningModal, + setShowUpdatePluginModal, }}> <> {children} @@ -339,6 +346,22 @@ export const ModalContextProvider = ({ onAutoAddPromptVariable={showOpeningModal.payload.onAutoAddPromptVariable} /> )} + + { + !!showUpdatePluginModal && ( + <UpdatePlugin + {...showUpdatePluginModal.payload} + onCancel={() => { + setShowUpdatePluginModal(null) + showUpdatePluginModal.onCancelCallback?.() + }} + onSave={() => { + setShowUpdatePluginModal(null) + showUpdatePluginModal.onSaveCallback?.({} as any) + }} + /> + ) + } </> </ModalContext.Provider> ) diff --git a/web/context/provider-context.tsx b/web/context/provider-context.tsx index 75747ba79c..83039ca7a0 100644 --- a/web/context/provider-context.tsx +++ b/web/context/provider-context.tsx @@ -21,6 +21,7 @@ import { defaultPlan } from '@/app/components/billing/config' type ProviderContextState = { modelProviders: ModelProvider[] + refreshModelProviders: () => void textGenerationModelList: Model[] supportRetrievalMethods: RETRIEVE_METHOD[] isAPIKeySet: boolean @@ -38,6 +39,7 @@ type ProviderContextState = { } const ProviderContext = createContext<ProviderContextState>({ modelProviders: [], + refreshModelProviders: () => { }, textGenerationModelList: [], supportRetrievalMethods: [], isAPIKeySet: true, @@ -70,7 +72,6 @@ export const useProviderContext = () => useContext(ProviderContext) // Adding a dangling comma to avoid the generic parsing issue in tsx, see: // https://github.com/microsoft/TypeScript/issues/15713 -// eslint-disable-next-line @typescript-eslint/comma-dangle export const useProviderContextSelector = <T,>(selector: (state: ProviderContextState) => T): T => useContextSelector(ProviderContext, selector) @@ -80,7 +81,7 @@ type ProviderContextProviderProps = { export const ProviderContextProvider = ({ children, }: ProviderContextProviderProps) => { - const { data: providersData } = useSWR('/workspaces/current/model-providers', fetchModelProviders) + const { data: providersData, mutate: refreshModelProviders } = useSWR('/workspaces/current/model-providers', fetchModelProviders) const fetchModelListUrlPrefix = '/workspaces/current/models/model-types/' const { data: textGenerationModelList } = useSWR(`${fetchModelListUrlPrefix}${ModelTypeEnum.textGeneration}`, fetchModelList) const { data: supportRetrievalMethods } = useSWR('/datasets/retrieval-setting', fetchSupportRetrievalMethods) @@ -113,6 +114,7 @@ export const ProviderContextProvider = ({ return ( <ProviderContext.Provider value={{ modelProviders: providersData?.data || [], + refreshModelProviders, textGenerationModelList: textGenerationModelList?.data || [], isAPIKeySet: !!textGenerationModelList?.data.some(model => model.status === ModelStatusEnum.active), supportRetrievalMethods: supportRetrievalMethods?.retrieval_method || [], diff --git a/web/docker/entrypoint.sh b/web/docker/entrypoint.sh index 8c6de0eb79..0822d17b02 100755 --- a/web/docker/entrypoint.sh +++ b/web/docker/entrypoint.sh @@ -16,6 +16,8 @@ export NEXT_PUBLIC_DEPLOY_ENV=${DEPLOY_ENV} export NEXT_PUBLIC_EDITION=${EDITION} export NEXT_PUBLIC_API_PREFIX=${CONSOLE_API_URL}/console/api export NEXT_PUBLIC_PUBLIC_API_PREFIX=${APP_API_URL}/api +export NEXT_PUBLIC_MARKETPLACE_API_PREFIX=${MARKETPLACE_API_URL}/api/v1 +export NEXT_PUBLIC_MARKETPLACE_URL_PREFIX=${MARKETPLACE_URL} export NEXT_PUBLIC_SENTRY_DSN=${SENTRY_DSN} export NEXT_PUBLIC_SITE_ABOUT=${SITE_ABOUT} diff --git a/web/eslint.config.mjs b/web/eslint.config.mjs new file mode 100644 index 0000000000..58dec4999e --- /dev/null +++ b/web/eslint.config.mjs @@ -0,0 +1,183 @@ +import { + GLOB_TESTS, combine, javascript, node, + stylistic, typescript, unicorn, +} from '@antfu/eslint-config' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import js from '@eslint/js' +import { FlatCompat } from '@eslint/eslintrc' +import globals from 'globals' +import storybook from 'eslint-plugin-storybook' +import { fixupConfigRules } from '@eslint/compat' +import tailwind from 'eslint-plugin-tailwindcss' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}) + +export default combine( + stylistic({ + lessOpinionated: true, + // original @antfu/eslint-config does not support jsx + jsx: false, + semi: false, + quotes: 'single', + overrides: { + // original config + 'style/indent': ['error', 2], + 'style/quotes': ['error', 'single'], + 'curly': ['error', 'multi-or-nest', 'consistent'], + 'style/comma-spacing': ['error', { before: false, after: true }], + 'style/quote-props': ['warn', 'consistent-as-needed'], + + // these options does not exist in old version + // maybe useless + 'style/indent-binary-ops': 'off', + 'style/multiline-ternary': 'off', + 'antfu/top-level-function': 'off', + 'antfu/curly': 'off', + 'antfu/consistent-chaining': 'off', + + // copy from eslint-config-antfu 0.36.0 + 'style/brace-style': ['error', 'stroustrup', { allowSingleLine: true }], + 'style/dot-location': ['error', 'property'], + 'style/object-curly-newline': ['error', { consistent: true, multiline: true }], + 'style/object-property-newline': ['error', { allowMultiplePropertiesPerLine: true }], + 'style/template-curly-spacing': ['error', 'never'], + 'style/keyword-spacing': 'off', + + // not exist in old version, and big change + 'style/member-delimiter-style': 'off', + }, + }), + javascript({ + overrides: { + // handled by unused-imports/no-unused-vars + 'no-unused-vars': 'off', + }, + }), + typescript({ + overrides: { + // original config + 'ts/consistent-type-definitions': ['warn', 'type'], + + // useful, but big change + 'ts/no-empty-object-type': 'off', + }, + }), + unicorn(), + node(), + // use nextjs config will break @eslint/config-inspector + // use `ESLINT_CONFIG_INSPECTOR=true pnpx @eslint/config-inspector` to check the config + ...process.env.ESLINT_CONFIG_INSPECTOR + ? [] + // TODO: remove this when upgrade to nextjs 15 + : fixupConfigRules(compat.extends('next')), + { + rules: { + // performance issue, and not used. + '@next/next/no-html-link-for-pages': 'off', + }, + }, + { + ignores: [ + '**/node_modules/*', + '**/node_modules/', + '**/dist/', + '**/build/', + '**/out/', + '**/.next/', + '**/public/*', + '**/*.json', + ], + }, + { + // orignal config + rules: { + // orignal ts/no-var-requires + 'ts/no-require-imports': 'off', + 'no-console': 'off', + 'react-hooks/exhaustive-deps': 'warn', + 'react/display-name': 'off', + 'array-callback-return': ['error', { + allowImplicit: false, + checkForEach: false, + }], + + // copy from eslint-config-antfu 0.36.0 + 'camelcase': 'off', + 'default-case-last': 'error', + + // antfu use eslint-plugin-perfectionist to replace this + // will cause big change, so keep the original sort-imports + 'sort-imports': [ + 'error', + { + ignoreCase: false, + ignoreDeclarationSort: true, + ignoreMemberSort: false, + memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], + allowSeparatedGroups: false, + }, + ], + + // antfu migrate to eslint-plugin-unused-imports + 'unused-imports/no-unused-vars': 'warn', + 'unused-imports/no-unused-imports': 'warn', + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2025, + ...globals.node, + React: 'readable', + JSX: 'readable', + }, + }, + }, + storybook.configs['flat/recommended'], + // need futher research + { + rules: { + // not exist in old version + 'antfu/consistent-list-newline': 'off', + 'node/prefer-global/process': 'off', + 'node/prefer-global/buffer': 'off', + 'node/no-callback-literal': 'off', + + // useful, but big change + 'unicorn/prefer-number-properties': 'warn', + 'unicorn/no-new-array': 'warn', + }, + }, + // suppress error for `no-undef` rule + { + files: GLOB_TESTS, + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2021, + ...globals.node, + ...globals.jest, + }, + }, + }, + tailwind.configs['flat/recommended'], + { + rules: { + // due to 1k lines of tailwind config, these rule have performance issue + 'tailwindcss/no-contradicting-classname': 'off', + 'tailwindcss/no-unnecessary-arbitrary-value': 'off', + 'tailwindcss/enforces-shorthand': 'off', + 'tailwindcss/no-custom-classname': 'off', + + // in the future + 'tailwindcss/classnames-order': 'off', + }, + }, +) diff --git a/web/hooks/use-i18n.ts b/web/hooks/use-i18n.ts new file mode 100644 index 0000000000..261293c86d --- /dev/null +++ b/web/hooks/use-i18n.ts @@ -0,0 +1,14 @@ +import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' + +export const renderI18nObject = (obj: Record<string, string>, language: string) => { + if (obj?.[language]) return obj[language] + if (obj?.en_US) return obj.en_US + return Object.values(obj)[0] +} + +export const useRenderI18nObject = () => { + const language = useLanguage() + return (obj: Record<string, string>) => { + return renderI18nObject(obj, language) + } +} diff --git a/web/hooks/use-metadata.ts b/web/hooks/use-metadata.ts index 5d1d86c20e..a3105d314a 100644 --- a/web/hooks/use-metadata.ts +++ b/web/hooks/use-metadata.ts @@ -9,22 +9,22 @@ export type metadataType = DocType | 'originInfo' | 'technicalParameters' type MetadataMap = Record< - metadataType, - { - text: string - allowEdit?: boolean - icon?: React.ReactNode - iconName?: string - subFieldsMap: Record< - string, + metadataType, { - label: string - inputType?: inputType - field?: string - render?: (value: any, total?: number) => React.ReactNode | string + text: string + allowEdit?: boolean + icon?: React.ReactNode + iconName?: string + subFieldsMap: Record< + string, + { + label: string + inputType?: inputType + field?: string + render?: (value: any, total?: number) => React.ReactNode | string + } + > } - > - } > const fieldPrefix = 'datasetDocuments.metadata.field' diff --git a/web/hooks/use-mitt.ts b/web/hooks/use-mitt.ts new file mode 100644 index 0000000000..b9094bc262 --- /dev/null +++ b/web/hooks/use-mitt.ts @@ -0,0 +1,74 @@ +import type { Emitter, EventType, Handler, WildcardHandler } from 'mitt' +import create from 'mitt' +import { useEffect, useRef } from 'react' + +const merge = <T extends Record<string, any>>( + ...args: Array<T | undefined> +): T => { + return Object.assign({}, ...args) +} + +export type _Events = Record<EventType, unknown> + +export type UseSubcribeOption = { + /** + * Whether the subscription is enabled. + * @default true + */ + enabled: boolean; +} + +export type ExtendedOn<Events extends _Events> = { + <Key extends keyof Events>( + type: Key, + handler: Handler<Events[Key]>, + options?: UseSubcribeOption, + ): void; + ( + type: '*', + handler: WildcardHandler<Events>, + option?: UseSubcribeOption, + ): void; +} + +export type UseMittReturn<Events extends _Events> = { + useSubcribe: ExtendedOn<Events>; + emit: Emitter<Events>['emit']; +} + +const defaultSubcribeOption: UseSubcribeOption = { + enabled: true, +} + +function useMitt<Events extends _Events>( + mitt?: Emitter<Events>, +): UseMittReturn<Events> { + const emitterRef = useRef<Emitter<Events>>() + if (!emitterRef.current) + emitterRef.current = mitt ?? create<Events>() + + if (mitt && emitterRef.current !== mitt) { + emitterRef.current.off('*') + emitterRef.current = mitt + } + const emitter = emitterRef.current + const useSubcribe: ExtendedOn<Events> = ( + type: string, + handler: any, + option?: UseSubcribeOption, + ) => { + const { enabled } = merge(defaultSubcribeOption, option) + useEffect(() => { + if (enabled) { + emitter.on(type, handler) + return () => emitter.off(type, handler) + } + }) + } + return { + emit: emitter.emit, + useSubcribe, + } +} + +export { useMitt } diff --git a/web/hooks/use-pay.tsx b/web/hooks/use-pay.tsx index 344f03955c..3ba23b6763 100644 --- a/web/hooks/use-pay.tsx +++ b/web/hooks/use-pay.tsx @@ -4,11 +4,8 @@ import { useCallback, useEffect, useState } from 'react' import { useRouter, useSearchParams } from 'next/navigation' import { useTranslation } from 'react-i18next' import useSWR from 'swr' -import { useContext } from 'use-context-selector' -import I18n from '@/context/i18n' import { fetchDataSourceNotionBinding, - fetchFreeQuotaVerify, } from '@/service/common' import type { IConfirm } from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm' @@ -53,66 +50,6 @@ export const useBillingPay = () => { return confirm } -const QUOTA_RECEIVE_STATUS: Record<string, any> = { - spark: { - success: { - 'en': 'Successful collection, the quota will be automatically increased after 5 minutes.', - 'zh-Hans': '领取成功,将在 5 分钟后自动增加配额', - }, - fail: { - 'en': 'Failure to collect', - 'zh-Hans': '领取失败', - }, - }, - zhipuai: { - success: { - 'en': 'Successful collection', - 'zh-Hans': '领取成功', - }, - fail: { - 'en': 'Failure to collect', - 'zh-Hans': '领取失败', - }, - }, -} - -const FREE_CHECK_PROVIDER = ['spark', 'zhipuai'] -export const useCheckFreeQuota = () => { - const { locale } = useContext(I18n) - const router = useRouter() - const [shouldVerify, setShouldVerify] = useState(false) - const searchParams = useSearchParams() - const type = searchParams.get('type') - const provider = searchParams.get('provider') - const result = searchParams.get('result') - const token = searchParams.get('token') - - const { data, error } = useSWR( - shouldVerify - ? `/workspaces/current/model-providers/${provider}/free-quota-qualification-verify?token=${token}` - : null, - fetchFreeQuotaVerify, - ) - - useEffect(() => { - if (error) - router.replace('/') - }, [error, router]) - - useEffect(() => { - if (type === 'provider_apply_callback' && FREE_CHECK_PROVIDER.includes(provider as string) && result === 'success') - setShouldVerify(true) - }, [type, provider, result]) - - return (data && provider) - ? { - type: data.flag ? 'info' : 'warning', - title: data.flag ? QUOTA_RECEIVE_STATUS[provider as string].success[locale] : QUOTA_RECEIVE_STATUS[provider].fail[locale], - desc: !data.flag ? data.reason : undefined, - } - : null -} - export const useCheckNotion = () => { const router = useRouter() const [confirm, setConfirm] = useState<ConfirmType | null>(null) @@ -154,7 +91,6 @@ export const CheckModal = () => { const { t } = useTranslation() const [showPayStatusModal, setShowPayStatusModal] = useState(true) const anthropicConfirmInfo = useAnthropicCheckPay() - const freeQuotaConfirmInfo = useCheckFreeQuota() const notionConfirmInfo = useCheckNotion() const billingConfirmInfo = useBillingPay() @@ -163,7 +99,7 @@ export const CheckModal = () => { router.replace('/') }, [router]) - const confirmInfo = anthropicConfirmInfo || freeQuotaConfirmInfo || notionConfirmInfo || billingConfirmInfo + const confirmInfo = anthropicConfirmInfo || notionConfirmInfo || billingConfirmInfo if (!confirmInfo || !showPayStatusModal) return null @@ -176,7 +112,7 @@ export const CheckModal = () => { showCancel={false} type={confirmInfo.type === 'info' ? 'info' : 'warning' } title={confirmInfo.title} - content={(confirmInfo as { desc: string }).desc || ''} + content={(confirmInfo as unknown as { desc: string }).desc || ''} confirmText={(confirmInfo.type === 'info' && t('common.operation.ok')) || ''} /> ) diff --git a/web/hooks/use-timestamp.ts b/web/hooks/use-timestamp.ts index 05cc48eaad..5242eb565a 100644 --- a/web/hooks/use-timestamp.ts +++ b/web/hooks/use-timestamp.ts @@ -15,7 +15,11 @@ const useTimestamp = () => { return dayjs.unix(value).tz(timezone).format(format) }, [timezone]) - return { formatTime } + const formatDate = useCallback((value: string, format: string) => { + return dayjs(value).tz(timezone).format(format) + }, [timezone]) + + return { formatTime, formatDate } } export default useTimestamp diff --git a/web/i18n/de-DE/plugin-tags.ts b/web/i18n/de-DE/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/de-DE/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/de-DE/plugin.ts b/web/i18n/de-DE/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/de-DE/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/en-US/app.ts b/web/i18n/en-US/app.ts index 861827d3e3..b77f09d7f3 100644 --- a/web/i18n/en-US/app.ts +++ b/web/i18n/en-US/app.ts @@ -169,6 +169,12 @@ const translation = { removeConfirmContent: 'The current configuration is in use, removing it will turn off the Tracing feature.', }, }, + appSelector: { + label: 'APP', + placeholder: 'Select an app...', + params: 'APP PARAMETERS', + noParams: 'No parameters needed', + }, showMyCreatedAppsOnly: 'Created by me', } diff --git a/web/i18n/en-US/common.ts b/web/i18n/en-US/common.ts index c116e080b4..bbe80b539c 100644 --- a/web/i18n/en-US/common.ts +++ b/web/i18n/en-US/common.ts @@ -23,9 +23,11 @@ const translation = { remove: 'Remove', send: 'Send', copy: 'Copy', + copied: 'Copied', lineBreak: 'Line break', sure: 'I\'m sure', download: 'Download', + viewDetails: 'View Details', delete: 'Delete', settings: 'Settings', setup: 'Setup', @@ -38,13 +40,14 @@ const translation = { duplicate: 'Duplicate', rename: 'Rename', audioSourceUnavailable: 'AudioSource is unavailable', + close: 'Close', copyImage: 'Copy Image', imageCopied: 'Image copied', zoomOut: 'Zoom Out', zoomIn: 'Zoom In', openInNewTab: 'Open in new tab', + in: 'in', saveAndRegenerate: 'Save & Regenerate Child Chunks', - close: 'Close', view: 'View', viewMore: 'VIEW MORE', regenerate: 'Regenerate', @@ -126,12 +129,15 @@ const translation = { Custom: 'Custom', }, addMoreModel: 'Go to settings to add more models', + settingsLink: 'Model Provider Settings', + capabilities: 'MultiModal Capabilities', }, menus: { status: 'beta', explore: 'Explore', apps: 'Studio', plugins: 'Plugins', + exploreMarketplace: 'Explore Marketplace', pluginsTips: 'Integrate third-party plugins or create ChatGPT-compatible AI-Plugins.', datasets: 'Knowledge', datasetsTips: 'COMING SOON: Import your own text data or write data in real-time via Webhook for LLM context enhancement.', @@ -154,6 +160,7 @@ const translation = { settings: { accountGroup: 'GENERAL', workplaceGroup: 'WORKSPACE', + generalGroup: 'GENERAL', account: 'My account', members: 'Members', billing: 'Billing', @@ -302,7 +309,7 @@ const translation = { }, }, modelProvider: { - notConfigured: 'The system model has not yet been fully configured, and some functions may be unavailable.', + notConfigured: 'The system model has not yet been fully configured', systemModelSettings: 'System Model Settings', systemModelSettingsLink: 'Why is it necessary to set up a system model?', selectModel: 'Select your model', @@ -400,6 +407,12 @@ const translation = { loadBalancingLeastKeyWarning: 'To enable load balancing at least 2 keys must be enabled.', loadBalancingInfo: 'By default, load balancing uses the Round-robin strategy. If rate limiting is triggered, a 1-minute cooldown period will be applied.', upgradeForLoadBalancing: 'Upgrade your plan to enable Load Balancing.', + configureRequired: 'Configure required', + configureTip: 'Set up api-key or add model to use', + installProvider: 'Install model providers', + discoverMore: 'Discover more in ', + emptyProviderTitle: 'Model provider not set up', + emptyProviderTip: 'Please install a model provider first.', }, dataSource: { add: 'Add a data source', diff --git a/web/i18n/en-US/plugin-tags.ts b/web/i18n/en-US/plugin-tags.ts new file mode 100644 index 0000000000..d2177b2848 --- /dev/null +++ b/web/i18n/en-US/plugin-tags.ts @@ -0,0 +1,25 @@ +const translation = { + allTags: 'All Tags', + searchTags: 'Search Tags', + tags: { + agent: 'Agent', + search: 'Search', + image: 'Image', + videos: 'Videos', + weather: 'Weather', + finance: 'Finance', + design: 'Design', + travel: 'Travel', + social: 'Social', + news: 'News', + medical: 'Medical', + productivity: 'Productivity', + education: 'Education', + business: 'Business', + entertainment: 'Entertainment', + utilities: 'Utilities', + other: 'Other', + }, +} + +export default translation diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts new file mode 100644 index 0000000000..ea93b8812d --- /dev/null +++ b/web/i18n/en-US/plugin.ts @@ -0,0 +1,206 @@ +const translation = { + category: { + all: 'All', + models: 'Models', + tools: 'Tools', + agents: 'Agent Strategies', + extensions: 'Extensions', + bundles: 'Bundles', + }, + categorySingle: { + model: 'Model', + tool: 'Tool', + agent: 'Agent Strategy', + extension: 'Extension', + bundle: 'Bundle', + }, + search: 'Search', + allCategories: 'All Categories', + searchCategories: 'Search Categories', + searchPlugins: 'Search plugins', + from: 'From', + findMoreInMarketplace: 'Find more in Marketplace', + searchInMarketplace: 'Search in Marketplace', + fromMarketplace: 'From Marketplace', + endpointsEnabled: '{{num}} sets of endpoints enabled', + searchTools: 'Search tools...', + installPlugin: 'Install plugin', + installFrom: 'INSTALL FROM', + list: { + noInstalled: 'No plugins installed', + notFound: 'No plugins found', + source: { + marketplace: 'Install from Marketplace', + github: 'Install from GitHub', + local: 'Install from Local Package File', + }, + }, + source: { + marketplace: 'Marketplace', + github: 'GitHub', + local: 'Local Package File', + }, + detailPanel: { + switchVersion: 'Switch Version', + categoryTip: { + marketplace: 'Installed from Marketplace', + github: 'Installed from Github', + local: 'Local Plugin', + debugging: 'Debugging Plugin', + }, + operation: { + install: 'Install', + detail: 'Details', + update: 'Update', + info: 'Plugin Info', + checkUpdate: 'Check Update', + viewDetail: 'View Detail', + remove: 'Remove', + }, + actionNum: '{{num}} {{action}} INCLUDED', + strategyNum: '{{num}} {{strategy}} INCLUDED', + endpoints: 'Endpoints', + endpointsTip: 'This plugin provides specific functionalities via endpoints, and you can configure multiple endpoint sets for current workspace.', + endpointsDocLink: 'View the document', + endpointsEmpty: 'Click the \'+\' button to add an endpoint', + endpointDisableTip: 'Disable Endpoint', + endpointDisableContent: 'Would you like to disable {{name}}? ', + endpointDeleteTip: 'Remove Endpoint', + endpointDeleteContent: 'Would you like to remove {{name}}? ', + endpointModalTitle: 'Setup endpoint', + endpointModalDesc: 'Once configured, the features provided by the plugin via API endpoints can be used.', + serviceOk: 'Service OK', + disabled: 'Disabled', + modelNum: '{{num}} MODELS INCLUDED', + toolSelector: { + title: 'Add tool', + toolLabel: 'Tool', + descriptionLabel: 'Tool description', + descriptionPlaceholder: 'Brief description of the tool\'s purpose, e.g., get the temperature for a specific location.', + placeholder: 'Select a tool...', + auth: 'AUTHORIZATION', + settings: 'TOOL SETTINGS', + empty: 'Click the \'+\' button to add tools. You can add multiple tools.', + uninstalledTitle: 'Tool not installed', + uninstalledContent: 'This plugin is installed from the local/GitHub repository. Please use after installation.', + uninstalledLink: 'Manage in Plugins', + unsupportedTitle: 'Unsupported Action', + unsupportedContent: 'The installed plugin version does not provide this action.', + unsupportedContent2: 'Click to switch version.', + }, + configureApp: 'Configure App', + configureModel: 'Configure model', + configureTool: 'Configure tool', + }, + install: '{{num}} installs', + installAction: 'Install', + debugInfo: { + title: 'Debugging', + viewDocs: 'View Docs', + }, + privilege: { + title: 'Plugin Preferences', + whoCanInstall: 'Who can install and manage plugins?', + whoCanDebug: 'Who can debug plugins?', + everyone: 'Everyone', + admins: 'Admins', + noone: 'No one', + }, + pluginInfoModal: { + title: 'Plugin info', + repository: 'Repository', + release: 'Release', + packageName: 'Package', + }, + action: { + checkForUpdates: 'Check for updates', + pluginInfo: 'Plugin info', + delete: 'Remove plugin', + deleteContentLeft: 'Would you like to remove ', + deleteContentRight: ' plugin?', + usedInApps: 'This plugin is being used in {{num}} apps.', + }, + installModal: { + installPlugin: 'Install Plugin', + installComplete: 'Installation complete', + installedSuccessfully: 'Installation successful', + installedSuccessfullyDesc: 'The plugin has been installed successfully.', + uploadFailed: 'Upload failed', + installFailed: 'Installation failed', + installFailedDesc: 'The plugin has been installed failed.', + install: 'Install', + installing: 'Installing...', + uploadingPackage: 'Uploading {{packageName}}...', + readyToInstall: 'About to install the following plugin', + readyToInstallPackage: 'About to install the following plugin', + readyToInstallPackages: 'About to install the following {{num}} plugins', + fromTrustSource: 'Please make sure that you only install plugins from a <trustSource>trusted source</trustSource>.', + dropPluginToInstall: 'Drop plugin package here to install', + labels: { + repository: 'Repository', + version: 'Version', + package: 'Package', + }, + close: 'Close', + cancel: 'Cancel', + back: 'Back', + next: 'Next', + pluginLoadError: 'Plugin load error', + pluginLoadErrorDesc: 'This plugin will not be installed', + }, + installFromGitHub: { + installPlugin: 'Install plugin from GitHub', + updatePlugin: 'Update plugin from GitHub', + installedSuccessfully: 'Installation successful', + installFailed: 'Installation failed', + uploadFailed: 'Upload failed', + gitHubRepo: 'GitHub repository', + selectVersion: 'Select version', + selectVersionPlaceholder: 'Please select a version', + installNote: 'Please make sure that you only install plugins from a trusted source.', + selectPackage: 'Select package', + selectPackagePlaceholder: 'Please select a package', + }, + upgrade: { + title: 'Install Plugin', + successfulTitle: 'Install successful', + description: 'About to install the following plugin', + usedInApps: 'Used in {{num}} apps', + upgrade: 'Install', + upgrading: 'Installing...', + close: 'Close', + }, + error: { + inValidGitHubUrl: 'Invalid GitHub URL. Please enter a valid URL in the format: https://github.com/owner/repo', + fetchReleasesError: 'Unable to retrieve releases. Please try again later.', + noReleasesFound: 'No releases found. Please check the GitHub repository or the input URL.', + }, + marketplace: { + empower: 'Empower your AI development', + discover: 'Discover', + and: 'and', + difyMarketplace: 'Dify Marketplace', + moreFrom: 'More from Marketplace', + noPluginFound: 'No plugin found', + pluginsResult: '{{num}} results', + sortBy: 'Sort by', + sortOption: { + mostPopular: 'Most Popular', + recentlyUpdated: 'Recently Updated', + newlyReleased: 'Newly Released', + firstReleased: 'First Released', + }, + viewMore: 'View more', + }, + task: { + installing: 'Installing {{installingLength}} plugins, 0 done.', + installingWithSuccess: 'Installing {{installingLength}} plugins, {{successLength}} success.', + installingWithError: 'Installing {{installingLength}} plugins, {{successLength}} success, {{errorLength}} failed', + installError: '{{errorLength}} plugins failed to install, click to view', + installedError: '{{errorLength}} plugins failed to install', + clearAll: 'Clear all', + }, + submitPlugin: 'Submit plugin', +} + +export default translation diff --git a/web/i18n/en-US/run-log.ts b/web/i18n/en-US/run-log.ts index 33fe5c1735..3c851f4548 100644 --- a/web/i18n/en-US/run-log.ts +++ b/web/i18n/en-US/run-log.ts @@ -24,6 +24,8 @@ const translation = { link: 'detail panel', tipRight: ' view it.', }, + actionLogs: 'Action Logs', + circularInvocationTip: 'There is circular invocation of tools/nodes in the current workflow.', } export default translation diff --git a/web/i18n/en-US/tools.ts b/web/i18n/en-US/tools.ts index b1f278f9ce..f624fac945 100644 --- a/web/i18n/en-US/tools.ts +++ b/web/i18n/en-US/tools.ts @@ -4,7 +4,7 @@ const translation = { customToolTip: 'Learn more about Dify custom tools', type: { all: 'All', - builtIn: 'Built-in', + builtIn: 'Tools', custom: 'Custom', workflow: 'Workflow', }, @@ -21,7 +21,7 @@ const translation = { setupModalTitle: 'Set Up Authorization', setupModalTitleDescription: 'After configuring credentials, all members within the workspace can use this tool when orchestrating applications.', }, - includeToolNum: '{{num}} tools included', + includeToolNum: '{{num}} {{action}} included', addTool: 'Add Tool', addToolModal: { type: 'type', @@ -131,6 +131,7 @@ const translation = { parameters: 'parameters', string: 'string', number: 'number', + file: 'file', required: 'Required', infoAndSetting: 'Info & Settings', }, @@ -146,10 +147,12 @@ const translation = { }, builtInPromptTitle: 'Prompt', toolRemoved: 'Tool removed', - notAuthorized: 'Tool not authorized', + notAuthorized: 'Not authorized', howToGet: 'How to get', openInStudio: 'Open in Studio', toolNameUsageTip: 'Tool call name for agent reasoning and prompting', + copyToolName: 'Copy Name', + noTools: 'No tools found', } export default translation diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index 42b7048f85..53c50073c0 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -210,7 +210,7 @@ const translation = { 'searchTool': 'Search tool', 'tools': 'Tools', 'allTool': 'All', - 'builtInTool': 'Built-in', + 'plugin': 'Plugin', 'customTool': 'Custom', 'workflowTool': 'Workflow', 'question-understand': 'Question Understand', @@ -218,6 +218,7 @@ const translation = { 'transform': 'Transform', 'utilities': 'Utilities', 'noResult': 'No match found', + 'agent': 'Agent Strategy', }, blocks: { 'start': 'Start', @@ -238,6 +239,7 @@ const translation = { 'parameter-extractor': 'Parameter Extractor', 'document-extractor': 'Doc Extractor', 'list-operator': 'List Operator', + 'agent': 'Agent', }, blocksAbout: { 'start': 'Define the initial parameters for launching a workflow', @@ -257,6 +259,7 @@ const translation = { 'parameter-extractor': 'Use LLM to extract structured parameters from natural language for tool invocations or HTTP requests.', 'document-extractor': 'Used to parse uploaded documents into text content that is easily understandable by LLM.', 'list-operator': 'Used to filter or sort array content.', + 'agent': 'Invoking large language models to answer questions or process natural language', }, operator: { zoomIn: 'Zoom In', @@ -697,6 +700,75 @@ const translation = { last_record: 'Last record', }, }, + agent: { + strategy: { + label: 'Agentic Strategy', + tooltip: 'Different Agentic strategies determine how the system plans and executes multi-step tool calls', + shortLabel: 'Strategy', + configureTip: 'Please configure agentic strategy.', + configureTipDesc: 'After configuring the agentic strategy, this node will automatically load the remaining configurations. The strategy will affect the mechanism of multi-step tool reasoning. ', + selectTip: 'Select agentic strategy', + searchPlaceholder: 'Search agentic strategy', + }, + learnMore: 'Learn more', + pluginNotInstalled: 'This plugin is not installed', + pluginNotInstalledDesc: 'This plugin is installed from GitHub. Please go to Plugins to reinstall', + linkToPlugin: 'Link to Plugins', + pluginInstaller: { + install: 'Install', + installing: 'Installing', + }, + modelNotInMarketplace: { + title: 'Model not installed', + desc: 'This model is installed from Local or GitHub repository. Please use after installation.', + manageInPlugins: 'Manage in Plugins', + }, + modelNotSupport: { + title: 'Unsupported Model', + desc: 'The installed plugin version does not provide this model.', + descForVersionSwitch: 'The installed plugin version does not provide this model. Click to switch version.', + }, + configureModel: 'Configure Model', + notAuthorized: 'Not Authorized', + model: 'model', + toolbox: 'toolbox', + strategyNotSet: 'Agentic strategy Not Set', + tools: 'Tools', + maxIterations: 'Max Iterations', + modelNotSelected: 'Model not selected', + modelNotInstallTooltip: 'This model is not installed', + toolNotInstallTooltip: '{{tool}} is not installed', + toolNotAuthorizedTooltip: '{{tool}} Not Authorized', + strategyNotInstallTooltip: '{{strategy}} is not installed', + unsupportedStrategy: 'Unsupported strategy', + pluginNotFoundDesc: 'This plugin is installed from GitHub. Please go to Plugins to reinstall', + strategyNotFoundDesc: 'The installed plugin version does not provide this strategy.', + strategyNotFoundDescAndSwitchVersion: 'The installed plugin version does not provide this strategy. Click to switch version.', + modelSelectorTooltips: { + deprecated: 'This model is deprecated', + }, + outputVars: { + text: 'agent generated content', + files: { + title: 'agent generated files', + type: 'Support type. Now only support image', + transfer_method: 'Transfer method.Value is remote_url or local_file', + url: 'Image url', + upload_file_id: 'Upload file id', + }, + json: 'agent generated json', + }, + checkList: { + strategyNotSelected: 'Strategy not selected', + }, + installPlugin: { + title: 'Install Plugin', + desc: 'About to install the following plugin', + changelog: 'Change log', + install: 'Install', + cancel: 'Cancel', + }, + }, }, tracing: { stopBy: 'Stop by {{user}}', diff --git a/web/i18n/es-ES/plugin-tags.ts b/web/i18n/es-ES/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/es-ES/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/es-ES/plugin.ts b/web/i18n/es-ES/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/es-ES/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/fa-IR/plugin-tags.ts b/web/i18n/fa-IR/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/fa-IR/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/fa-IR/plugin.ts b/web/i18n/fa-IR/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/fa-IR/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/fr-FR/plugin-tags.ts b/web/i18n/fr-FR/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/fr-FR/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/fr-FR/plugin.ts b/web/i18n/fr-FR/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/fr-FR/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/hi-IN/plugin-tags.ts b/web/i18n/hi-IN/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/hi-IN/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/hi-IN/plugin.ts b/web/i18n/hi-IN/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/hi-IN/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/hi-IN/share-app.ts b/web/i18n/hi-IN/share-app.ts index a5c7816fe2..74c23f8fda 100644 --- a/web/i18n/hi-IN/share-app.ts +++ b/web/i18n/hi-IN/share-app.ts @@ -3,6 +3,8 @@ const translation = { welcome: 'आपका स्वागत है', appUnavailable: 'ऐप उपलब्ध नहीं है', appUnknownError: 'अज्ञात त्रुटि, कृपया पुनः प्रयास करें', + // @ts-expect-error TODO: fix this + // eslint-disable-next-line no-dupe-keys appUnknownError: 'ऐप अनुपलब्ध है', }, chat: { diff --git a/web/i18n/i18next-config.ts b/web/i18n/i18next-config.ts index 661475ea21..bbba4c7c35 100644 --- a/web/i18n/i18next-config.ts +++ b/web/i18n/i18next-config.ts @@ -28,6 +28,8 @@ const loadLangResources = (lang: string) => ({ tools: require(`./${lang}/tools`).default, workflow: require(`./${lang}/workflow`).default, runLog: require(`./${lang}/run-log`).default, + plugin: require(`./${lang}/plugin`).default, + pluginTags: require(`./${lang}/plugin-tags`).default, }, }) diff --git a/web/i18n/it-IT/plugin-tags.ts b/web/i18n/it-IT/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/it-IT/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/it-IT/plugin.ts b/web/i18n/it-IT/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/it-IT/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ja-JP/plugin-tags.ts b/web/i18n/ja-JP/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ja-JP/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ja-JP/plugin.ts b/web/i18n/ja-JP/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ja-JP/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ko-KR/plugin-tags.ts b/web/i18n/ko-KR/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ko-KR/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ko-KR/plugin.ts b/web/i18n/ko-KR/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ko-KR/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/pl-PL/plugin-tags.ts b/web/i18n/pl-PL/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/pl-PL/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/pl-PL/plugin.ts b/web/i18n/pl-PL/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/pl-PL/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/pt-BR/plugin-tags.ts b/web/i18n/pt-BR/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/pt-BR/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/pt-BR/plugin.ts b/web/i18n/pt-BR/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/pt-BR/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ro-RO/plugin-tags.ts b/web/i18n/ro-RO/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ro-RO/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ro-RO/plugin.ts b/web/i18n/ro-RO/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ro-RO/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ru-RU/plugin-tags.ts b/web/i18n/ru-RU/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ru-RU/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/ru-RU/plugin.ts b/web/i18n/ru-RU/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/ru-RU/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/stop-sequence.tsx b/web/i18n/sl-SI/plugin-tags.ts similarity index 100% rename from web/app/components/header/account-setting/model-provider-page/model-parameter-modal/stop-sequence.tsx rename to web/i18n/sl-SI/plugin-tags.ts diff --git a/web/i18n/sl-SI/plugin.ts b/web/i18n/sl-SI/plugin.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/i18n/th-TH/plugin-tags.ts b/web/i18n/th-TH/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/th-TH/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/th-TH/plugin.ts b/web/i18n/th-TH/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/th-TH/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/tr-TR/plugin-tags.ts b/web/i18n/tr-TR/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/tr-TR/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/tr-TR/plugin.ts b/web/i18n/tr-TR/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/tr-TR/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/uk-UA/plugin-tags.ts b/web/i18n/uk-UA/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/uk-UA/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/uk-UA/plugin.ts b/web/i18n/uk-UA/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/uk-UA/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/vi-VN/plugin-tags.ts b/web/i18n/vi-VN/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/vi-VN/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/vi-VN/plugin.ts b/web/i18n/vi-VN/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/vi-VN/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/zh-Hans/app.ts b/web/i18n/zh-Hans/app.ts index 3d3e95130d..4e212279a6 100644 --- a/web/i18n/zh-Hans/app.ts +++ b/web/i18n/zh-Hans/app.ts @@ -169,6 +169,12 @@ const translation = { removeConfirmContent: '当前配置正在使用中,删除它将关闭追踪功能。', }, }, + appSelector: { + label: '应用', + placeholder: '选择一个应用', + params: '应用参数', + noParams: '无需参数', + }, openInExplore: '在“探索”中打开', showMyCreatedAppsOnly: '我创建的', } diff --git a/web/i18n/zh-Hans/common.ts b/web/i18n/zh-Hans/common.ts index 53c5337cab..614d3f8528 100644 --- a/web/i18n/zh-Hans/common.ts +++ b/web/i18n/zh-Hans/common.ts @@ -23,9 +23,11 @@ const translation = { remove: '移除', send: '发送', copy: '复制', + copied: ' 已复制', lineBreak: '换行', sure: '我确定', download: '下载', + viewDetails: '查看详情', delete: '删除', settings: '设置', setup: '设置', @@ -43,6 +45,7 @@ const translation = { zoomOut: '缩小', zoomIn: '放大', openInNewTab: '在新标签页打开', + in: '在', saveAndRegenerate: '保存并重新生成子分段', close: '关闭', view: '查看', @@ -126,12 +129,15 @@ const translation = { Custom: '自定义', }, addMoreModel: '添加更多模型', + settingsLink: '模型设置', + capabilities: '多模态能力', }, menus: { status: 'beta', explore: '探索', apps: '工作室', plugins: '插件', + exploreMarketplace: '探索 Marketplace', pluginsTips: '集成第三方插件或创建与 ChatGPT 兼容的 AI 插件。', datasets: '知识库', datasetsTips: '即将到来: 上传自己的长文本数据,或通过 Webhook 集成自己的数据源', @@ -154,6 +160,7 @@ const translation = { settings: { accountGroup: '通用', workplaceGroup: '工作空间', + generalGroup: '通用', account: '我的账户', members: '成员', billing: '账单', @@ -302,7 +309,7 @@ const translation = { }, }, modelProvider: { - notConfigured: '系统模型尚未完全配置,部分功能可能无法使用。', + notConfigured: '系统模型尚未完全配置', systemModelSettings: '系统模型设置', systemModelSettingsLink: '为什么需要设置系统模型?', selectModel: '选择您的模型', @@ -400,6 +407,12 @@ const translation = { loadBalancingInfo: '默认情况下,负载均衡使用 Round-robin 策略。如果触发速率限制,将应用 1 分钟的冷却时间', upgradeForLoadBalancing: '升级以解锁负载均衡功能', apiKey: 'API 密钥', + configureRequired: '尚未配置', + configureTip: '请配置 API 密钥,添加模型。', + installProvider: '安装模型供应商', + discoverMore: '发现更多就在', + emptyProviderTitle: '尚未安装模型供应商', + emptyProviderTip: '请安装模型供应商。', }, dataSource: { add: '添加数据源', diff --git a/web/i18n/zh-Hans/plugin-tags.ts b/web/i18n/zh-Hans/plugin-tags.ts new file mode 100644 index 0000000000..c133992b38 --- /dev/null +++ b/web/i18n/zh-Hans/plugin-tags.ts @@ -0,0 +1,25 @@ +const translation = { + allTags: '所有标签', + searchTags: '搜索标签', + tags: { + agent: 'Agent', + search: '搜索', + image: '图片', + videos: '视频', + weather: '天气', + finance: '金融', + design: '设计', + travel: '旅行', + social: '社交', + news: '新闻', + medical: '医疗', + productivity: '生产力', + education: '教育', + business: '商业', + entertainment: '娱乐', + utilities: '工具', + other: '其他', + }, +} + +export default translation diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts new file mode 100644 index 0000000000..53f2ef8e5c --- /dev/null +++ b/web/i18n/zh-Hans/plugin.ts @@ -0,0 +1,206 @@ +const translation = { + category: { + all: '全部', + models: '模型', + tools: '工具', + agents: 'Agent 策略', + extensions: '扩展', + bundles: '插件集', + }, + categorySingle: { + model: '模型', + tool: '工具', + agent: 'Agent 策略', + extension: '扩展', + bundle: '插件集', + }, + search: '搜索', + allCategories: '所有类别', + searchCategories: '搜索类别', + searchPlugins: '搜索插件', + from: '来自', + findMoreInMarketplace: '在 Marketplace 中查找更多', + searchInMarketplace: '在 Marketplace 中搜索', + fromMarketplace: '来自市场', + endpointsEnabled: '{{num}} 组端点已启用', + searchTools: '搜索工具...', + installPlugin: '安装插件', + installFrom: '安装源', + list: { + noInstalled: '无已安装的插件', + notFound: '未找到插件', + source: { + marketplace: '从 Marketplace 安装', + github: '从 GitHub 安装', + local: '本地插件', + }, + }, + source: { + marketplace: 'Marketplace', + github: 'GitHub', + local: '本地插件', + }, + detailPanel: { + switchVersion: '切换版本', + categoryTip: { + marketplace: '从 Marketplace 安装', + github: '从 Github 安装', + local: '本地插件', + debugging: '调试插件', + }, + operation: { + install: '安装', + detail: '详情', + update: '更新', + info: '插件信息', + checkUpdate: '检查更新', + viewDetail: '查看详情', + remove: '移除', + }, + actionNum: '包含 {{num}} 个 {{action}}', + strategyNum: '包含 {{num}} 个 {{strategy}}', + endpoints: 'API 端点', + endpointsTip: '此插件通过 API 端点提供特定功能,您可以为当前工作区配置多个 API 端点集。', + endpointsDocLink: '查看文档', + endpointsEmpty: '点击 \'+\' 按钮添加 API 端点', + endpointDisableTip: '停用 API 端点', + endpointDisableContent: '是否要停用 {{name}} 的 API 端点 ?', + endpointDeleteTip: '移除 API 端点', + endpointDeleteContent: '是否要移除 {{name}} ?', + endpointModalTitle: '设置 API 端点', + endpointModalDesc: '完成配置后可使用插件 API 端点提供的功能', + serviceOk: '服务正常', + disabled: '停用', + modelNum: '{{num}} 模型已包含', + toolSelector: { + title: '添加工具', + toolLabel: '工具', + descriptionLabel: '工具描述', + descriptionPlaceholder: '简要描述工具目的,例如,获取特定位置的温度。', + placeholder: '选择工具', + auth: '授权', + settings: '工具设置', + empty: '点击 "+" 按钮添加工具。您可以添加多个工具。', + uninstalledTitle: '工具未安装', + uninstalledContent: '此插件安装自 本地 / GitHub 仓库,请安装后使用。', + uninstalledLink: '在插件中管理', + unsupportedTitle: '不支持的 Action', + unsupportedContent: '已安装的插件版本不提供这个 action。', + unsupportedContent2: '点击切换版本', + }, + configureApp: '应用设置', + configureModel: '模型设置', + configureTool: '工具设置', + }, + install: '{{num}} 次安装', + installAction: '安装', + debugInfo: { + title: '调试', + viewDocs: '查看文档', + }, + privilege: { + title: '插件偏好', + whoCanInstall: '谁可以安装和管理插件?', + whoCanDebug: '谁可以调试插件?', + everyone: '所有人', + admins: '管理员', + noone: '无人', + }, + pluginInfoModal: { + title: '插件信息', + repository: '仓库', + release: '发布版本', + packageName: '包', + }, + action: { + checkForUpdates: '检查更新', + pluginInfo: '插件信息', + delete: '移除插件', + deleteContentLeft: '是否要移除 ', + deleteContentRight: ' 插件?', + usedInApps: '此插件正在 {{num}} 个应用中使用。', + }, + installModal: { + installPlugin: '安装插件', + installComplete: '安装完成', + installedSuccessfully: '安装成功', + installedSuccessfullyDesc: '插件已成功安装。', + uploadFailed: '上传失败', + installFailed: '安装失败', + installFailedDesc: '插件安装失败。', + install: '安装', + installing: '安装中...', + uploadingPackage: '上传 {{packageName}} 中...', + readyToInstall: '即将安装以下插件', + readyToInstallPackage: '即将安装以下插件', + readyToInstallPackages: '即将安装以下 {{num}} 个插件', + fromTrustSource: '请保证仅从<trustSource>可信源</trustSource>安装插件。', + dropPluginToInstall: '拖放插件包到此处安装', + labels: { + repository: '仓库', + version: '版本', + package: '包', + }, + close: '关闭', + cancel: '取消', + back: '返回', + next: '下一步', + pluginLoadError: '插件加载错误', + pluginLoadErrorDesc: '此插件将不会被安装', + }, + installFromGitHub: { + installPlugin: '从 GitHub 安装插件', + updatePlugin: '更新来自 GitHub 的插件', + installedSuccessfully: '安装成功', + installFailed: '安装失败', + uploadFailed: '上传失败', + gitHubRepo: 'GitHub 仓库', + selectVersion: '选择版本', + selectVersionPlaceholder: '请选择一个版本', + installNote: '请确保只从可信源安装插件。', + selectPackage: '选择包', + selectPackagePlaceholder: '请选择一个包', + }, + upgrade: { + title: '安装插件', + successfulTitle: '安装成功', + description: '即将安装以下插件', + usedInApps: '在 {{num}} 个应用中使用', + upgrade: '安装', + upgrading: '安装中...', + close: '关闭', + }, + error: { + inValidGitHubUrl: '无效的 GitHub URL。请输入格式为 https://github.com/owner/repo 的有效 URL', + fetchReleasesError: '无法获取发布版本。请稍后再试。', + noReleasesFound: '未找到发布版本。请检查 GitHub 仓库或输入的 URL。', + }, + marketplace: { + empower: '助力您的 AI 开发', + discover: '探索', + and: '和', + difyMarketplace: 'Dify 市场', + moreFrom: '更多来自市场', + noPluginFound: '未找到插件', + pluginsResult: '{{num}} 个插件结果', + sortBy: '排序方式', + sortOption: { + mostPopular: '最受欢迎', + recentlyUpdated: '最近更新', + newlyReleased: '最新发布', + firstReleased: '首次发布', + }, + viewMore: '查看更多', + }, + task: { + installing: '{{installingLength}} 个插件安装中,0 已完成', + installingWithSuccess: '{{installingLength}} 个插件安装中,{{successLength}} 安装成功', + installingWithError: '{{installingLength}} 个插件安装中,{{successLength}} 安装成功,{{errorLength}} 安装失败', + installError: '{{errorLength}} 个插件安装失败,点击查看', + installedError: '{{errorLength}} 个插件安装失败', + clearAll: '清除所有', + }, + submitPlugin: '上传插件', +} + +export default translation diff --git a/web/i18n/zh-Hans/run-log.ts b/web/i18n/zh-Hans/run-log.ts index 225874d827..dc93e9aeb0 100644 --- a/web/i18n/zh-Hans/run-log.ts +++ b/web/i18n/zh-Hans/run-log.ts @@ -24,6 +24,8 @@ const translation = { link: '详细信息面板', tipRight: '查看它。', }, + actionLogs: 'Action 日志', + circularInvocationTip: '当前工作流中存在工具/节点的循环调用。', } export default translation diff --git a/web/i18n/zh-Hans/tools.ts b/web/i18n/zh-Hans/tools.ts index a788ef0abe..98e7b6e271 100644 --- a/web/i18n/zh-Hans/tools.ts +++ b/web/i18n/zh-Hans/tools.ts @@ -4,7 +4,7 @@ const translation = { customToolTip: '了解更多关于 Dify 自定义工具的信息', type: { all: '全部', - builtIn: '内置', + builtIn: '工具', custom: '自定义', workflow: '工作流', }, @@ -21,7 +21,7 @@ const translation = { setupModalTitle: '设置授权', setupModalTitleDescription: '配置凭据后,工作区中的所有成员都可以在编排应用程序时使用此工具。', }, - includeToolNum: '包含 {{num}} 个工具', + includeToolNum: '包含 {{num}} 个 {{action}}', addTool: '添加工具', addToolModal: { type: '类型', @@ -131,6 +131,7 @@ const translation = { parameters: '参数', string: '字符串', number: '数字', + file: '文件', required: '必填', infoAndSetting: '信息和设置', }, @@ -150,6 +151,8 @@ const translation = { howToGet: '如何获取', openInStudio: '在工作室中打开', toolNameUsageTip: '工具调用名称,用于 Agent 推理和提示词', + copyToolName: '复制名称', + noTools: '没有工具', } export default translation diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index 93ebda4ce9..c622581e2d 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -210,7 +210,7 @@ const translation = { 'searchTool': '搜索工具', 'tools': '工具', 'allTool': '全部', - 'builtInTool': '内置', + 'plugin': '插件', 'customTool': '自定义', 'workflowTool': '工作流', 'question-understand': '问题理解', @@ -218,6 +218,7 @@ const translation = { 'transform': '转换', 'utilities': '工具', 'noResult': '未找到匹配项', + 'agent': 'Agent 策略', }, blocks: { 'start': '开始', @@ -238,6 +239,7 @@ const translation = { 'parameter-extractor': '参数提取器', 'document-extractor': '文档提取器', 'list-operator': '列表操作', + 'agent': 'Agent', }, blocksAbout: { 'start': '定义一个 workflow 流程启动的初始参数', @@ -257,6 +259,7 @@ const translation = { 'parameter-extractor': '利用 LLM 从自然语言内推理提取出结构化参数,用于后置的工具调用或 HTTP 请求。', 'document-extractor': '用于将用户上传的文档解析为 LLM 便于理解的文本内容。', 'list-operator': '用于过滤或排序数组内容。', + 'agent': '调用大型语言模型回答问题或处理自然语言', }, operator: { zoomIn: '放大', @@ -697,6 +700,75 @@ const translation = { last_record: '最后一条记录', }, }, + agent: { + strategy: { + label: 'Agent 策略', + tooltip: '不同的 Agent 策略决定了系统如何规划和执行多步工具调用', + shortLabel: '策略', + configureTip: '请配置 Agent 策略。', + configureTipDesc: '配置完成后,此节点将自动加载剩余配置。策略将影响多步工具推理的机制。', + selectTip: '选择 Agent 策略', + searchPlaceholder: '搜索 Agent 策略', + }, + learnMore: '了解更多', + pluginNotInstalled: '插件未安装', + pluginNotInstalledDesc: '此插件是从 GitHub 安装的。请转到插件重新安装', + linkToPlugin: '转到插件', + pluginInstaller: { + install: '安装', + installing: '安装中', + }, + modelNotInMarketplace: { + title: '模型未安装', + desc: '此模型安装自本地或 GitHub 仓库。请安装后使用。', + manageInPlugins: '在插件中管理', + }, + modelNotSupport: { + title: '不支持的模型', + desc: '已安装的插件版本不提供此模型。', + descForVersionSwitch: '已安装的插件版本不提供此模型。点击切换版本。', + }, + model: '模型', + toolbox: '工具箱', + strategyNotSet: '代理策略未设置', + configureModel: '配置模型', + notAuthorized: '未授权', + tools: '工具', + maxIterations: '最大迭代次数', + modelNotInstallTooltip: '此模型未安装', + modelNotSelected: '未选择模型', + toolNotInstallTooltip: '{{tool}} 未安装', + toolNotAuthorizedTooltip: '{{tool}} 未授权', + strategyNotInstallTooltip: '{{strategy}} 未安装', + unsupportedStrategy: '不支持的策略', + strategyNotFoundDesc: '安装的插件版本不提供此策略。', + pluginNotFoundDesc: '此插件安装自 GitHub。请转到插件重新安装。', + strategyNotFoundDescAndSwitchVersion: '安装的插件版本不提供此策略。点击切换版本。', + modelSelectorTooltips: { + deprecated: '此模型已弃用', + }, + outputVars: { + text: 'agent 生成的内容', + files: { + title: 'agent 生成的文件', + type: '支持类型。现在只支持图片', + transfer_method: '传输方式。值为 remote_url 或 local_file', + url: '图片链接', + upload_file_id: '上传文件ID', + }, + json: 'agent 生成的json', + }, + checkList: { + strategyNotSelected: '未选择策略', + }, + installPlugin: { + title: '安装插件', + desc: '即将安装以下插件', + changelog: '更新日志', + install: '安装', + cancel: '取消', + }, + }, }, tracing: { stopBy: '由{{user}}终止', diff --git a/web/i18n/zh-Hant/plugin-tags.ts b/web/i18n/zh-Hant/plugin-tags.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/zh-Hant/plugin-tags.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/i18n/zh-Hant/plugin.ts b/web/i18n/zh-Hant/plugin.ts new file mode 100644 index 0000000000..928649474b --- /dev/null +++ b/web/i18n/zh-Hant/plugin.ts @@ -0,0 +1,4 @@ +const translation = { +} + +export default translation diff --git a/web/models/app.ts b/web/models/app.ts index acb1c09622..81a8575dd8 100644 --- a/web/models/app.ts +++ b/web/models/app.ts @@ -1,5 +1,6 @@ import type { LangFuseConfig, LangSmithConfig, TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type' import type { App, AppSSO, AppTemplate, SiteConfig } from '@/types/app' +import type { Dependency } from '@/app/components/plugins/types' /* export type App = { id: string @@ -87,6 +88,7 @@ export type DSLImportResponse = { current_dsl_version?: string imported_dsl_version?: string error: string + leaked_dependencies: Dependency[] } export type AppSSOResponse = { enabled: AppSSO['enable_sso'] } diff --git a/web/models/common.ts b/web/models/common.ts index dc2b1120b9..48bdc8ae44 100644 --- a/web/models/common.ts +++ b/web/models/common.ts @@ -1,23 +1,23 @@ import type { I18nText } from '@/i18n/language' -export type CommonResponse = { +export interface CommonResponse { result: 'success' | 'fail' } -export type OauthResponse = { +export interface OauthResponse { redirect_url: string } -export type SetupStatusResponse = { +export interface SetupStatusResponse { step: 'finished' | 'not_started' setup_at?: Date } -export type InitValidateStatusResponse = { +export interface InitValidateStatusResponse { status: 'finished' | 'not_started' } -export type UserProfileResponse = { +export interface UserProfileResponse { id: string name: string email: string @@ -32,13 +32,13 @@ export type UserProfileResponse = { created_at?: string } -export type UserProfileOriginResponse = { +export interface UserProfileOriginResponse { json: () => Promise<UserProfileResponse> bodyUsed: boolean headers: any } -export type LangGeniusVersionResponse = { +export interface LangGeniusVersionResponse { current_version: string latest_version: string version: string @@ -48,7 +48,7 @@ export type LangGeniusVersionResponse = { current_env: string } -export type TenantInfoResponse = { +export interface TenantInfoResponse { name: string created_at: string providers: Array<{ @@ -79,14 +79,14 @@ export enum ProviderName { Tongyi = 'tongyi', ChatGLM = 'chatglm', } -export type ProviderAzureToken = { +export interface ProviderAzureToken { openai_api_base?: string openai_api_key?: string } -export type ProviderAnthropicToken = { +export interface ProviderAnthropicToken { anthropic_api_key?: string } -export type ProviderTokenType = { +export interface ProviderTokenType { [ProviderName.OPENAI]: string [ProviderName.AZURE_OPENAI]: ProviderAzureToken [ProviderName.ANTHROPIC]: ProviderAnthropicToken @@ -109,14 +109,14 @@ export type ProviderHosted = Provider & { quota_used: number } -export type AccountIntegrate = { +export interface AccountIntegrate { provider: 'google' | 'github' created_at: number is_bound: boolean link: string } -export type IWorkspace = { +export interface IWorkspace { id: string name: string plan: string @@ -136,7 +136,7 @@ export type ICurrentWorkspace = Omit<IWorkspace, 'current'> & { } } -export type DataSourceNotionPage = { +export interface DataSourceNotionPage { page_icon: null | { type: string | null url: string | null @@ -155,7 +155,7 @@ export type NotionPage = DataSourceNotionPage & { export type DataSourceNotionPageMap = Record<string, DataSourceNotionPage & { workspace_id: string }> -export type DataSourceNotionWorkspace = { +export interface DataSourceNotionWorkspace { workspace_name: string workspace_id: string workspace_icon: string | null @@ -165,7 +165,7 @@ export type DataSourceNotionWorkspace = { export type DataSourceNotionWorkspaceMap = Record<string, DataSourceNotionWorkspace> -export type DataSourceNotion = { +export interface DataSourceNotion { id: string provider: string is_bound: boolean @@ -180,12 +180,12 @@ export enum DataSourceProvider { jinaReader = 'jinareader', } -export type FirecrawlConfig = { +export interface FirecrawlConfig { api_key: string base_url: string } -export type DataSourceItem = { +export interface DataSourceItem { id: string category: DataSourceCategory provider: DataSourceProvider @@ -194,15 +194,15 @@ export type DataSourceItem = { updated_at: number } -export type DataSources = { +export interface DataSources { sources: DataSourceItem[] } -export type GithubRepo = { +export interface GithubRepo { stargazers_count: number } -export type PluginProvider = { +export interface PluginProvider { tool_name: string is_enabled: boolean credentials: { @@ -210,7 +210,7 @@ export type PluginProvider = { } | null } -export type FileUploadConfigResponse = { +export interface FileUploadConfigResponse { batch_count_limit: number image_file_size_limit?: number | string // default is 10MB file_size_limit: number // default is 15MB @@ -233,14 +233,14 @@ export type InvitationResponse = CommonResponse & { invitation_results: InvitationResult[] } -export type ApiBasedExtension = { +export interface ApiBasedExtension { id?: string name?: string api_endpoint?: string api_key?: string } -export type CodeBasedExtensionForm = { +export interface CodeBasedExtensionForm { type: string label: I18nText variable: string @@ -251,17 +251,17 @@ export type CodeBasedExtensionForm = { max_length?: number } -export type CodeBasedExtensionItem = { +export interface CodeBasedExtensionItem { name: string label: any form_schema: CodeBasedExtensionForm[] } -export type CodeBasedExtension = { +export interface CodeBasedExtension { module: string data: CodeBasedExtensionItem[] } -export type ExternalDataTool = { +export interface ExternalDataTool { type?: string label?: string icon?: string @@ -273,7 +273,7 @@ export type ExternalDataTool = { } & Partial<Record<string, any>> } -export type ModerateResponse = { +export interface ModerateResponse { flagged: boolean text: string } diff --git a/web/models/debug.ts b/web/models/debug.ts index 00a78f927a..301248b234 100644 --- a/web/models/debug.ts +++ b/web/models/debug.ts @@ -10,25 +10,25 @@ export enum PromptMode { advanced = 'advanced', } -export type PromptItem = { +export interface PromptItem { role?: PromptRole text: string } -export type ChatPromptConfig = { +export interface ChatPromptConfig { prompt: PromptItem[] } -export type ConversationHistoriesRole = { +export interface ConversationHistoriesRole { user_prefix: string assistant_prefix: string } -export type CompletionPromptConfig = { +export interface CompletionPromptConfig { prompt: PromptItem conversation_histories_role: ConversationHistoriesRole } -export type BlockStatus = { +export interface BlockStatus { context: boolean history: boolean query: boolean @@ -40,7 +40,7 @@ export enum PromptRole { assistant = 'assistant', } -export type PromptVariable = { +export interface PromptVariable { key: string name: string type: string // "string" | "number" | "select", @@ -55,7 +55,7 @@ export type PromptVariable = { icon_background?: string } -export type CompletionParams = { +export interface CompletionParams { max_tokens: number temperature: number top_p: number @@ -66,12 +66,12 @@ export type CompletionParams = { export type ModelId = 'gpt-3.5-turbo' | 'text-davinci-003' -export type PromptConfig = { +export interface PromptConfig { prompt_template: string prompt_variables: PromptVariable[] } -export type MoreLikeThisConfig = { +export interface MoreLikeThisConfig { enabled: boolean } @@ -79,7 +79,7 @@ export type SuggestedQuestionsAfterAnswerConfig = MoreLikeThisConfig export type SpeechToTextConfig = MoreLikeThisConfig -export type TextToSpeechConfig = { +export interface TextToSpeechConfig { enabled: boolean voice?: string language?: string @@ -88,7 +88,7 @@ export type TextToSpeechConfig = { export type CitationConfig = MoreLikeThisConfig -export type AnnotationReplyConfig = { +export interface AnnotationReplyConfig { id: string enabled: boolean score_threshold: number @@ -98,7 +98,7 @@ export type AnnotationReplyConfig = { } } -export type ModerationContentConfig = { +export interface ModerationContentConfig { enabled: boolean preset_response?: string } @@ -113,14 +113,14 @@ export type ModerationConfig = MoreLikeThisConfig & { } export type RetrieverResourceConfig = MoreLikeThisConfig -export type AgentConfig = { +export interface AgentConfig { enabled: boolean strategy: AgentStrategy max_iteration: number tools: ToolItem[] } // frontend use. Not the same as backend -export type ModelConfig = { +export interface ModelConfig { provider: string // LLM Provider: for example "OPENAI" model_id: string mode: ModelModeType @@ -138,12 +138,12 @@ export type ModelConfig = { dataSets: any[] agentConfig: AgentConfig } -export type DatasetConfigItem = { +export interface DatasetConfigItem { enable: boolean value: number } -export type DatasetConfigs = { +export interface DatasetConfigs { retrieval_model: RETRIEVE_TYPE reranking_model: { reranking_provider_name: string @@ -172,39 +172,39 @@ export type DatasetConfigs = { reranking_enable?: boolean } -export type DebugRequestBody = { +export interface DebugRequestBody { inputs: Inputs query: string completion_params: CompletionParams model_config: ModelConfig } -export type DebugResponse = { +export interface DebugResponse { id: string answer: string created_at: string } -export type DebugResponseStream = { +export interface DebugResponseStream { id: string data: string created_at: string } -export type FeedBackRequestBody = { +export interface FeedBackRequestBody { message_id: string rating: 'like' | 'dislike' content?: string from_source: 'api' | 'log' } -export type FeedBackResponse = { +export interface FeedBackResponse { message_id: string rating: 'like' | 'dislike' } // Log session list -export type LogSessionListQuery = { +export interface LogSessionListQuery { keyword?: string start?: string // format datetime(YYYY-mm-dd HH:ii) end?: string // format datetime(YYYY-mm-dd HH:ii) @@ -212,7 +212,7 @@ export type LogSessionListQuery = { limit: number // default 20. 1-100 } -export type LogSessionListResponse = { +export interface LogSessionListResponse { data: { id: string conversation_id: string @@ -226,7 +226,7 @@ export type LogSessionListResponse = { } // log session detail and debug -export type LogSessionDetailResponse = { +export interface LogSessionDetailResponse { id: string conversation_id: string model_provider: string @@ -240,7 +240,7 @@ export type LogSessionDetailResponse = { from_source: 'api' | 'log' } -export type SavedMessage = { +export interface SavedMessage { id: string answer: string } diff --git a/web/package.json b/web/package.json index 304a42871b..5306c5c31b 100644 --- a/web/package.json +++ b/web/package.json @@ -6,166 +6,180 @@ "node": ">=18.17.0" }, "scripts": { - "dev": "next dev", + "dev": "NODE_OPTIONS='--inspect' next dev", "build": "next build", "start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js", "lint": "next lint", "fix": "next lint --fix", "eslint-fix": "eslint --fix", - "prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky install ./web/.husky", - "gen-icons": "node ./app/components/base/icons/script.js", + "prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky ./web/.husky", + "gen-icons": "node ./app/components/base/icons/script.mjs", "uglify-embed": "node ./bin/uglify-embed", "check-i18n": "node ./i18n/check-i18n.js", "auto-gen-i18n": "node ./i18n/auto-gen-i18n.js", "test": "jest", "test:watch": "jest --watch", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build-storybook": "storybook build", + "preinstall": "npx only-allow pnpm" }, "dependencies": { "@babel/runtime": "^7.22.3", - "@dagrejs/dagre": "^1.1.2", - "@emoji-mart/data": "^1.1.2", - "@floating-ui/react": "^0.25.2", - "@formatjs/intl-localematcher": "^0.5.4", + "@dagrejs/dagre": "^1.1.4", + "@emoji-mart/data": "^1.2.1", + "@floating-ui/react": "^0.26.25", + "@formatjs/intl-localematcher": "^0.5.6", "@headlessui/react": "^1.7.13", "@heroicons/react": "^2.0.16", - "@hookform/resolvers": "^3.3.4", - "@lexical/react": "^0.16.0", - "@mdx-js/loader": "^2.3.0", - "@mdx-js/react": "^2.3.0", + "@hookform/resolvers": "^3.9.0", + "@lexical/react": "^0.18.0", + "@mdx-js/loader": "^3.1.0", + "@mdx-js/react": "^3.1.0", "@monaco-editor/react": "^4.6.0", "@next/mdx": "^14.0.4", + "@octokit/core": "^6.1.2", + "@octokit/request-error": "^6.1.5", "@remixicon/react": "^4.5.0", "@sentry/react": "^7.54.0", "@sentry/utils": "^7.54.0", "@svgdotjs/svg.js": "^3.2.4", - "@tailwindcss/line-clamp": "^0.4.4", - "@tailwindcss/typography": "^0.5.9", + "@tailwindcss/typography": "^0.5.15", "@tanstack/react-query": "^5.60.5", "@tanstack/react-query-devtools": "^5.60.5", - "ahooks": "^3.7.5", + "ahooks": "^3.8.1", "class-variance-authority": "^0.7.0", - "classnames": "^2.3.2", + "classnames": "^2.5.1", "copy-to-clipboard": "^3.3.3", "crypto-js": "^4.2.0", - "dayjs": "^1.11.7", + "dayjs": "^1.11.13", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", "elkjs": "^0.9.3", "emoji-mart": "^5.5.2", "fast-deep-equal": "^3.1.3", - "i18next": "^22.4.13", - "i18next-resources-to-backend": "^1.1.3", + "globals": "^15.11.0", + "i18next": "^23.16.4", + "i18next-resources-to-backend": "^1.2.1", "immer": "^9.0.19", "js-audio-recorder": "^1.0.7", - "js-cookie": "^3.0.1", + "js-cookie": "^3.0.5", "jwt-decode": "^4.0.0", - "katex": "^0.16.10", + "katex": "^0.16.11", + "ky": "^1.7.2", "lamejs": "^1.2.1", - "lexical": "^0.16.0", + "lexical": "^0.18.0", "line-clamp": "^1.0.0", "lodash-es": "^4.17.21", "mermaid": "11.4.1", "mime": "^4.0.4", + "mitt": "^3.0.1", "negotiator": "^0.6.3", "next": "^14.2.10", - "pinyin-pro": "^3.23.0", - "qrcode.react": "^3.1.0", - "qs": "^6.11.1", - "rc-textarea": "^1.5.2", + "pinyin-pro": "^3.25.0", + "qrcode.react": "^4.1.0", + "qs": "^6.13.0", + "rc-textarea": "^1.8.2", "react": "~18.2.0", "react-18-input-autosize": "^3.0.0", "react-dom": "~18.2.0", - "react-easy-crop": "^5.0.8", - "react-error-boundary": "^4.0.2", - "react-hook-form": "^7.51.4", - "react-hotkeys-hook": "^4.6.1", - "react-i18next": "^12.2.0", + "react-easy-crop": "^5.1.0", + "react-error-boundary": "^4.1.2", + "react-headless-pagination": "^1.1.6", + "react-hook-form": "^7.53.1", + "react-i18next": "^15.1.0", "react-infinite-scroll-component": "^6.1.0", - "react-markdown": "^8.0.6", - "react-multi-email": "^1.0.14", - "react-papaparse": "^4.1.0", + "react-markdown": "^9.0.1", + "react-multi-email": "^1.0.25", + "react-papaparse": "^4.4.0", + "react-slider": "^2.0.6", + "react-hotkeys-hook": "^4.6.1", "react-pdf-highlighter": "^8.0.0-rc.0", - "react-slider": "^2.0.4", "react-sortablejs": "^6.1.4", - "react-syntax-highlighter": "^15.5.0", + "react-syntax-highlighter": "^15.6.1", "react-tooltip": "5.8.3", - "react-window": "^1.8.9", + "react-window": "^1.8.10", "react-window-infinite-loader": "^1.0.9", "reactflow": "^11.11.3", "recordrtc": "^5.6.2", - "rehype-katex": "^6.0.2", + "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", - "remark-breaks": "^3.0.2", - "remark-gfm": "^3.0.1", - "remark-math": "^5.1.1", + "remark-breaks": "^4.0.0", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", "scheduler": "^0.23.0", + "semver": "^7.6.3", "server-only": "^0.0.1", "sharp": "^0.33.2", "shave": "^5.0.4", "sortablejs": "^1.15.0", "swr": "^2.1.0", - "tailwind-merge": "^2.4.0", - "use-context-selector": "^1.4.1", - "uuid": "^9.0.1", - "zod": "^3.23.6", + "tailwind-merge": "^2.5.4", + "use-context-selector": "^2.0.0", + "uuid": "^10.0.0", + "zod": "^3.23.8", "zundo": "^2.1.0", "zustand": "^4.5.2" }, "devDependencies": { - "@antfu/eslint-config": "^0.36.0", - "@chromatic-com/storybook": "^1.9.0", - "@faker-js/faker": "^7.6.0", + "@antfu/eslint-config": "^3.8.0", + "@chromatic-com/storybook": "^3.1.0", + "@eslint-react/eslint-plugin": "^1.15.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.13.0", + "@faker-js/faker": "^9.0.3", "@rgrove/parse-xml": "^4.1.0", - "@storybook/addon-essentials": "^8.3.5", - "@storybook/addon-interactions": "^8.3.5", - "@storybook/addon-links": "^8.3.5", - "@storybook/addon-onboarding": "^8.3.5", - "@storybook/addon-themes": "^8.3.5", - "@storybook/blocks": "^8.3.5", - "@storybook/nextjs": "^8.3.5", - "@storybook/react": "^8.3.5", - "@storybook/test": "^8.3.5", - "@testing-library/dom": "^10.3.2", - "@testing-library/jest-dom": "^6.4.6", - "@testing-library/react": "^16.0.0", - "@types/crypto-js": "^4.1.1", + "@storybook/addon-essentials": "^8.3.6", + "@storybook/addon-interactions": "^8.3.6", + "@storybook/addon-links": "^8.3.6", + "@storybook/addon-onboarding": "^8.3.6", + "@storybook/addon-themes": "^8.3.6", + "@storybook/blocks": "^8.3.6", + "@storybook/nextjs": "^8.3.6", + "@storybook/react": "^8.3.6", + "@storybook/test": "^8.3.6", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.2", + "@testing-library/react": "^16.0.1", + "@types/crypto-js": "^4.2.2", "@types/dagre": "^0.7.52", - "@types/jest": "^29.5.12", - "@types/js-cookie": "^3.0.3", - "@types/lodash-es": "^4.17.7", - "@types/negotiator": "^0.6.1", + "@types/jest": "^29.5.13", + "@types/js-cookie": "^3.0.6", + "@types/lodash-es": "^4.17.12", + "@types/negotiator": "^0.6.3", "@types/node": "18.15.0", - "@types/qs": "^6.9.7", + "@types/qs": "^6.9.16", "@types/react": "~18.2.0", "@types/react-dom": "~18.2.0", - "@types/react-slider": "^1.3.1", - "@types/react-syntax-highlighter": "^15.5.6", - "@types/react-window": "^1.8.5", - "@types/react-window-infinite-loader": "^1.0.6", - "@types/recordrtc": "^5.6.11", + "@types/react-slider": "^1.3.6", + "@types/react-syntax-highlighter": "^15.5.13", + "@types/react-window": "^1.8.8", + "@types/react-window-infinite-loader": "^1.0.9", + "@types/recordrtc": "^5.6.14", + "@types/semver": "^7.5.8", "@types/sortablejs": "^1.15.1", - "@types/uuid": "^9.0.8", - "autoprefixer": "^10.4.14", + "@types/uuid": "^10.0.0", + "autoprefixer": "^10.4.20", "bing-translate-api": "^4.0.2", "code-inspector-plugin": "^0.18.1", "cross-env": "^7.0.3", - "eslint": "^8.36.0", - "eslint-config-next": "^14.0.4", - "eslint-plugin-storybook": "^0.9.0", - "husky": "^8.0.3", + "eslint": "^9.13.0", + "eslint-config-next": "^15.0.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.13", + "eslint-plugin-storybook": "^0.10.1", + "eslint-plugin-tailwindcss": "^3.17.5", + "husky": "^9.1.6", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", - "lint-staged": "^13.2.2", + "lint-staged": "^15.2.10", "magicast": "^0.3.4", - "postcss": "^8.4.31", - "sass": "^1.61.0", - "storybook": "^8.3.5", - "tailwindcss": "^3.4.4", + "postcss": "^8.4.47", + "sass": "^1.80.3", + "storybook": "^8.3.6", + "tailwindcss": "^3.4.14", "ts-node": "^10.9.2", "typescript": "4.9.5", - "uglify-js": "^3.17.4" + "uglify-js": "^3.19.3" }, "resolutions": { "@types/react": "~18.2.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml new file mode 100644 index 0000000000..e857736357 --- /dev/null +++ b/web/pnpm-lock.yaml @@ -0,0 +1,18306 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + '@types/react': ~18.2.0 + '@types/react-dom': ~18.2.0 + string-width: 4.2.3 + +importers: + + .: + dependencies: + '@babel/runtime': + specifier: ^7.22.3 + version: 7.25.7 + '@dagrejs/dagre': + specifier: ^1.1.4 + version: 1.1.4 + '@emoji-mart/data': + specifier: ^1.2.1 + version: 1.2.1 + '@floating-ui/react': + specifier: ^0.26.25 + version: 0.26.27(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@formatjs/intl-localematcher': + specifier: ^0.5.6 + version: 0.5.6 + '@headlessui/react': + specifier: ^1.7.13 + version: 1.7.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@heroicons/react': + specifier: ^2.0.16 + version: 2.1.5(react@18.2.0) + '@hookform/resolvers': + specifier: ^3.9.0 + version: 3.9.0(react-hook-form@7.53.1(react@18.2.0)) + '@lexical/react': + specifier: ^0.18.0 + version: 0.18.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(yjs@13.6.20) + '@mdx-js/loader': + specifier: ^3.1.0 + version: 3.1.0(acorn@8.13.0)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + '@mdx-js/react': + specifier: ^3.1.0 + version: 3.1.0(@types/react@18.2.79)(react@18.2.0) + '@monaco-editor/react': + specifier: ^4.6.0 + version: 4.6.0(monaco-editor@0.52.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@next/mdx': + specifier: ^14.0.4 + version: 14.2.15(@mdx-js/loader@3.1.0(acorn@8.13.0)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)))(@mdx-js/react@3.1.0(@types/react@18.2.79)(react@18.2.0)) + '@octokit/core': + specifier: ^6.1.2 + version: 6.1.2 + '@octokit/request-error': + specifier: ^6.1.5 + version: 6.1.5 + '@remixicon/react': + specifier: ^4.5.0 + version: 4.5.0(react@18.2.0) + '@sentry/react': + specifier: ^7.54.0 + version: 7.119.2(react@18.2.0) + '@sentry/utils': + specifier: ^7.54.0 + version: 7.119.2 + '@svgdotjs/svg.js': + specifier: ^3.2.4 + version: 3.2.4 + '@tailwindcss/typography': + specifier: ^0.5.15 + version: 0.5.15(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5))) + '@tanstack/react-query': + specifier: ^5.60.5 + version: 5.61.0(react@18.2.0) + '@tanstack/react-query-devtools': + specifier: ^5.60.5 + version: 5.61.0(@tanstack/react-query@5.61.0(react@18.2.0))(react@18.2.0) + ahooks: + specifier: ^3.8.1 + version: 3.8.1(react@18.2.0) + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + classnames: + specifier: ^2.5.1 + version: 2.5.1 + copy-to-clipboard: + specifier: ^3.3.3 + version: 3.3.3 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + dayjs: + specifier: ^1.11.13 + version: 1.11.13 + echarts: + specifier: ^5.5.1 + version: 5.5.1 + echarts-for-react: + specifier: ^3.0.2 + version: 3.0.2(echarts@5.5.1)(react@18.2.0) + elkjs: + specifier: ^0.9.3 + version: 0.9.3 + emoji-mart: + specifier: ^5.5.2 + version: 5.6.0 + fast-deep-equal: + specifier: ^3.1.3 + version: 3.1.3 + globals: + specifier: ^15.11.0 + version: 15.11.0 + i18next: + specifier: ^23.16.4 + version: 23.16.4 + i18next-resources-to-backend: + specifier: ^1.2.1 + version: 1.2.1 + immer: + specifier: ^9.0.19 + version: 9.0.21 + js-audio-recorder: + specifier: ^1.0.7 + version: 1.0.7 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 + katex: + specifier: ^0.16.11 + version: 0.16.11 + ky: + specifier: ^1.7.2 + version: 1.7.2 + lamejs: + specifier: ^1.2.1 + version: 1.2.1 + lexical: + specifier: ^0.18.0 + version: 0.18.0 + line-clamp: + specifier: ^1.0.0 + version: 1.0.0 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 + mermaid: + specifier: 11.4.1 + version: 11.4.1 + mime: + specifier: ^4.0.4 + version: 4.0.4 + mitt: + specifier: ^3.0.1 + version: 3.0.1 + negotiator: + specifier: ^0.6.3 + version: 0.6.4 + next: + specifier: ^14.2.10 + version: 14.2.15(@babel/core@7.25.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3) + pinyin-pro: + specifier: ^3.25.0 + version: 3.25.0 + qrcode.react: + specifier: ^4.1.0 + version: 4.1.0(react@18.2.0) + qs: + specifier: ^6.13.0 + version: 6.13.0 + rc-textarea: + specifier: ^1.8.2 + version: 1.8.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: + specifier: ~18.2.0 + version: 18.2.0 + react-18-input-autosize: + specifier: ^3.0.0 + version: 3.0.0(react@18.2.0) + react-dom: + specifier: ~18.2.0 + version: 18.2.0(react@18.2.0) + react-easy-crop: + specifier: ^5.1.0 + version: 5.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-error-boundary: + specifier: ^4.1.2 + version: 4.1.2(react@18.2.0) + react-headless-pagination: + specifier: ^1.1.6 + version: 1.1.6(react@18.2.0) + react-hook-form: + specifier: ^7.53.1 + version: 7.53.1(react@18.2.0) + react-hotkeys-hook: + specifier: ^4.6.1 + version: 4.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-i18next: + specifier: ^15.1.0 + version: 15.1.0(i18next@23.16.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-infinite-scroll-component: + specifier: ^6.1.0 + version: 6.1.0(react@18.2.0) + react-markdown: + specifier: ^9.0.1 + version: 9.0.1(@types/react@18.2.79)(react@18.2.0) + react-multi-email: + specifier: ^1.0.25 + version: 1.0.25(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-papaparse: + specifier: ^4.4.0 + version: 4.4.0 + react-pdf-highlighter: + specifier: ^8.0.0-rc.0 + version: 8.0.0-rc.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-slider: + specifier: ^2.0.6 + version: 2.0.6(react@18.2.0) + react-sortablejs: + specifier: ^6.1.4 + version: 6.1.4(@types/sortablejs@1.15.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sortablejs@1.15.3) + react-syntax-highlighter: + specifier: ^15.6.1 + version: 15.6.1(react@18.2.0) + react-tooltip: + specifier: 5.8.3 + version: 5.8.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-window: + specifier: ^1.8.10 + version: 1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-window-infinite-loader: + specifier: ^1.0.9 + version: 1.0.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + reactflow: + specifier: ^11.11.3 + version: 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + recordrtc: + specifier: ^5.6.2 + version: 5.6.2 + rehype-katex: + specifier: ^7.0.1 + version: 7.0.1 + rehype-raw: + specifier: ^7.0.0 + version: 7.0.0 + remark-breaks: + specifier: ^4.0.0 + version: 4.0.0 + remark-gfm: + specifier: ^4.0.0 + version: 4.0.0 + remark-math: + specifier: ^6.0.0 + version: 6.0.0 + scheduler: + specifier: ^0.23.0 + version: 0.23.2 + semver: + specifier: ^7.6.3 + version: 7.6.3 + server-only: + specifier: ^0.0.1 + version: 0.0.1 + sharp: + specifier: ^0.33.2 + version: 0.33.5 + shave: + specifier: ^5.0.4 + version: 5.0.4 + sortablejs: + specifier: ^1.15.0 + version: 1.15.3 + swr: + specifier: ^2.1.0 + version: 2.2.5(react@18.2.0) + tailwind-merge: + specifier: ^2.5.4 + version: 2.5.4 + use-context-selector: + specifier: ^2.0.0 + version: 2.0.0(react@18.2.0)(scheduler@0.23.2) + uuid: + specifier: ^10.0.0 + version: 10.0.0 + zod: + specifier: ^3.23.8 + version: 3.23.8 + zundo: + specifier: ^2.1.0 + version: 2.2.0(zustand@4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0)) + zustand: + specifier: ^4.5.2 + version: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + devDependencies: + '@antfu/eslint-config': + specifier: ^3.8.0 + version: 3.8.0(@eslint-react/eslint-plugin@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(@vue/compiler-sfc@3.5.12)(eslint-plugin-react-hooks@5.0.0(eslint@9.13.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.13(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@chromatic-com/storybook': + specifier: ^3.1.0 + version: 3.1.0(react@18.2.0)(storybook@8.3.6) + '@eslint-react/eslint-plugin': + specifier: ^1.15.0 + version: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint/eslintrc': + specifier: ^3.1.0 + version: 3.1.0 + '@eslint/js': + specifier: ^9.13.0 + version: 9.13.0 + '@faker-js/faker': + specifier: ^9.0.3 + version: 9.0.3 + '@rgrove/parse-xml': + specifier: ^4.1.0 + version: 4.1.0 + '@storybook/addon-essentials': + specifier: ^8.3.6 + version: 8.3.6(storybook@8.3.6)(webpack-sources@3.2.3) + '@storybook/addon-interactions': + specifier: ^8.3.6 + version: 8.3.6(storybook@8.3.6) + '@storybook/addon-links': + specifier: ^8.3.6 + version: 8.3.6(react@18.2.0)(storybook@8.3.6) + '@storybook/addon-onboarding': + specifier: ^8.3.6 + version: 8.3.6(react@18.2.0)(storybook@8.3.6) + '@storybook/addon-themes': + specifier: ^8.3.6 + version: 8.3.6(storybook@8.3.6) + '@storybook/blocks': + specifier: ^8.3.6 + version: 8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6) + '@storybook/nextjs': + specifier: ^8.3.6 + version: 8.3.6(esbuild@0.23.1)(next@14.2.15(@babel/core@7.25.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3)(storybook@8.3.6)(type-fest@2.19.0)(typescript@4.9.5)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + '@storybook/react': + specifier: ^8.3.6 + version: 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5) + '@storybook/test': + specifier: ^8.3.6 + version: 8.3.6(storybook@8.3.6) + '@testing-library/dom': + specifier: ^10.4.0 + version: 10.4.0 + '@testing-library/jest-dom': + specifier: ^6.6.2 + version: 6.6.2 + '@testing-library/react': + specifier: ^16.0.1 + version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@types/crypto-js': + specifier: ^4.2.2 + version: 4.2.2 + '@types/dagre': + specifier: ^0.7.52 + version: 0.7.52 + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/negotiator': + specifier: ^0.6.3 + version: 0.6.3 + '@types/node': + specifier: 18.15.0 + version: 18.15.0 + '@types/qs': + specifier: ^6.9.16 + version: 6.9.16 + '@types/react': + specifier: ~18.2.0 + version: 18.2.79 + '@types/react-dom': + specifier: ~18.2.0 + version: 18.2.25 + '@types/react-slider': + specifier: ^1.3.6 + version: 1.3.6 + '@types/react-syntax-highlighter': + specifier: ^15.5.13 + version: 15.5.13 + '@types/react-window': + specifier: ^1.8.8 + version: 1.8.8 + '@types/react-window-infinite-loader': + specifier: ^1.0.9 + version: 1.0.9 + '@types/recordrtc': + specifier: ^5.6.14 + version: 5.6.14 + '@types/semver': + specifier: ^7.5.8 + version: 7.5.8 + '@types/sortablejs': + specifier: ^1.15.1 + version: 1.15.8 + '@types/uuid': + specifier: ^10.0.0 + version: 10.0.0 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.47) + bing-translate-api: + specifier: ^4.0.2 + version: 4.0.2 + code-inspector-plugin: + specifier: ^0.18.1 + version: 0.18.3 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + eslint: + specifier: ^9.13.0 + version: 9.13.0(jiti@1.21.6) + eslint-config-next: + specifier: ^15.0.0 + version: 15.0.0(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-hooks: + specifier: ^5.0.0 + version: 5.0.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-react-refresh: + specifier: ^0.4.13 + version: 0.4.13(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-storybook: + specifier: ^0.10.1 + version: 0.10.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-tailwindcss: + specifier: ^3.17.5 + version: 3.17.5(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5))) + husky: + specifier: ^9.1.6 + version: 9.1.6 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + jest-environment-jsdom: + specifier: ^29.7.0 + version: 29.7.0(canvas@2.11.2) + lint-staged: + specifier: ^15.2.10 + version: 15.2.10 + magicast: + specifier: ^0.3.4 + version: 0.3.5 + postcss: + specifier: ^8.4.47 + version: 8.4.47 + sass: + specifier: ^1.80.3 + version: 1.80.3 + storybook: + specifier: ^8.3.6 + version: 8.3.6 + tailwindcss: + specifier: ^3.4.14 + version: 3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.15.0)(typescript@4.9.5) + typescript: + specifier: 4.9.5 + version: 4.9.5 + uglify-js: + specifier: ^3.19.3 + version: 3.19.3 + +packages: + + '@adobe/css-tools@4.4.0': + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@antfu/eslint-config@3.8.0': + resolution: {integrity: sha512-O5QSufPHpKTm0wk1OQ5c2mOZVzCqYV3hIDrt5zt+cOWqiG8YXLPkSOD4fFwjomATtOuUbcLUwkcgY5dErM7aIw==} + hasBin: true + peerDependencies: + '@eslint-react/eslint-plugin': ^1.5.8 + '@prettier/plugin-xml': ^3.4.1 + '@unocss/eslint-plugin': '>=0.50.0' + astro-eslint-parser: ^1.0.2 + eslint: ^9.10.0 + eslint-plugin-astro: ^1.2.0 + eslint-plugin-format: '>=0.1.0' + eslint-plugin-react-hooks: ^5.0.0 + eslint-plugin-react-refresh: ^0.4.4 + eslint-plugin-solid: ^0.14.3 + eslint-plugin-svelte: '>=2.35.1' + prettier-plugin-astro: ^0.13.0 + prettier-plugin-slidev: ^1.0.5 + svelte-eslint-parser: '>=0.37.0' + peerDependenciesMeta: + '@eslint-react/eslint-plugin': + optional: true + '@prettier/plugin-xml': + optional: true + '@unocss/eslint-plugin': + optional: true + astro-eslint-parser: + optional: true + eslint-plugin-astro: + optional: true + eslint-plugin-format: + optional: true + eslint-plugin-react-hooks: + optional: true + eslint-plugin-react-refresh: + optional: true + eslint-plugin-solid: + optional: true + eslint-plugin-svelte: + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-slidev: + optional: true + svelte-eslint-parser: + optional: true + + '@antfu/install-pkg@0.4.1': + resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} + + '@antfu/utils@0.7.10': + resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + + '@babel/code-frame@7.25.7': + resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.25.8': + resolution: {integrity: sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.25.8': + resolution: {integrity: sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.25.7': + resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.7': + resolution: {integrity: sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-builder-binary-assignment-operator-visitor@7.25.7': + resolution: {integrity: sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.25.7': + resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.25.7': + resolution: {integrity: sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.25.7': + resolution: {integrity: sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.2': + resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-member-expression-to-functions@7.25.7': + resolution: {integrity: sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.7': + resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.25.7': + resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.25.7': + resolution: {integrity: sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.25.7': + resolution: {integrity: sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.25.7': + resolution: {integrity: sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.25.7': + resolution: {integrity: sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-simple-access@7.25.7': + resolution: {integrity: sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-skip-transparent-expression-wrappers@7.25.7': + resolution: {integrity: sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.7': + resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.7': + resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.7': + resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.25.7': + resolution: {integrity: sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.25.7': + resolution: {integrity: sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.25.7': + resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.25.8': + resolution: {integrity: sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.7': + resolution: {integrity: sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.7': + resolution: {integrity: sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.7': + resolution: {integrity: sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.7': + resolution: {integrity: sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.7': + resolution: {integrity: sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-dynamic-import@7.8.3': + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.25.7': + resolution: {integrity: sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.25.7': + resolution: {integrity: sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.7': + resolution: {integrity: sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.7': + resolution: {integrity: sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.25.7': + resolution: {integrity: sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.25.8': + resolution: {integrity: sha512-9ypqkozyzpG+HxlH4o4gdctalFGIjjdufzo7I2XPda0iBnZ6a+FO0rIEQcdSPXp02CkvGsII1exJhmROPQd5oA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.25.7': + resolution: {integrity: sha512-ZUCjAavsh5CESCmi/xCpX1qcCaAglzs/7tmuvoFnJgA1dM7gQplsguljoTg+Ru8WENpX89cQyAtWoaE0I3X3Pg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.25.7': + resolution: {integrity: sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.25.7': + resolution: {integrity: sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.25.7': + resolution: {integrity: sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.25.8': + resolution: {integrity: sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.25.7': + resolution: {integrity: sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.25.7': + resolution: {integrity: sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.25.7': + resolution: {integrity: sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.25.7': + resolution: {integrity: sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.25.7': + resolution: {integrity: sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.7': + resolution: {integrity: sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.25.8': + resolution: {integrity: sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.25.7': + resolution: {integrity: sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.25.8': + resolution: {integrity: sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.25.7': + resolution: {integrity: sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.25.7': + resolution: {integrity: sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.25.8': + resolution: {integrity: sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.25.7': + resolution: {integrity: sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.25.8': + resolution: {integrity: sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.25.7': + resolution: {integrity: sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.25.7': + resolution: {integrity: sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.25.7': + resolution: {integrity: sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.25.7': + resolution: {integrity: sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.25.7': + resolution: {integrity: sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.7': + resolution: {integrity: sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.25.7': + resolution: {integrity: sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.25.8': + resolution: {integrity: sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.25.8': + resolution: {integrity: sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.25.8': + resolution: {integrity: sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.25.7': + resolution: {integrity: sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.25.8': + resolution: {integrity: sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.25.8': + resolution: {integrity: sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.25.7': + resolution: {integrity: sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.25.7': + resolution: {integrity: sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.25.8': + resolution: {integrity: sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.25.7': + resolution: {integrity: sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.25.7': + resolution: {integrity: sha512-r0QY7NVU8OnrwE+w2IWiRom0wwsTbjx4+xH2RTd7AVdof3uurXOF+/mXHQDRk+2jIvWgSaCHKMgggfvM4dyUGA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.25.7': + resolution: {integrity: sha512-5yd3lH1PWxzW6IZj+p+Y4OLQzz0/LzlOG8vGqonHfVR3euf1vyzyMUJk9Ac+m97BH46mFc/98t9PmYLyvgL3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.25.7': + resolution: {integrity: sha512-vILAg5nwGlR9EXE8JIOX4NHXd49lrYbN8hnjffDtoULwpL9hUx/N55nqh2qd0q6FyNDfjl9V79ecKGvFbcSA0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.25.7': + resolution: {integrity: sha512-6YTHJ7yjjgYqGc8S+CbEXhLICODk0Tn92j+vNJo07HFk9t3bjFgAKxPLFhHwF2NjmQVSI1zBRfBWUeVBa2osfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.25.7': + resolution: {integrity: sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-reserved-words@7.25.7': + resolution: {integrity: sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.25.7': + resolution: {integrity: sha512-Y9p487tyTzB0yDYQOtWnC+9HGOuogtP3/wNpun1xJXEEvI6vip59BSBTsHnekZLqxmPcgsrAKt46HAAb//xGhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.25.7': + resolution: {integrity: sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.25.7': + resolution: {integrity: sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.25.7': + resolution: {integrity: sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.25.7': + resolution: {integrity: sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.25.7': + resolution: {integrity: sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.25.7': + resolution: {integrity: sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.25.7': + resolution: {integrity: sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.25.7': + resolution: {integrity: sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.25.7': + resolution: {integrity: sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.25.7': + resolution: {integrity: sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.25.8': + resolution: {integrity: sha512-58T2yulDHMN8YMUxiLq5YmWUnlDCyY1FsHM+v12VMx+1/FlrUj5tY50iDCpofFQEM8fMYOaY9YRvym2jcjn1Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-react@7.25.7': + resolution: {integrity: sha512-GjV0/mUEEXpi1U5ZgDprMRRgajGMRW3G5FjMr5KLKD8nT2fTG8+h/klV3+6Dm5739QE+K5+2e91qFKAYI3pmRg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.25.7': + resolution: {integrity: sha512-rkkpaXJZOFN45Fb+Gki0c+KMIglk4+zZXOoMJuyEK8y8Kkc8Jd3BDmP7qPsz0zQMJj+UD7EprF+AqAXcILnexw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.25.7': + resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.25.7': + resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.7': + resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.25.8': + resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} + engines: {node: '>=6.9.0'} + + '@base2/pretty-print-object@1.0.1': + resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@braintree/sanitize-url@7.1.0': + resolution: {integrity: sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==} + + '@chevrotain/cst-dts-gen@11.0.3': + resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} + + '@chevrotain/gast@11.0.3': + resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} + + '@chevrotain/regexp-to-ast@11.0.3': + resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} + + '@chevrotain/types@11.0.3': + resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} + + '@chevrotain/utils@11.0.3': + resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + + '@chromatic-com/storybook@3.1.0': + resolution: {integrity: sha512-AM8jDwoBNNwJKgmoWkHIOhu4ObsxvDtOzZC9tPCVEW6P+pFwg5xjSZAQglIE2c8/SsEPSduNdxBt31ES3iDwoA==} + engines: {node: '>=16.0.0', yarn: '>=1.22.18'} + peerDependencies: + storybook: ^8.3.0 + + '@clack/core@0.3.4': + resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} + + '@clack/prompts@0.7.0': + resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + bundledDependencies: + - is-unicode-supported + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@dagrejs/dagre@1.1.4': + resolution: {integrity: sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg==} + + '@dagrejs/graphlib@2.2.4': + resolution: {integrity: sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==} + engines: {node: '>17.0.0'} + + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + + '@emoji-mart/data@1.2.1': + resolution: {integrity: sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==} + + '@es-joy/jsdoccomment@0.48.0': + resolution: {integrity: sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==} + engines: {node: '>=16'} + + '@es-joy/jsdoccomment@0.49.0': + resolution: {integrity: sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==} + engines: {node: '>=16'} + + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-plugin-eslint-comments@4.4.0': + resolution: {integrity: sha512-yljsWl5Qv3IkIRmJ38h3NrHXFCm4EUl55M8doGTF6hvzvFF8kRpextgSrg2dwHev9lzBZyafCr9RelGIyQm6fw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.11.1': + resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint-react/ast@1.15.0': + resolution: {integrity: sha512-7rOLLfGER82FQJy7pCFNs4j/47RYTEiPDfMFGAu4W7yerJrvU2rRNqjSwwm1Iq0DrrasBV8a3IVtPYQoDOqycg==} + + '@eslint-react/core@1.15.0': + resolution: {integrity: sha512-T7KirkdempegOxQznW1xclZtv5hQRChgbeYqisPRENkNg90w3uY7ia5iPf6FEZntkja/NF00VUnUetIw4rO0og==} + + '@eslint-react/eslint-plugin@1.15.0': + resolution: {integrity: sha512-5cuu7gNBgwQwgDX1YJugL7ujay0NT27g3UN0qtJAON9WLBv/ESq+qLMxddGwPSljV/XGxhwbbys09Jgww/fy8A==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + '@eslint-react/jsx@1.15.0': + resolution: {integrity: sha512-VZy8RWPx+2PUuBKaXPtu2qWnWN9SpkdgY3ohkZoGdoqkEYkYaXjvABNByQLwvk2+Ewqt0K+1f8r7QoQi47pQmw==} + + '@eslint-react/shared@1.15.0': + resolution: {integrity: sha512-LRgcKKhNePEJzuwICe3rgUC5KVd4ZhlKys91gMxmUob3RCiUj4BjfAURJMqzwsPGF32WQeHkipw1hWNGpQNdlw==} + + '@eslint-react/tools@1.15.0': + resolution: {integrity: sha512-zdd2K3EV2tWaCzNH60wD159HuX904kWzv+X87yqzZ0Nf2OBUDJ4a561NoDX3Pn8A3E6hFdu666zpIGdeaej9eg==} + + '@eslint-react/types@1.15.0': + resolution: {integrity: sha512-bajL6xIUxZp36fezn5HEhQpL0eJM923hwfRj6cym2Xl0Jn2YgahSztHorsOpId71MYBgn9ERy9yXItcnrz0rsQ==} + + '@eslint-react/var@1.15.0': + resolution: {integrity: sha512-/QycKnbgZRygM/lhHtUFQrvvrswdOyaXfVxwtIFVEYoPHP9q7NaUn0mrBu4VWkXQC9zPk1nWQeC3rZMUxzretg==} + + '@eslint/compat@1.2.1': + resolution: {integrity: sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/config-array@0.18.0': + resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.7.0': + resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.13.0': + resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/markdown@6.2.1': + resolution: {integrity: sha512-cKVd110hG4ICHmWhIwZJfKmmJBvbiDWyrHODJknAtudKgZtlROGoLX9UEOA0o746zC0hCY4UV4vR+aOGW9S6JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.1': + resolution: {integrity: sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@faker-js/faker@9.0.3': + resolution: {integrity: sha512-lWrrK4QNlFSU+13PL9jMbMKLJYXDFu3tQfayBsMXX7KL/GiQeqfB1CzHkqD5UHBUtPAuPo6XwGbMFNdVMZObRA==} + engines: {node: '>=18.0.0', npm: '>=9.0.0'} + + '@floating-ui/core@1.6.8': + resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==} + + '@floating-ui/dom@1.1.1': + resolution: {integrity: sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==} + + '@floating-ui/dom@1.6.11': + resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==} + + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.26.27': + resolution: {integrity: sha512-jLP72x0Kr2CgY6eTYi/ra3VA9LOkTo4C+DUTrbFgFOExKy3omYVmwMjNKqxAHdsnyLS96BIDLcO2SlnsNf8KUQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.8': + resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} + + '@formatjs/intl-localematcher@0.5.6': + resolution: {integrity: sha512-roz1+Ba5e23AHX6KUAWmLEyTRZegM5YDuxuvkHCyK3RJddf/UXB2f+s7pOMm9ktfPGla0g+mQXOn5vsuYirnaA==} + + '@headlessui/react@1.7.19': + resolution: {integrity: sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==} + engines: {node: '>=10'} + peerDependencies: + react: ^16 || ^17 || ^18 + react-dom: ^16 || ^17 || ^18 + + '@heroicons/react@2.1.5': + resolution: {integrity: sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA==} + peerDependencies: + react: '>= 16' + + '@hookform/resolvers@3.9.0': + resolution: {integrity: sha512-bU0Gr4EepJ/EQsH/IwEzYLsT/PEj5C0ynLQ4m+GSHS+xKH4TfSelhluTgOaoc4kA5s7eCsQbM4wvZLzELmWzUg==} + peerDependencies: + react-hook-form: ^7.0.0 + + '@humanfs/core@0.19.0': + resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.5': + resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.2.0': + resolution: {integrity: sha512-9A5eZQV9eKlNCXlI/SgYsGRS7YmGmB1oAsRpNVIYBmIzGJRgH+hfG+lo4069s+GFWFNnBAtDg10c53vQZBLfnA==} + + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@lexical/clipboard@0.18.0': + resolution: {integrity: sha512-ybc+hx14wj0n2ZjdOkLcZ02MRB3UprXjpLDXlByFIuVcZpUxVcp3NzA0UBPOKXYKvdt0bmgjnAsFWM5OSbwS0w==} + + '@lexical/code@0.18.0': + resolution: {integrity: sha512-VB8fRHIrB8QTqyZUvGBMVWP2tpKe3ArOjPdWAqgrS8MVFldqUhuTHcW+XJFkVxcEBYCXynNT29YRYtQhfQ+vDQ==} + + '@lexical/devtools-core@0.18.0': + resolution: {integrity: sha512-gVgtEkLwGjz1frOmDpFJzDPFxPgAcC9n5ZaaZWHo5GLcptnQmkuLm1t+UInQWujXhFmcyJzfiqDaMJ8EIcb2Ww==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/dragon@0.18.0': + resolution: {integrity: sha512-toD/y2/TgtG+eFVKXf65kDk/Mv02FwgmcGH18nyAabZnO1TLBaMYPkGFdTTZ8hVmQxqIu9nZuLWUbdIBMs8UWw==} + + '@lexical/hashtag@0.18.0': + resolution: {integrity: sha512-bm+Sv7keguVYbUY0ngd+iAv2Owd3dePzdVkzkmw9Al8GPXkE5ll8fjq6Xjw2u3OVhf+9pTnesIo/AS7H+h0exw==} + + '@lexical/history@0.18.0': + resolution: {integrity: sha512-c87J4ke1Sae03coElJay2Ikac/4OcA2OmhtNbt2gAi/XBtcsP4mPuz1yZfZf9XIe+weekObgjinvZekQ2AFw0g==} + + '@lexical/html@0.18.0': + resolution: {integrity: sha512-8lhba1DFnnobXgYm4Rk5Gr2tZedD4Gl6A/NKCt7whO/CET63vT3UnK2ggcVVgtIJG530Cv0bdZoJbJu5DauI5w==} + + '@lexical/link@0.18.0': + resolution: {integrity: sha512-GCYcbNTSTwJk0lr+GMc8nn6Meq44BZs3QL2d1B0skpZAspd8yI53sRS6HDy5P+jW5P0dzyZr/XJAU4U+7zsEEg==} + + '@lexical/list@0.18.0': + resolution: {integrity: sha512-DEWs9Scbg3+STZeE2O0OoG8SWnKnxQccObBzyeHRjn4GAN6JA7lgcAzfrdgp0fNWTbMM/ku876MmXKGnqhvg9Q==} + + '@lexical/mark@0.18.0': + resolution: {integrity: sha512-QA4YWfTP5WWnCnoH/RmfcsSZyhhd7oeFWDpfP7S8Bbmhz6kiPwGcsVr+uRQBBT56AqEX167xX2rX8JR6FiYZqA==} + + '@lexical/markdown@0.18.0': + resolution: {integrity: sha512-uSWwcK8eJw5C+waEhU5WoX8W+JxNZbKuFnZwsn5nsp+iQgqMj4qY6g0yJub4sq8vvh6jjl4vVXhXTq2up9aykw==} + + '@lexical/offset@0.18.0': + resolution: {integrity: sha512-KGlboyLSxQAH5PMOlJmyvHlbYXZneVnKiHpfyBV5IUX5kuyB/eZbQEYcJP9saekfQ5Xb1FWXWmsZEo+sWtrrZA==} + + '@lexical/overflow@0.18.0': + resolution: {integrity: sha512-3ATTwttVgZtVLq60ZUWbpbXBbpuMa3PZD5CxSP3nulviL+2I4phvacV4WUN+8wMeq+PGmuarl+cYfrFL02ii3g==} + + '@lexical/plain-text@0.18.0': + resolution: {integrity: sha512-L6yQpiwW0ZacY1oNwvRBxSuW2TZaUcveZLheJc8JzGcZoVxzII/CAbLZG8691VbNuKsbOURiNXZIsgwujKmo4Q==} + + '@lexical/react@0.18.0': + resolution: {integrity: sha512-DLvIbTsjvFIFqm+9zvAjEwuZHAbSxzZf1AGqf1lLctlL/Ran0f+8EZOv5jttELTe7xISZ2+xSXTLRfyxhNwGXQ==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/rich-text@0.18.0': + resolution: {integrity: sha512-xMANCB7WueMsmWK8qxik5FZN4ApyaHWHQILS9r4FTbdv/DlNepsR7Pt8kg2317xZ56NAueQLIdyyKYXG1nBrHw==} + + '@lexical/selection@0.18.0': + resolution: {integrity: sha512-mJoMhmxeZLfM9K2JMYETs9u179IkHQUlgtYG5GZJHjKx2iUn+9KvJ9RVssq+Lusi7C/N42wWPGNHDPdUvFtxXg==} + + '@lexical/table@0.18.0': + resolution: {integrity: sha512-TeTAnuFAAgVjm1QE8adRB3GFWN+DUUiS4vzGq+ynPRCtNdpmW27NmTkRMyxKsetUtt7nIFfj4DvLvor4RwqIpA==} + + '@lexical/text@0.18.0': + resolution: {integrity: sha512-MTHSBeq3K0+lqSsP5oysBMnY4tPVhB8kAa2xBnEc3dYgXFxEEvJwZahbHNX93EPObtJkxXfUuI63Al4G3lYK8A==} + + '@lexical/utils@0.18.0': + resolution: {integrity: sha512-4s9dVpBZjqIaA/1q2GtfWFjKsv2Wqhjer0Zw2mcl1TIVN0zreXxcTKN316QppAWmSQJxVGvkWHjjaZJwl6/TSw==} + + '@lexical/yjs@0.18.0': + resolution: {integrity: sha512-rl7Rl9XIb3ygQEEHOFtACdXs3BE+UUUmdyNqB6kK9A6IRGz+w4Azp+qzt8It/t+c0oaSYHpAtcLNXg1amJz+kA==} + peerDependencies: + yjs: '>=13.5.22' + + '@mapbox/node-pre-gyp@1.0.11': + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + + '@mdx-js/loader@3.1.0': + resolution: {integrity: sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg==} + peerDependencies: + webpack: '>=5' + peerDependenciesMeta: + webpack: + optional: true + + '@mdx-js/mdx@3.1.0': + resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} + + '@mdx-js/react@3.1.0': + resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} + peerDependencies: + '@types/react': ~18.2.0 + react: '>=16' + + '@mermaid-js/parser@0.3.0': + resolution: {integrity: sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==} + + '@monaco-editor/loader@1.4.0': + resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} + peerDependencies: + monaco-editor: '>= 0.21.0 < 1' + + '@monaco-editor/react@4.6.0': + resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@next/env@14.2.15': + resolution: {integrity: sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==} + + '@next/eslint-plugin-next@15.0.0': + resolution: {integrity: sha512-UG/Gnsq6Sc4wRhO9qk+vc/2v4OfRXH7GEH6/TGlNF5eU/vI9PIO7q+kgd65X2DxJ+qIpHWpzWwlPLmqMi1FE9A==} + + '@next/mdx@14.2.15': + resolution: {integrity: sha512-OQWxKY5jWtHqPXdN3s5mj/LsD57pxt8CQsY4VQtTfQdQn6rNPd1bjN+kpbtezXdjgrKhvTJAb1yv1XGvzlh0uw==} + peerDependencies: + '@mdx-js/loader': '>=0.15.0' + '@mdx-js/react': '>=0.15.0' + peerDependenciesMeta: + '@mdx-js/loader': + optional: true + '@mdx-js/react': + optional: true + + '@next/swc-darwin-arm64@14.2.15': + resolution: {integrity: sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@14.2.15': + resolution: {integrity: sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@14.2.15': + resolution: {integrity: sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@14.2.15': + resolution: {integrity: sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@14.2.15': + resolution: {integrity: sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@14.2.15': + resolution: {integrity: sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@14.2.15': + resolution: {integrity: sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-ia32-msvc@14.2.15': + resolution: {integrity: sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@next/swc-win32-x64-msvc@14.2.15': + resolution: {integrity: sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + + '@octokit/auth-token@5.1.1': + resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==} + engines: {node: '>= 18'} + + '@octokit/core@6.1.2': + resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@10.1.1': + resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==} + engines: {node: '>= 18'} + + '@octokit/graphql@8.1.1': + resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@22.2.0': + resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} + + '@octokit/request-error@6.1.5': + resolution: {integrity: sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==} + engines: {node: '>= 18'} + + '@octokit/request@9.1.3': + resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==} + engines: {node: '>= 18'} + + '@octokit/types@13.6.1': + resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==} + + '@parcel/watcher-android-arm64@2.4.1': + resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.4.1': + resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.4.1': + resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.4.1': + resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.4.1': + resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.4.1': + resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.4.1': + resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.4.1': + resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.4.1': + resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.4.1': + resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.4.1': + resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.4.1': + resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.4.1': + resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@pmmmwh/react-refresh-webpack-plugin@0.5.15': + resolution: {integrity: sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==} + engines: {node: '>= 10.13'} + peerDependencies: + '@types/webpack': 4.x || 5.x + react-refresh: '>=0.10.0 <1.0.0' + sockjs-client: ^1.4.0 + type-fest: '>=0.17.0 <5.0.0' + webpack: '>=4.43.0 <6.0.0' + webpack-dev-server: 3.x || 4.x || 5.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + '@types/webpack': + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + + '@reactflow/background@11.3.14': + resolution: {integrity: sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/controls@11.2.14': + resolution: {integrity: sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/core@11.11.4': + resolution: {integrity: sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/minimap@11.7.14': + resolution: {integrity: sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/node-resizer@2.2.14': + resolution: {integrity: sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/node-toolbar@1.3.14': + resolution: {integrity: sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@remixicon/react@4.5.0': + resolution: {integrity: sha512-Xr20SxMpRNlgXZnoF5BCMyZuQEhXY3yJCyms8kxB/vJCCiV1nWdiO48XqRG5LBd1192iSHC4m658AIWi6rmBFg==} + peerDependencies: + react: '>=18.2.0' + + '@rgrove/parse-xml@4.1.0': + resolution: {integrity: sha512-pBiltENdy8SfI0AeR1e5TRpS9/9Gl0eiOEt6ful2jQfzsgvZYWqsKiBWaOCLdocQuk0wS7KOHI37n0C1pnKqTw==} + engines: {node: '>=14.0.0'} + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@rushstack/eslint-patch@1.10.4': + resolution: {integrity: sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==} + + '@sentry-internal/feedback@7.119.2': + resolution: {integrity: sha512-bnR1yJWVBZfXGx675nMXE8hCXsxluCBfIFy9GQT8PTN/urxpoS9cGz+5F7MA7Xe3Q06/7TT0Mz3fcDvjkqTu3Q==} + engines: {node: '>=12'} + + '@sentry-internal/replay-canvas@7.119.2': + resolution: {integrity: sha512-Lqo8IFyeKkdOrOGRqm9jCEqeBl8kINe5+c2VqULpkO/I6ql6ISwPSYnmG6yL8cCVIaT1893CLog/pS4FxCv8/Q==} + engines: {node: '>=12'} + + '@sentry-internal/tracing@7.119.2': + resolution: {integrity: sha512-V2W+STWrafyGJhQv3ulMFXYDwWHiU6wHQAQBShsHVACiFaDrJ2kPRet38FKv4dMLlLlP2xN+ss2e5zv3tYlTiQ==} + engines: {node: '>=8'} + + '@sentry/browser@7.119.2': + resolution: {integrity: sha512-Wb2RzCsJBTNCmS9KPmbVyV5GGzFXjFdUThAN9xlnN5GgemMBwdQjGu/tRYr8yJAVsRb0EOFH8IuJBNKKNnO49g==} + engines: {node: '>=8'} + + '@sentry/core@7.119.2': + resolution: {integrity: sha512-hQr3d2yWq/2lMvoyBPOwXw1IHqTrCjOsU1vYKhAa6w9vGbJZFGhKGGE2KEi/92c3gqGn+gW/PC7cV6waCTDuVA==} + engines: {node: '>=8'} + + '@sentry/integrations@7.119.2': + resolution: {integrity: sha512-dCuXKvbUE3gXVVa696SYMjlhSP6CxpMH/gl4Jk26naEB8Xjsn98z/hqEoXLg6Nab73rjR9c/9AdKqBbwVMHyrQ==} + engines: {node: '>=8'} + + '@sentry/react@7.119.2': + resolution: {integrity: sha512-fE48R/mtb/bpc4/YVvKurKSAZ0ueUI5Ma0cVSr/Fi09rFdGwLRMcweM1UydREO/ILiyt8FezyZg7L20VAp4/TQ==} + engines: {node: '>=8'} + peerDependencies: + react: 15.x || 16.x || 17.x || 18.x + + '@sentry/replay@7.119.2': + resolution: {integrity: sha512-nHDsBt0mlJXTWAHjzQdCzDbhV2fv8B62PPB5mu5SpI+G5h+ir3r5lR0lZZrMT8eurVowb/HnLXAs+XYVug3blg==} + engines: {node: '>=12'} + + '@sentry/types@7.119.2': + resolution: {integrity: sha512-ydq1tWsdG7QW+yFaTp0gFaowMLNVikIqM70wxWNK+u98QzKnVY/3XTixxNLsUtnAB4Y+isAzFhrc6Vb5GFdFeg==} + engines: {node: '>=8'} + + '@sentry/utils@7.119.2': + resolution: {integrity: sha512-TLdUCvcNgzKP0r9YD7tgCL1PEUp42TObISridsPJ5rhpVGQJvpr+Six0zIkfDUxerLYWZoK8QMm9KgFlPLNQzA==} + engines: {node: '>=8'} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@storybook/addon-actions@8.3.6': + resolution: {integrity: sha512-nOqgl0WoZK2KwjaABaXMoIgrIHOQl9inOzJvqQau0HOtsvnXGXYfJXYnpjZenoZDoZXKbUDl0U2haDFx2a2fJw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-backgrounds@8.3.6': + resolution: {integrity: sha512-yBn+a8i5OJzJaX6Bx5MAkfei7c2nvq+RRmvuyvxw11rtDGR6Nz4OBBe56reWxo868wVUggpRTPJCMVe5tDYgVg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-controls@8.3.6': + resolution: {integrity: sha512-9IMLHgtWPuFoRCt3hDsIk1FbkK5SlCMDW1DDwtTBIeWYYZLvptS42+vGVTeQ8v5SejmVzZkzuUdzu3p4sb3IcA==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-docs@8.3.6': + resolution: {integrity: sha512-31Rk1TOhDIzGM2wNCUIB1xKuWtArW0D2Puua9warEXlQ3FtvwmxnPrwbIzw6ufYZDWPwl9phDYTcRh8WqZIoGg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-essentials@8.3.6': + resolution: {integrity: sha512-MQPFvThlGU7wlda1xhBPQCmDh90cSSZ31OsVs1uC5kJh0aLbY2gYXPurq1G54kzrYo8SMfBxsXrCplz8Ir6UTg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-highlight@8.3.6': + resolution: {integrity: sha512-A7uU+1OPVXGpkklEUJjSl2VEEDLCSNvmffUJlvW1GjajsNFIHOW2CSD+KnfFlQyPxyVbnWAYLqUP4XJxoqrvDw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-interactions@8.3.6': + resolution: {integrity: sha512-Y0YUJj0oE1+6DFkaTPXM/8+dwTSoy0ltj2Sn2KOTJYzxKQYXBp8TlUv0QOQiGH7o/GKXIWek/VlTuvG/JEeiWw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-links@8.3.6': + resolution: {integrity: sha512-EGEH/kEjndEldbqyiJ8XSASkxqwzL/lgA/+6mHpa6Ljxhk1s5IMGcdA1ymJYJ2BpNdkUxRj/uxAa38eGcQiJ/g==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + peerDependenciesMeta: + react: + optional: true + + '@storybook/addon-measure@8.3.6': + resolution: {integrity: sha512-VHWeGgYjhzhwb2WAqYW/qyEPqg5pwKR/XqFfd+3tEirUs/64olL1l3lzLwZ8Cm07cJ81T8Z4myywb9kObZfQlw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-onboarding@8.3.6': + resolution: {integrity: sha512-DvwtK3k5docaO7ZO0LRXL1myCwOnW2X+e9c383GEk9AykgL5otzkMjxRZ1rSAw39q/WIE9H0vBvUmzGVRpUm+A==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-outline@8.3.6': + resolution: {integrity: sha512-+VXpM8SIHX2cn30qLlMvER9/6iioFRSn2sAfLniqy4RrcQmcMP+qgE7ZzbzExt7cneJh3VFsYqBS/HElu14Vgg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-themes@8.3.6': + resolution: {integrity: sha512-NX6zVWs0JVUg0xICL2v1zlb6eTAQYlE/vd6ATA4bNUNL5sabWGEd1w2ArQaHC9nTnfV60JuRQ8o3SvD7Gg0xMg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-toolbars@8.3.6': + resolution: {integrity: sha512-FJH+lRoZXENfpMR/G09ZqB0TmL/k6bv07GN1ysoVs420tKRgjfz6uXaZz5COrhcdISr5mTNmG+mw9x7xXTfX3Q==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/addon-viewport@8.3.6': + resolution: {integrity: sha512-bL51v837W1cng/+0pypkoLsWKWmvux96zLOzqLCpcWAQ4OSMhW3foIWpCiFwMG/KY+GanoOocTx6i7j5hLtuTA==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/blocks@8.3.6': + resolution: {integrity: sha512-Oc5jU6EzfsENjrd91KcKyEKBh60RT+8uyLi1RIrymC2C/mzZMTEoNIrbnQt0eIqbjlHxn6y9JMJxHu4NJ4EmZg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@storybook/builder-webpack5@8.3.6': + resolution: {integrity: sha512-Eqn2k8aA9f0o6IMQNAxGAMfSDeTP3YYCQAtOL5Gt5lgrqLV5JMTbZOfmaRBZ82ej/BBSAopnQKIJjQBBFx6kAQ==} + peerDependencies: + storybook: ^8.3.6 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@storybook/channels@8.3.6': + resolution: {integrity: sha512-6ahY0n1A19diR5cI63lhDEpMaDsq7LFtMOgWab2NwCsdXoEAl6anvDptyPWW60umN3HrDzSKFdpRx4imOEjlWw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/components@8.3.6': + resolution: {integrity: sha512-TXuoGZY7X3iixF45lXkYOFk8k2q9OHcqHyHyem1gATLLQXgyOvDgzm+VB7uKBNzssRQPEE+La70nfG8bq/viRw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/core-webpack@8.3.6': + resolution: {integrity: sha512-ks306CFKD7FePQzRYyTjddiLsSriceblzv4rI+IjVtftkJvcEbxub2yWkV27kPP/e9kSd4Li3M34bX5mkiwkZA==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/core@8.3.6': + resolution: {integrity: sha512-frwfgf0EJ7QL29DWZ5bla/g0eOOWqJGd14t+VUBlpP920zB6sdDfo7+p9JoCjD9u08lGeFDqbPNKayUk+0qDag==} + + '@storybook/csf-plugin@8.3.6': + resolution: {integrity: sha512-TJyJPFejO6Gyr3+bXqE/+LomQbivvfHEbee/GwtlRj0XF4KQlqnvuEdEdcK25JbD0NXT8AbyncEUmjoxE7ojQw==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/csf@0.1.11': + resolution: {integrity: sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==} + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@1.2.12': + resolution: {integrity: sha512-UxgyK5W3/UV4VrI3dl6ajGfHM4aOqMAkFLWe2KibeQudLf6NJpDrDMSHwZj+3iKC4jFU7dkKbbtH2h/al4sW3Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@storybook/instrumenter@8.3.6': + resolution: {integrity: sha512-0RowbKwoB/s7rtymlnKNiyWN1Z3ZK5mwgzVjlRmzxDL8hrdi5KDjTNExuJTRR3ZaBP2RR0/I3m/n0p9JhHAZvg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/manager-api@8.3.6': + resolution: {integrity: sha512-Xt5VFZcL+G/9uzaHjzWFhxRNrP+4rPhSRKEvCZorAbC9+Hv+ZDs1JSZS5wMb4WKpXBZ0rwDVOLwngqbVtfRHuQ==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/nextjs@8.3.6': + resolution: {integrity: sha512-jNrEcS26OER645kJ3nMuSSgu8BWJhEY8MM9rDlE/133A/hojTBc2vZXwSfgZ22tAc7ckrbyw2gygEUPI2rHImA==} + engines: {node: '>=18.0.0'} + peerDependencies: + next: ^13.5.0 || ^14.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + typescript: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + webpack: + optional: true + + '@storybook/preset-react-webpack@8.3.6': + resolution: {integrity: sha512-Ar0vhJITXa4xsXT3RdgYZ2mhXxE3jfUisQzsITey5a2RVgnSBIENggmRZ/6j1oVgEXFthbarNEsebGiA+2vDZg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@storybook/preview-api@8.3.6': + resolution: {integrity: sha512-/Wxvb7wbI2O2iH63arRQQyyojA630vibdshkFjuC/u1nYdptEV1jkxa0OYmbZbKCn4/ze6uH4hfsKOpDPV9SWg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0': + resolution: {integrity: sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==} + peerDependencies: + typescript: '>= 4.x' + webpack: '>= 4' + + '@storybook/react-dom-shim@8.3.6': + resolution: {integrity: sha512-9BO6VXIdli4GHSfiP/Z0gwAf7oQig3D/yWK2U1+91UWDV8nIAgnNBAi76U4ORC6MiK5MdkDfIikIxnLLeLnahA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + + '@storybook/react@8.3.6': + resolution: {integrity: sha512-s3COryqIOYK7urgZaCPb77zlxGjPKr6dIsYmblQJcsFY2ZlG2x0Ysm8b5oRgD8Pv71hCJ0PKYA4RzDgBVYJS9A==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@storybook/test': 8.3.6 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.3.6 + typescript: '>= 4.2.x' + peerDependenciesMeta: + '@storybook/test': + optional: true + typescript: + optional: true + + '@storybook/telemetry@8.3.6': + resolution: {integrity: sha512-fhpbZok7mPeujjFxAKo2vuqhfjhv5BO/mHH7Z8QtgsYqeR7px56arDRgV6CngBZWgFvrQ2wBS0HPV4nB6YWvJQ==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/test@8.3.6': + resolution: {integrity: sha512-WIc8LzK9jaEw+e3OiweEM2j3cppPzsWod59swuf6gDBf176EQLIyjtVc+Kh3qO4NNkcL+lwmqaLPjOxlBLaDbg==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/theming@8.3.6': + resolution: {integrity: sha512-LQjUk6GXRW9ELkoBKuqzQKFUW+ajfGPfVELcfs3/VQX61VhthJ4olov4bGPc04wsmmFMgN/qODxT485IwOHfPQ==} + peerDependencies: + storybook: ^8.3.6 + + '@storybook/types@8.3.6': + resolution: {integrity: sha512-EY+bjIxxmKkFrL7CyDQb3EXbmy0+Y9OieaPrNNM7QXTfGgp81lXhfqMX3HLMMjplk+rcxVJLyzXSBx0nIn91fQ==} + peerDependencies: + storybook: ^8.3.6 + + '@stylistic/eslint-plugin@2.9.0': + resolution: {integrity: sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.40.0' + + '@svgdotjs/svg.js@3.2.4': + resolution: {integrity: sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==} + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.5': + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + + '@tailwindcss/typography@0.5.15': + resolution: {integrity: sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20' + + '@tanstack/query-core@5.60.6': + resolution: {integrity: sha512-tI+k0KyCo1EBJ54vxK1kY24LWj673ujTydCZmzEZKAew4NqZzTaVQJEuaG1qKj2M03kUHN46rchLRd+TxVq/zQ==} + + '@tanstack/query-devtools@5.59.20': + resolution: {integrity: sha512-vxhuQ+8VV4YWQSFxQLsuM+dnEKRY7VeRzpNabFXdhEwsBYLrjXlF1pM38A8WyKNLqZy8JjyRO8oP4Wd/oKHwuQ==} + + '@tanstack/react-query-devtools@5.61.0': + resolution: {integrity: sha512-hd3yXl+KV+OGQmAw946qHAFp6DygcXcYN+1ai9idYddx6uEQyCwYk3jyIBOQEUw9uzN5DOGJLBsgd/QcimDQsA==} + peerDependencies: + '@tanstack/react-query': ^5.61.0 + react: ^18 || ^19 + + '@tanstack/react-query@5.61.0': + resolution: {integrity: sha512-SBzV27XAeCRBOQ8QcC94w2H1Md0+LI0gTWwc3qRJoaGuewKn5FNW4LSqwPFJZVEItfhMfGT7RpZuSFXjTi12pQ==} + peerDependencies: + react: ^18 || ^19 + + '@tanstack/react-virtual@3.10.8': + resolution: {integrity: sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@tanstack/virtual-core@3.10.8': + resolution: {integrity: sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==} + + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.5.0': + resolution: {integrity: sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/jest-dom@6.6.2': + resolution: {integrity: sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.0.1': + resolution: {integrity: sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ~18.2.0 + '@types/react-dom': ~18.2.0 + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@testing-library/user-event@14.5.2': + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@types/acorn@4.0.6': + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/crypto-js@4.2.2': + resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==} + + '@types/d3-array@3.2.1': + resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.6': + resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.0': + resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.3': + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + + '@types/d3-scale-chromatic@3.0.3': + resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} + + '@types/d3-scale@4.0.8': + resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.6': + resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.3': + resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + + '@types/dagre@0.7.52': + resolution: {integrity: sha512-XKJdy+OClLk3hketHi9Qg6gTfe1F3y+UFnHxKA2rn9Dw+oXa4Gb378Ztz9HlMgZKSxpPmn4BNVh9wgkpvrK1uw==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} + + '@types/escodegen@0.0.6': + resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@0.0.51': + resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/geojson@7946.0.14': + resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/hast@2.3.10': + resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/html-minifier-terser@6.1.0': + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.13': + resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==} + + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + + '@types/jsdom@20.0.1': + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/katex@0.16.7': + resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.12': + resolution: {integrity: sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/negotiator@0.6.3': + resolution: {integrity: sha512-JkXTOdKs5MF086b/pt8C3+yVp3iDUwG635L7oCH6HvJvvr6lSUU5oe/gLXnPEfYRROHjJIPgCV6cuAg8gGkntQ==} + + '@types/node@18.15.0': + resolution: {integrity: sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==} + + '@types/node@22.7.8': + resolution: {integrity: sha512-a922jJy31vqR5sk+kAdIENJjHblqcZ4RmERviFsER4WJcEONqxKcjNOlk0q7OUfrF5sddT+vng070cdfMlrPLg==} + + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + + '@types/papaparse@5.3.15': + resolution: {integrity: sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/prop-types@15.7.13': + resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} + + '@types/qs@6.9.16': + resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/react-dom@18.2.25': + resolution: {integrity: sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==} + + '@types/react-slider@1.3.6': + resolution: {integrity: sha512-RS8XN5O159YQ6tu3tGZIQz1/9StMLTg/FCIPxwqh2gwVixJnlfIodtVx+fpXVMZHe7A58lAX1Q4XTgAGOQaCQg==} + + '@types/react-syntax-highlighter@15.5.13': + resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} + + '@types/react-window-infinite-loader@1.0.9': + resolution: {integrity: sha512-gEInTjQwURCnDOFyIEK2+fWB5gTjqwx30O62QfxA9stE5aiB6EWkGj4UMhc0axq7/FV++Gs/TGW8FtgEx0S6Tw==} + + '@types/react-window@1.8.8': + resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==} + + '@types/react@18.2.79': + resolution: {integrity: sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==} + + '@types/recordrtc@5.6.14': + resolution: {integrity: sha512-Reiy1sl11xP0r6w8DW3iQjc1BgXFyNC7aDuutysIjpFoqyftbQps9xPA2FoBkfVXpJM61betgYPNt+v65zvMhA==} + + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + + '@types/sortablejs@1.15.8': + resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@typescript-eslint/eslint-plugin@8.11.0': + resolution: {integrity: sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@8.11.0': + resolution: {integrity: sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@8.11.0': + resolution: {integrity: sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.11.0': + resolution: {integrity: sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@8.11.0': + resolution: {integrity: sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.11.0': + resolution: {integrity: sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.11.0': + resolution: {integrity: sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + '@typescript-eslint/visitor-keys@8.11.0': + resolution: {integrity: sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitest/eslint-plugin@1.1.7': + resolution: {integrity: sha512-pTWGW3y6lH2ukCuuffpan6kFxG6nIuoesbhMiQxskyQMRcCN5t9SXsKrNHvEw3p8wcCsgJoRqFZVkOTn6TjclA==} + peerDependencies: + '@typescript-eslint/utils': '>= 8.0' + eslint: '>= 8.57.0' + typescript: '>= 5.0.0' + vitest: '*' + peerDependenciesMeta: + typescript: + optional: true + vitest: + optional: true + + '@vitest/expect@2.0.5': + resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + + '@vitest/pretty-format@2.0.5': + resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} + + '@vitest/pretty-format@2.1.3': + resolution: {integrity: sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==} + + '@vitest/spy@2.0.5': + resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + + '@vitest/utils@2.0.5': + resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} + + '@vitest/utils@2.1.3': + resolution: {integrity: sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==} + + '@vue/compiler-core@3.5.12': + resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==} + + '@vue/compiler-dom@3.5.12': + resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==} + + '@vue/compiler-sfc@3.5.12': + resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==} + + '@vue/compiler-ssr@3.5.12': + resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==} + + '@vue/shared@3.5.12': + resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==} + + '@webassemblyjs/ast@1.12.1': + resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + + '@webassemblyjs/floating-point-hex-parser@1.11.6': + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + + '@webassemblyjs/helper-api-error@1.11.6': + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + + '@webassemblyjs/helper-buffer@1.12.1': + resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + + '@webassemblyjs/helper-numbers@1.11.6': + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + + '@webassemblyjs/helper-wasm-bytecode@1.11.6': + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + + '@webassemblyjs/helper-wasm-section@1.12.1': + resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + + '@webassemblyjs/ieee754@1.11.6': + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + + '@webassemblyjs/leb128@1.11.6': + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + + '@webassemblyjs/utf8@1.11.6': + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + + '@webassemblyjs/wasm-edit@1.12.1': + resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + + '@webassemblyjs/wasm-gen@1.12.1': + resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + + '@webassemblyjs/wasm-opt@1.12.1': + resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + + '@webassemblyjs/wasm-parser@1.12.1': + resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + + '@webassemblyjs/wast-printer@1.12.1': + resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.13.0: + resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ahooks@3.8.1: + resolution: {integrity: sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-html@0.0.9: + resolution: {integrity: sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + + are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + + async@2.6.4: + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.10.1: + resolution: {integrity: sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-loader@9.2.1: + resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-plugin-polyfill-corejs2@0.4.11: + resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.10.6: + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.2: + resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + before-after-hook@3.0.2: + resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + + better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bing-translate-api@4.0.2: + resolution: {integrity: sha512-JJ8XUehnxzOhHU91oy86xEtp8OOMjVEjCZJX042fKxoO19NNvxJ5omeCcxQNFoPbDqVpBJwqiGVquL0oPdQm1Q==} + + birecord@0.1.1: + resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==} + + bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + + bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-assert@1.2.1: + resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + + browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + + browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001669: + resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} + + canvas@2.11.2: + resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} + engines: {node: '>=6'} + + case-sensitive-paths-webpack-plugin@2.4.0: + resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} + engines: {node: '>=4'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.1: + resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} + engines: {node: '>=10'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chevrotain-allstar@0.3.1: + resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} + peerDependencies: + chevrotain: ^11.0.0 + + chevrotain@11.0.3: + resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + chromatic@11.15.0: + resolution: {integrity: sha512-5WBm+akQnxsdJv7A//XBafYxk88RJYmRjOh61lVitbPCIN2J9jcsQR+hYApnInmQsWRZvO8GKkMy7SdTlnm1dg==} + hasBin: true + peerDependencies: + '@chromatic-com/cypress': ^0.*.* || ^1.0.0 + '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + peerDependenciesMeta: + '@chromatic-com/cypress': + optional: true + '@chromatic-com/playwright': + optional: true + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + + cipher-base@1.0.4: + resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + + class-variance-authority@0.7.0: + resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} + + classcat@5.0.5: + resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} + + classnames@2.3.1: + resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==} + + classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + + clsx@2.0.0: + resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} + engines: {node: '>=6'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + code-inspector-core@0.18.3: + resolution: {integrity: sha512-60pT2cPoguMTUYdN1MMpjoPUnuF0ud/u7M2y+Vqit/bniLEit9dySEWAVxLU/Ukc5ILrDeLKEttc6fCMl9RUrA==} + + code-inspector-plugin@0.18.3: + resolution: {integrity: sha512-d9oJXZUsnvfTaQDwFmDNA2F+AR/TXIxWg1rr8KGcEskltR2prbZsfuu1z70EAn4khpx0smfi/PvIIwNJQ7FAMw==} + + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@1.0.8: + resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + + common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + + core-js-compat@3.38.1: + resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} + + core-js-pure@3.38.1: + resolution: {integrity: sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-browserify@3.12.0: + resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + css-loader@6.11.0: + resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.30.2: + resolution: {integrity: sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.11: + resolution: {integrity: sha512-tvlJLyQf834SylNKax8Wkzco/1ias1OPw8DcUMDE7oUIoSEW25riQVuiu/0OWEFqT0cxHT3Pa9/D82Jr47IONw==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + decompress-response@4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domain-browser@4.23.0: + resolution: {integrity: sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==} + engines: {node: '>=10'} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + dompurify@3.2.3: + resolution: {integrity: sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} + engines: {node: '>=12'} + + echarts-for-react@3.0.2: + resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} + peerDependencies: + echarts: ^3.0.0 || ^4.0.0 || ^5.0.0 + react: ^15.0.0 || >=16.0.0 + + echarts@5.5.1: + resolution: {integrity: sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.41: + resolution: {integrity: sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==} + + elkjs@0.9.3: + resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} + + elliptic@6.6.0: + resolution: {integrity: sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-mart@5.6.0: + resolution: {integrity: sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + endent@2.1.0: + resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==} + + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} + engines: {node: '>=10.13.0'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.1.0: + resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild-code-inspector-plugin@0.18.3: + resolution: {integrity: sha512-FaPt5eFMtW1oXMWqAcqfAJByNagP1V/R9dwDDLQO29JmryMF35+frskTqy+G53whmTaVi19+TCrFqhNbMZH5ZQ==} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-flat-gitignore@0.3.0: + resolution: {integrity: sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og==} + peerDependencies: + eslint: ^9.5.0 + + eslint-config-next@15.0.0: + resolution: {integrity: sha512-HFeTwCR2lFEUWmdB00WZrzaak2CvMvxici38gQknA6Bu2HPizSE4PNFGaFzr5GupjBt+SBJ/E0GIP57ZptOD3g==} + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + + eslint-flat-config-utils@0.4.0: + resolution: {integrity: sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A==} + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.6.3: + resolution: {integrity: sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-merge-processors@0.1.0: + resolution: {integrity: sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ==} + peerDependencies: + eslint: '*' + + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-antfu@2.7.0: + resolution: {integrity: sha512-gZM3jq3ouqaoHmUNszb1Zo2Ux7RckSvkGksjLWz9ipBYGSv1EwwBETN6AdiUXn+RpVHXTbEMPAPlXJazcA6+iA==} + peerDependencies: + eslint: '*' + + eslint-plugin-command@0.2.6: + resolution: {integrity: sha512-T0bHZ1oblW1xUHUVoBKZJR2osSNNGkfZuK4iqboNwuNS/M7tdp3pmURaJtTi/XDzitxaQ02lvOdFH0mUd5QLvQ==} + peerDependencies: + eslint: '*' + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import-x@4.3.1: + resolution: {integrity: sha512-5TriWkXulDl486XnYYRgsL+VQoS/7mhN/2ci02iLCuL7gdhbiWxnsuL/NTcaKY9fpMgsMFjWZBtIGW7pb+RX0g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jsdoc@50.4.3: + resolution: {integrity: sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-plugin-jsonc@2.16.0: + resolution: {integrity: sha512-Af/ZL5mgfb8FFNleH6KlO4/VdmDuTqmM+SPnWcdoWywTetv7kq+vQe99UyQb9XO3b0OWLVuTH7H0d/PXYCMdSg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-plugin-jsx-a11y@6.10.1: + resolution: {integrity: sha512-zHByM9WTUMnfsDTafGXRiqxp6lFtNoSOWBY6FonVRn3A+BUwN1L/tdBXT40BcBJi0cZjOGTXZ0eD/rTG9fEJ0g==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-n@17.11.1: + resolution: {integrity: sha512-93IUD82N6tIEgjztVI/l3ElHtC2wTa9boJHrD8iN+NyDxjxz/daZUZKfkedjBZNdg6EqDk4irybUsiPwDqXAEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.23.0' + + eslint-plugin-no-only-tests@3.3.0: + resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} + engines: {node: '>=5.0.0'} + + eslint-plugin-perfectionist@3.9.1: + resolution: {integrity: sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + astro-eslint-parser: ^1.0.2 + eslint: '>=8.0.0' + svelte: '>=3.0.0' + svelte-eslint-parser: ^0.41.1 + vue-eslint-parser: '>=9.0.0' + peerDependenciesMeta: + astro-eslint-parser: + optional: true + svelte: + optional: true + svelte-eslint-parser: + optional: true + vue-eslint-parser: + optional: true + + eslint-plugin-react-debug@1.15.0: + resolution: {integrity: sha512-zD5WOVPwKNnO4897gz2yjZZcvdGIObKEi4QURDammVEc3sCU0evHcAPEknTC1WEd7T8A4Zu7Vt7sDaUz/DALnA==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-dom@1.15.0: + resolution: {integrity: sha512-P8IdPfiEpDR8SHZdnYJzfdSkV++0hHzOJQhLW9eACyuGCBuzLj2gglmPR5gH2RG44R+Iq5+hsUVNv7sklThvRg==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-hooks-extra@1.15.0: + resolution: {integrity: sha512-guIcax3c4Z/iWyDwZdo5b0qzqpJrhH4svYIfj+wEpfjRdIwpAvL0xM1uqJKdz8Hbgw1D+6dePSau4zmVkuaMqA==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-hooks@5.0.0: + resolution: {integrity: sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-naming-convention@1.15.0: + resolution: {integrity: sha512-XjbkBFEsaGvhDUKCxDCdJ34dsr/XnQu5a7hq6h2aNpnu05VGCAW6CXf3VuyI/sKfj3Em+aX/9eHdcRi12+dmLg==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-refresh@0.4.13: + resolution: {integrity: sha512-f1EppwrpJRWmqDTyvAyomFVDYRtrS7iTEqv3nokETnMiMzs2SSTmKRTACce4O2p4jYyowiSMvpdwC/RLcMFhuQ==} + peerDependencies: + eslint: '>=7' + + eslint-plugin-react-web-api@1.15.0: + resolution: {integrity: sha512-LUwzKumBApdKzUgl+9F5/TyJbYGQIOy450s6kr3rLPrc9tk8GQrBmSQKmWh2g7C1x7DIoMNFXeUuAD1q/1AKnw==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react-x@1.15.0: + resolution: {integrity: sha512-TIZVElFYVXvybmMBVzHPF2hmsaG7greytHd80efUPopxlr+JGjKba6zA3cJAURn+yzN1x2zPJzss2BkB8/48aQ==} + engines: {bun: '>=1.0.15', node: '>=18.18.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ^4.9.5 || ^5.3.3 + peerDependenciesMeta: + typescript: + optional: true + + eslint-plugin-react@7.37.1: + resolution: {integrity: sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-plugin-regexp@2.6.0: + resolution: {integrity: sha512-FCL851+kislsTEQEMioAlpDuK5+E5vs0hi1bF8cFlPlHcEjeRhuAzEsGikXRreE+0j4WhW2uO54MqTjXtYOi3A==} + engines: {node: ^18 || >=20} + peerDependencies: + eslint: '>=8.44.0' + + eslint-plugin-storybook@0.10.1: + resolution: {integrity: sha512-YpxkdqyiKpMIrRquuvBaCinsqmZJ86JvXRX/gtRa4Qctpk0ipFt2cWqEjkB1HHWWG0DVRXlUBKHjRogC2Ig1fg==} + engines: {node: '>= 18'} + peerDependencies: + eslint: '>=6' + + eslint-plugin-tailwindcss@3.17.5: + resolution: {integrity: sha512-8Mi7p7dm+mO1dHgRHHFdPu4RDTBk69Cn4P0B40vRQR+MrguUpwmKwhZy1kqYe3Km8/4nb+cyrCF+5SodOEmaow==} + engines: {node: '>=18.12.0'} + peerDependencies: + tailwindcss: ^3.4.0 + + eslint-plugin-toml@0.11.1: + resolution: {integrity: sha512-Y1WuMSzfZpeMIrmlP1nUh3kT8p96mThIq4NnHrYUhg10IKQgGfBZjAWnrg9fBqguiX4iFps/x/3Hb5TxBisfdw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-plugin-unicorn@56.0.0: + resolution: {integrity: sha512-aXpddVz/PQMmd69uxO98PA4iidiVNvA0xOtbpUoz1WhBd4RxOQQYqN618v68drY0hmy5uU2jy1bheKEVWBjlPw==} + engines: {node: '>=18.18'} + peerDependencies: + eslint: '>=8.56.0' + + eslint-plugin-unused-imports@4.1.4: + resolution: {integrity: sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-plugin-vue@9.29.1: + resolution: {integrity: sha512-MH/MbVae4HV/tM8gKAVWMPJbYgW04CK7SuzYRrlNERpxbO0P3+Zdsa2oAcFBW6xNu7W6lIkGOsFAMCRTYmrlWQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-plugin-yml@1.14.0: + resolution: {integrity: sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + eslint-processor-vue-blocks@0.1.2: + resolution: {integrity: sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ==} + peerDependencies: + '@vue/compiler-sfc': ^3.3.0 + eslint: ^8.50.0 || ^9.0.0 + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.1.0: + resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.1.0: + resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.13.0: + resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.2.0: + resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + express@4.21.1: + resolution: {integrity: sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-parse@1.0.3: + resolution: {integrity: sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fault@1.0.4: + resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + filter-obj@2.0.2: + resolution: {integrity: sha512-lO3ttPjHZRfjMcxWKb1j1eDhTFsu4meeR3lnMcnBFhk6RuLhvEiuALu2TlfL310ph4lCYYwgF/ElIjdP739tdg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-cache-dir@4.0.0: + resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} + engines: {node: '>=14.16'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + fork-ts-checker-webpack-plugin@8.0.0: + resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + + format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.11.0: + resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==} + engines: {node: '>=18'} + + globals@15.13.0: + resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hash-base@3.0.4: + resolution: {integrity: sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==} + engines: {node: '>=4'} + + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-from-dom@5.0.0: + resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} + + hast-util-from-html-isomorphic@2.0.0: + resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + + hast-util-heading-rank@3.0.0: + resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-parse-selector@2.2.5: + resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-raw@9.0.4: + resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} + + hast-util-to-estree@3.1.0: + resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} + + hast-util-to-jsx-runtime@2.3.2: + resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==} + + hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@6.0.0: + resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} + + hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + highlightjs-vue@1.0.0: + resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + + html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-parse-stringify@3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + html-url-attributes@3.0.1: + resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + html-webpack-plugin@5.6.2: + resolution: {integrity: sha512-q7xp/FO9RGBVoTKNItkdX1jKLscLFkgn/dLVFNYbHVbfHLBk6DYW5nsQ8kCzIWcgKP/kUBocetjvav6lD8YfCQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.20.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.1.6: + resolution: {integrity: sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==} + engines: {node: '>=18'} + hasBin: true + + i18next-resources-to-backend@1.2.1: + resolution: {integrity: sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==} + + i18next@23.16.4: + resolution: {integrity: sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + image-size@1.1.1: + resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} + engines: {node: '>=16.x'} + hasBin: true + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + + immutable@4.3.7: + resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + + inline-style-parser@0.2.4: + resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + intersection-observer@0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-absolute-url@4.0.1: + resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-bun-module@1.2.1: + resolution: {integrity: sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-immutable-type@5.0.0: + resolution: {integrity: sha512-mcvHasqbRBWJznuPqqHRKiJgYAz60sZ0mvO3bN70JbkuK7ksfmgc489aKZYxMEjIbRvyOseaTjaRZLRF/xFeRA==} + peerDependencies: + eslint: '*' + typescript: '>=4.7.4' + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isomorphic.js@0.2.5: + resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + iterator.prototype@1.1.3: + resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} + engines: {node: '>= 0.4'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-jsdom@29.7.0: + resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + js-audio-recorder@1.0.7: + resolution: {integrity: sha512-JiDODCElVHGrFyjGYwYyNi7zCbKk9va9C77w+zCPMmi4C6ix7zsX2h3ddHugmo4dOTOTCym9++b/wVW9nC0IaA==} + + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} + engines: {node: '>=12.0.0'} + + jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-eslint-parser@2.4.0: + resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + + katex@0.16.11: + resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + ky@1.7.2: + resolution: {integrity: sha512-OzIvbHKKDpi60TnF9t7UUVAF1B4mcqc02z5PIvrm08Wyb+yOcz63GRvEuVxNT18a9E1SrNouhB4W2NNLeD7Ykg==} + engines: {node: '>=18'} + + lamejs@1.2.1: + resolution: {integrity: sha512-s7bxvjvYthw6oPLCm5pFxvA84wUROODB8jEO2+CE1adhKgrIvVOlmMgY8zyugxGrvRaDHNJanOiS21/emty6dQ==} + + langium@3.0.0: + resolution: {integrity: sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==} + engines: {node: '>=16.0.0'} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + launch-ide@1.0.1: + resolution: {integrity: sha512-U7qBxSNk774PxWq4XbmRe0ThiIstPoa4sMH/OGSYxrFVvg8x3biXcF1fsH6wasDpEmEXMdINUrQhBdwsSgKyMg==} + + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lexical@0.18.0: + resolution: {integrity: sha512-3K/B0RpzjoW+Wj2E455wWXxkqxqK8UgdIiuqkOqdOsoSSo5mCkHOU6eVw7Nlmlr1MFvAMzGmz4RPn8NZaLQ2Mw==} + + lib0@0.2.98: + resolution: {integrity: sha512-XteTiNO0qEXqqweWx+b21p/fBnNHUA1NwAtJNJek1oPrewEZs2uiT4gWivHKr9GqCjDPAhchz0UQO8NwU3bBNA==} + engines: {node: '>=16'} + hasBin: true + + lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + line-clamp@1.0.0: + resolution: {integrity: sha512-dCDlvMj572RIRBQ3x9aIX0DTdt2St1bMdpi64jVTAi5vqBck7wf+J97//+J7+pS80rFJaYa8HiyXCTp0flpnBA==} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.2.10: + resolution: {integrity: sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.2.5: + resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==} + engines: {node: '>=18.0.0'} + + loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} + + localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lowlight@1.20.0: + resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + map-or-similar@1.5.0: + resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + + markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + + markdown-to-jsx@7.5.0: + resolution: {integrity: sha512-RrBNcMHiFPcz/iqIj0n3wclzHXjwS7mzjBNWecKKVhNTIxQepIix6Il/wZCn2Cg5Y1ow2Qi84+eJrryFRWBEWw==} + engines: {node: '>= 10'} + peerDependencies: + react: '>= 0.14.0' + + marked@13.0.3: + resolution: {integrity: sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==} + engines: {node: '>= 18'} + hasBin: true + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + + mdast-util-from-markdown@2.0.1: + resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + + mdast-util-math@3.0.0: + resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.1.3: + resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-newline-to-break@2.0.0: + resolution: {integrity: sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + + memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + + memoizerific@1.11.3: + resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + mermaid@11.4.1: + resolution: {integrity: sha512-Mb01JT/x6CKDWaxigwfZYuYmDZ6xtrNwNlidKZwkSrDaY9n90tdrJTV5Umk+wP1fZscGptmKFXHsXMDEVZ+Q6A==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromark-core-commonmark@2.0.1: + resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.0: + resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-math@3.1.0: + resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} + + micromark-extension-mdx-expression@3.0.0: + resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} + + micromark-extension-mdx-jsx@3.0.1: + resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + + micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + + micromark-factory-mdx-expression@2.0.2: + resolution: {integrity: sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==} + + micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + + micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + + micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + + micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + + micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + + micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + + micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + + micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-events-to-acorn@2.0.2: + resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} + + micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + + micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + + micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-subtokenize@2.0.1: + resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@4.0.4: + resolution: {integrity: sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==} + engines: {node: '>=16'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mlly@1.7.2: + resolution: {integrity: sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==} + + mlly@1.7.3: + resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} + + monaco-editor@0.52.0: + resolution: {integrity: sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nan@2.22.0: + resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + next@14.2.15: + resolution: {integrity: sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==} + engines: {node: '>=18.17.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + sass: + optional: true + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-polyfill-webpack-plugin@2.0.1: + resolution: {integrity: sha512-ZUMiCnZkP1LF0Th2caY6J/eKKoA0TefpoVa68m/LQU1I/mE8rGt4fNYGgNuCcK+aG8P8P43nbeJ2RqJMOL/Y1A==} + engines: {node: '>=12'} + peerDependencies: + webpack: '>=5' + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + normalize-wheel@1.0.1: + resolution: {integrity: sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nwsapi@2.2.13: + resolution: {integrity: sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + + objectorarray@1.0.5: + resolution: {integrity: sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.2: + resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + papaparse@5.4.1: + resolution: {integrity: sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + + parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + + parse-entities@4.0.1: + resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + + parse-gitignore@2.0.0: + resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==} + engines: {node: '>=14'} + + parse-imports@2.2.1: + resolution: {integrity: sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==} + engines: {node: '>= 18'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse5@7.2.0: + resolution: {integrity: sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.10: + resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + path2d@0.2.2: + resolution: {integrity: sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ==} + engines: {node: '>=6'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + + pdfjs-dist@4.4.168: + resolution: {integrity: sha512-MbkAjpwka/dMHaCfQ75RY1FXX3IewBVu6NGZOcxerRFlaBiIkZmUoR0jotX5VUzYZEXAGzSFtknWs5xRKliXPA==} + engines: {node: '>=18'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pinyin-pro@3.25.0: + resolution: {integrity: sha512-MpwQPa9Ry+1vVHrsRgfJTvbtoMn0Gk529OZEWqN+O/iiSOqnd2dbKrDMaX87n7YvVPhy2W1/sKakK9zheYNWeg==} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pkg-dir@7.0.0: + resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} + engines: {node: '>=14.16'} + + pkg-types@1.2.1: + resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + pnp-webpack-plugin@1.7.0: + resolution: {integrity: sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==} + engines: {node: '>=6'} + + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} + engines: {node: '>=10'} + + portfinder@1.0.32: + resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} + engines: {node: '>= 0.12.0'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-loader@8.1.1: + resolution: {integrity: sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.0.5: + resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.0: + resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + prismjs@1.27.0: + resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} + engines: {node: '>=6'} + + prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + property-information@5.6.0: + resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} + + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + + public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + + qrcode.react@4.1.0: + resolution: {integrity: sha512-uqXVIIVD/IPgWLYxbOczCNAQw80XCM/LulYDADF+g2xDsPj5OoRwSWtIS4jGyp295wyjKstfG1qIv/I2/rNWpQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + queue@6.0.2: + resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + rc-input@1.6.3: + resolution: {integrity: sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + rc-resize-observer@1.4.0: + resolution: {integrity: sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-textarea@1.8.2: + resolution: {integrity: sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + rc-util@5.43.0: + resolution: {integrity: sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + re-resizable@6.10.0: + resolution: {integrity: sha512-hysSK0xmA5nz24HBVztlk4yCqCLCvS32E6ZpWxVKop9x3tqCa4yAj1++facrmkOf62JsJHjmjABdKxXofYioCw==} + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + + react-18-input-autosize@3.0.0: + resolution: {integrity: sha512-7tsUc9PJWg6Vsp8qYuzlKKBf7hbCoTBdNfjYZSprEPbxf3meuhjklg9QPBe9rIyoR3uDAzmG7NpoJ1+kP5ns+w==} + peerDependencies: + react: ^16.3.0 || ^17.0.0 || ^18.0.0 + + react-colorful@5.6.1: + resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + react-confetti@6.1.0: + resolution: {integrity: sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==} + engines: {node: '>=10.18'} + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 + + react-docgen-typescript@2.2.2: + resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} + peerDependencies: + typescript: '>= 4.3.x' + + react-docgen@7.1.0: + resolution: {integrity: sha512-APPU8HB2uZnpl6Vt/+0AFoVYgSRtfiP6FLrZgPPTDmqSb2R4qZRbgd0A3VzIFxDt5e+Fozjx79WjLWnF69DK8g==} + engines: {node: '>=16.14.0'} + + react-dom@18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + + react-draggable@4.4.6: + resolution: {integrity: sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==} + peerDependencies: + react: '>= 16.3.0' + react-dom: '>= 16.3.0' + + react-easy-crop@5.1.0: + resolution: {integrity: sha512-UsYeF/N7zoqtfOSD+2xSt1nRaoBYCI2YLkzmq+hi+aVepS4/bAMhbrLwJtDAP60jsVzWRiQCX7JG+ZtfWcHsiw==} + peerDependencies: + react: '>=16.4.0' + react-dom: '>=16.4.0' + + react-element-to-jsx-string@15.0.0: + resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==} + peerDependencies: + react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 + react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 + + react-error-boundary@3.1.4: + resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13.1' + + react-error-boundary@4.1.2: + resolution: {integrity: sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==} + peerDependencies: + react: '>=16.13.1' + + react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + + react-headless-pagination@1.1.6: + resolution: {integrity: sha512-t7L/Q4xpyZszw8iC8ALERs/G2644JESmssahUkRp65WFWvw2k9HXVmfI6VbXvTXrqy+a8fbKT6BQ6SgS2ULNOA==} + engines: {node: '>=18.13'} + peerDependencies: + react: '>=16' + + react-hook-form@7.53.1: + resolution: {integrity: sha512-6aiQeBda4zjcuaugWvim9WsGqisoUk+etmFEsSUMm451/Ic8L/UAb7sRtMj3V+Hdzm6mMjU1VhiSzYUZeBm0Vg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + + react-hotkeys-hook@4.6.1: + resolution: {integrity: sha512-XlZpbKUj9tkfgPgT9gA+1p7Ey6vFIZHttUjPqpTdyT5nqQ8mHL7elxvSbaC+dpSiHUSmr21Ya1mDxBZG3aje4Q==} + peerDependencies: + react: '>=16.8.1' + react-dom: '>=16.8.1' + + react-i18next@15.1.0: + resolution: {integrity: sha512-zj3nJynMnZsy2gPZiOTC7XctCY5eQGqT3tcKMmfJWC9FMvgd+960w/adq61j8iPzpwmsXejqID9qC3Mqu1Xu2Q==} + peerDependencies: + i18next: '>= 23.2.3' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + + react-infinite-scroll-component@6.1.0: + resolution: {integrity: sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==} + peerDependencies: + react: '>=16.0.0' + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-is@18.1.0: + resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-markdown@9.0.1: + resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==} + peerDependencies: + '@types/react': ~18.2.0 + react: '>=18' + + react-multi-email@1.0.25: + resolution: {integrity: sha512-Wmv28FvIk4nWgdpHzlIPonY4iSs7bPV35+fAiWYzSBhTo+vhXfglEhjY1WnjHQINW/Pibu2xlb/q1heVuytQHQ==} + peerDependencies: + react: ^18.2.0 + react-dom: ^18.2.0 + + react-papaparse@4.4.0: + resolution: {integrity: sha512-xTEwHZYJ+1dh9mQDQjjwJXmWyX20DdZ52u+ddw75V+Xm5qsjXSvWmC7c8K82vRwMjKAOH2S9uFyGpHEyEztkUQ==} + engines: {node: '>=8', npm: '>=5'} + + react-pdf-highlighter@8.0.0-rc.0: + resolution: {integrity: sha512-zYHDq5XxsXA02UbFUoMdo7Cex1l42vHJxszywXmct2kUMZm6TmU3b/a5zOS6ssXWqdjEx5Vpq6/gW+Mek9rDTQ==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react-rnd@10.4.13: + resolution: {integrity: sha512-Vgbf0iihspcQ6nkaFhpOGWfmnuVbhkhoB0hBbYl8aRDA4horsQHESc4E1z7O/P27kFFjK2aqM0u5CGzfr9gEZA==} + peerDependencies: + react: '>=16.3.0' + react-dom: '>=16.3.0' + + react-slider@2.0.6: + resolution: {integrity: sha512-gJxG1HwmuMTJ+oWIRCmVWvgwotNCbByTwRkFZC6U4MBsHqJBmxwbYRJUmxy4Tke1ef8r9jfXjgkmY/uHOCEvbA==} + peerDependencies: + react: ^16 || ^17 || ^18 + + react-sortablejs@6.1.4: + resolution: {integrity: sha512-fc7cBosfhnbh53Mbm6a45W+F735jwZ1UFIYSrIqcO/gRIFoDyZeMtgKlpV4DdyQfbCzdh5LoALLTDRxhMpTyXQ==} + peerDependencies: + '@types/sortablejs': '1' + react: '>=16.9.0' + react-dom: '>=16.9.0' + sortablejs: '1' + + react-syntax-highlighter@15.6.1: + resolution: {integrity: sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==} + peerDependencies: + react: '>= 0.14.0' + + react-tooltip@5.8.3: + resolution: {integrity: sha512-h7maAlm2Xeymc14gWKhhrzsENeB83N65EzZ+AcQIGrOpNE0yefVRJIHhNcWHEJ0FEtf7VZXxtsj5glVXKxEtvA==} + peerDependencies: + react: '>=16.14.0' + react-dom: '>=16.14.0' + + react-window-infinite-loader@1.0.9: + resolution: {integrity: sha512-5Hg89IdU4Vrp0RT8kZYKeTIxWZYhNkVXeI1HbKo01Vm/Z7qztDvXljwx16sMzsa9yapRJQW3ODZfMUw38SOWHw==} + engines: {node: '>8.0.0'} + peerDependencies: + react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 + react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 + + react-window@1.8.10: + resolution: {integrity: sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==} + engines: {node: '>8.0.0'} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + + react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + + reactflow@11.11.4: + resolution: {integrity: sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + recast@0.23.9: + resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} + engines: {node: '>= 4'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.0: + resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + + recordrtc@5.6.2: + resolution: {integrity: sha512-1QNKKNtl7+KcwD1lyOgP3ZlbiJ1d0HtXnypUy7yq49xEERxk31PHvE9RCciDrulPCY7WJ+oz0R9hpNxgsIurGQ==} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + refa@0.12.1: + resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + + refractor@3.6.0: + resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + + regex-parser@2.3.0: + resolution: {integrity: sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==} + + regexp-ast-analysis@0.7.1: + resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} + engines: {node: '>= 0.4'} + + regexpu-core@6.1.1: + resolution: {integrity: sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.10.0: + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + hasBin: true + + regjsparser@0.11.1: + resolution: {integrity: sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==} + hasBin: true + + rehype-external-links@3.0.0: + resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} + + rehype-katex@7.0.1: + resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + + rehype-slug@6.0.0: + resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + remark-breaks@4.0.0: + resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==} + + remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + + remark-math@6.0.0: + resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} + + remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.1: + resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve-url-loader@5.0.0: + resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==} + engines: {node: '>=12'} + + resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sass-loader@13.3.3: + resolution: {integrity: sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + + sass@1.80.3: + resolution: {integrity: sha512-ptDWyVmDMVielpz/oWy3YP3nfs7LpJTHIJZboMVs8GEC9eUmtZTZhMHlTW98wY4aEorDfjN38+Wr/XjskFWcfA==} + engines: {node: '>=14.0.0'} + hasBin: true + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.2.0: + resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} + engines: {node: '>= 12.13.0'} + + screenfull@5.2.0: + resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + engines: {node: '>=0.10.0'} + + scslre@0.3.0: + resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} + engines: {node: ^14.0.0 || >=16.0.0} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + server-only@0.0.1: + resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shave@5.0.4: + resolution: {integrity: sha512-AnvEI1wM2rQmrwCl364LVLLhzCzSHJ7DQmdd+fHJTnNzbD2mjsUAOcxWLLYKam7Q63skwyQf2CB2TCdJ2O5c8w==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + short-unique-id@5.2.0: + resolution: {integrity: sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg==} + hasBin: true + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@3.1.1: + resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + size-sensor@1.0.2: + resolution: {integrity: sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slashes@3.0.12: + resolution: {integrity: sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + sortablejs@1.15.3: + resolution: {integrity: sha512-zdK3/kwwAK1cJgy1rwl1YtNTbRmc8qW/+vgXf75A7NHag5of4pyI6uK86ktmQETyWRH7IGaE73uZOOBcGxgqZg==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + space-separated-tokens@1.1.5: + resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + storybook@8.3.6: + resolution: {integrity: sha512-9GVbtej6ZzPRUM7KRQ7848506FfHrUiJGqPuIQdoSJd09EmuEoLjmLAgEOmrHBQKgGYMaM7Vh9GsTLim6vwZTQ==} + hasBin: true + + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + + stream-http@3.2.0: + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-ts@2.2.0: + resolution: {integrity: sha512-VTP0LLZo4Jp9Gz5IiDVMS9WyLx/3IeYh0PXUn0NdPqusUFNgkHPWiEdbB9TU2Iv3myUskraD5WtYEdHUrQEIlQ==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-indent@4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + style-loader@3.3.4: + resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + + style-to-object@1.0.8: + resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} + + styled-jsx@5.1.1: + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + stylis@4.3.4: + resolution: {integrity: sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + swr@2.2.5: + resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + synckit@0.6.2: + resolution: {integrity: sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==} + engines: {node: '>=12.20'} + + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} + engines: {node: ^14.18.0 || >=16.0.0} + + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + + tailwind-merge@2.5.4: + resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} + + tailwindcss@3.4.14: + resolution: {integrity: sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==} + engines: {node: '>=14.0.0'} + hasBin: true + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + telejson@7.2.0: + resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} + + terser-webpack-plugin@5.3.10: + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@5.36.0: + resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + throttle-debounce@2.3.0: + resolution: {integrity: sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==} + engines: {node: '>=8'} + + timers-browserify@2.0.12: + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} + + tiny-invariant@1.2.0: + resolution: {integrity: sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toml-eslint-parser@0.10.0: + resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-debounce@4.0.0: + resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} + + ts-declaration-location@1.0.4: + resolution: {integrity: sha512-r4JoxYhKULbZuH81Pjrp9OEG5St7XWk7zXwGkLKhmVcjiBVHTJXV5wK6dEa9JKW5QGSTW6b1lOjxAKp8R1SQhg==} + peerDependencies: + typescript: '>=4.0.0' + + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + ts-pattern@5.5.0: + resolution: {integrity: sha512-jqbIpTsa/KKTJYWgPNsFNbLVpwCgzXfFJ1ukNn4I8hMwyQzHMJnk/BqWzggB0xpkILuKzaO/aMYhS0SkaJyKXg==} + + ts-pnp@1.2.0: + resolution: {integrity: sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==} + engines: {node: '>=6'} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + tsconfig-paths-webpack-plugin@4.1.0: + resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} + engines: {node: '>=10.13.0'} + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + + tty-browserify@0.0.1: + resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} + + tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + universal-user-agent@7.0.2: + resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unplugin@1.14.1: + resolution: {integrity: sha512-lBlHbfSFPToDYp9pjXlUEFVxYLaue9f9T1HC+4OHlmj+HnMDdz9oZY+erXfoCe/5V/7gKUSY2jpXPb9S7f0f/w==} + engines: {node: '>=14.0.0'} + peerDependencies: + webpack-sources: ^3 + peerDependenciesMeta: + webpack-sources: + optional: true + + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + use-context-selector@2.0.0: + resolution: {integrity: sha512-owfuSmUNd3eNp3J9CdDl0kMgfidV+MkDvHPpvthN5ThqM+ibMccNE0k+Iq7TWC6JPFvGZqanqiGCuQx6DyV24g==} + peerDependencies: + react: '>=18.0.0' + scheduler: '>=0.19.0' + + use-strict@1.0.1: + resolution: {integrity: sha512-IeiWvvEXfW5ltKVMkxq6FvNf2LojMKvB2OCeja6+ct24S1XOmQw2dGr2JyndwACWAGJva9B7yPHwAmeA9QCqAQ==} + + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + utila@0.4.0: + resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite-code-inspector-plugin@0.18.3: + resolution: {integrity: sha512-178H73vbDUHE+JpvfAfioUHlUr7qXCYIEa2YNXtzenFQGOjtae59P1jjcxGfa6pPHEnOoaitb13K+0qxwhi/WA==} + + vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + + void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + + vue-eslint-parser@9.4.3: + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '>=6.0.0' + + w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + webpack-code-inspector-plugin@0.18.3: + resolution: {integrity: sha512-3782rsJhBnRiw0IpR6EqnyGDQoiSq0CcGeLJ52rZXlszYCe8igXtcujq7OhI0byaivWQ1LW7sXKyMEoVpBhq0w==} + + webpack-dev-middleware@6.1.3: + resolution: {integrity: sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-hot-middleware@2.26.1: + resolution: {integrity: sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==} + + webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + webpack@5.95.0: + resolution: {integrity: sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-builtin-type@1.1.4: + resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml-eslint-parser@1.2.3: + resolution: {integrity: sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==} + engines: {node: ^14.17.0 || >=16.0.0} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + + yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yjs@13.6.20: + resolution: {integrity: sha512-Z2YZI+SYqK7XdWlloI3lhMiKnCdFCVC4PchpdO+mCYwtiTwncjUbnRK9R1JmkNfdmHyDXuWN3ibJAt0wsqTbLQ==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zrender@5.6.0: + resolution: {integrity: sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==} + + zundo@2.2.0: + resolution: {integrity: sha512-WYCiSO3Uqm7TN9KtT3dpfhOuAS1t5CixjYJuPfVMKl88BZVpP449XtXeiuHWEtRAfYE3yFvRkFCgAThm7v3QuQ==} + peerDependencies: + zustand: ^4.3.0 + + zustand@4.5.5: + resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': ~18.2.0 + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@adobe/css-tools@4.4.0': {} + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@antfu/eslint-config@3.8.0(@eslint-react/eslint-plugin@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(@vue/compiler-sfc@3.5.12)(eslint-plugin-react-hooks@5.0.0(eslint@9.13.0(jiti@1.21.6)))(eslint-plugin-react-refresh@0.4.13(eslint@9.13.0(jiti@1.21.6)))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@clack/prompts': 0.7.0 + '@eslint-community/eslint-plugin-eslint-comments': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@eslint/markdown': 6.2.1 + '@stylistic/eslint-plugin': 2.9.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/eslint-plugin': 8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/parser': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@vitest/eslint-plugin': 1.1.7(@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + eslint-config-flat-gitignore: 0.3.0(eslint@9.13.0(jiti@1.21.6)) + eslint-flat-config-utils: 0.4.0 + eslint-merge-processors: 0.1.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-antfu: 2.7.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-command: 0.2.6(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-import-x: 4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-jsdoc: 50.4.3(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-jsonc: 2.16.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-n: 17.11.1(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-no-only-tests: 3.3.0 + eslint-plugin-perfectionist: 3.9.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)(vue-eslint-parser@9.4.3(eslint@9.13.0(jiti@1.21.6))) + eslint-plugin-regexp: 2.6.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-toml: 0.11.1(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-unicorn: 56.0.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-vue: 9.29.1(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-yml: 1.14.0(eslint@9.13.0(jiti@1.21.6)) + eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.5.12)(eslint@9.13.0(jiti@1.21.6)) + globals: 15.11.0 + jsonc-eslint-parser: 2.4.0 + local-pkg: 0.5.0 + parse-gitignore: 2.0.0 + picocolors: 1.1.1 + toml-eslint-parser: 0.10.0 + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@1.21.6)) + yaml-eslint-parser: 1.2.3 + yargs: 17.7.2 + optionalDependencies: + '@eslint-react/eslint-plugin': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-hooks: 5.0.0(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-react-refresh: 0.4.13(eslint@9.13.0(jiti@1.21.6)) + transitivePeerDependencies: + - '@typescript-eslint/utils' + - '@vue/compiler-sfc' + - supports-color + - svelte + - typescript + - vitest + + '@antfu/install-pkg@0.4.1': + dependencies: + package-manager-detector: 0.2.2 + tinyexec: 0.3.1 + + '@antfu/utils@0.7.10': {} + + '@babel/code-frame@7.25.7': + dependencies: + '@babel/highlight': 7.25.7 + picocolors: 1.1.1 + + '@babel/compat-data@7.25.8': {} + + '@babel/core@7.25.8': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) + '@babel/helpers': 7.25.7 + '@babel/parser': 7.25.8 + '@babel/template': 7.25.7 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + convert-source-map: 2.0.0 + debug: 4.3.7 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.25.7': + dependencies: + '@babel/types': 7.25.8 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 + + '@babel/helper-annotate-as-pure@7.25.7': + dependencies: + '@babel/types': 7.25.8 + + '@babel/helper-builder-binary-assignment-operator-visitor@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-compilation-targets@7.25.7': + dependencies: + '@babel/compat-data': 7.25.8 + '@babel/helper-validator-option': 7.25.7 + browserslist: 4.24.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-member-expression-to-functions': 7.25.7 + '@babel/helper-optimise-call-expression': 7.25.7 + '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.8) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + '@babel/traverse': 7.25.7 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + regexpu-core: 6.1.1 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + debug: 4.3.7 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-imports': 7.25.7 + '@babel/helper-simple-access': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.7': + dependencies: + '@babel/types': 7.25.8 + + '@babel/helper-plugin-utils@7.25.7': {} + + '@babel/helper-remap-async-to-generator@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-wrap-function': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-member-expression-to-functions': 7.25.7 + '@babel/helper-optimise-call-expression': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-simple-access@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.7': + dependencies: + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.7': {} + + '@babel/helper-validator-identifier@7.25.7': {} + + '@babel/helper-validator-option@7.25.7': {} + + '@babel/helper-wrap-function@7.25.7': + dependencies: + '@babel/template': 7.25.7 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.25.7': + dependencies: + '@babel/template': 7.25.7 + '@babel/types': 7.25.8 + + '@babel/highlight@7.25.7': + dependencies: + '@babel/helper-validator-identifier': 7.25.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/parser@7.25.8': + dependencies: + '@babel/types': 7.25.8 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + '@babel/plugin-transform-optional-chaining': 7.25.8(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-import-assertions@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-import-attributes@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-jsx@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-typescript@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-arrow-functions@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-async-generator-functions@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-remap-async-to-generator': 7.25.7(@babel/core@7.25.8) + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-imports': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-remap-async-to-generator': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-block-scoping@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-class-properties@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.8) + '@babel/traverse': 7.25.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/template': 7.25.7 + + '@babel/plugin-transform-destructuring@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-dotall-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-duplicate-keys@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-dynamic-import@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-exponentiation-operator@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-export-namespace-from@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-for-of@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-literals@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-logical-assignment-operators@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-member-expression-literals@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-modules-amd@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-simple-access': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 + '@babel/traverse': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-new-target@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-nullish-coalescing-operator@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-numeric-separator@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-object-rest-spread@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/plugin-transform-parameters': 7.25.7(@babel/core@7.25.8) + + '@babel/plugin-transform-object-super@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-replace-supers': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-optional-chaining@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-private-methods@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-react-display-name@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-react-jsx-development@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/plugin-transform-react-jsx': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-module-imports': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.8) + '@babel/types': 7.25.8 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-regenerator@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + regenerator-transform: 0.15.2 + + '@babel/plugin-transform-reserved-words@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-runtime@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-imports': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.8) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.8) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.8) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-spread@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-template-literals@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-typeof-symbol@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-typescript@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-annotate-as-pure': 7.25.7 + '@babel/helper-create-class-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.7 + '@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-unicode-property-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-unicode-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/plugin-transform-unicode-sets-regex@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-create-regexp-features-plugin': 7.25.7(@babel/core@7.25.8) + '@babel/helper-plugin-utils': 7.25.7 + + '@babel/preset-env@7.25.8(@babel/core@7.25.8)': + dependencies: + '@babel/compat-data': 7.25.8 + '@babel/core': 7.25.8 + '@babel/helper-compilation-targets': 7.25.7 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-validator-option': 7.25.7 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.8) + '@babel/plugin-syntax-import-assertions': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-syntax-import-attributes': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.25.8) + '@babel/plugin-transform-arrow-functions': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-async-generator-functions': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-async-to-generator': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-block-scoped-functions': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-block-scoping': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-class-properties': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-class-static-block': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-classes': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-computed-properties': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-destructuring': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-dotall-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-duplicate-keys': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-dynamic-import': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-exponentiation-operator': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-export-namespace-from': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-for-of': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-function-name': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-json-strings': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-literals': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-logical-assignment-operators': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-member-expression-literals': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-modules-amd': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-modules-commonjs': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-modules-systemjs': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-modules-umd': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-new-target': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-nullish-coalescing-operator': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-numeric-separator': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-object-rest-spread': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-object-super': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-optional-catch-binding': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-optional-chaining': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-parameters': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-private-methods': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-private-property-in-object': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-property-literals': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-regenerator': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-reserved-words': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-shorthand-properties': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-spread': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-sticky-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-template-literals': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-typeof-symbol': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-unicode-escapes': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-unicode-property-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-unicode-regex': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-unicode-sets-regex': 7.25.7(@babel/core@7.25.8) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.25.8) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.8) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.8) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.8) + core-js-compat: 3.38.1 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/types': 7.25.8 + esutils: 2.0.3 + + '@babel/preset-react@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-validator-option': 7.25.7 + '@babel/plugin-transform-react-display-name': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-react-jsx': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-react-jsx-development': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-react-pure-annotations': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/helper-validator-option': 7.25.7 + '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-modules-commonjs': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-typescript': 7.25.7(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.25.7': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.25.7': + dependencies: + '@babel/code-frame': 7.25.7 + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + + '@babel/traverse@7.25.7': + dependencies: + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 + '@babel/parser': 7.25.8 + '@babel/template': 7.25.7 + '@babel/types': 7.25.8 + debug: 4.3.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.25.8': + dependencies: + '@babel/helper-string-parser': 7.25.7 + '@babel/helper-validator-identifier': 7.25.7 + to-fast-properties: 2.0.0 + + '@base2/pretty-print-object@1.0.1': {} + + '@bcoe/v8-coverage@0.2.3': {} + + '@braintree/sanitize-url@7.1.0': {} + + '@chevrotain/cst-dts-gen@11.0.3': + dependencies: + '@chevrotain/gast': 11.0.3 + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/gast@11.0.3': + dependencies: + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/regexp-to-ast@11.0.3': {} + + '@chevrotain/types@11.0.3': {} + + '@chevrotain/utils@11.0.3': {} + + '@chromatic-com/storybook@3.1.0(react@18.2.0)(storybook@8.3.6)': + dependencies: + '@storybook/channels': 8.3.6(storybook@8.3.6) + '@storybook/telemetry': 8.3.6(storybook@8.3.6) + '@storybook/types': 8.3.6(storybook@8.3.6) + chromatic: 11.15.0 + filesize: 10.1.6 + jsonfile: 6.1.0 + react-confetti: 6.1.0(react@18.2.0) + storybook: 8.3.6 + strip-ansi: 7.1.0 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + - react + + '@clack/core@0.3.4': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@0.7.0': + dependencies: + '@clack/core': 0.3.4 + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@dagrejs/dagre@1.1.4': + dependencies: + '@dagrejs/graphlib': 2.2.4 + + '@dagrejs/graphlib@2.2.4': {} + + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.8.0 + optional: true + + '@emoji-mart/data@1.2.1': {} + + '@es-joy/jsdoccomment@0.48.0': + dependencies: + comment-parser: 1.4.1 + esquery: 1.6.0 + jsdoc-type-pratt-parser: 4.1.0 + + '@es-joy/jsdoccomment@0.49.0': + dependencies: + comment-parser: 1.4.1 + esquery: 1.6.0 + jsdoc-type-pratt-parser: 4.1.0 + + '@esbuild/aix-ppc64@0.23.1': + optional: true + + '@esbuild/android-arm64@0.23.1': + optional: true + + '@esbuild/android-arm@0.23.1': + optional: true + + '@esbuild/android-x64@0.23.1': + optional: true + + '@esbuild/darwin-arm64@0.23.1': + optional: true + + '@esbuild/darwin-x64@0.23.1': + optional: true + + '@esbuild/freebsd-arm64@0.23.1': + optional: true + + '@esbuild/freebsd-x64@0.23.1': + optional: true + + '@esbuild/linux-arm64@0.23.1': + optional: true + + '@esbuild/linux-arm@0.23.1': + optional: true + + '@esbuild/linux-ia32@0.23.1': + optional: true + + '@esbuild/linux-loong64@0.23.1': + optional: true + + '@esbuild/linux-mips64el@0.23.1': + optional: true + + '@esbuild/linux-ppc64@0.23.1': + optional: true + + '@esbuild/linux-riscv64@0.23.1': + optional: true + + '@esbuild/linux-s390x@0.23.1': + optional: true + + '@esbuild/linux-x64@0.23.1': + optional: true + + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + + '@esbuild/openbsd-x64@0.23.1': + optional: true + + '@esbuild/sunos-x64@0.23.1': + optional: true + + '@esbuild/win32-arm64@0.23.1': + optional: true + + '@esbuild/win32-ia32@0.23.1': + optional: true + + '@esbuild/win32-x64@0.23.1': + optional: true + + '@eslint-community/eslint-plugin-eslint-comments@4.4.0(eslint@9.13.0(jiti@1.21.6))': + dependencies: + escape-string-regexp: 4.0.0 + eslint: 9.13.0(jiti@1.21.6) + ignore: 5.3.2 + + '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0(jiti@1.21.6))': + dependencies: + eslint: 9.13.0(jiti@1.21.6) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.11.1': {} + + '@eslint-react/ast@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/typescript-estree': 8.11.0(typescript@4.9.5) + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + birecord: 0.1.1 + string-ts: 2.2.0 + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/core@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + birecord: 0.1.1 + short-unique-id: 5.2.0 + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/eslint-plugin@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + eslint-plugin-react-debug: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-dom: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-hooks-extra: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-naming-convention: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-web-api: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint-plugin-react-x: 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@eslint-react/jsx@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/shared@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/tools': 1.15.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + picomatch: 4.0.2 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/tools@1.15.0': {} + + '@eslint-react/types@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/tools': 1.15.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint-react/var@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + ts-pattern: 5.5.0 + transitivePeerDependencies: + - eslint + - supports-color + - typescript + + '@eslint/compat@1.2.1(eslint@9.13.0(jiti@1.21.6))': + optionalDependencies: + eslint: 9.13.0(jiti@1.21.6) + + '@eslint/config-array@0.18.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/core@0.7.0': {} + + '@eslint/eslintrc@3.1.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 10.2.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.13.0': {} + + '@eslint/markdown@6.2.1': + dependencies: + '@eslint/plugin-kit': 0.2.1 + mdast-util-from-markdown: 2.0.1 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@eslint/object-schema@2.1.4': {} + + '@eslint/plugin-kit@0.2.1': + dependencies: + levn: 0.4.1 + + '@faker-js/faker@9.0.3': {} + + '@floating-ui/core@1.6.8': + dependencies: + '@floating-ui/utils': 0.2.8 + + '@floating-ui/dom@1.1.1': + dependencies: + '@floating-ui/core': 1.6.8 + + '@floating-ui/dom@1.6.11': + dependencies: + '@floating-ui/core': 1.6.8 + '@floating-ui/utils': 0.2.8 + + '@floating-ui/react-dom@2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@floating-ui/dom': 1.6.11 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@floating-ui/react@0.26.27(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@floating-ui/utils': 0.2.8 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + + '@floating-ui/utils@0.2.8': {} + + '@formatjs/intl-localematcher@0.5.6': + dependencies: + tslib: 2.8.0 + + '@headlessui/react@1.7.19(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/react-virtual': 3.10.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + client-only: 0.0.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@heroicons/react@2.1.5(react@18.2.0)': + dependencies: + react: 18.2.0 + + '@hookform/resolvers@3.9.0(react-hook-form@7.53.1(react@18.2.0))': + dependencies: + react-hook-form: 7.53.1(react@18.2.0) + + '@humanfs/core@0.19.0': {} + + '@humanfs/node@0.16.5': + dependencies: + '@humanfs/core': 0.19.0 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.2.0': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.4.0 + globals: 15.13.0 + kolorist: 1.8.0 + local-pkg: 0.5.1 + mlly: 1.7.3 + transitivePeerDependencies: + - supports-color + + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 4.2.3 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 18.15.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 18.15.0 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.25.8 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 18.15.0 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@lexical/clipboard@0.18.0': + dependencies: + '@lexical/html': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/code@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + prismjs: 1.29.0 + + '@lexical/devtools-core@0.18.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@lexical/html': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/mark': 0.18.0 + '@lexical/table': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@lexical/dragon@0.18.0': + dependencies: + lexical: 0.18.0 + + '@lexical/hashtag@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/history@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/html@0.18.0': + dependencies: + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/link@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/list@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/mark@0.18.0': + dependencies: + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/markdown@0.18.0': + dependencies: + '@lexical/code': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/rich-text': 0.18.0 + '@lexical/text': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/offset@0.18.0': + dependencies: + lexical: 0.18.0 + + '@lexical/overflow@0.18.0': + dependencies: + lexical: 0.18.0 + + '@lexical/plain-text@0.18.0': + dependencies: + '@lexical/clipboard': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/react@0.18.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(yjs@13.6.20)': + dependencies: + '@lexical/clipboard': 0.18.0 + '@lexical/code': 0.18.0 + '@lexical/devtools-core': 0.18.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@lexical/dragon': 0.18.0 + '@lexical/hashtag': 0.18.0 + '@lexical/history': 0.18.0 + '@lexical/link': 0.18.0 + '@lexical/list': 0.18.0 + '@lexical/mark': 0.18.0 + '@lexical/markdown': 0.18.0 + '@lexical/overflow': 0.18.0 + '@lexical/plain-text': 0.18.0 + '@lexical/rich-text': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/table': 0.18.0 + '@lexical/text': 0.18.0 + '@lexical/utils': 0.18.0 + '@lexical/yjs': 0.18.0(yjs@13.6.20) + lexical: 0.18.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-error-boundary: 3.1.4(react@18.2.0) + transitivePeerDependencies: + - yjs + + '@lexical/rich-text@0.18.0': + dependencies: + '@lexical/clipboard': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/selection@0.18.0': + dependencies: + lexical: 0.18.0 + + '@lexical/table@0.18.0': + dependencies: + '@lexical/clipboard': 0.18.0 + '@lexical/utils': 0.18.0 + lexical: 0.18.0 + + '@lexical/text@0.18.0': + dependencies: + lexical: 0.18.0 + + '@lexical/utils@0.18.0': + dependencies: + '@lexical/list': 0.18.0 + '@lexical/selection': 0.18.0 + '@lexical/table': 0.18.0 + lexical: 0.18.0 + + '@lexical/yjs@0.18.0(yjs@13.6.20)': + dependencies: + '@lexical/offset': 0.18.0 + '@lexical/selection': 0.18.0 + lexical: 0.18.0 + yjs: 13.6.20 + + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.0.3 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.6.3 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@mdx-js/loader@3.1.0(acorn@8.13.0)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3))': + dependencies: + '@mdx-js/mdx': 3.1.0(acorn@8.13.0) + source-map: 0.7.4 + optionalDependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + transitivePeerDependencies: + - acorn + - supports-color + + '@mdx-js/mdx@3.1.0(acorn@8.13.0)': + dependencies: + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-util-scope: 1.0.0 + estree-walker: 3.0.3 + hast-util-to-jsx-runtime: 2.3.2 + markdown-extensions: 2.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.0(acorn@8.13.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + source-map: 0.7.4 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - acorn + - supports-color + + '@mdx-js/react@3.1.0(@types/react@18.2.79)(react@18.2.0)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 18.2.79 + react: 18.2.0 + + '@mermaid-js/parser@0.3.0': + dependencies: + langium: 3.0.0 + + '@monaco-editor/loader@1.4.0(monaco-editor@0.52.0)': + dependencies: + monaco-editor: 0.52.0 + state-local: 1.0.7 + + '@monaco-editor/react@4.6.0(monaco-editor@0.52.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@monaco-editor/loader': 1.4.0(monaco-editor@0.52.0) + monaco-editor: 0.52.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@next/env@14.2.15': {} + + '@next/eslint-plugin-next@15.0.0': + dependencies: + fast-glob: 3.3.1 + + '@next/mdx@14.2.15(@mdx-js/loader@3.1.0(acorn@8.13.0)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)))(@mdx-js/react@3.1.0(@types/react@18.2.79)(react@18.2.0))': + dependencies: + source-map: 0.7.4 + optionalDependencies: + '@mdx-js/loader': 3.1.0(acorn@8.13.0)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + '@mdx-js/react': 3.1.0(@types/react@18.2.79)(react@18.2.0) + + '@next/swc-darwin-arm64@14.2.15': + optional: true + + '@next/swc-darwin-x64@14.2.15': + optional: true + + '@next/swc-linux-arm64-gnu@14.2.15': + optional: true + + '@next/swc-linux-arm64-musl@14.2.15': + optional: true + + '@next/swc-linux-x64-gnu@14.2.15': + optional: true + + '@next/swc-linux-x64-musl@14.2.15': + optional: true + + '@next/swc-win32-arm64-msvc@14.2.15': + optional: true + + '@next/swc-win32-ia32-msvc@14.2.15': + optional: true + + '@next/swc-win32-x64-msvc@14.2.15': + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@nolyfill/is-core-module@1.0.39': {} + + '@octokit/auth-token@5.1.1': {} + + '@octokit/core@6.1.2': + dependencies: + '@octokit/auth-token': 5.1.1 + '@octokit/graphql': 8.1.1 + '@octokit/request': 9.1.3 + '@octokit/request-error': 6.1.5 + '@octokit/types': 13.6.1 + before-after-hook: 3.0.2 + universal-user-agent: 7.0.2 + + '@octokit/endpoint@10.1.1': + dependencies: + '@octokit/types': 13.6.1 + universal-user-agent: 7.0.2 + + '@octokit/graphql@8.1.1': + dependencies: + '@octokit/request': 9.1.3 + '@octokit/types': 13.6.1 + universal-user-agent: 7.0.2 + + '@octokit/openapi-types@22.2.0': {} + + '@octokit/request-error@6.1.5': + dependencies: + '@octokit/types': 13.6.1 + + '@octokit/request@9.1.3': + dependencies: + '@octokit/endpoint': 10.1.1 + '@octokit/request-error': 6.1.5 + '@octokit/types': 13.6.1 + universal-user-agent: 7.0.2 + + '@octokit/types@13.6.1': + dependencies: + '@octokit/openapi-types': 22.2.0 + + '@parcel/watcher-android-arm64@2.4.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.4.1': + optional: true + + '@parcel/watcher-darwin-x64@2.4.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.4.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.4.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.4.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.4.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.4.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.4.1': + optional: true + + '@parcel/watcher-win32-arm64@2.4.1': + optional: true + + '@parcel/watcher-win32-ia32@2.4.1': + optional: true + + '@parcel/watcher-win32-x64@2.4.1': + optional: true + + '@parcel/watcher@2.4.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.4.1 + '@parcel/watcher-darwin-arm64': 2.4.1 + '@parcel/watcher-darwin-x64': 2.4.1 + '@parcel/watcher-freebsd-x64': 2.4.1 + '@parcel/watcher-linux-arm-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-musl': 2.4.1 + '@parcel/watcher-linux-x64-glibc': 2.4.1 + '@parcel/watcher-linux-x64-musl': 2.4.1 + '@parcel/watcher-win32-arm64': 2.4.1 + '@parcel/watcher-win32-ia32': 2.4.1 + '@parcel/watcher-win32-x64': 2.4.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3))': + dependencies: + ansi-html: 0.0.9 + core-js-pure: 3.38.1 + error-stack-parser: 2.1.4 + html-entities: 2.5.2 + loader-utils: 2.0.4 + react-refresh: 0.14.2 + schema-utils: 4.2.0 + source-map: 0.7.4 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + optionalDependencies: + type-fest: 2.19.0 + webpack-hot-middleware: 2.26.1 + + '@reactflow/background@11.3.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + classcat: 5.0.5 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/controls@11.2.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + classcat: 5.0.5 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/core@11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@types/d3': 7.4.3 + '@types/d3-drag': 3.0.7 + '@types/d3-selection': 3.0.11 + '@types/d3-zoom': 3.0.8 + classcat: 5.0.5 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/minimap@11.7.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@types/d3-selection': 3.0.11 + '@types/d3-zoom': 3.0.8 + classcat: 5.0.5 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/node-resizer@2.2.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + classcat: 5.0.5 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/node-toolbar@1.3.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + classcat: 5.0.5 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + '@remixicon/react@4.5.0(react@18.2.0)': + dependencies: + react: 18.2.0 + + '@rgrove/parse-xml@4.1.0': {} + + '@rtsao/scc@1.1.0': {} + + '@rushstack/eslint-patch@1.10.4': {} + + '@sentry-internal/feedback@7.119.2': + dependencies: + '@sentry/core': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry-internal/replay-canvas@7.119.2': + dependencies: + '@sentry/core': 7.119.2 + '@sentry/replay': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry-internal/tracing@7.119.2': + dependencies: + '@sentry/core': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry/browser@7.119.2': + dependencies: + '@sentry-internal/feedback': 7.119.2 + '@sentry-internal/replay-canvas': 7.119.2 + '@sentry-internal/tracing': 7.119.2 + '@sentry/core': 7.119.2 + '@sentry/integrations': 7.119.2 + '@sentry/replay': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry/core@7.119.2': + dependencies: + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry/integrations@7.119.2': + dependencies: + '@sentry/core': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + localforage: 1.10.0 + + '@sentry/react@7.119.2(react@18.2.0)': + dependencies: + '@sentry/browser': 7.119.2 + '@sentry/core': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + + '@sentry/replay@7.119.2': + dependencies: + '@sentry-internal/tracing': 7.119.2 + '@sentry/core': 7.119.2 + '@sentry/types': 7.119.2 + '@sentry/utils': 7.119.2 + + '@sentry/types@7.119.2': {} + + '@sentry/utils@7.119.2': + dependencies: + '@sentry/types': 7.119.2 + + '@sinclair/typebox@0.27.8': {} + + '@sindresorhus/is@4.6.0': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@storybook/addon-actions@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 8.3.6 + uuid: 9.0.1 + + '@storybook/addon-backgrounds@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + memoizerific: 1.11.3 + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 + lodash: 4.17.21 + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/addon-docs@8.3.6(storybook@8.3.6)(webpack-sources@3.2.3)': + dependencies: + '@mdx-js/react': 3.1.0(@types/react@18.2.79)(react@18.2.0) + '@storybook/blocks': 8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6) + '@storybook/csf-plugin': 8.3.6(storybook@8.3.6)(webpack-sources@3.2.3) + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6) + '@types/react': 18.2.79 + fs-extra: 11.2.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + rehype-external-links: 3.0.0 + rehype-slug: 6.0.0 + storybook: 8.3.6 + ts-dedent: 2.2.0 + transitivePeerDependencies: + - webpack-sources + + '@storybook/addon-essentials@8.3.6(storybook@8.3.6)(webpack-sources@3.2.3)': + dependencies: + '@storybook/addon-actions': 8.3.6(storybook@8.3.6) + '@storybook/addon-backgrounds': 8.3.6(storybook@8.3.6) + '@storybook/addon-controls': 8.3.6(storybook@8.3.6) + '@storybook/addon-docs': 8.3.6(storybook@8.3.6)(webpack-sources@3.2.3) + '@storybook/addon-highlight': 8.3.6(storybook@8.3.6) + '@storybook/addon-measure': 8.3.6(storybook@8.3.6) + '@storybook/addon-outline': 8.3.6(storybook@8.3.6) + '@storybook/addon-toolbars': 8.3.6(storybook@8.3.6) + '@storybook/addon-viewport': 8.3.6(storybook@8.3.6) + storybook: 8.3.6 + ts-dedent: 2.2.0 + transitivePeerDependencies: + - webpack-sources + + '@storybook/addon-highlight@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.3.6 + + '@storybook/addon-interactions@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.3.6(storybook@8.3.6) + '@storybook/test': 8.3.6(storybook@8.3.6) + polished: 4.3.1 + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/addon-links@8.3.6(react@18.2.0)(storybook@8.3.6)': + dependencies: + '@storybook/csf': 0.1.11 + '@storybook/global': 5.0.0 + storybook: 8.3.6 + ts-dedent: 2.2.0 + optionalDependencies: + react: 18.2.0 + + '@storybook/addon-measure@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.3.6 + tiny-invariant: 1.3.3 + + '@storybook/addon-onboarding@8.3.6(react@18.2.0)(storybook@8.3.6)': + dependencies: + react-confetti: 6.1.0(react@18.2.0) + storybook: 8.3.6 + transitivePeerDependencies: + - react + + '@storybook/addon-outline@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/addon-themes@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/addon-toolbars@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/addon-viewport@8.3.6(storybook@8.3.6)': + dependencies: + memoizerific: 1.11.3 + storybook: 8.3.6 + + '@storybook/blocks@8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)': + dependencies: + '@storybook/csf': 0.1.11 + '@storybook/global': 5.0.0 + '@storybook/icons': 1.2.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@types/lodash': 4.17.12 + color-convert: 2.0.1 + dequal: 2.0.3 + lodash: 4.17.21 + markdown-to-jsx: 7.5.0(react@18.2.0) + memoizerific: 1.11.3 + polished: 4.3.1 + react-colorful: 5.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + storybook: 8.3.6 + telejson: 7.2.0 + ts-dedent: 2.2.0 + util-deprecate: 1.0.2 + optionalDependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@storybook/builder-webpack5@8.3.6(esbuild@0.23.1)(storybook@8.3.6)(typescript@4.9.5)(uglify-js@3.19.3)': + dependencies: + '@storybook/core-webpack': 8.3.6(storybook@8.3.6) + '@types/node': 22.7.8 + '@types/semver': 7.5.8 + browser-assert: 1.2.1 + case-sensitive-paths-webpack-plugin: 2.4.0 + cjs-module-lexer: 1.4.1 + constants-browserify: 1.0.0 + css-loader: 6.11.0(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + es-module-lexer: 1.5.4 + express: 4.21.1 + fork-ts-checker-webpack-plugin: 8.0.0(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + fs-extra: 11.2.0 + html-webpack-plugin: 5.6.2(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + magic-string: 0.30.12 + path-browserify: 1.0.1 + process: 0.11.10 + semver: 7.6.3 + storybook: 8.3.6 + style-loader: 3.3.4(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + terser-webpack-plugin: 5.3.10(esbuild@0.23.1)(uglify-js@3.19.3)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + ts-dedent: 2.2.0 + url: 0.11.4 + util: 0.12.5 + util-deprecate: 1.0.2 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + webpack-dev-middleware: 6.1.3(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + webpack-hot-middleware: 2.26.1 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - '@rspack/core' + - '@swc/core' + - esbuild + - supports-color + - uglify-js + - webpack-cli + + '@storybook/channels@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/components@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/core-webpack@8.3.6(storybook@8.3.6)': + dependencies: + '@types/node': 22.7.8 + storybook: 8.3.6 + ts-dedent: 2.2.0 + + '@storybook/core@8.3.6': + dependencies: + '@storybook/csf': 0.1.11 + '@types/express': 4.17.21 + better-opn: 3.0.2 + browser-assert: 1.2.1 + esbuild: 0.23.1 + esbuild-register: 3.6.0(esbuild@0.23.1) + express: 4.21.1 + jsdoc-type-pratt-parser: 4.1.0 + process: 0.11.10 + recast: 0.23.9 + semver: 7.6.3 + util: 0.12.5 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@storybook/csf-plugin@8.3.6(storybook@8.3.6)(webpack-sources@3.2.3)': + dependencies: + storybook: 8.3.6 + unplugin: 1.14.1(webpack-sources@3.2.3) + transitivePeerDependencies: + - webpack-sources + + '@storybook/csf@0.1.11': + dependencies: + type-fest: 2.19.0 + + '@storybook/global@5.0.0': {} + + '@storybook/icons@1.2.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@storybook/instrumenter@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.3 + storybook: 8.3.6 + util: 0.12.5 + + '@storybook/manager-api@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/nextjs@8.3.6(esbuild@0.23.1)(next@14.2.15(@babel/core@7.25.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3)(storybook@8.3.6)(type-fest@2.19.0)(typescript@4.9.5)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3))': + dependencies: + '@babel/core': 7.25.8 + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-import-assertions': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-class-properties': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-transform-export-namespace-from': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-numeric-separator': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-object-rest-spread': 7.25.8(@babel/core@7.25.8) + '@babel/plugin-transform-runtime': 7.25.7(@babel/core@7.25.8) + '@babel/preset-env': 7.25.8(@babel/core@7.25.8) + '@babel/preset-react': 7.25.7(@babel/core@7.25.8) + '@babel/preset-typescript': 7.25.7(@babel/core@7.25.8) + '@babel/runtime': 7.25.7 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + '@storybook/builder-webpack5': 8.3.6(esbuild@0.23.1)(storybook@8.3.6)(typescript@4.9.5)(uglify-js@3.19.3) + '@storybook/preset-react-webpack': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(esbuild@0.23.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5)(uglify-js@3.19.3) + '@storybook/react': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5) + '@storybook/test': 8.3.6(storybook@8.3.6) + '@types/node': 22.7.8 + '@types/semver': 7.5.8 + babel-loader: 9.2.1(@babel/core@7.25.8)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + css-loader: 6.11.0(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + find-up: 5.0.0 + fs-extra: 11.2.0 + image-size: 1.1.1 + loader-utils: 3.3.1 + next: 14.2.15(@babel/core@7.25.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + pnp-webpack-plugin: 1.7.0(typescript@4.9.5) + postcss: 8.4.47 + postcss-loader: 8.1.1(postcss@8.4.47)(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-refresh: 0.14.2 + resolve-url-loader: 5.0.0 + sass-loader: 13.3.3(sass@1.80.3)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + semver: 7.6.3 + storybook: 8.3.6 + style-loader: 3.3.4(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + styled-jsx: 5.1.6(@babel/core@7.25.8)(react@18.2.0) + ts-dedent: 2.2.0 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.1.0 + optionalDependencies: + sharp: 0.33.5 + typescript: 4.9.5 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + transitivePeerDependencies: + - '@rspack/core' + - '@swc/core' + - '@types/webpack' + - babel-plugin-macros + - esbuild + - fibers + - node-sass + - sass + - sass-embedded + - sockjs-client + - supports-color + - type-fest + - uglify-js + - webpack-cli + - webpack-dev-server + - webpack-hot-middleware + - webpack-plugin-serve + + '@storybook/preset-react-webpack@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(esbuild@0.23.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5)(uglify-js@3.19.3)': + dependencies: + '@storybook/core-webpack': 8.3.6(storybook@8.3.6) + '@storybook/react': 8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + '@types/node': 22.7.8 + '@types/semver': 7.5.8 + find-up: 5.0.0 + fs-extra: 11.2.0 + magic-string: 0.30.12 + react: 18.2.0 + react-docgen: 7.1.0 + react-dom: 18.2.0(react@18.2.0) + resolve: 1.22.8 + semver: 7.6.3 + storybook: 8.3.6 + tsconfig-paths: 4.2.0 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - '@storybook/test' + - '@swc/core' + - esbuild + - supports-color + - uglify-js + - webpack-cli + + '@storybook/preview-api@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3))': + dependencies: + debug: 4.3.7 + endent: 2.1.0 + find-cache-dir: 3.3.2 + flat-cache: 3.2.0 + micromatch: 4.0.8 + react-docgen-typescript: 2.2.2(typescript@4.9.5) + tslib: 2.8.0 + typescript: 4.9.5 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + transitivePeerDependencies: + - supports-color + + '@storybook/react-dom-shim@8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)': + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + storybook: 8.3.6 + + '@storybook/react@8.3.6(@storybook/test@8.3.6(storybook@8.3.6))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6)(typescript@4.9.5)': + dependencies: + '@storybook/components': 8.3.6(storybook@8.3.6) + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.3.6(storybook@8.3.6) + '@storybook/preview-api': 8.3.6(storybook@8.3.6) + '@storybook/react-dom-shim': 8.3.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(storybook@8.3.6) + '@storybook/theming': 8.3.6(storybook@8.3.6) + '@types/escodegen': 0.0.6 + '@types/estree': 0.0.51 + '@types/node': 22.7.8 + acorn: 7.4.1 + acorn-jsx: 5.3.2(acorn@7.4.1) + acorn-walk: 7.2.0 + escodegen: 2.1.0 + html-tags: 3.3.1 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-element-to-jsx-string: 15.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + semver: 7.6.3 + storybook: 8.3.6 + ts-dedent: 2.2.0 + type-fest: 2.19.0 + util-deprecate: 1.0.2 + optionalDependencies: + '@storybook/test': 8.3.6(storybook@8.3.6) + typescript: 4.9.5 + + '@storybook/telemetry@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/test@8.3.6(storybook@8.3.6)': + dependencies: + '@storybook/csf': 0.1.11 + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.3.6(storybook@8.3.6) + '@testing-library/dom': 10.4.0 + '@testing-library/jest-dom': 6.5.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/expect': 2.0.5 + '@vitest/spy': 2.0.5 + storybook: 8.3.6 + util: 0.12.5 + + '@storybook/theming@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@storybook/types@8.3.6(storybook@8.3.6)': + dependencies: + storybook: 8.3.6 + + '@stylistic/eslint-plugin@2.9.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + eslint-visitor-keys: 4.1.0 + espree: 10.2.0 + estraverse: 5.3.0 + picomatch: 4.0.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@svgdotjs/svg.js@3.2.4': {} + + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.5': + dependencies: + '@swc/counter': 0.1.3 + tslib: 2.8.0 + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@tailwindcss/typography@0.5.15(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)))': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + + '@tanstack/query-core@5.60.6': {} + + '@tanstack/query-devtools@5.59.20': {} + + '@tanstack/react-query-devtools@5.61.0(@tanstack/react-query@5.61.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/query-devtools': 5.59.20 + '@tanstack/react-query': 5.61.0(react@18.2.0) + react: 18.2.0 + + '@tanstack/react-query@5.61.0(react@18.2.0)': + dependencies: + '@tanstack/query-core': 5.60.6 + react: 18.2.0 + + '@tanstack/react-virtual@3.10.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/virtual-core': 3.10.8 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@tanstack/virtual-core@3.10.8': {} + + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.25.7 + '@babel/runtime': 7.25.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.5.0': + dependencies: + '@adobe/css-tools': 4.4.0 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/jest-dom@6.6.2': + dependencies: + '@adobe/css-tools': 4.4.0 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/react@16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.2.25)(@types/react@18.2.79)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@babel/runtime': 7.25.7 + '@testing-library/dom': 10.4.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + + '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + + '@tootallnate/once@2.0.0': {} + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/acorn@4.0.6': + dependencies: + '@types/estree': 1.0.6 + + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.25.8 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.25.8 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 18.15.0 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 18.15.0 + '@types/responselike': 1.0.3 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 18.15.0 + + '@types/crypto-js@4.2.2': {} + + '@types/d3-array@3.2.1': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.1 + '@types/geojson': 7946.0.14 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.6': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.14 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.0': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-scale-chromatic@3.0.3': {} + + '@types/d3-scale@4.0.8': + dependencies: + '@types/d3-time': 3.0.3 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.6': + dependencies: + '@types/d3-path': 3.1.0 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.3': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.1 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.6 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.0 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.8 + '@types/d3-scale-chromatic': 3.0.3 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.6 + '@types/d3-time': 3.0.3 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + + '@types/dagre@0.7.52': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 0.7.34 + + '@types/doctrine@0.0.9': {} + + '@types/escodegen@0.0.6': {} + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.6 + + '@types/estree@0.0.51': {} + + '@types/estree@1.0.6': {} + + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 18.15.0 + '@types/qs': 6.9.16 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.16 + '@types/serve-static': 1.15.7 + + '@types/geojson@7946.0.14': {} + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 18.15.0 + + '@types/hast@2.3.10': + dependencies: + '@types/unist': 2.0.11 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/html-minifier-terser@6.1.0': {} + + '@types/http-cache-semantics@4.0.4': {} + + '@types/http-errors@2.0.4': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.13': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + + '@types/js-cookie@3.0.6': {} + + '@types/jsdom@20.0.1': + dependencies: + '@types/node': 18.15.0 + '@types/tough-cookie': 4.0.5 + parse5: 7.2.0 + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/katex@0.16.7': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 18.15.0 + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.12 + + '@types/lodash@4.17.12': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdx@2.0.13': {} + + '@types/mime@1.3.5': {} + + '@types/ms@0.7.34': {} + + '@types/negotiator@0.6.3': {} + + '@types/node@18.15.0': {} + + '@types/node@22.7.8': + dependencies: + undici-types: 6.19.8 + + '@types/normalize-package-data@2.4.4': {} + + '@types/papaparse@5.3.15': + dependencies: + '@types/node': 18.15.0 + + '@types/parse-json@4.0.2': {} + + '@types/prop-types@15.7.13': {} + + '@types/qs@6.9.16': {} + + '@types/range-parser@1.2.7': {} + + '@types/react-dom@18.2.25': + dependencies: + '@types/react': 18.2.79 + + '@types/react-slider@1.3.6': + dependencies: + '@types/react': 18.2.79 + + '@types/react-syntax-highlighter@15.5.13': + dependencies: + '@types/react': 18.2.79 + + '@types/react-window-infinite-loader@1.0.9': + dependencies: + '@types/react': 18.2.79 + '@types/react-window': 1.8.8 + + '@types/react-window@1.8.8': + dependencies: + '@types/react': 18.2.79 + + '@types/react@18.2.79': + dependencies: + '@types/prop-types': 15.7.13 + csstype: 3.1.3 + + '@types/recordrtc@5.6.14': {} + + '@types/resolve@1.20.6': {} + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 18.15.0 + + '@types/semver@7.5.8': {} + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 18.15.0 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 18.15.0 + '@types/send': 0.17.4 + + '@types/sortablejs@1.15.8': {} + + '@types/stack-utils@2.0.3': {} + + '@types/tough-cookie@4.0.5': {} + + '@types/trusted-types@2.0.7': + optional: true + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/uuid@10.0.0': {} + + '@types/uuid@9.0.8': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-community/regexpp': 4.11.1 + '@typescript-eslint/parser': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/visitor-keys': 8.11.0 + eslint: 9.13.0(jiti@1.21.6) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/typescript-estree': 8.11.0(typescript@4.9.5) + '@typescript-eslint/visitor-keys': 8.11.0 + debug: 4.3.7 + eslint: 9.13.0(jiti@1.21.6) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.11.0': + dependencies: + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/visitor-keys': 8.11.0 + + '@typescript-eslint/type-utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/typescript-estree': 8.11.0(typescript@4.9.5) + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + debug: 4.3.7 + ts-api-utils: 1.3.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - eslint + - supports-color + + '@typescript-eslint/types@8.11.0': {} + + '@typescript-eslint/typescript-estree@8.11.0(typescript@4.9.5)': + dependencies: + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/visitor-keys': 8.11.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/typescript-estree': 8.11.0(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@8.11.0': + dependencies: + '@typescript-eslint/types': 8.11.0 + eslint-visitor-keys: 3.4.3 + + '@ungap/structured-clone@1.2.0': {} + + '@vitest/eslint-plugin@1.1.7(@typescript-eslint/utils@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)': + dependencies: + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + optionalDependencies: + typescript: 4.9.5 + + '@vitest/expect@2.0.5': + dependencies: + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 + chai: 5.1.1 + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.0.5': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.1.3': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/spy@2.0.5': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.0.5': + dependencies: + '@vitest/pretty-format': 2.0.5 + estree-walker: 3.0.3 + loupe: 3.1.2 + tinyrainbow: 1.2.0 + + '@vitest/utils@2.1.3': + dependencies: + '@vitest/pretty-format': 2.1.3 + loupe: 3.1.2 + tinyrainbow: 1.2.0 + + '@vue/compiler-core@3.5.12': + dependencies: + '@babel/parser': 7.25.8 + '@vue/shared': 3.5.12 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.12': + dependencies: + '@vue/compiler-core': 3.5.12 + '@vue/shared': 3.5.12 + + '@vue/compiler-sfc@3.5.12': + dependencies: + '@babel/parser': 7.25.8 + '@vue/compiler-core': 3.5.12 + '@vue/compiler-dom': 3.5.12 + '@vue/compiler-ssr': 3.5.12 + '@vue/shared': 3.5.12 + estree-walker: 2.0.2 + magic-string: 0.30.12 + postcss: 8.4.47 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.12': + dependencies: + '@vue/compiler-dom': 3.5.12 + '@vue/shared': 3.5.12 + + '@vue/shared@3.5.12': {} + + '@webassemblyjs/ast@1.12.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + + '@webassemblyjs/floating-point-hex-parser@1.11.6': {} + + '@webassemblyjs/helper-api-error@1.11.6': {} + + '@webassemblyjs/helper-buffer@1.12.1': {} + + '@webassemblyjs/helper-numbers@1.11.6': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.11.6': {} + + '@webassemblyjs/helper-wasm-section@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.12.1 + + '@webassemblyjs/ieee754@1.11.6': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.11.6': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.11.6': {} + + '@webassemblyjs/wasm-edit@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-opt': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/wast-printer': 1.12.1 + + '@webassemblyjs/wasm-gen@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + + '@webassemblyjs/wasm-opt@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + + '@webassemblyjs/wasm-parser@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + + '@webassemblyjs/wast-printer@1.12.1': + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@xtuc/long': 4.2.2 + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + abab@2.0.6: {} + + abbrev@1.1.1: + optional: true + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-globals@7.0.1: + dependencies: + acorn: 8.13.0 + acorn-walk: 8.3.4 + + acorn-import-attributes@1.9.5(acorn@8.13.0): + dependencies: + acorn: 8.13.0 + + acorn-jsx@5.3.2(acorn@7.4.1): + dependencies: + acorn: 7.4.1 + + acorn-jsx@5.3.2(acorn@8.13.0): + dependencies: + acorn: 8.13.0 + + acorn-walk@7.2.0: {} + + acorn-walk@8.3.4: + dependencies: + acorn: 8.13.0 + + acorn@7.4.1: {} + + acorn@8.13.0: {} + + acorn@8.14.0: {} + + adjust-sourcemap-loader@4.0.0: + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.3.0 + + agent-base@6.0.2: + dependencies: + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + ahooks@3.8.1(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + dayjs: 1.11.13 + intersection-observer: 0.12.2 + js-cookie: 3.0.5 + lodash: 4.17.21 + react: 18.2.0 + react-fast-compare: 3.2.2 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + tslib: 2.8.0 + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + + ansi-html-community@0.0.8: {} + + ansi-html@0.0.9: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + aproba@2.0.0: + optional: true + + are-docs-informative@0.0.2: {} + + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + optional: true + + arg@4.1.3: {} + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + + array-flatten@1.1.1: {} + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.flat@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.flatmap@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-shim-unscopables: 1.0.2 + + arraybuffer.prototype.slice@1.0.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@2.1.0: + dependencies: + call-bind: 1.0.7 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.5 + util: 0.12.5 + + assertion-error@2.0.1: {} + + ast-types-flow@0.0.8: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.0 + + astring@1.9.0: {} + + async@2.6.4: + dependencies: + lodash: 4.17.21 + + asynckit@0.4.0: {} + + autoprefixer@10.4.20(postcss@8.4.47): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001669 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + axe-core@4.10.1: {} + + axobject-query@4.1.0: {} + + babel-jest@29.7.0(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.25.8) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-loader@9.2.1(@babel/core@7.25.8)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + '@babel/core': 7.25.8 + find-cache-dir: 4.0.0 + schema-utils: 4.2.0 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.25.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.25.7 + '@babel/types': 7.25.8 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.25.8): + dependencies: + '@babel/compat-data': 7.25.8 + '@babel/core': 7.25.8 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8) + core-js-compat: 3.38.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8) + transitivePeerDependencies: + - supports-color + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.8) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.8) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.8) + '@babel/plugin-syntax-import-attributes': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.8) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.8) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.8) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.8) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.8) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.8) + + babel-preset-jest@29.6.3(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.8) + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + before-after-hook@3.0.2: {} + + better-opn@3.0.2: + dependencies: + open: 8.4.2 + + big.js@5.2.2: {} + + binary-extensions@2.3.0: {} + + bing-translate-api@4.0.2: + dependencies: + got: 11.8.6 + + birecord@0.1.1: {} + + bn.js@4.12.0: {} + + bn.js@5.2.1: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brorand@1.1.0: {} + + browser-assert@1.2.1: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.4 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.4 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.1 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.3: + dependencies: + bn.js: 5.2.1 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.0 + hash-base: 3.0.4 + inherits: 2.0.4 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001669 + electron-to-chromium: 1.5.41 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + buffer-xor@1.0.3: {} + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builtin-modules@3.3.0: {} + + builtin-status-codes@3.0.0: {} + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + bytes@3.1.2: {} + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + + call-bind@1.0.7: + dependencies: + 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.2 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.0 + + camelcase-css@2.0.1: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001669: {} + + canvas@2.11.2: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + nan: 2.22.0 + simple-get: 3.1.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + case-sensitive-paths-webpack-plugin@2.4.0: {} + + ccount@2.0.1: {} + + chai@5.1.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.2 + pathval: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.1: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + char-regex@1.0.2: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@1.1.4: {} + + character-entities-legacy@3.0.0: {} + + character-entities@1.2.4: {} + + character-entities@2.0.2: {} + + character-reference-invalid@1.1.4: {} + + character-reference-invalid@2.0.1: {} + + check-error@2.1.1: {} + + chevrotain-allstar@0.3.1(chevrotain@11.0.3): + dependencies: + chevrotain: 11.0.3 + lodash-es: 4.17.21 + + chevrotain@11.0.3: + dependencies: + '@chevrotain/cst-dts-gen': 11.0.3 + '@chevrotain/gast': 11.0.3 + '@chevrotain/regexp-to-ast': 11.0.3 + '@chevrotain/types': 11.0.3 + '@chevrotain/utils': 11.0.3 + lodash-es: 4.17.21 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + + chownr@2.0.0: + optional: true + + chromatic@11.15.0: {} + + chrome-trace-event@1.0.4: {} + + ci-info@3.9.0: {} + + ci-info@4.0.0: {} + + cipher-base@1.0.4: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + cjs-module-lexer@1.4.1: {} + + class-variance-authority@0.7.0: + dependencies: + clsx: 2.0.0 + + classcat@5.0.5: {} + + classnames@2.3.1: {} + + classnames@2.5.1: {} + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 4.2.3 + + client-only@0.0.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clsx@1.2.1: {} + + clsx@2.0.0: {} + + clsx@2.1.1: {} + + co@4.6.0: {} + + code-inspector-core@0.18.3: + dependencies: + '@vue/compiler-dom': 3.5.12 + chalk: 4.1.2 + dotenv: 16.4.7 + launch-ide: 1.0.1 + portfinder: 1.0.32 + transitivePeerDependencies: + - supports-color + + code-inspector-plugin@0.18.3: + dependencies: + chalk: 4.1.1 + code-inspector-core: 0.18.3 + dotenv: 16.4.7 + esbuild-code-inspector-plugin: 0.18.3 + vite-code-inspector-plugin: 0.18.3 + webpack-code-inspector-plugin: 0.18.3 + transitivePeerDependencies: + - supports-color + + collapse-white-space@2.1.0: {} + + collect-v8-coverage@1.0.2: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color-support@1.1.3: + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@1.0.8: {} + + comma-separated-tokens@2.0.3: {} + + commander@12.1.0: {} + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + comment-parser@1.4.1: {} + + common-path-prefix@3.0.0: {} + + commondir@1.0.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.8: {} + + console-browserify@1.2.0: {} + + console-control-strings@1.1.0: + optional: true + + constants-browserify@1.0.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + + core-js-compat@3.38.1: + dependencies: + browserslist: 4.24.2 + + core-js-pure@3.38.1: {} + + core-util-is@1.0.3: {} + + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@9.0.0(typescript@4.9.5): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 4.9.5 + + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.0 + elliptic: 6.6.0 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.4 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.4 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + create-jest@29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + create-require@1.1.1: {} + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-browserify@3.12.0: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.3 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + inherits: 2.0.4 + pbkdf2: 3.1.2 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + + crypto-js@4.2.0: {} + + css-loader@6.11.0(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + icss-utils: 5.1.0(postcss@8.4.47) + postcss: 8.4.47 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.47) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.47) + postcss-modules-scope: 3.2.0(postcss@8.4.47) + postcss-modules-values: 4.0.0(postcss@8.4.47) + postcss-value-parser: 4.2.0 + semver: 7.6.3 + optionalDependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-what@6.1.0: {} + + css.escape@1.5.1: {} + + cssesc@3.0.0: {} + + cssom@0.3.8: {} + + cssom@0.5.0: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + + csstype@3.1.3: {} + + cytoscape-cose-bilkent@4.1.0(cytoscape@3.30.2): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.30.2 + + cytoscape-fcose@2.2.0(cytoscape@3.30.2): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.30.2 + + cytoscape@3.30.2: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.0.1 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.0: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.11: + dependencies: + d3: 7.9.0 + lodash-es: 4.17.21 + + damerau-levenshtein@1.0.8: {} + + data-urls@3.0.2: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + dayjs@1.11.13: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decimal.js@10.4.3: {} + + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + + decompress-response@4.2.1: + dependencies: + mimic-response: 2.1.0 + optional: true + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + dedent@0.7.0: {} + + dedent@1.5.3: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delaunator@5.0.1: + dependencies: + robust-predicates: 3.0.2 + + delayed-stream@1.0.0: {} + + delegates@1.0.0: + optional: true + + depd@2.0.0: {} + + dequal@2.0.3: {} + + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + destroy@1.2.0: {} + + detect-libc@1.0.3: {} + + detect-libc@2.0.3: {} + + detect-newline@3.1.0: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + didyoumean@1.2.2: {} + + diff-sequences@29.6.3: {} + + diff@4.0.2: {} + + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.0 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + + dlv@1.1.3: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-converter@0.2.0: + dependencies: + utila: 0.4.0 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domain-browser@4.23.0: {} + + domelementtype@2.3.0: {} + + domexception@4.0.0: + dependencies: + webidl-conversions: 7.0.0 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + dompurify@3.2.3: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.0 + + dotenv@16.4.7: {} + + echarts-for-react@3.0.2(echarts@5.5.1)(react@18.2.0): + dependencies: + echarts: 5.5.1 + fast-deep-equal: 3.1.3 + react: 18.2.0 + size-sensor: 1.0.2 + + echarts@5.5.1: + dependencies: + tslib: 2.3.0 + zrender: 5.6.0 + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.41: {} + + elkjs@0.9.3: {} + + elliptic@6.6.0: + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + emittery@0.13.1: {} + + emoji-mart@5.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + endent@2.1.0: + dependencies: + dedent: 0.7.0 + fast-json-parse: 1.0.3 + objectorarray: 1.0.5 + + enhanced-resolve@5.17.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + entities@2.2.0: {} + + entities@4.5.0: {} + + env-paths@2.2.1: {} + + environment@1.1.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + es-abstract@1.23.3: + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.2 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.3 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-iterator-helpers@1.1.0: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + iterator.prototype: 1.1.3 + safe-array-concat: 1.1.2 + + es-module-lexer@1.5.4: {} + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.0.2: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.2.1: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.13.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.2 + + esbuild-code-inspector-plugin@0.18.3: + dependencies: + code-inspector-core: 0.18.3 + transitivePeerDependencies: + - supports-color + + esbuild-register@3.6.0(esbuild@0.23.1): + dependencies: + debug: 4.3.7 + esbuild: 0.23.1 + transitivePeerDependencies: + - supports-color + + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-compat-utils@0.5.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + eslint: 9.13.0(jiti@1.21.6) + semver: 7.6.3 + + eslint-config-flat-gitignore@0.3.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint/compat': 1.2.1(eslint@9.13.0(jiti@1.21.6)) + eslint: 9.13.0(jiti@1.21.6) + find-up-simple: 1.0.0 + + eslint-config-next@15.0.0(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@next/eslint-plugin-next': 15.0.0 + '@rushstack/eslint-patch': 1.10.4 + '@typescript-eslint/eslint-plugin': 8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/parser': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-jsx-a11y: 6.10.1(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-react: 7.37.1(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-react-hooks: 5.0.0(eslint@9.13.0(jiti@1.21.6)) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + + eslint-flat-config-utils@0.4.0: + dependencies: + pathe: 1.1.2 + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.15.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.3.7 + enhanced-resolve: 5.17.1 + eslint: 9.13.0(jiti@1.21.6) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)) + fast-glob: 3.3.2 + get-tsconfig: 4.8.1 + is-bun-module: 1.2.1 + is-glob: 4.0.3 + optionalDependencies: + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)) + eslint-plugin-import-x: 4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + + eslint-merge-processors@0.1.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + eslint: 9.13.0(jiti@1.21.6) + + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.13.0(jiti@1.21.6)) + transitivePeerDependencies: + - supports-color + + eslint-plugin-antfu@2.7.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@antfu/utils': 0.7.10 + eslint: 9.13.0(jiti@1.21.6) + + eslint-plugin-command@0.2.6(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@es-joy/jsdoccomment': 0.48.0 + eslint: 9.13.0(jiti@1.21.6) + + eslint-plugin-es-x@7.8.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@eslint-community/regexpp': 4.11.1 + eslint: 9.13.0(jiti@1.21.6) + eslint-compat-utils: 0.5.1(eslint@9.13.0(jiti@1.21.6)) + + eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + debug: 4.3.7 + doctrine: 3.0.0 + eslint: 9.13.0(jiti@1.21.6) + eslint-import-resolver-node: 0.3.9 + get-tsconfig: 4.8.1 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + stable-hash: 0.0.4 + tslib: 2.8.0 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.13.0(jiti@1.21.6) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.13.0(jiti@1.21.6)) + hasown: 2.0.2 + is-core-module: 2.15.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + string.prototype.trimend: 1.0.8 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jsdoc@50.4.3(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@es-joy/jsdoccomment': 0.49.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.3.7 + escape-string-regexp: 4.0.0 + eslint: 9.13.0(jiti@1.21.6) + espree: 10.2.0 + esquery: 1.6.0 + parse-imports: 2.2.1 + semver: 7.6.3 + spdx-expression-parse: 4.0.0 + synckit: 0.9.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsonc@2.16.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + eslint: 9.13.0(jiti@1.21.6) + eslint-compat-utils: 0.5.1(eslint@9.13.0(jiti@1.21.6)) + espree: 9.6.1 + graphemer: 1.4.0 + jsonc-eslint-parser: 2.4.0 + natural-compare: 1.4.0 + synckit: 0.6.2 + + eslint-plugin-jsx-a11y@6.10.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.10.1 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.1.0 + eslint: 9.13.0(jiti@1.21.6) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.0.3 + string.prototype.includes: 2.0.1 + + eslint-plugin-n@17.11.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + enhanced-resolve: 5.17.1 + eslint: 9.13.0(jiti@1.21.6) + eslint-plugin-es-x: 7.8.0(eslint@9.13.0(jiti@1.21.6)) + get-tsconfig: 4.8.1 + globals: 15.11.0 + ignore: 5.3.2 + minimatch: 9.0.5 + semver: 7.6.3 + + eslint-plugin-no-only-tests@3.3.0: {} + + eslint-plugin-perfectionist@3.9.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5)(vue-eslint-parser@9.4.3(eslint@9.13.0(jiti@1.21.6))): + dependencies: + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + minimatch: 9.0.5 + natural-compare-lite: 1.4.0 + optionalDependencies: + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@1.21.6)) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-react-debug@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + string-ts: 2.2.0 + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-dom@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-hooks-extra@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-hooks@5.0.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + eslint: 9.13.0(jiti@1.21.6) + + eslint-plugin-react-naming-convention@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-refresh@0.4.13(eslint@9.13.0(jiti@1.21.6)): + dependencies: + eslint: 9.13.0(jiti@1.21.6) + + eslint-plugin-react-web-api@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + birecord: 0.1.1 + eslint: 9.13.0(jiti@1.21.6) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-x@1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@eslint-react/ast': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/core': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/jsx': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/shared': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/tools': 1.15.0 + '@eslint-react/types': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@eslint-react/var': 1.15.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/scope-manager': 8.11.0 + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + '@typescript-eslint/types': 8.11.0 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + is-immutable-type: 5.0.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + ts-pattern: 5.5.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.2 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.1.0 + eslint: 9.13.0(jiti@1.21.6) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.values: 1.2.0 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.11 + string.prototype.repeat: 1.0.0 + + eslint-plugin-regexp@2.6.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@eslint-community/regexpp': 4.11.1 + comment-parser: 1.4.1 + eslint: 9.13.0(jiti@1.21.6) + jsdoc-type-pratt-parser: 4.1.0 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + + eslint-plugin-storybook@0.10.1(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@storybook/csf': 0.1.11 + '@typescript-eslint/utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-tailwindcss@3.17.5(tailwindcss@3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5))): + dependencies: + fast-glob: 3.3.2 + postcss: 8.4.47 + tailwindcss: 3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + + eslint-plugin-toml@0.11.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + debug: 4.3.7 + eslint: 9.13.0(jiti@1.21.6) + eslint-compat-utils: 0.5.1(eslint@9.13.0(jiti@1.21.6)) + lodash: 4.17.21 + toml-eslint-parser: 0.10.0 + transitivePeerDependencies: + - supports-color + + eslint-plugin-unicorn@56.0.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@babel/helper-validator-identifier': 7.25.7 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + ci-info: 4.0.0 + clean-regexp: 1.0.0 + core-js-compat: 3.38.1 + eslint: 9.13.0(jiti@1.21.6) + esquery: 1.6.0 + globals: 15.11.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.0.2 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.6.3 + strip-indent: 3.0.0 + + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6)): + dependencies: + eslint: 9.13.0(jiti@1.21.6) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.11.0(@typescript-eslint/parser@8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5))(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + + eslint-plugin-vue@9.29.1(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + eslint: 9.13.0(jiti@1.21.6) + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.6.3 + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@1.21.6)) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + + eslint-plugin-yml@1.14.0(eslint@9.13.0(jiti@1.21.6)): + dependencies: + debug: 4.3.7 + eslint: 9.13.0(jiti@1.21.6) + eslint-compat-utils: 0.5.1(eslint@9.13.0(jiti@1.21.6)) + lodash: 4.17.21 + natural-compare: 1.4.0 + yaml-eslint-parser: 1.2.3 + transitivePeerDependencies: + - supports-color + + eslint-processor-vue-blocks@0.1.2(@vue/compiler-sfc@3.5.12)(eslint@9.13.0(jiti@1.21.6)): + dependencies: + '@vue/compiler-sfc': 3.5.12 + eslint: 9.13.0(jiti@1.21.6) + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.1.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.1.0: {} + + eslint@9.13.0(jiti@1.21.6): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@1.21.6)) + '@eslint-community/regexpp': 4.11.1 + '@eslint/config-array': 0.18.0 + '@eslint/core': 0.7.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.13.0 + '@eslint/plugin-kit': 0.2.1 + '@humanfs/node': 0.16.5 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.3.7 + escape-string-regexp: 4.0.0 + eslint-scope: 8.1.0 + eslint-visitor-keys: 4.1.0 + espree: 10.2.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + text-table: 0.2.0 + optionalDependencies: + jiti: 1.21.6 + transitivePeerDependencies: + - supports-color + + espree@10.2.0: + dependencies: + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) + eslint-visitor-keys: 4.1.0 + + espree@9.6.1: + dependencies: + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-util-attach-comments@3.0.0: + dependencies: + '@types/estree': 1.0.6 + + estree-util-build-jsx@3.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-walker: 3.0.3 + + estree-util-is-identifier-name@3.0.0: {} + + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + + estree-util-to-js@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 + source-map: 0.7.4 + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + + express@4.21.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.10 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.1: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-parse@1.0.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.3: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fault@1.0.4: + dependencies: + format: 0.2.2 + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filesize@10.1.6: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + filter-obj@2.0.2: {} + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-cache-dir@4.0.0: + dependencies: + common-path-prefix: 3.0.0 + pkg-dir: 7.0.0 + + find-up-simple@1.0.0: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-up@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fork-ts-checker-webpack-plugin@8.0.0(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + '@babel/code-frame': 7.25.7 + chalk: 4.1.2 + chokidar: 3.6.0 + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + node-abort-controller: 3.1.1 + schema-utils: 3.3.0 + semver: 7.6.3 + tapable: 2.2.1 + typescript: 4.9.5 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + form-data@4.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + format@0.2.2: {} + + forwarded@0.2.0: {} + + fraction.js@4.3.7: {} + + fresh@0.5.2: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + optional: true + + fs-monkey@1.0.6: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + + functions-have-names@1.2.3: {} + + gauge@3.0.2: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + optional: true + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-package-type@0.1.0: {} + + get-stream@5.2.0: + dependencies: + pump: 3.0.2 + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + get-symbol-description@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + github-slugger@2.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@11.12.0: {} + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + globals@15.11.0: {} + + globals@15.13.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + hachure-fill@0.5.2: {} + + has-bigints@1.0.2: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + + has-unicode@2.0.1: + optional: true + + hash-base@3.0.4: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash-base@3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-from-dom@5.0.0: + dependencies: + '@types/hast': 3.0.4 + hastscript: 8.0.0 + web-namespaces: 2.0.1 + + hast-util-from-html-isomorphic@2.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-dom: 5.0.0 + hast-util-from-html: 2.0.3 + unist-util-remove-position: 5.0.0 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.2.0 + vfile: 6.0.3 + vfile-message: 4.0.2 + + hast-util-from-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.5.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + + hast-util-heading-rank@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-parse-selector@2.2.5: {} + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-raw@9.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + parse5: 7.2.0 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-estree@3.1.0: + dependencies: + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + style-to-object: 0.4.4 + unist-util-position: 5.0.0 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + hast-util-to-jsx-runtime@2.3.2: + dependencies: + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + style-to-object: 1.0.8 + unist-util-position: 5.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-string@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hastscript@6.0.0: + dependencies: + '@types/hast': 2.3.10 + comma-separated-tokens: 1.0.8 + hast-util-parse-selector: 2.2.5 + property-information: 5.6.0 + space-separated-tokens: 1.1.5 + + hastscript@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + + he@1.2.0: {} + + highlight.js@10.7.3: {} + + highlightjs-vue@1.0.0: {} + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + hosted-git-info@2.8.9: {} + + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + + html-entities@2.5.2: {} + + html-escaper@2.0.2: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.36.0 + + html-parse-stringify@3.0.1: + dependencies: + void-elements: 3.1.0 + + html-tags@3.3.1: {} + + html-url-attributes@3.0.1: {} + + html-void-elements@3.0.0: {} + + html-webpack-plugin@5.6.2(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + '@types/html-minifier-terser': 6.1.0 + html-minifier-terser: 6.1.0 + lodash: 4.17.21 + pretty-error: 4.0.0 + tapable: 2.2.1 + optionalDependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + htmlparser2@6.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + + http-cache-semantics@4.1.1: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-browserify@1.0.0: {} + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + human-signals@5.0.0: {} + + husky@9.1.6: {} + + i18next-resources-to-backend@1.2.1: + dependencies: + '@babel/runtime': 7.25.7 + + i18next@23.16.4: + dependencies: + '@babel/runtime': 7.25.7 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + icss-utils@5.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + image-size@1.1.1: + dependencies: + queue: 6.0.2 + + immediate@3.0.6: {} + + immer@9.0.21: {} + + immutable@4.3.7: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + inline-style-parser@0.1.1: {} + + inline-style-parser@0.2.4: {} + + internal-slot@1.0.7: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + + internmap@1.0.1: {} + + internmap@2.0.3: {} + + intersection-observer@0.12.2: {} + + ipaddr.js@1.9.1: {} + + is-absolute-url@4.0.1: {} + + is-alphabetical@1.0.4: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@1.0.4: + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.4: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.2: {} + + is-async-function@2.0.0: + dependencies: + has-tostringtag: 1.0.2 + + is-bigint@1.0.4: + dependencies: + has-bigints: 1.0.2 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.1.2: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-bun-module@1.2.1: + dependencies: + semver: 7.6.3 + + is-callable@1.2.7: {} + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: + dependencies: + is-typed-array: 1.1.13 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-decimal@1.0.4: {} + + is-decimal@2.0.1: {} + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.0.2: + dependencies: + call-bind: 1.0.7 + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.3.0 + + is-generator-fn@2.1.0: {} + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hexadecimal@1.0.4: {} + + is-hexadecimal@2.0.1: {} + + is-immutable-type@5.0.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5): + dependencies: + '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0(jiti@1.21.6))(typescript@4.9.5) + eslint: 9.13.0(jiti@1.21.6) + ts-api-utils: 1.3.0(typescript@4.9.5) + ts-declaration-location: 1.0.4(typescript@4.9.5) + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + is-map@2.0.3: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + is-negative-zero@2.0.3: {} + + is-number-object@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} + + is-plain-object@5.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.1.4: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.3: + dependencies: + call-bind: 1.0.7 + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-string@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-symbol@1.0.4: + dependencies: + has-symbols: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.15 + + is-weakmap@2.0.2: {} + + is-weakref@1.0.2: + dependencies: + call-bind: 1.0.7 + + is-weakset@2.0.3: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isomorphic.js@0.2.5: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.25.8 + '@babel/parser': 7.25.8 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.25.8 + '@babel/parser': 7.25.8 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.3.7 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterator.prototype@1.1.3: + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + '@babel/core': 7.25.8 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.8) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 18.15.0 + ts-node: 10.9.2(@types/node@18.15.0)(typescript@4.9.5) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-jsdom@29.7.0(canvas@2.11.2): + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/jsdom': 20.0.1 + '@types/node': 18.15.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jsdom: 20.0.3(canvas@2.11.2) + optionalDependencies: + canvas: 2.11.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 18.15.0 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.25.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + chalk: 4.1.2 + cjs-module-lexer: 1.4.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.25.8 + '@babel/generator': 7.25.7 + '@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.25.8) + '@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.25.8) + '@babel/types': 7.25.8 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.8) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.15.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@27.5.1: + dependencies: + '@types/node': 18.15.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest-worker@29.7.0: + dependencies: + '@types/node': 18.15.0 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@18.15.0)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jiti@1.21.6: {} + + js-audio-recorder@1.0.7: {} + + js-cookie@3.0.5: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.1.0: {} + + jsdom@20.0.3(canvas@2.11.2): + dependencies: + abab: 2.0.6 + acorn: 8.13.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.1 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.13 + parse5: 7.2.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.18.0 + xml-name-validator: 4.0.0 + optionalDependencies: + canvas: 2.11.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@0.5.0: {} + + jsesc@3.0.2: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonc-eslint-parser@2.4.0: + dependencies: + acorn: 8.13.0 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + semver: 7.6.3 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + + jwt-decode@4.0.0: {} + + katex@0.16.11: + dependencies: + commander: 8.3.0 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + khroma@2.1.0: {} + + kleur@3.0.3: {} + + kolorist@1.8.0: {} + + ky@1.7.2: {} + + lamejs@1.2.1: + dependencies: + use-strict: 1.0.1 + + langium@3.0.0: + dependencies: + chevrotain: 11.0.3 + chevrotain-allstar: 0.3.1(chevrotain@11.0.3) + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + launch-ide@1.0.1: + dependencies: + chalk: 4.1.2 + dotenv: 16.4.7 + + layout-base@1.0.2: {} + + layout-base@2.0.1: {} + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lexical@0.18.0: {} + + lib0@0.2.98: + dependencies: + isomorphic.js: 0.2.5 + + lie@3.1.1: + dependencies: + immediate: 3.0.6 + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + line-clamp@1.0.0: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.2.10: + dependencies: + chalk: 5.3.0 + commander: 12.1.0 + debug: 4.3.7 + execa: 8.0.1 + lilconfig: 3.1.2 + listr2: 8.2.5 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.5.1 + transitivePeerDependencies: + - supports-color + + listr2@8.2.5: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + loader-runner@4.3.0: {} + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + loader-utils@3.3.1: {} + + local-pkg@0.5.0: + dependencies: + mlly: 1.7.2 + pkg-types: 1.2.1 + + local-pkg@0.5.1: + dependencies: + mlly: 1.7.3 + pkg-types: 1.2.1 + + localforage@1.10.0: + dependencies: + lie: 3.1.1 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash-es@4.17.21: {} + + lodash.castarray@4.4.0: {} + + lodash.debounce@4.0.8: {} + + lodash.isplainobject@4.0.6: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + longest-streak@3.1.0: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.1.2: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.0 + + lowercase-keys@2.0.0: {} + + lowlight@1.20.0: + dependencies: + fault: 1.0.4 + highlight.js: 10.7.3 + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lz-string@1.5.0: {} + + magic-string@0.30.12: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + source-map-js: 1.2.1 + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + map-or-similar@1.5.0: {} + + markdown-extensions@2.0.0: {} + + markdown-table@3.0.3: {} + + markdown-to-jsx@7.5.0(react@18.2.0): + dependencies: + react: 18.2.0 + + marked@13.0.3: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + mdast-util-find-and-replace@3.0.1: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + mdast-util-from-markdown@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.1.0 + + mdast-util-gfm-footnote@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.3 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.1 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-math@3.0.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + longest-streak: 3.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + unist-util-remove-position: 5.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.1.3: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.1 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + mdast-util-newline-to-break@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-find-and-replace: 3.0.1 + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + media-typer@0.3.0: {} + + memfs@3.5.3: + dependencies: + fs-monkey: 1.0.6 + + memoize-one@5.2.1: {} + + memoizerific@1.11.3: + dependencies: + map-or-similar: 1.5.0 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + mermaid@11.4.1: + dependencies: + '@braintree/sanitize-url': 7.1.0 + '@iconify/utils': 2.2.0 + '@mermaid-js/parser': 0.3.0 + '@types/d3': 7.4.3 + cytoscape: 3.30.2 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.30.2) + cytoscape-fcose: 2.2.0(cytoscape@3.30.2) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.11 + dayjs: 1.11.13 + dompurify: 3.2.3 + katex: 0.16.11 + khroma: 2.1.0 + lodash-es: 4.17.21 + marked: 13.0.3 + roughjs: 4.6.6 + stylis: 4.3.4 + ts-dedent: 2.2.0 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + methods@1.1.2: {} + + micromark-core-commonmark@2.0.1: + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-table@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.0 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-math@3.1.0: + dependencies: + '@types/katex': 0.16.7 + devlop: 1.1.0 + katex: 0.16.11 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-mdx-expression@3.0.0: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-extension-mdx-jsx@3.0.1: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.6 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.2 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.0 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) + micromark-extension-mdx-expression: 3.0.0 + micromark-extension-mdx-jsx: 3.0.1 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-factory-destination@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-factory-label@2.0.0: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-factory-mdx-expression@2.0.2: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + micromark-factory-space@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-types: 2.0.0 + + micromark-factory-title@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-factory-whitespace@2.0.0: + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-chunked@2.0.0: + dependencies: + micromark-util-symbol: 2.0.0 + + micromark-util-classify-character@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-combine-extensions@2.0.0: + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-decode-numeric-character-reference@2.0.1: + dependencies: + micromark-util-symbol: 2.0.0 + + micromark-util-decode-string@2.0.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.0 + + micromark-util-encode@2.0.0: {} + + micromark-util-events-to-acorn@2.0.2: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.6 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + + micromark-util-html-tag-name@2.0.0: {} + + micromark-util-normalize-identifier@2.0.0: + dependencies: + micromark-util-symbol: 2.0.0 + + micromark-util-resolve-all@2.0.0: + dependencies: + micromark-util-types: 2.0.0 + + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + + micromark-util-subtokenize@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-symbol@2.0.0: {} + + micromark-util-types@2.0.0: {} + + micromark@4.0.0: + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.7 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-subtokenize: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.0 + brorand: 1.1.0 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mime@4.0.4: {} + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + mimic-response@1.0.1: {} + + mimic-response@2.1.0: + optional: true + + mimic-response@3.1.0: {} + + min-indent@1.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + optional: true + + minipass@5.0.0: + optional: true + + minipass@7.1.2: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + optional: true + + mitt@3.0.1: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: + optional: true + + mlly@1.7.2: + dependencies: + acorn: 8.13.0 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + + mlly@1.7.3: + dependencies: + acorn: 8.14.0 + pathe: 1.1.2 + pkg-types: 1.2.1 + ufo: 1.5.4 + + monaco-editor@0.52.0: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nan@2.22.0: + optional: true + + nanoid@3.3.7: {} + + natural-compare-lite@1.4.0: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + next@14.2.15(@babel/core@7.25.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.80.3): + dependencies: + '@next/env': 14.2.15 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001669 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(@babel/core@7.25.8)(react@18.2.0) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.15 + '@next/swc-darwin-x64': 14.2.15 + '@next/swc-linux-arm64-gnu': 14.2.15 + '@next/swc-linux-arm64-musl': 14.2.15 + '@next/swc-linux-x64-gnu': 14.2.15 + '@next/swc-linux-x64-musl': 14.2.15 + '@next/swc-win32-arm64-msvc': 14.2.15 + '@next/swc-win32-ia32-msvc': 14.2.15 + '@next/swc-win32-x64-msvc': 14.2.15 + sass: 1.80.3 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.0 + + node-abort-controller@3.1.1: {} + + node-addon-api@7.1.1: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + optional: true + + node-int64@0.4.0: {} + + node-polyfill-webpack-plugin@2.0.1(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + assert: 2.1.0 + browserify-zlib: 0.2.0 + buffer: 6.0.3 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + crypto-browserify: 3.12.0 + domain-browser: 4.23.0 + events: 3.3.0 + filter-obj: 2.0.2 + https-browserify: 1.0.0 + os-browserify: 0.3.0 + path-browserify: 1.0.1 + process: 0.11.10 + punycode: 2.3.1 + querystring-es3: 0.2.1 + readable-stream: 4.5.2 + stream-browserify: 3.0.0 + stream-http: 3.2.0 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.1 + type-fest: 2.19.0 + url: 0.11.4 + util: 0.12.5 + vm-browserify: 1.1.2 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + node-releases@2.0.18: {} + + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + optional: true + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-url@6.1.0: {} + + normalize-wheel@1.0.1: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + optional: true + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nwsapi@2.2.13: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.2: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + object.entries@1.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + + object.values@1.2.0: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + objectorarray@1.0.5: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-browserify@0.3.0: {} + + p-cancelable@2.1.1: {} + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.2: {} + + pako@1.0.11: {} + + papaparse@5.4.1: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-asn1@5.1.7: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + hash-base: 3.0.4 + pbkdf2: 3.1.2 + safe-buffer: 5.2.1 + + parse-entities@2.0.0: + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + + parse-entities@4.0.1: + dependencies: + '@types/unist': 2.0.11 + character-entities: 2.0.2 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.0.2 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-gitignore@2.0.0: {} + + parse-imports@2.2.1: + dependencies: + es-module-lexer: 1.5.4 + slashes: 3.0.12 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.25.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse5@7.2.0: + dependencies: + entities: 4.5.0 + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.0 + + path-browserify@1.0.1: {} + + path-data-parser@0.1.0: {} + + path-exists@4.0.0: {} + + path-exists@5.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@0.1.10: {} + + path-type@4.0.0: {} + + path2d@0.2.2: + optional: true + + pathe@1.1.2: {} + + pathval@2.0.0: {} + + pbkdf2@3.1.2: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + + pdfjs-dist@4.4.168: + optionalDependencies: + canvas: 2.11.2 + path2d: 0.2.2 + transitivePeerDependencies: + - encoding + - supports-color + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pidtree@0.6.0: {} + + pify@2.3.0: {} + + pinyin-pro@3.25.0: {} + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-dir@7.0.0: + dependencies: + find-up: 6.3.0 + + pkg-types@1.2.1: + dependencies: + confbox: 0.1.8 + mlly: 1.7.2 + pathe: 1.1.2 + + pluralize@8.0.0: {} + + pnp-webpack-plugin@1.7.0(typescript@4.9.5): + dependencies: + ts-pnp: 1.2.0(typescript@4.9.5) + transitivePeerDependencies: + - typescript + + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + + polished@4.3.1: + dependencies: + '@babel/runtime': 7.25.7 + + portfinder@1.0.32: + dependencies: + async: 2.6.4 + debug: 3.2.7 + mkdirp: 0.5.6 + transitivePeerDependencies: + - supports-color + + possible-typed-array-names@1.0.0: {} + + postcss-import@15.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.47): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.47 + + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + lilconfig: 3.1.2 + yaml: 2.6.0 + optionalDependencies: + postcss: 8.4.47 + ts-node: 10.9.2(@types/node@18.15.0)(typescript@4.9.5) + + postcss-loader@8.1.1(postcss@8.4.47)(typescript@4.9.5)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + cosmiconfig: 9.0.0(typescript@4.9.5) + jiti: 1.21.6 + postcss: 8.4.47 + semver: 7.6.3 + optionalDependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + transitivePeerDependencies: + - typescript + + postcss-modules-extract-imports@3.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + + postcss-modules-local-by-default@4.0.5(postcss@8.4.47): + dependencies: + icss-utils: 5.1.0(postcss@8.4.47) + postcss: 8.4.47 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-selector-parser: 6.1.2 + + postcss-modules-values@4.0.0(postcss@8.4.47): + dependencies: + icss-utils: 5.1.0(postcss@8.4.47) + postcss: 8.4.47 + + postcss-nested@6.2.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.31: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + pretty-error@4.0.0: + dependencies: + lodash: 4.17.21 + renderkid: 3.0.0 + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + prismjs@1.27.0: {} + + prismjs@1.29.0: {} + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + property-information@5.6.0: + dependencies: + xtend: 4.0.2 + + property-information@6.5.0: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + psl@1.9.0: {} + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.0 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + pure-rand@6.1.0: {} + + qrcode.react@4.1.0(react@18.2.0): + dependencies: + react: 18.2.0 + + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + + querystring-es3@0.2.1: {} + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + queue@6.0.2: + dependencies: + inherits: 2.0.4 + + quick-lru@5.1.1: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + rc-input@1.6.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + classnames: 2.5.1 + rc-util: 5.43.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + rc-resize-observer@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + classnames: 2.5.1 + rc-util: 5.43.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + resize-observer-polyfill: 1.5.1 + + rc-textarea@1.8.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + classnames: 2.5.1 + rc-input: 1.6.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + rc-resize-observer: 1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + rc-util: 5.43.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + rc-util@5.43.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-is: 18.3.1 + + re-resizable@6.10.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-18-input-autosize@3.0.0(react@18.2.0): + dependencies: + prop-types: 15.8.1 + react: 18.2.0 + + react-colorful@5.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-confetti@6.1.0(react@18.2.0): + dependencies: + react: 18.2.0 + tween-functions: 1.2.0 + + react-docgen-typescript@2.2.2(typescript@4.9.5): + dependencies: + typescript: 4.9.5 + + react-docgen@7.1.0: + dependencies: + '@babel/core': 7.25.8 + '@babel/traverse': 7.25.7 + '@babel/types': 7.25.8 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 + doctrine: 3.0.0 + resolve: 1.22.8 + strip-indent: 4.0.0 + transitivePeerDependencies: + - supports-color + + react-dom@18.2.0(react@18.2.0): + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.2 + + react-draggable@4.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + clsx: 1.2.1 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-easy-crop@5.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + normalize-wheel: 1.0.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.8.0 + + react-element-to-jsx-string@15.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@base2/pretty-print-object': 1.0.1 + is-plain-object: 5.0.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-is: 18.1.0 + + react-error-boundary@3.1.4(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + react: 18.2.0 + + react-error-boundary@4.1.2(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + react: 18.2.0 + + react-fast-compare@3.2.2: {} + + react-headless-pagination@1.1.6(react@18.2.0): + dependencies: + clsx: 2.1.1 + react: 18.2.0 + + react-hook-form@7.53.1(react@18.2.0): + dependencies: + react: 18.2.0 + + react-hotkeys-hook@4.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-i18next@15.1.0(i18next@23.16.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + html-parse-stringify: 3.0.1 + i18next: 23.16.4 + react: 18.2.0 + optionalDependencies: + react-dom: 18.2.0(react@18.2.0) + + react-infinite-scroll-component@6.1.0(react@18.2.0): + dependencies: + react: 18.2.0 + throttle-debounce: 2.3.0 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-is@18.1.0: {} + + react-is@18.3.1: {} + + react-markdown@9.0.1(@types/react@18.2.79)(react@18.2.0): + dependencies: + '@types/hast': 3.0.4 + '@types/react': 18.2.79 + devlop: 1.1.0 + hast-util-to-jsx-runtime: 2.3.2 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.0 + react: 18.2.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + unified: 11.0.5 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + react-multi-email@1.0.25(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-papaparse@4.4.0: + dependencies: + '@types/papaparse': 5.3.15 + papaparse: 5.4.1 + + react-pdf-highlighter@8.0.0-rc.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + pdfjs-dist: 4.4.168 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-rnd: 10.4.13(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + ts-debounce: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + react-refresh@0.14.2: {} + + react-rnd@10.4.13(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + re-resizable: 6.10.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-draggable: 4.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + tslib: 2.6.2 + + react-slider@2.0.6(react@18.2.0): + dependencies: + prop-types: 15.8.1 + react: 18.2.0 + + react-sortablejs@6.1.4(@types/sortablejs@1.15.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sortablejs@1.15.3): + dependencies: + '@types/sortablejs': 1.15.8 + classnames: 2.3.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + sortablejs: 1.15.3 + tiny-invariant: 1.2.0 + + react-syntax-highlighter@15.6.1(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + highlight.js: 10.7.3 + highlightjs-vue: 1.0.0 + lowlight: 1.20.0 + prismjs: 1.29.0 + react: 18.2.0 + refractor: 3.6.0 + + react-tooltip@5.8.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@floating-ui/dom': 1.1.1 + classnames: 2.5.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-window-infinite-loader@1.0.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react-window@1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.25.7 + memoize-one: 5.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + react@18.2.0: + dependencies: + loose-envify: 1.4.0 + + reactflow@11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@reactflow/background': 11.3.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@reactflow/controls': 11.2.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@reactflow/core': 11.11.4(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@reactflow/minimap': 11.7.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@reactflow/node-resizer': 2.2.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@reactflow/node-toolbar': 1.3.14(@types/react@18.2.79)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - immer + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.0.2: {} + + recast@0.23.9: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.0 + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.0(acorn@8.13.0): + dependencies: + acorn-jsx: 5.3.2(acorn@8.13.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - acorn + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.6 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + + recordrtc@5.6.2: {} + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + refa@0.12.1: + dependencies: + '@eslint-community/regexpp': 4.11.1 + + reflect.getprototypeof@1.0.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + which-builtin-type: 1.1.4 + + refractor@3.6.0: + dependencies: + hastscript: 6.0.0 + parse-entities: 2.0.0 + prismjs: 1.27.0 + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.14.1: {} + + regenerator-transform@0.15.2: + dependencies: + '@babel/runtime': 7.25.7 + + regex-parser@2.3.0: {} + + regexp-ast-analysis@0.7.1: + dependencies: + '@eslint-community/regexpp': 4.11.1 + refa: 0.12.1 + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + regexpu-core@6.1.1: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.11.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} + + regjsparser@0.10.0: + dependencies: + jsesc: 0.5.0 + + regjsparser@0.11.1: + dependencies: + jsesc: 3.0.2 + + rehype-external-links@3.0.0: + dependencies: + '@types/hast': 3.0.4 + '@ungap/structured-clone': 1.2.0 + hast-util-is-element: 3.0.0 + is-absolute-url: 4.0.1 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.0.0 + + rehype-katex@7.0.1: + dependencies: + '@types/hast': 3.0.4 + '@types/katex': 0.16.7 + hast-util-from-html-isomorphic: 2.0.0 + hast-util-to-text: 4.0.2 + katex: 0.16.11 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.0.4 + vfile: 6.0.3 + + rehype-recma@1.0.0: + dependencies: + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.0 + transitivePeerDependencies: + - supports-color + + rehype-slug@6.0.0: + dependencies: + '@types/hast': 3.0.4 + github-slugger: 2.0.0 + hast-util-heading-rank: 3.0.0 + hast-util-to-string: 3.0.1 + unist-util-visit: 5.0.0 + + relateurl@0.2.7: {} + + remark-breaks@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-newline-to-break: 2.0.0 + unified: 11.0.5 + + remark-gfm@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-math@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-math: 3.0.0 + micromark-extension-math: 3.1.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-mdx@3.1.0: + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.1 + micromark-util-types: 2.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.0 + unified: 11.0.5 + vfile: 6.0.3 + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.5 + + renderkid@3.0.0: + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 6.0.1 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resize-observer-polyfill@1.5.1: {} + + resolve-alpn@1.2.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve-url-loader@5.0.0: + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 8.4.47 + source-map: 0.6.1 + + resolve.exports@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + reusify@1.0.4: {} + + rfdc@1.4.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + ripemd160@2.0.2: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + + robust-predicates@3.0.2: {} + + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rw@1.3.3: {} + + safe-array-concat@1.1.2: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.0.3: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + + safer-buffer@2.1.2: {} + + sass-loader@13.3.3(sass@1.80.3)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + neo-async: 2.6.2 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + optionalDependencies: + sass: 1.80.3 + + sass@1.80.3: + dependencies: + '@parcel/watcher': 2.4.1 + chokidar: 4.0.1 + immutable: 4.3.7 + source-map-js: 1.2.1 + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.2.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + screenfull@5.2.0: {} + + scslre@0.3.0: + dependencies: + '@eslint-community/regexpp': 4.11.1 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.3: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + server-only@0.0.1: {} + + set-blocking@2.0.0: + optional: true + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sha.js@2.4.11: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + + shave@5.0.4: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + short-unique-id@5.2.0: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-concat@1.0.1: + optional: true + + simple-get@3.1.1: + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + optional: true + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + sisteransi@1.0.5: {} + + size-sensor@1.0.2: {} + + slash@3.0.0: {} + + slashes@3.0.12: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + sortablejs@1.15.3: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + space-separated-tokens@1.1.5: {} + + space-separated-tokens@2.0.2: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.20 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.20 + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.20 + + spdx-license-ids@3.0.20: {} + + sprintf-js@1.0.3: {} + + stable-hash@0.0.4: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackframe@1.3.4: {} + + state-local@1.0.7: {} + + statuses@2.0.1: {} + + storybook@8.3.6: + dependencies: + '@storybook/core': 8.3.6 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + + stream-http@3.2.0: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + + streamsearch@1.1.0: {} + + string-argv@0.3.2: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-ts@2.2.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + + string.prototype.matchall@4.0.11: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + regexp.prototype.flags: 1.5.3 + set-function-name: 2.0.2 + side-channel: 1.0.6 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + + string.prototype.trim@1.2.9: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + string.prototype.trimend@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-indent@4.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + style-loader@3.3.4(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + style-to-object@0.4.4: + dependencies: + inline-style-parser: 0.1.1 + + style-to-object@1.0.8: + dependencies: + inline-style-parser: 0.2.4 + + styled-jsx@5.1.1(@babel/core@7.25.8)(react@18.2.0): + dependencies: + client-only: 0.0.1 + react: 18.2.0 + optionalDependencies: + '@babel/core': 7.25.8 + + styled-jsx@5.1.6(@babel/core@7.25.8)(react@18.2.0): + dependencies: + client-only: 0.0.1 + react: 18.2.0 + optionalDependencies: + '@babel/core': 7.25.8 + + stylis@4.3.4: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + swr@2.2.5(react@18.2.0): + dependencies: + client-only: 0.0.1 + react: 18.2.0 + use-sync-external-store: 1.2.2(react@18.2.0) + + symbol-tree@3.2.4: {} + + synckit@0.6.2: + dependencies: + tslib: 2.8.0 + + synckit@0.9.2: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.8.0 + + tabbable@6.2.0: {} + + tailwind-merge@2.5.4: {} + + tailwindcss@3.4.14(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-import: 15.1.0(postcss@8.4.47) + postcss-js: 4.0.1(postcss@8.4.47) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5)) + postcss-nested: 6.2.0(postcss@8.4.47) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + tapable@2.2.1: {} + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + optional: true + + telejson@7.2.0: + dependencies: + memoizerific: 1.11.3 + + terser-webpack-plugin@5.3.10(esbuild@0.23.1)(uglify-js@3.19.3)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.36.0 + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + optionalDependencies: + esbuild: 0.23.1 + uglify-js: 3.19.3 + + terser@5.36.0: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.13.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + throttle-debounce@2.3.0: {} + + timers-browserify@2.0.12: + dependencies: + setimmediate: 1.0.5 + + tiny-invariant@1.2.0: {} + + tiny-invariant@1.3.3: {} + + tinyexec@0.3.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + tmpl@1.0.5: {} + + to-fast-properties@2.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toggle-selection@1.0.6: {} + + toidentifier@1.0.1: {} + + toml-eslint-parser@0.10.0: + dependencies: + eslint-visitor-keys: 3.4.3 + + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: + optional: true + + tr46@3.0.0: + dependencies: + punycode: 2.3.1 + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + ts-api-utils@1.3.0(typescript@4.9.5): + dependencies: + typescript: 4.9.5 + + ts-debounce@4.0.0: {} + + ts-declaration-location@1.0.4(typescript@4.9.5): + dependencies: + minimatch: 10.0.1 + typescript: 4.9.5 + + ts-dedent@2.2.0: {} + + ts-interface-checker@0.1.13: {} + + ts-node@10.9.2(@types/node@18.15.0)(typescript@4.9.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.15.0 + acorn: 8.13.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 4.9.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + ts-pattern@5.5.0: {} + + ts-pnp@1.2.0(typescript@4.9.5): + optionalDependencies: + typescript: 4.9.5 + + tsconfig-paths-webpack-plugin@4.1.0: + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.17.1 + tsconfig-paths: 4.2.0 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.3.0: {} + + tslib@2.6.2: {} + + tslib@2.8.0: {} + + tty-browserify@0.0.1: {} + + tween-functions@1.2.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.20.2: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + type-fest@2.19.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + + typed-array-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-byte-offset@1.0.2: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-length@1.0.6: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + + typescript@4.9.5: {} + + ufo@1.5.4: {} + + uglify-js@3.19.3: {} + + unbox-primitive@1.0.2: + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + + undici-types@6.19.8: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.0.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + universal-user-agent@7.0.2: {} + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + unplugin@1.14.1(webpack-sources@3.2.3): + dependencies: + acorn: 8.13.0 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + webpack-sources: 3.2.3 + + update-browserslist-db@1.1.1(browserslist@4.24.2): + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.13.0 + + use-context-selector@2.0.0(react@18.2.0)(scheduler@0.23.2): + dependencies: + react: 18.2.0 + scheduler: 0.23.2 + + use-strict@1.0.1: {} + + use-sync-external-store@1.2.2(react@18.2.0): + dependencies: + react: 18.2.0 + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + + utila@0.4.0: {} + + utils-merge@1.0.1: {} + + uuid@10.0.0: {} + + uuid@9.0.1: {} + + v8-compile-cache-lib@3.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + vary@1.1.2: {} + + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite-code-inspector-plugin@0.18.3: + dependencies: + code-inspector-core: 0.18.3 + transitivePeerDependencies: + - supports-color + + vm-browserify@1.1.2: {} + + void-elements@3.1.0: {} + + vscode-jsonrpc@8.2.0: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-uri@3.0.8: {} + + vue-eslint-parser@9.4.3(eslint@9.13.0(jiti@1.21.6)): + dependencies: + debug: 4.3.7 + eslint: 9.13.0(jiti@1.21.6) + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + lodash: 4.17.21 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + w3c-xmlserializer@4.0.0: + dependencies: + xml-name-validator: 4.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + web-namespaces@2.0.1: {} + + webidl-conversions@3.0.1: + optional: true + + webidl-conversions@7.0.0: {} + + webpack-code-inspector-plugin@0.18.3: + dependencies: + code-inspector-core: 0.18.3 + transitivePeerDependencies: + - supports-color + + webpack-dev-middleware@6.1.3(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)): + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.2.0 + optionalDependencies: + webpack: 5.95.0(esbuild@0.23.1)(uglify-js@3.19.3) + + webpack-hot-middleware@2.26.1: + dependencies: + ansi-html-community: 0.0.8 + html-entities: 2.5.2 + strip-ansi: 6.0.1 + + webpack-sources@3.2.3: {} + + webpack-virtual-modules@0.6.2: {} + + webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3): + dependencies: + '@types/estree': 1.0.6 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.13.0 + acorn-import-attributes: 1.9.5(acorn@8.13.0) + browserslist: 4.24.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(esbuild@0.23.1)(uglify-js@3.19.3)(webpack@5.95.0(esbuild@0.23.1)(uglify-js@3.19.3)) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@3.0.0: {} + + whatwg-url@11.0.0: + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + optional: true + + which-boxed-primitive@1.0.2: + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + which-builtin-type@1.1.4: + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + + which-typed-array@1.1.15: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + optional: true + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 4.2.3 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 4.2.3 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + ws@8.18.0: {} + + xml-name-validator@4.0.0: {} + + xmlchars@2.2.0: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: + optional: true + + yaml-eslint-parser@1.2.3: + dependencies: + eslint-visitor-keys: 3.4.3 + lodash: 4.17.21 + yaml: 2.6.0 + + yaml@1.10.2: {} + + yaml@2.5.1: {} + + yaml@2.6.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yjs@13.6.20: + dependencies: + lib0: 0.2.98 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} + + zod@3.23.8: {} + + zrender@5.6.0: + dependencies: + tslib: 2.3.0 + + zundo@2.2.0(zustand@4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0)): + dependencies: + zustand: 4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0) + + zustand@4.5.5(@types/react@18.2.79)(immer@9.0.21)(react@18.2.0): + dependencies: + use-sync-external-store: 1.2.2(react@18.2.0) + optionalDependencies: + '@types/react': 18.2.79 + immer: 9.0.21 + react: 18.2.0 + + zwitch@2.0.4: {} diff --git a/web/public/logo/logo.png b/web/public/logo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0e77ae481423960a9199a093bf49f65ee9abc35a GIT binary patch literal 6249 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 T*BNv-00000NkvXXu0mjf=atdo literal 0 HcmV?d00001 diff --git a/web/service/base.ts b/web/service/base.ts index 22b1a43ad1..38aaae0b1c 100644 --- a/web/service/base.ts +++ b/web/service/base.ts @@ -1,9 +1,10 @@ -import { refreshAccessTokenOrRelogin } from './refresh-token' import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config' +import { refreshAccessTokenOrRelogin } from './refresh-token' import Toast from '@/app/components/base/toast' import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/base/chat/chat/type' import type { VisionFile } from '@/types/app' import type { + AgentLogResponse, IterationFinishedResponse, IterationNextResponse, IterationStartedResponse, @@ -17,28 +18,11 @@ import type { WorkflowStartedResponse, } from '@/types/workflow' import { removeAccessToken } from '@/app/components/share/utils' +import type { FetchOptionType, ResponseError } from './fetch' +import { ContentType, base, baseOptions, getAccessToken } from './fetch' import { asyncRunSafe } from '@/utils' const TIME_OUT = 100000 -const ContentType = { - json: 'application/json', - stream: 'text/event-stream', - audio: 'audio/mpeg', - form: 'application/x-www-form-urlencoded; charset=UTF-8', - download: 'application/octet-stream', // for download - upload: 'multipart/form-data', // for upload -} - -const baseOptions = { - method: 'GET', - mode: 'cors', - credentials: 'include', // always send cookies、HTTP Basic authentication. - headers: new Headers({ - 'Content-Type': ContentType.json, - }), - redirect: 'follow', -} - export type IOnDataMoreInfo = { conversationId?: string taskId?: string @@ -70,9 +54,11 @@ export type IOnTextChunk = (textChunk: TextChunkResponse) => void export type IOnTTSChunk = (messageId: string, audioStr: string, audioType?: string) => void export type IOnTTSEnd = (messageId: string, audioStr: string, audioType?: string) => void export type IOnTextReplace = (textReplace: TextReplaceResponse) => void +export type IOnAgentLog = (agentLog: AgentLogResponse) => void export type IOtherOptions = { isPublicAPI?: boolean + isMarketplaceAPI?: boolean bodyStringify?: boolean needAllResponseContent?: boolean deleteContentType?: boolean @@ -100,17 +86,7 @@ export type IOtherOptions = { onTTSChunk?: IOnTTSChunk onTTSEnd?: IOnTTSEnd onTextReplace?: IOnTextReplace -} - -type ResponseError = { - code: string - message: string - status: number -} - -type FetchOptionType = Omit<RequestInit, 'body'> & { - params?: Record<string, any> - body?: BodyInit | Record<string, any> | null + onAgentLog?: IOnAgentLog } function unicodeToChar(text: string) { @@ -118,7 +94,7 @@ function unicodeToChar(text: string) { return '' return text.replace(/\\u[0-9a-f]{4}/g, (_match, p1) => { - return String.fromCharCode(parseInt(p1, 16)) + return String.fromCharCode(Number.parseInt(p1, 16)) }) } @@ -126,24 +102,6 @@ function requiredWebSSOLogin() { globalThis.location.href = `/webapp-signin?redirect_url=${globalThis.location.pathname}` } -function getAccessToken(isPublicAPI?: boolean) { - if (isPublicAPI) { - const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0] - const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' }) - let accessTokenJson = { [sharedToken]: '' } - try { - accessTokenJson = JSON.parse(accessToken) - } - catch (e) { - - } - return accessTokenJson[sharedToken] - } - else { - return localStorage.getItem('console_token') || '' - } -} - export function format(text: string) { let res = text.trim() if (res.startsWith('\n')) @@ -174,6 +132,7 @@ const handleStream = ( onTTSChunk?: IOnTTSChunk, onTTSEnd?: IOnTTSEnd, onTextReplace?: IOnTextReplace, + onAgentLog?: IOnAgentLog, ) => { if (!response.ok) throw new Error('Network response was not ok') @@ -274,6 +233,9 @@ const handleStream = ( else if (bufferObj.event === 'text_replace') { onTextReplace?.(bufferObj as TextReplaceResponse) } + else if (bufferObj.event === 'agent_log') { + onAgentLog?.(bufferObj as AgentLogResponse) + } else if (bufferObj.event === 'tts_message') { onTTSChunk?.(bufferObj.message_id, bufferObj.audio, bufferObj.audio_type) } @@ -301,115 +263,7 @@ const handleStream = ( read() } -const baseFetch = <T>( - url: string, - fetchOptions: FetchOptionType, - { - isPublicAPI = false, - bodyStringify = true, - needAllResponseContent, - deleteContentType, - getAbortController, - silent, - }: IOtherOptions, -): Promise<T> => { - const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions) - if (getAbortController) { - const abortController = new AbortController() - getAbortController(abortController) - options.signal = abortController.signal - } - const accessToken = getAccessToken(isPublicAPI) - options.headers.set('Authorization', `Bearer ${accessToken}`) - - if (deleteContentType) { - options.headers.delete('Content-Type') - } - else { - const contentType = options.headers.get('Content-Type') - if (!contentType) - options.headers.set('Content-Type', ContentType.json) - } - - const urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX - let urlWithPrefix = (url.startsWith('http://') || url.startsWith('https://')) - ? url - : `${urlPrefix}${url.startsWith('/') ? url : `/${url}`}` - - const { method, params, body } = options - // handle query - if (method === 'GET' && params) { - const paramsArray: string[] = [] - Object.keys(params).forEach(key => - paramsArray.push(`${key}=${encodeURIComponent(params[key])}`), - ) - if (urlWithPrefix.search(/\?/) === -1) - urlWithPrefix += `?${paramsArray.join('&')}` - - else - urlWithPrefix += `&${paramsArray.join('&')}` - - delete options.params - } - - if (body && bodyStringify) - options.body = JSON.stringify(body) - - // Handle timeout - return Promise.race([ - new Promise((resolve, reject) => { - setTimeout(() => { - reject(new Error('request timeout')) - }, TIME_OUT) - }), - new Promise((resolve, reject) => { - globalThis.fetch(urlWithPrefix, options as RequestInit) - .then((res) => { - const resClone = res.clone() - // Error handler - if (!/^(2|3)\d{2}$/.test(String(res.status))) { - const bodyJson = res.json() - switch (res.status) { - case 401: - return Promise.reject(resClone) - case 403: - bodyJson.then((data: ResponseError) => { - if (!silent) - Toast.notify({ type: 'error', message: data.message }) - if (data.code === 'already_setup') - globalThis.location.href = `${globalThis.location.origin}/signin` - }) - break - // fall through - default: - bodyJson.then((data: ResponseError) => { - if (!silent) - Toast.notify({ type: 'error', message: data.message }) - }) - } - return Promise.reject(resClone) - } - - // handle delete api. Delete api not return content. - if (res.status === 204) { - resolve({ result: 'success' }) - return - } - - // return data - if (options.headers.get('Content-type') === ContentType.download || options.headers.get('Content-type') === ContentType.audio) - resolve(needAllResponseContent ? resClone : res.blob()) - - else resolve(needAllResponseContent ? resClone : res.json()) - }) - .catch((err) => { - if (!silent) - Toast.notify({ type: 'error', message: err }) - reject(err) - }) - }), - ]) as Promise<T> -} +const baseFetch = base export const upload = (options: any, isPublicAPI?: boolean, url?: string, searchParams?: string): Promise<any> => { const urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX @@ -475,19 +329,25 @@ export const ssePost = ( onTTSChunk, onTTSEnd, onTextReplace, + onAgentLog, onError, getAbortController, } = otherOptions const abortController = new AbortController() + const token = localStorage.getItem('console_token') + const options = Object.assign({}, baseOptions, { method: 'POST', signal: abortController.signal, - }, fetchOptions) + headers: new Headers({ + Authorization: `Bearer ${token}`, + }), + } as RequestInit, fetchOptions) - const contentType = options.headers.get('Content-Type') + const contentType = (options.headers as Headers).get('Content-Type') if (!contentType) - options.headers.set('Content-Type', ContentType.json) + (options.headers as Headers).set('Content-Type', ContentType.json) getAbortController?.(abortController) @@ -501,7 +361,7 @@ export const ssePost = ( options.body = JSON.stringify(body) const accessToken = getAccessToken(isPublicAPI) - options.headers.set('Authorization', `Bearer ${accessToken}`) + options.headers!.set('Authorization', `Bearer ${accessToken}`) globalThis.fetch(urlWithPrefix, options as RequestInit) .then((res) => { @@ -540,7 +400,7 @@ export const ssePost = ( return } onData?.(str, isFirstMessage, moreInfo) - }, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace) + }, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace, onAgentLog) }).catch((e) => { if (e.toString() !== 'AbortError: The user aborted a request.' && !e.toString().errorMessage.includes('TypeError: Cannot assign to read only property')) Toast.notify({ type: 'error', message: e }) @@ -633,10 +493,20 @@ export const getPublic = <T>(url: string, options = {}, otherOptions?: IOtherOpt return get<T>(url, options, { ...otherOptions, isPublicAPI: true }) } +// For Marketplace API +export const getMarketplace = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => { + return get<T>(url, options, { ...otherOptions, isMarketplaceAPI: true }) +} + export const post = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => { return request<T>(url, Object.assign({}, options, { method: 'POST' }), otherOptions) } +// For Marketplace API +export const postMarketplace = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => { + return post<T>(url, options, { ...otherOptions, isMarketplaceAPI: true }) +} + export const postPublic = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => { return post<T>(url, options, { ...otherOptions, isPublicAPI: true }) } diff --git a/web/service/common.ts b/web/service/common.ts index 5910965ec2..770b839668 100644 --- a/web/service/common.ts +++ b/web/service/common.ts @@ -257,10 +257,6 @@ export const fetchFileUploadConfig: Fetcher<FileUploadConfigResponse, { url: str return get<FileUploadConfigResponse>(url) } -export const fetchFreeQuotaVerify: Fetcher<{ result: string; flag: boolean; reason: string }, string> = (url) => { - return get(url) as Promise<{ result: string; flag: boolean; reason: string }> -} - export const fetchNotionConnection: Fetcher<{ data: string }, string> = (url) => { return get(url) as Promise<{ data: string }> } @@ -298,7 +294,7 @@ export const moderate = (url: string, body: { app_id: string; text: string }) => } type RetrievalMethodsRes = { - 'retrieval_method': RETRIEVE_METHOD[] + retrieval_method: RETRIEVE_METHOD[] } export const fetchSupportRetrievalMethods: Fetcher<RetrievalMethodsRes, string> = (url) => { return get<RetrievalMethodsRes>(url) diff --git a/web/service/debug.ts b/web/service/debug.ts index 3770c4d398..093cddfd62 100644 --- a/web/service/debug.ts +++ b/web/service/debug.ts @@ -3,13 +3,13 @@ import type { IOnCompleted, IOnData, IOnError, IOnFile, IOnMessageEnd, IOnMessag import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug' import type { ModelModeType } from '@/types/app' import type { ModelParameterRule } from '@/app/components/header/account-setting/model-provider-page/declarations' -export type AutomaticRes = { +export interface AutomaticRes { prompt: string variables: string[] opening_statement: string error?: string } -export type CodeGenRes = { +export interface CodeGenRes { code: string language: string[] error?: string diff --git a/web/service/fetch.ts b/web/service/fetch.ts new file mode 100644 index 0000000000..10643173bc --- /dev/null +++ b/web/service/fetch.ts @@ -0,0 +1,205 @@ +import type { AfterResponseHook, BeforeErrorHook, BeforeRequestHook, Hooks } from 'ky' +import ky from 'ky' +import type { IOtherOptions } from './base' +import Toast from '@/app/components/base/toast' +import { API_PREFIX, MARKETPLACE_API_PREFIX, PUBLIC_API_PREFIX } from '@/config' + +const TIME_OUT = 100000 + +export const ContentType = { + json: 'application/json', + stream: 'text/event-stream', + audio: 'audio/mpeg', + form: 'application/x-www-form-urlencoded; charset=UTF-8', + download: 'application/octet-stream', // for download + downloadZip: 'application/zip', // for download + upload: 'multipart/form-data', // for upload +} + +export type FetchOptionType = Omit<RequestInit, 'body'> & { + params?: Record<string, any> + body?: BodyInit | Record<string, any> | null +} + +const afterResponse204: AfterResponseHook = async (_request, _options, response) => { + if (response.status === 204) return Response.json({ result: 'success' }) +} + +export type ResponseError = { + code: string + message: string + status: number +} + +const afterResponseErrorCode = (otherOptions: IOtherOptions): AfterResponseHook => { + return async (_request, _options, response) => { + const clonedResponse = response.clone() + if (!/^(2|3)\d{2}$/.test(String(clonedResponse.status))) { + const bodyJson = clonedResponse.json() as Promise<ResponseError> + switch (clonedResponse.status) { + case 403: + bodyJson.then((data: ResponseError) => { + if (!otherOptions.silent) + Toast.notify({ type: 'error', message: data.message }) + if (data.code === 'already_setup') + globalThis.location.href = `${globalThis.location.origin}/signin` + }) + break + case 401: + return Promise.reject(response) + // fall through + default: + bodyJson.then((data: ResponseError) => { + if (!otherOptions.silent) + Toast.notify({ type: 'error', message: data.message }) + }) + return Promise.reject(response) + } + } + } +} + +const beforeErrorToast = (otherOptions: IOtherOptions): BeforeErrorHook => { + return (error) => { + if (!otherOptions.silent) + Toast.notify({ type: 'error', message: error.message }) + return error + } +} + +export const getPublicToken = () => { + let token = '' + const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0] + const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' }) + let accessTokenJson = { [sharedToken]: '' } + try { + accessTokenJson = JSON.parse(accessToken) + } + catch { } + token = accessTokenJson[sharedToken] + return token || '' +} + +export function getAccessToken(isPublicAPI?: boolean) { + if (isPublicAPI) { + const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0] + const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' }) + let accessTokenJson = { [sharedToken]: '' } + try { + accessTokenJson = JSON.parse(accessToken) + } + catch (e) { + + } + return accessTokenJson[sharedToken] + } + else { + return localStorage.getItem('console_token') || '' + } +} + +const beforeRequestPublicAuthorization: BeforeRequestHook = (request) => { + const token = getAccessToken(true) + request.headers.set('Authorization', `Bearer ${token}`) +} + +const beforeRequestAuthorization: BeforeRequestHook = (request) => { + const accessToken = getAccessToken() + request.headers.set('Authorization', `Bearer ${accessToken}`) +} + +const baseHooks: Hooks = { + afterResponse: [ + afterResponse204, + ], +} + +const baseClient = ky.create({ + hooks: baseHooks, + timeout: TIME_OUT, +}) + +export const baseOptions: RequestInit = { + method: 'GET', + mode: 'cors', + credentials: 'include', // always send cookies、HTTP Basic authentication. + headers: new Headers({ + 'Content-Type': ContentType.json, + }), + redirect: 'follow', +} + +async function base<T>(url: string, options: FetchOptionType = {}, otherOptions: IOtherOptions = {}): Promise<T> { + const { params, body, headers, ...init } = Object.assign({}, baseOptions, options) + const { + isPublicAPI = false, + isMarketplaceAPI = false, + bodyStringify = true, + needAllResponseContent, + deleteContentType, + getAbortController, + } = otherOptions + + const base + = isMarketplaceAPI + ? MARKETPLACE_API_PREFIX + : isPublicAPI + ? PUBLIC_API_PREFIX + : API_PREFIX + + if (getAbortController) { + const abortController = new AbortController() + getAbortController(abortController) + options.signal = abortController.signal + } + + const fetchPathname = `${base}${url.startsWith('/') ? url : `/${url}`}` + + if (deleteContentType) + (headers as any).delete('Content-Type') + + const client = baseClient.extend({ + hooks: { + ...baseHooks, + beforeError: [ + ...baseHooks.beforeError || [], + beforeErrorToast(otherOptions), + ], + beforeRequest: [ + ...baseHooks.beforeRequest || [], + isPublicAPI && beforeRequestPublicAuthorization, + !isPublicAPI && !isMarketplaceAPI && beforeRequestAuthorization, + ].filter(Boolean), + afterResponse: [ + ...baseHooks.afterResponse || [], + afterResponseErrorCode(otherOptions), + ], + }, + }) + + const res = await client(fetchPathname, { + ...init, + headers, + credentials: isMarketplaceAPI + ? 'omit' + : (options.credentials || 'include'), + retry: { + methods: [], + }, + ...(bodyStringify ? { json: body } : { body: body as BodyInit }), + searchParams: params, + }) + + if (needAllResponseContent) + return res as T + const contentType = res.headers.get('content-type') + if ( + contentType + && [ContentType.download, ContentType.audio, ContentType.downloadZip].includes(contentType) + ) + return await res.blob() as T + + return await res.json() as T +} + +export { base } diff --git a/web/service/plugins.ts b/web/service/plugins.ts new file mode 100644 index 0000000000..0a880b865f --- /dev/null +++ b/web/service/plugins.ts @@ -0,0 +1,108 @@ +import type { Fetcher } from 'swr' +import { get, getMarketplace, post, upload } from './base' +import type { + Dependency, + InstallPackageResponse, + Permissions, + PluginDeclaration, + PluginInfoFromMarketPlace, + PluginManifestInMarket, + PluginTasksResponse, + TaskStatusResponse, + UninstallPluginResponse, + updatePackageResponse, + uploadGitHubResponse, +} from '@/app/components/plugins/types' +import type { + MarketplaceCollectionPluginsResponse, + MarketplaceCollectionsResponse, +} from '@/app/components/plugins/marketplace/types' + +export const uploadFile = async (file: File, isBundle: boolean) => { + const formData = new FormData() + formData.append(isBundle ? 'bundle' : 'pkg', file) + return upload({ + xhr: new XMLHttpRequest(), + data: formData, + }, false, `/workspaces/current/plugin/upload/${isBundle ? 'bundle' : 'pkg'}`) +} + +export const updateFromMarketPlace = async (body: Record<string, string>) => { + return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', { + body, + }) +} + +export const updateFromGitHub = async (repoUrl: string, selectedVersion: string, selectedPackage: string, + originalPlugin: string, newPlugin: string) => { + return post<updatePackageResponse>('/workspaces/current/plugin/upgrade/github', { + body: { + repo: repoUrl, + version: selectedVersion, + package: selectedPackage, + original_plugin_unique_identifier: originalPlugin, + new_plugin_unique_identifier: newPlugin, + }, + }) +} + +export const uploadGitHub = async (repoUrl: string, selectedVersion: string, selectedPackage: string) => { + return post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', { + body: { + repo: repoUrl, + version: selectedVersion, + package: selectedPackage, + }, + }) +} + +export const fetchIcon = (tenantId: string, fileName: string) => { + return get(`workspaces/current/plugin/icon?tenant_id=${tenantId}&filename=${fileName}`) +} + +export const fetchManifest = async (uniqueIdentifier: string) => { + return get<PluginDeclaration>(`/workspaces/current/plugin/fetch-manifest?plugin_unique_identifier=${uniqueIdentifier}`) +} + +export const fetchManifestFromMarketPlace = async (uniqueIdentifier: string) => { + return getMarketplace<{ data: { plugin: PluginManifestInMarket, version: { version: string } } }>(`/plugins/identifier?unique_identifier=${uniqueIdentifier}`) +} + +export const fetchBundleInfoFromMarketPlace = async ({ + org, + name, + version, +}: Record<string, string>) => { + return getMarketplace<{ data: { version: { dependencies: Dependency[] } } }>(`/bundles/${org}/${name}/${version}`) +} + +export const fetchPluginInfoFromMarketPlace = async ({ + org, + name, +}: Record<string, string>) => { + return getMarketplace<{ data: { plugin: PluginInfoFromMarketPlace, version: { version: string } } }>(`/plugins/${org}/${name}`) +} + +export const fetchMarketplaceCollections: Fetcher<MarketplaceCollectionsResponse, { url: string; }> = ({ url }) => { + return get<MarketplaceCollectionsResponse>(url) +} + +export const fetchMarketplaceCollectionPlugins: Fetcher<MarketplaceCollectionPluginsResponse, { url: string }> = ({ url }) => { + return get<MarketplaceCollectionPluginsResponse>(url) +} + +export const fetchPluginTasks = async () => { + return get<PluginTasksResponse>('/workspaces/current/plugin/tasks?page=1&page_size=255') +} + +export const checkTaskStatus = async (taskId: string) => { + return get<TaskStatusResponse>(`/workspaces/current/plugin/tasks/${taskId}`) +} + +export const updatePermission = async (permissions: Permissions) => { + return post('/workspaces/current/plugin/permission/change', { body: permissions }) +} + +export const uninstallPlugin = async (pluginId: string) => { + return post<UninstallPluginResponse>('/workspaces/current/plugin/uninstall', { body: { plugin_installation_id: pluginId } }) +} diff --git a/web/service/strategy.ts b/web/service/strategy.ts new file mode 100644 index 0000000000..bb032ba286 --- /dev/null +++ b/web/service/strategy.ts @@ -0,0 +1,10 @@ +import type { StrategyPluginDetail } from '@/app/components/plugins/types' +import { get } from './base' + +export const fetchStrategyList = () => { + return get<StrategyPluginDetail[]>('/workspaces/current/agent-providers') +} + +export const fetchStrategyDetail = (agentProvider: string) => { + return get<StrategyPluginDetail>(`/workspaces/current/agent-provider/${agentProvider}`) +} diff --git a/web/service/tools.ts b/web/service/tools.ts index 90221edec2..d6b2f2034b 100644 --- a/web/service/tools.ts +++ b/web/service/tools.ts @@ -15,6 +15,10 @@ export const fetchCollectionList = () => { return get<Collection[]>('/workspaces/current/tool-providers') } +export const fetchCollectionDetail = (collectionName: string) => { + return get<Collection>(`/workspaces/current/tool-provider/${collectionName}/info`) +} + export const fetchBuiltInToolList = (collectionName: string) => { return get<Tool[]>(`/workspaces/current/tool-provider/builtin/${collectionName}/tools`) } diff --git a/web/service/use-apps.ts b/web/service/use-apps.ts new file mode 100644 index 0000000000..1a3e9cedbb --- /dev/null +++ b/web/service/use-apps.ts @@ -0,0 +1,27 @@ +import { get } from './base' +import type { App } from '@/types/app' +import type { AppListResponse } from '@/models/app' +import { useInvalid } from './use-base' +import { useQuery } from '@tanstack/react-query' + +const NAME_SPACE = 'apps' + +// TODO paging for list +const useAppFullListKey = [NAME_SPACE, 'full-list'] +export const useAppFullList = () => { + return useQuery<AppListResponse>({ + queryKey: useAppFullListKey, + queryFn: () => get<AppListResponse>('/apps', { params: { page: 1, limit: 100 } }), + }) +} + +export const useInvalidateAppFullList = () => { + return useInvalid(useAppFullListKey) +} + +export const useAppDetail = (appID: string) => { + return useQuery<App>({ + queryKey: [NAME_SPACE, 'detail', appID], + queryFn: () => get<App>(`/apps/${appID}`), + }) +} diff --git a/web/service/use-common.ts b/web/service/use-common.ts new file mode 100644 index 0000000000..98ab535948 --- /dev/null +++ b/web/service/use-common.ts @@ -0,0 +1,14 @@ +import { get } from './base' +import type { + FileUploadConfigResponse, +} from '@/models/common' +import { useQuery } from '@tanstack/react-query' + +const NAME_SPACE = 'common' + +export const useFileUploadConfig = () => { + return useQuery<FileUploadConfigResponse>({ + queryKey: [NAME_SPACE, 'file-upload-config'], + queryFn: () => get<FileUploadConfigResponse>('/files/upload'), + }) +} diff --git a/web/service/use-endpoints.ts b/web/service/use-endpoints.ts new file mode 100644 index 0000000000..43a82480b9 --- /dev/null +++ b/web/service/use-endpoints.ts @@ -0,0 +1,149 @@ +import { get, post } from './base' +import type { + EndpointsResponse, +} from '@/app/components/plugins/types' +import { + useMutation, + useQuery, + useQueryClient, +} from '@tanstack/react-query' + +const NAME_SPACE = 'endpoints' + +export const useEndpointList = (pluginID: string) => { + return useQuery({ + queryKey: [NAME_SPACE, 'list', pluginID], + queryFn: () => get<EndpointsResponse>('/workspaces/current/endpoints/list/plugin', { + params: { + plugin_id: pluginID, + page: 1, + page_size: 100, + }, + }), + }) +} + +export const useInvalidateEndpointList = () => { + const queryClient = useQueryClient() + return (pluginID: string) => { + queryClient.invalidateQueries( + { + queryKey: [NAME_SPACE, 'list', pluginID], + }) + } +} + +export const useCreateEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'create'], + mutationFn: (payload: { pluginUniqueID: string, state: Record<string, any> }) => { + const { pluginUniqueID, state } = payload + const newName = state.name + delete state.name + return post('/workspaces/current/endpoints/create', { + body: { + plugin_unique_identifier: pluginUniqueID, + settings: state, + name: newName, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useUpdateEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'update'], + mutationFn: (payload: { endpointID: string, state: Record<string, any> }) => { + const { endpointID, state } = payload + const newName = state.name + delete state.name + return post('/workspaces/current/endpoints/update', { + body: { + endpoint_id: endpointID, + settings: state, + name: newName, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useDeleteEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'delete'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/delete', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useEnableEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'enable'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/enable', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} + +export const useDisableEndpoint = ({ + onSuccess, + onError, +}: { + onSuccess?: () => void + onError?: (error: any) => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'disable'], + mutationFn: (endpointID: string) => { + return post('/workspaces/current/endpoints/disable', { + body: { + endpoint_id: endpointID, + }, + }) + }, + onSuccess, + onError, + }) +} diff --git a/web/service/use-models.ts b/web/service/use-models.ts new file mode 100644 index 0000000000..84122cdd1f --- /dev/null +++ b/web/service/use-models.ts @@ -0,0 +1,17 @@ +import { get } from './base' +import type { + ModelItem, +} from '@/app/components/header/account-setting/model-provider-page/declarations' +import { + useQuery, + // useQueryClient, +} from '@tanstack/react-query' + +const NAME_SPACE = 'models' + +export const useModelProviderModelList = (provider: string) => { + return useQuery({ + queryKey: [NAME_SPACE, 'model-list', provider], + queryFn: () => get<{ data: ModelItem[] }>(`/workspaces/current/model-providers/${provider}/models`), + }) +} diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts new file mode 100644 index 0000000000..66e55c6431 --- /dev/null +++ b/web/service/use-plugins.ts @@ -0,0 +1,432 @@ +import { useCallback, useState } from 'react' +import type { + DebugInfo as DebugInfoTypes, + Dependency, + GitHubItemAndMarketPlaceDependency, + InstallPackageResponse, + InstalledPluginListResponse, + PackageDependency, + Permissions, + Plugin, + PluginDetail, + PluginInfoFromMarketPlace, + PluginTask, + PluginsFromMarketplaceByInfoResponse, + PluginsFromMarketplaceResponse, + VersionInfo, + VersionListResponse, + uploadGitHubResponse, +} from '@/app/components/plugins/types' +import { TaskStatus } from '@/app/components/plugins/types' +import type { + PluginsSearchParams, +} from '@/app/components/plugins/marketplace/types' +import { get, getMarketplace, post, postMarketplace } from './base' +import type { MutateOptions, QueryOptions } from '@tanstack/react-query' +import { + useMutation, + useQuery, + useQueryClient, +} from '@tanstack/react-query' +import { useInvalidateAllBuiltInTools } from './use-tools' + +const NAME_SPACE = 'plugins' + +const useInstalledPluginListKey = [NAME_SPACE, 'installedPluginList'] +export const useCheckInstalled = ({ + pluginIds, + enabled, +}: { + pluginIds: string[], + enabled: boolean +}) => { + return useQuery<{ plugins: PluginDetail[] }>({ + queryKey: [NAME_SPACE, 'checkInstalled', pluginIds], + queryFn: () => post<{ plugins: PluginDetail[] }>('/workspaces/current/plugin/list/installations/ids', { + body: { + plugin_ids: pluginIds, + }, + }), + enabled, + staleTime: 0, // always fresh + }) +} + +export const useInstalledPluginList = (disable?: boolean) => { + return useQuery<InstalledPluginListResponse>({ + queryKey: useInstalledPluginListKey, + queryFn: () => get<InstalledPluginListResponse>('/workspaces/current/plugin/list'), + enabled: !disable, + initialData: !disable ? undefined : { plugins: [] }, + }) +} + +export const useInvalidateInstalledPluginList = () => { + const queryClient = useQueryClient() + const invalidateAllBuiltInTools = useInvalidateAllBuiltInTools() + return () => { + queryClient.invalidateQueries( + { + queryKey: useInstalledPluginListKey, + }) + invalidateAllBuiltInTools() + } +} + +export const useInstallPackageFromMarketPlace = (options?: MutateOptions<InstallPackageResponse, Error, string>) => { + return useMutation({ + ...options, + mutationFn: (uniqueIdentifier: string) => { + return post<InstallPackageResponse>('/workspaces/current/plugin/install/marketplace', { body: { plugin_unique_identifiers: [uniqueIdentifier] } }) + }, + }) +} + +export const useUpdatePackageFromMarketPlace = (options?: MutateOptions<InstallPackageResponse, Error, object>) => { + return useMutation({ + ...options, + mutationFn: (body: object) => { + return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', { + body, + }) + }, + }) +} + +export const useVersionListOfPlugin = (pluginID: string) => { + return useQuery<{ data: VersionListResponse }>({ + enabled: !!pluginID, + queryKey: [NAME_SPACE, 'versions', pluginID], + queryFn: () => getMarketplace<{ data: VersionListResponse }>(`/plugins/${pluginID}/versions`, { params: { page: 1, page_size: 100 } }), + }) +} +export const useInvalidateVersionListOfPlugin = () => { + const queryClient = useQueryClient() + return (pluginID: string) => { + queryClient.invalidateQueries({ queryKey: [NAME_SPACE, 'versions', pluginID] }) + } +} + +export const useInstallPackageFromLocal = () => { + return useMutation({ + mutationFn: (uniqueIdentifier: string) => { + return post<InstallPackageResponse>('/workspaces/current/plugin/install/pkg', { + body: { plugin_unique_identifiers: [uniqueIdentifier] }, + }) + }, + }) +} + +export const useInstallPackageFromGitHub = () => { + return useMutation({ + mutationFn: ({ repoUrl, selectedVersion, selectedPackage, uniqueIdentifier }: { + repoUrl: string + selectedVersion: string + selectedPackage: string + uniqueIdentifier: string + }) => { + return post<InstallPackageResponse>('/workspaces/current/plugin/install/github', { + body: { + repo: repoUrl, + version: selectedVersion, + package: selectedPackage, + plugin_unique_identifier: uniqueIdentifier, + }, + }) + }, + }) +} + +export const useUploadGitHub = (payload: { + repo: string + version: string + package: string +}) => { + return useQuery({ + queryKey: [NAME_SPACE, 'uploadGitHub', payload], + queryFn: () => post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', { + body: payload, + }), + retry: 0, + }) +} + +export const useInstallOrUpdate = ({ + onSuccess, +}: { + onSuccess?: (res: { success: boolean }[]) => void +}) => { + const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace() + + return useMutation({ + mutationFn: (data: { + payload: Dependency[], + plugin: Plugin[], + installedInfo: Record<string, VersionInfo> + }) => { + const { payload, plugin, installedInfo } = data + + return Promise.all(payload.map(async (item, i) => { + try { + const orgAndName = `${plugin[i]?.org || plugin[i]?.author}/${plugin[i]?.name}` + const installedPayload = installedInfo[orgAndName] + const isInstalled = !!installedPayload + let uniqueIdentifier = '' + + if (item.type === 'github') { + const data = item as GitHubItemAndMarketPlaceDependency + // From local bundle don't have data.value.github_plugin_unique_identifier + if (!data.value.github_plugin_unique_identifier) { + const { unique_identifier } = await post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', { + body: { + repo: data.value.repo!, + version: data.value.release! || data.value.version!, + package: data.value.packages! || data.value.package!, + }, + }) + uniqueIdentifier = data.value.github_plugin_unique_identifier! || unique_identifier + // has the same version, but not installed + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + } + if (!isInstalled) { + await post<InstallPackageResponse>('/workspaces/current/plugin/install/github', { + body: { + repo: data.value.repo!, + version: data.value.release! || data.value.version!, + package: data.value.packages! || data.value.package!, + plugin_unique_identifier: uniqueIdentifier, + }, + }) + } + } + if (item.type === 'marketplace') { + const data = item as GitHubItemAndMarketPlaceDependency + uniqueIdentifier = data.value.plugin_unique_identifier! || plugin[i]?.plugin_id + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + if (!isInstalled) { + await post<InstallPackageResponse>('/workspaces/current/plugin/install/marketplace', { + body: { + plugin_unique_identifiers: [uniqueIdentifier], + }, + }) + } + } + if (item.type === 'package') { + const data = item as PackageDependency + uniqueIdentifier = data.value.unique_identifier + if (uniqueIdentifier === installedPayload?.uniqueIdentifier) { + return { + success: true, + } + } + if (!isInstalled) { + await post<InstallPackageResponse>('/workspaces/current/plugin/install/pkg', { + body: { + plugin_unique_identifiers: [uniqueIdentifier], + }, + }) + } + } + if (isInstalled) { + await updatePackageFromMarketPlace({ + original_plugin_unique_identifier: installedPayload?.uniqueIdentifier, + new_plugin_unique_identifier: uniqueIdentifier, + }) + } + return ({ success: true }) + } + // eslint-disable-next-line unused-imports/no-unused-vars + catch (e) { + return Promise.resolve({ success: false }) + } + })) + }, + onSuccess, + }) +} + +export const useDebugKey = () => { + return useQuery({ + queryKey: [NAME_SPACE, 'debugKey'], + queryFn: () => get<DebugInfoTypes>('/workspaces/current/plugin/debugging-key'), + }) +} + +const usePermissionsKey = [NAME_SPACE, 'permissions'] +export const usePermissions = () => { + return useQuery({ + queryKey: usePermissionsKey, + queryFn: () => get<Permissions>('/workspaces/current/plugin/permission/fetch'), + }) +} + +export const useInvalidatePermissions = () => { + const queryClient = useQueryClient() + return () => { + queryClient.invalidateQueries( + { + queryKey: usePermissionsKey, + }) + } +} + +export const useMutationPermissions = ({ + onSuccess, +}: { + onSuccess?: () => void +}) => { + return useMutation({ + mutationFn: (payload: Permissions) => { + return post('/workspaces/current/plugin/permission/change', { body: payload }) + }, + onSuccess, + }) +} + +export const useMutationPluginsFromMarketplace = () => { + return useMutation({ + mutationFn: (pluginsSearchParams: PluginsSearchParams) => { + const { + query, + sortBy, + sortOrder, + category, + tags, + exclude, + type, + page = 1, + pageSize = 40, + } = pluginsSearchParams + return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', { + body: { + page, + page_size: pageSize, + query, + sort_by: sortBy, + sort_order: sortOrder, + category: category !== 'all' ? category : '', + tags, + exclude, + type, + }, + }) + }, + }) +} + +export const useFetchPluginsInMarketPlaceByIds = (unique_identifiers: string[], options?: QueryOptions<{ data: PluginsFromMarketplaceResponse }>) => { + return useQuery({ + ...options, + queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByIds', unique_identifiers], + queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/identifier/batch', { + body: { + unique_identifiers, + }, + }), + enabled: unique_identifiers?.filter(i => !!i).length > 0, + retry: 0, + }) +} + +export const useFetchPluginsInMarketPlaceByInfo = (infos: Record<string, any>[]) => { + return useQuery({ + queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByInfo', infos], + queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceByInfoResponse }>('/plugins/versions/batch', { + body: { + plugin_tuples: infos.map(info => ({ + org: info.organization, + name: info.plugin, + version: info.version, + })), + }, + }), + enabled: infos?.filter(i => !!i).length > 0, + retry: 0, + }) +} + +const usePluginTaskListKey = [NAME_SPACE, 'pluginTaskList'] +export const usePluginTaskList = () => { + const [enabled, setEnabled] = useState(true) + const { + data, + isFetched, + refetch, + ...rest + } = useQuery({ + queryKey: usePluginTaskListKey, + queryFn: async () => { + const currentData = await get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100') + const taskDone = currentData.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed) + + if (taskDone) + setEnabled(false) + + return currentData + }, + refetchInterval: 5000, + enabled, + }) + const handleRefetch = useCallback(() => { + setEnabled(true) + refetch() + }, [refetch]) + + return { + data, + pluginTasks: data?.tasks || [], + isFetched, + handleRefetch, + ...rest, + } +} + +export const useMutationClearTaskPlugin = () => { + return useMutation({ + mutationFn: ({ taskId, pluginId }: { taskId: string; pluginId: string }) => { + return post<{ success: boolean }>(`/workspaces/current/plugin/tasks/${taskId}/delete/${pluginId}`) + }, + }) +} + +export const useMutationClearAllTaskPlugin = () => { + return useMutation({ + mutationFn: () => { + return post<{ success: boolean }>('/workspaces/current/plugin/tasks/delete_all') + }, + }) +} + +export const usePluginManifestInfo = (pluginUID: string) => { + return useQuery({ + enabled: !!pluginUID, + queryKey: [[NAME_SPACE, 'manifest', pluginUID]], + queryFn: () => getMarketplace<{ data: { plugin: PluginInfoFromMarketPlace, version: { version: string } } }>(`/plugins/${pluginUID}`), + retry: 0, + }) +} + +export const useDownloadPlugin = (info: { organization: string; pluginName: string; version: string }, needDownload: boolean) => { + return useQuery({ + queryKey: [NAME_SPACE, 'downloadPlugin', info], + queryFn: () => getMarketplace<Blob>(`/plugins/${info.organization}/${info.pluginName}/${info.version}/download`), + enabled: needDownload, + retry: 0, + }) +} + +export const useMutationCheckDependencies = () => { + return useMutation({ + mutationFn: (appId: string) => { + return get<{ leaked_dependencies: Dependency[] }>(`/apps/imports/${appId}/check-dependencies`) + }, + }) +} diff --git a/web/service/use-strategy.ts b/web/service/use-strategy.ts new file mode 100644 index 0000000000..af591ac019 --- /dev/null +++ b/web/service/use-strategy.ts @@ -0,0 +1,36 @@ +import type { + StrategyPluginDetail, +} from '@/app/components/plugins/types' +import { useInvalid } from './use-base' +import type { QueryOptions } from '@tanstack/react-query' +import { + useQuery, +} from '@tanstack/react-query' +import { fetchStrategyDetail, fetchStrategyList } from './strategy' + +const NAME_SPACE = 'agent_strategy' + +const useStrategyListKey = [NAME_SPACE, 'strategyList'] +export const useStrategyProviders = () => { + return useQuery<StrategyPluginDetail[]>({ + queryKey: useStrategyListKey, + queryFn: fetchStrategyList, + }) +} + +export const useInvalidateStrategyProviders = () => { + return useInvalid(useStrategyListKey) +} + +export const useStrategyProviderDetail = (agentProvider: string, options?: QueryOptions<StrategyPluginDetail>) => { + return useQuery<StrategyPluginDetail>({ + ...options, + queryKey: [NAME_SPACE, 'detail', agentProvider], + queryFn: () => fetchStrategyDetail(agentProvider), + enabled: !!agentProvider, + }) +} + +export const useInvalidateStrategyProviderDetail = (agentProvider: string) => { + return useInvalid([NAME_SPACE, 'detail', agentProvider]) +} diff --git a/web/service/use-tools.ts b/web/service/use-tools.ts new file mode 100644 index 0000000000..ceaa4b14b3 --- /dev/null +++ b/web/service/use-tools.ts @@ -0,0 +1,121 @@ +import { get, post } from './base' +import type { + Collection, + Tool, +} from '@/app/components/tools/types' +import type { ToolWithProvider } from '@/app/components/workflow/types' +import { useInvalid } from './use-base' +import { + useMutation, + useQuery, + useQueryClient, +} from '@tanstack/react-query' + +const NAME_SPACE = 'tools' + +const useAllToolProvidersKey = [NAME_SPACE, 'allToolProviders'] +export const useAllToolProviders = () => { + return useQuery<Collection[]>({ + queryKey: useAllToolProvidersKey, + queryFn: () => get<Collection[]>('/workspaces/current/tool-providers'), + }) +} + +export const useInvalidateAllToolProviders = () => { + return useInvalid(useAllToolProvidersKey) +} + +const useAllBuiltInToolsKey = [NAME_SPACE, 'builtIn'] +export const useAllBuiltInTools = () => { + return useQuery<ToolWithProvider[]>({ + queryKey: useAllBuiltInToolsKey, + queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/builtin'), + }) +} + +export const useInvalidateAllBuiltInTools = () => { + return useInvalid(useAllBuiltInToolsKey) +} + +const useAllCustomToolsKey = [NAME_SPACE, 'customTools'] +export const useAllCustomTools = () => { + return useQuery<ToolWithProvider[]>({ + queryKey: useAllCustomToolsKey, + queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/api'), + }) +} + +export const useInvalidateAllCustomTools = () => { + return useInvalid(useAllCustomToolsKey) +} + +const useAllWorkflowToolsKey = [NAME_SPACE, 'workflowTools'] +export const useAllWorkflowTools = () => { + return useQuery<ToolWithProvider[]>({ + queryKey: useAllWorkflowToolsKey, + queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/workflow'), + }) +} + +export const useInvalidateAllWorkflowTools = () => { + return useInvalid(useAllWorkflowToolsKey) +} + +export const useBuiltinProviderInfo = (providerName: string) => { + return useQuery({ + queryKey: [NAME_SPACE, 'builtin-provider-info', providerName], + queryFn: () => get<Collection>(`/workspaces/current/tool-provider/builtin/${providerName}/info`), + }) +} + +export const useInvalidateBuiltinProviderInfo = () => { + const queryClient = useQueryClient() + return (providerName: string) => { + queryClient.invalidateQueries( + { + queryKey: [NAME_SPACE, 'builtin-provider-info', providerName], + }) + } +} + +export const useBuiltinTools = (providerName: string) => { + return useQuery({ + queryKey: [NAME_SPACE, 'builtin-provider-tools', providerName], + queryFn: () => get<Tool[]>(`/workspaces/current/tool-provider/builtin/${providerName}/tools`), + }) +} + +export const useUpdateProviderCredentials = ({ + onSuccess, +}: { + onSuccess?: () => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'update-provider-credentials'], + mutationFn: (payload: { providerName: string, credentials: Record<string, any> }) => { + const { providerName, credentials } = payload + return post(`/workspaces/current/tool-provider/builtin/${providerName}/update`, { + body: { + credentials, + }, + }) + }, + onSuccess, + }) +} + +export const useRemoveProviderCredentials = ({ + onSuccess, +}: { + onSuccess?: () => void +}) => { + return useMutation({ + mutationKey: [NAME_SPACE, 'remove-provider-credentials'], + mutationFn: (providerName: string) => { + return post(`/workspaces/current/tool-provider/builtin/${providerName}/delete`, { + body: {}, + }) + }, + onSuccess, + }) +} diff --git a/web/service/use-workflow.ts b/web/service/use-workflow.ts index 948a114b04..43fa4b22c3 100644 --- a/web/service/use-workflow.ts +++ b/web/service/use-workflow.ts @@ -1,9 +1,20 @@ -import { useQuery } from '@tanstack/react-query' import { get } from './base' +import type { + FetchWorkflowDraftResponse, +} from '@/types/workflow' +import { useQuery } from '@tanstack/react-query' import type { WorkflowConfigResponse } from '@/types/workflow' const NAME_SPACE = 'workflow' +export const useAppWorkflow = (appID: string) => { + return useQuery<FetchWorkflowDraftResponse>({ + enabled: !!appID, + queryKey: [NAME_SPACE, 'publish', appID], + queryFn: () => get<FetchWorkflowDraftResponse>(`/apps/${appID}/workflows/publish`), + }) +} + export const useWorkflowConfig = (appId: string) => { return useQuery({ queryKey: [NAME_SPACE, 'config', appId], diff --git a/web/tailwind-common-config.ts b/web/tailwind-common-config.ts new file mode 100644 index 0000000000..72682b9864 --- /dev/null +++ b/web/tailwind-common-config.ts @@ -0,0 +1,113 @@ +import tailwindThemeVarDefine from './themes/tailwind-theme-var-define' + +const config = { + theme: { + typography: require('./typography'), + extend: { + colors: { + gray: { + 25: '#fcfcfd', + 50: '#f9fafb', + 100: '#f2f4f7', + 200: '#eaecf0', + 300: '#d0d5dd', + 400: '#98a2b3', + 500: '#667085', + 700: '#475467', + 600: '#344054', + 800: '#1d2939', + 900: '#101828', + }, + primary: { + 25: '#f5f8ff', + 50: '#eff4ff', + 100: '#d1e0ff', + 200: '#b2ccff', + 300: '#84adff', + 400: '#528bff', + 500: '#2970ff', + 600: '#155eef', + 700: '#004eeb', + 800: '#0040c1', + 900: '#00359e', + }, + blue: { + 500: '#E1EFFE', + }, + green: { + 50: '#F3FAF7', + 100: '#DEF7EC', + 800: '#03543F', + + }, + yellow: { + 100: '#FDF6B2', + 800: '#723B13', + }, + purple: { + 50: '#F6F5FF', + 200: '#DCD7FE', + }, + indigo: { + 25: '#F5F8FF', + 50: '#EEF4FF', + 100: '#E0EAFF', + 300: '#A4BCFD', + 400: '#8098F9', + 600: '#444CE7', + 800: '#2D31A6', + }, + ...tailwindThemeVarDefine, + }, + screens: { + mobile: '100px', + // => @media (min-width: 100px) { ... } + tablet: '640px', // 391 + // => @media (min-width: 600px) { ... } + pc: '769px', + // => @media (min-width: 769px) { ... } + '2k': '2560px', + }, + boxShadow: { + 'xs': '0px 1px 2px 0px rgba(16, 24, 40, 0.05)', + 'sm': '0px 1px 2px 0px rgba(16, 24, 40, 0.06), 0px 1px 3px 0px rgba(16, 24, 40, 0.10)', + 'md': '0px 2px 4px -2px rgba(16, 24, 40, 0.06), 0px 4px 8px -2px rgba(16, 24, 40, 0.10)', + 'lg': '0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)', + 'xl': '0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)', + '2xl': '0px 24px 48px -12px rgba(16, 24, 40, 0.18)', + '3xl': '0px 32px 64px -12px rgba(16, 24, 40, 0.14)', + }, + opacity: { + 2: '0.02', + 8: '0.08', + }, + fontSize: { + '2xs': '0.625rem', + }, + backgroundImage: { + 'chatbot-bg': 'var(--color-chatbot-bg)', + 'chat-bubble-bg': 'var(--color-chat-bubble-bg)', + 'workflow-process-bg': 'var(--color-workflow-process-bg)', + 'mask-top2bottom-gray-50-to-transparent': 'var(--mask-top2bottom-gray-50-to-transparent)', + 'marketplace-divider-bg': 'var(--color-marketplace-divider-bg)', + 'marketplace-plugin-empty': 'var(--color-marketplace-plugin-empty)', + 'toast-success-bg': 'var(--color-toast-success-bg)', + 'toast-warning-bg': 'var(--color-toast-warning-bg)', + 'toast-error-bg': 'var(--color-toast-error-bg)', + 'toast-info-bg': 'var(--color-toast-info-bg)', + }, + animation: { + 'spin-slow': 'spin 2s linear infinite', + }, + }, + }, + plugins: [ + require('@tailwindcss/typography'), + ], + // https://github.com/tailwindlabs/tailwindcss/discussions/5969 + corePlugins: { + preflight: false, + }, +} + +export default config diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 0da4968a7f..a9959e7b76 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -1,126 +1,12 @@ -import tailwindThemeVarDefine from './themes/tailwind-theme-var-define' - -/** @type {import('tailwindcss').Config} */ +// import type { Config } from 'tailwindcss' +import commonConfig from './tailwind-common-config' const config = { content: [ './app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}', './context/**/*.{js,ts,jsx,tsx}', ], - theme: { - typography: require('./typography'), - extend: { - colors: { - gray: { - 25: '#fcfcfd', - 50: '#f9fafb', - 100: '#f2f4f7', - 200: '#eaecf0', - 300: '#d0d5dd', - 400: '#98a2b3', - 500: '#667085', - 700: '#475467', - 600: '#344054', - 800: '#1d2939', - 900: '#101828', - }, - primary: { - 25: '#f5f8ff', - 50: '#eff4ff', - 100: '#d1e0ff', - 200: '#b2ccff', - 300: '#84adff', - 400: '#528bff', - 500: '#2970ff', - 600: '#155eef', - 700: '#004eeb', - 800: '#0040c1', - 900: '#00359e', - }, - blue: { - 500: '#E1EFFE', - }, - green: { - 50: '#F3FAF7', - 100: '#DEF7EC', - 800: '#03543F', - - }, - yellow: { - 100: '#FDF6B2', - 800: '#723B13', - }, - purple: { - 50: '#F6F5FF', - 200: '#DCD7FE', - }, - indigo: { - 25: '#F5F8FF', - 50: '#EEF4FF', - 100: '#E0EAFF', - 300: '#A4BCFD', - 400: '#8098F9', - 600: '#444CE7', - 800: '#2D31A6', - }, - ...tailwindThemeVarDefine, - }, - screens: { - 'mobile': '100px', - // => @media (min-width: 100px) { ... } - 'tablet': '640px', // 391 - // => @media (min-width: 600px) { ... } - 'pc': '769px', - // => @media (min-width: 769px) { ... } - '2k': '2560px', - }, - boxShadow: { - 'xs': '0px 1px 2px 0px rgba(16, 24, 40, 0.05)', - 'sm': '0px 1px 2px 0px rgba(16, 24, 40, 0.06), 0px 1px 3px 0px rgba(16, 24, 40, 0.10)', - 'md': '0px 2px 4px -2px rgba(16, 24, 40, 0.06), 0px 4px 8px -2px rgba(16, 24, 40, 0.10)', - 'lg': '0px 4px 6px -2px rgba(16, 24, 40, 0.03), 0px 12px 16px -4px rgba(16, 24, 40, 0.08)', - 'xl': '0px 8px 8px -4px rgba(16, 24, 40, 0.03), 0px 20px 24px -4px rgba(16, 24, 40, 0.08)', - '2xl': '0px 24px 48px -12px rgba(16, 24, 40, 0.18)', - '3xl': '0px 32px 64px -12px rgba(16, 24, 40, 0.14)', - 'status-indicator-green-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-success-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)', - 'status-indicator-warning-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-warning-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)', - 'status-indicator-red-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-error-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)', - 'status-indicator-blue-shadow': '0px 2px 6px 0px var(--color-components-badge-status-light-normal-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)', - 'status-indicator-gray-shadow': '0px 1px 2px 0px var(--color-components-badge-status-light-disabled-halo), 0px 0px 0px 1px var(--color-components-badge-status-light-border-outer)', - }, - opacity: { - 2: '0.02', - 8: '0.08', - }, - fontSize: { - '2xs': '0.625rem', - }, - backgroundImage: { - 'chatbot-bg': 'var(--color-chatbot-bg)', - 'chat-bubble-bg': 'var(--color-chat-bubble-bg)', - 'workflow-process-bg': 'var(--color-workflow-process-bg)', - 'dataset-chunk-process-success-bg': 'var(--color-dataset-chunk-process-success-bg)', - 'dataset-chunk-process-error-bg': 'var(--color-dataset-chunk-process-error-bg)', - 'dataset-chunk-detail-card-hover-bg': 'var(--color-dataset-chunk-detail-card-hover-bg)', - 'dataset-child-chunk-expand-btn-bg': 'var(--color-dataset-child-chunk-expand-btn-bg)', - 'dataset-option-card-blue-gradient': 'var(--color-dataset-option-card-blue-gradient)', - 'dataset-option-card-purple-gradient': 'var(--color-dataset-option-card-purple-gradient)', - 'dataset-option-card-orange-gradient': 'var(--color-dataset-option-card-orange-gradient)', - 'dataset-chunk-list-mask-bg': 'var(--color-dataset-chunk-list-mask-bg)', - }, - lineClamp: { - '20': '20', - 'mask-top2bottom-gray-50-to-transparent': 'var(--mask-top2bottom-gray-50-to-transparent)', - }, - }, - }, - plugins: [ - require('@tailwindcss/typography'), - ], - // https://github.com/tailwindlabs/tailwindcss/discussions/5969 - corePlugins: { - preflight: false, - }, + ...commonConfig, } export default config diff --git a/web/themes/dark.css b/web/themes/dark.css index 892f48fa48..dc24322bf5 100644 --- a/web/themes/dark.css +++ b/web/themes/dark.css @@ -721,6 +721,7 @@ html[data-theme="dark"] { --color-third-party-LangChain: #FFFFFF; --color-third-party-Langfuse: #FFFFFF; + --color-third-party-Github: #FFFFFF; --color-third-party-Github-tertiary: #C8CEDA99; --color-third-party-Github-secondary: #D9D9DE; diff --git a/web/themes/manual-dark.css b/web/themes/manual-dark.css index 6d4c5f3908..878ed68000 100644 --- a/web/themes/manual-dark.css +++ b/web/themes/manual-dark.css @@ -1,21 +1,31 @@ html[data-theme="dark"] { - --color-chatbot-bg: linear-gradient( - 180deg, - rgba(34, 34, 37, 0.9) 0%, - rgba(29, 29, 32, 0.9) 90.48% - ); - --color-chat-bubble-bg: linear-gradient( - 180deg, - rgba(200, 206, 218, 0.08) 0%, - rgba(200, 206, 218, 0.02) 100% - ); - --color-workflow-process-bg: linear-gradient( - 90deg, - rgba(24, 24, 27, 0.25) 0%, - rgba(24, 24, 27, 0.04) 100% - ); - --color-account-teams-bg: linear-gradient( - 271deg, + --color-chatbot-bg: linear-gradient(180deg, + rgba(34, 34, 37, 0.9) 0%, + rgba(29, 29, 32, 0.9) 90.48%); + --color-chat-bubble-bg: linear-gradient(180deg, + rgba(200, 206, 218, 0.08) 0%, + rgba(200, 206, 218, 0.02) 100%); + --color-workflow-process-bg: linear-gradient(90deg, + rgba(24, 24, 27, 0.25) 0%, + rgba(24, 24, 27, 0.04) 100%); + --color-marketplace-divider-bg: linear-gradient(90deg, + rgba(200, 206, 218, 0.14) 0%, + rgba(0, 0, 0, 0) 100%); + --color-marketplace-plugin-empty: linear-gradient(180deg, + rgba(0, 0, 0, 0) 0%, + #222225 100%); + --color-toast-success-bg: linear-gradient(92deg, + rgba(23, 178, 106, 0.3) 0%, + rgba(0, 0, 0, 0) 100%); + --color-toast-warning-bg: linear-gradient(92deg, + rgba(247, 144, 9, 0.3) 0%, + rgba(0, 0, 0, 0) 100%); + --color-toast-error-bg: linear-gradient(92deg, + rgba(240, 68, 56, 0.3) 0%, + rgba(0, 0, 0, 0) 100%); + --color-toast-info-bg: linear-gradient(92deg, + rgba(11, 165, 236, 0.3) 0%), + --color-account-teams-bg: linear-gradient(271deg, rgba(34, 34, 37, 0.9) -0.1%, rgba(29, 29, 32, 0.9) 98.26% ); @@ -30,6 +40,5 @@ html[data-theme="dark"] { --mask-top2bottom-gray-50-to-transparent: linear-gradient( 180deg, rgba(24, 24, 27, 0.08) 0%, - rgba(0, 0, 0, 0) 100% - ); -} + rgba(0, 0, 0, 0) 100%); +} \ No newline at end of file diff --git a/web/themes/manual-light.css b/web/themes/manual-light.css index 501f9f1d1f..f3840cee16 100644 --- a/web/themes/manual-light.css +++ b/web/themes/manual-light.css @@ -1,21 +1,31 @@ html[data-theme="light"] { - --color-chatbot-bg: linear-gradient( - 180deg, - rgba(249, 250, 251, 0.9) 0%, - rgba(242, 244, 247, 0.9) 90.48% - ); - --color-chat-bubble-bg: linear-gradient( - 180deg, - #fff 0%, - rgba(255, 255, 255, 0.6) 100% - ); - --color-workflow-process-bg: linear-gradient( - 90deg, - rgba(200, 206, 218, 0.2) 0%, - rgba(200, 206, 218, 0.04) 100% - ); - --color-account-teams-bg: linear-gradient( - 271deg, + --color-chatbot-bg: linear-gradient(180deg, + rgba(249, 250, 251, 0.9) 0%, + rgba(242, 244, 247, 0.9) 90.48%); + --color-chat-bubble-bg: linear-gradient(180deg, + #fff 0%, + rgba(255, 255, 255, 0.6) 100%); + --color-workflow-process-bg: linear-gradient(90deg, + rgba(200, 206, 218, 0.2) 0%, + rgba(200, 206, 218, 0.04) 100%); + --color-marketplace-divider-bg: linear-gradient(90deg, + rgba(16, 24, 40, 0.08) 0%, + rgba(255, 255, 255, 0) 100%); + --color-marketplace-plugin-empty: linear-gradient(180deg, + rgba(255, 255, 255, 0) 0%, + #fcfcfd 100%); + --color-toast-success-bg: linear-gradient(92deg, + rgba(23, 178, 106, 0.25) 0%, + rgba(255, 255, 255, 0) 100%); + --color-toast-warning-bg: linear-gradient(92deg, + rgba(247, 144, 9, 0.25) 0%, + rgba(255, 255, 255, 0) 100%); + --color-toast-error-bg: linear-gradient(92deg, + rgba(240, 68, 56, 0.25) 0%, + rgba(255, 255, 255, 0) 100%); + --color-toast-info-bg: linear-gradient(92deg, + rgba(11, 165, 236, 0.25) 0%), + --color-account-teams-bg: linear-gradient(271deg, rgba(249, 250, 251, 0.9) -0.1%, rgba(242, 244, 247, 0.9) 98.26% ); @@ -30,6 +40,5 @@ html[data-theme="light"] { --mask-top2bottom-gray-50-to-transparent: linear-gradient( 180deg, rgba(200, 206, 218, 0.2) 0%, - rgba(255, 255, 255, 0) 100% - ); -} + rgba(255, 255, 255, 0) 100%); +} \ No newline at end of file diff --git a/web/types/app.ts b/web/types/app.ts index 7be1d30b85..2f5f6254ff 100644 --- a/web/types/app.ts +++ b/web/types/app.ts @@ -25,14 +25,14 @@ export enum ProviderType { } export enum AppType { - 'chat' = 'chat', - 'completion' = 'completion', + chat = 'chat', + completion = 'completion', } export enum ModelModeType { - 'chat' = 'chat', - 'completion' = 'completion', - 'unset' = '', + chat = 'chat', + completion = 'completion', + unset = '', } export enum RETRIEVE_TYPE { @@ -110,9 +110,9 @@ export type ParagraphTypeFormItem = { export type UserInputFormItem = { 'text-input': TextTypeFormItem } | { - 'select': SelectTypeFormItem + select: SelectTypeFormItem } | { - 'paragraph': TextTypeFormItem + paragraph: TextTypeFormItem } export type AgentTool = { @@ -351,6 +351,13 @@ export type App = { /** api site url */ api_base_url: string tags: Tag[] + workflow?: { + id: string + created_at: number + created_by?: string + updated_at: number + updated_by?: string + } } export type AppSSO = { diff --git a/web/types/feature.ts b/web/types/feature.ts index 053ce3d7c9..3d7763bf46 100644 --- a/web/types/feature.ts +++ b/web/types/feature.ts @@ -24,6 +24,7 @@ export type SystemFeatures = { sso_enforced_for_web: boolean sso_enforced_for_web_protocol: SSOProtocol | '' enable_web_sso_switch_component: boolean + enable_marketplace: boolean enable_email_code_login: boolean enable_email_password_login: boolean enable_social_oauth_login: boolean @@ -39,6 +40,7 @@ export const defaultSystemFeatures: SystemFeatures = { sso_enforced_for_web: false, sso_enforced_for_web_protocol: '', enable_web_sso_switch_component: false, + enable_marketplace: false, enable_email_code_login: false, enable_email_password_login: false, enable_social_oauth_login: false, diff --git a/web/types/workflow.ts b/web/types/workflow.ts index ee0c1c6454..31ea759582 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -3,11 +3,33 @@ import type { BlockEnum, ConversationVariable, Edge, EnvironmentVariable, Node } import type { TransferMethod } from '@/types/app' import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' +export type AgentLogItem = { + node_execution_id: string, + id: string, + node_id: string, + parent_id?: string, + label: string, + data: object, // debug data + error?: string, + status: string, + metadata?: { + elapsed_time?: number + provider?: string + icon?: string + }, +} + +export type AgentLogItemWithChildren = AgentLogItem & { + hasCircle?: boolean + children: AgentLogItemWithChildren[] +} + export type NodeTracing = { id: string index: number predecessor_node_id: string node_id: string + iteration_id?: string node_type: BlockEnum title: string inputs: any @@ -30,6 +52,11 @@ export type NodeTracing = { parallel_mode_run_id?: string iteration_duration_map?: IterationDurationMap error_strategy?: ErrorHandleTypeEnum + agent_log?: AgentLogItem[] + tool_info?: { + agent_strategy?: string + icon?: string + } } metadata: { iterator_length: number @@ -47,11 +74,18 @@ export type NodeTracing = { expand?: boolean // for UI details?: NodeTracing[][] // iteration detail retryDetail?: NodeTracing[] // retry detail + retry_index?: number + parallelDetail?: { // parallel detail. if is in parallel, this field will be set + isParallelStartNode?: boolean + parallelTitle?: string + branchTitle?: string + children?: NodeTracing[] + } parallel_id?: string parallel_start_node_id?: string parent_parallel_id?: string parent_parallel_start_node_id?: string - retry_index?: number + agentLog?: AgentLogItemWithChildren[] // agent log } export type FetchWorkflowDraftResponse = { @@ -128,18 +162,7 @@ export type NodeStartedResponse = { task_id: string workflow_run_id: string event: string - data: { - id: string - node_id: string - iteration_id?: string - parallel_run_id?: string - node_type: string - index: number - predecessor_node_id?: string - inputs: any - created_at: number - extras?: any - } + data: NodeTracing } export type FileResponse = { @@ -157,120 +180,42 @@ export type NodeFinishedResponse = { task_id: string workflow_run_id: string event: string - data: { - id: string - node_id: string - iteration_id?: string - node_type: string - index: number - predecessor_node_id?: string - inputs: any - process_data: any - outputs: any - status: string - error: string - elapsed_time: number - execution_metadata: { - total_tokens: number - total_price: number - currency: string - parallel_id?: string - parallel_start_node_id?: string - iteration_index?: number - iteration_id?: string - parallel_mode_run_id: string - error_strategy?: ErrorHandleTypeEnum - } - created_at: number - files?: FileResponse[] - retry_index?: number - } + data: NodeTracing } export type IterationStartedResponse = { task_id: string workflow_run_id: string event: string - data: { - id: string - node_id: string - metadata: { - iterator_length: number - iteration_id: string - iteration_index: number - } - created_at: number - extras?: any - } + data: NodeTracing } export type IterationNextResponse = { task_id: string workflow_run_id: string event: string - data: { - id: string - node_id: string - index: number - output: any - extras?: any - created_at: number - parallel_mode_run_id: string - execution_metadata: { - parallel_id?: string - iteration_index: number - parallel_mode_run_id?: string - } - duration?: number - } + data: NodeTracing } export type IterationFinishedResponse = { task_id: string workflow_run_id: string event: string - data: { - id: string - node_id: string - outputs: any - extras?: any - status: string - created_at: number - error: string - execution_metadata: { - parallel_id?: string - } - } + data: NodeTracing } export type ParallelBranchStartedResponse = { task_id: string workflow_run_id: string event: string - data: { - parallel_id: string - parallel_start_node_id: string - parent_parallel_id: string - parent_parallel_start_node_id: string - iteration_id?: string - created_at: number - } + data: NodeTracing } export type ParallelBranchFinishedResponse = { task_id: string workflow_run_id: string event: string - data: { - parallel_id: string - parallel_start_node_id: string - parent_parallel_id: string - parent_parallel_start_node_id: string - iteration_id?: string - status: string - created_at: number - error: string - } + data: NodeTracing } export type TextChunkResponse = { @@ -291,6 +236,12 @@ export type TextReplaceResponse = { } } +export type AgentLogResponse = { + task_id: string + event: string + data: AgentLogItemWithChildren +} + export type WorkflowRunHistory = { id: string sequence_number: number diff --git a/web/utils/format.ts b/web/utils/format.ts index 1eeb6af807..45f0e51878 100644 --- a/web/utils/format.ts +++ b/web/utils/format.ts @@ -34,3 +34,14 @@ export const formatTime = (num: number) => { } return `${num.toFixed(2)} ${units[index]}` } + +export const downloadFile = ({ data, fileName }: { data: Blob; fileName: string }) => { + const url = window.URL.createObjectURL(data) + const a = document.createElement('a') + a.href = url + a.download = fileName + document.body.appendChild(a) + a.click() + a.remove() + window.URL.revokeObjectURL(url) +} diff --git a/web/utils/get-icon.ts b/web/utils/get-icon.ts new file mode 100644 index 0000000000..f2ed116a14 --- /dev/null +++ b/web/utils/get-icon.ts @@ -0,0 +1,5 @@ +import { MARKETPLACE_API_PREFIX } from '@/config' + +export const getIconFromMarketPlace = (plugin_id: string) => { + return `${MARKETPLACE_API_PREFIX}/plugins/${plugin_id}/icon` +} diff --git a/web/utils/index.ts b/web/utils/index.ts index cabad6c35c..4342a08519 100644 --- a/web/utils/index.ts +++ b/web/utils/index.ts @@ -55,3 +55,13 @@ export async function fetchWithRetry<T = any>(fn: Promise<T>, retries = 3): Prom return [null, res] } } + +export const correctProvider = (provider: string) => { + if (!provider) + return '' + + if (provider.includes('/')) + return provider + + return `langgenius/${provider}/${provider}` +} diff --git a/web/utils/semver.ts b/web/utils/semver.ts new file mode 100644 index 0000000000..f1b9eb8d7e --- /dev/null +++ b/web/utils/semver.ts @@ -0,0 +1,9 @@ +import semver from 'semver' + +export const getLatestVersion = (versionList: string[]) => { + return semver.rsort(versionList)[0] +} + +export const compareVersion = (v1: string, v2: string) => { + return semver.compare(v1, v2) +} diff --git a/web/yarn.lock b/web/yarn.lock index 339f47c236..7e01efac97 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -20,65 +20,46 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@antfu/eslint-config-basic@0.36.0": - version "0.36.0" - resolved "https://registry.npmjs.org/@antfu/eslint-config-basic/-/eslint-config-basic-0.36.0.tgz" - integrity sha512-2b3ZB7pO00nxAERDXo82iYPjLQ4l/AOMm0CTKmGmqWbN3RB33EIQWzYheZRboSbAVzWpI1/3rg/Gu+7xYVMYHA== +"@antfu/eslint-config@^3.8.0": + version "3.12.1" + resolved "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.12.1.tgz" + integrity sha512-6sRgO4u63GK75xeZ2MfCSRT9GcfLti4ZN3Xw+bIu39oo6HY50fBY+rXnWvgwNimzHBOh3yV5xUHfTqcHq1M5AA== dependencies: - eslint-plugin-antfu "0.36.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-html "^7.1.0" - eslint-plugin-import "^2.27.5" - eslint-plugin-jsonc "^2.6.0" - eslint-plugin-markdown "^3.0.0" - eslint-plugin-n "^15.6.1" - eslint-plugin-no-only-tests "^3.1.0" - eslint-plugin-promise "^6.1.1" - eslint-plugin-unicorn "^45.0.2" - eslint-plugin-unused-imports "^2.0.0" - eslint-plugin-yml "^1.5.0" - jsonc-eslint-parser "^2.1.0" - yaml-eslint-parser "^1.1.0" - -"@antfu/eslint-config-ts@0.36.0": - version "0.36.0" - resolved "https://registry.npmjs.org/@antfu/eslint-config-ts/-/eslint-config-ts-0.36.0.tgz" - integrity sha512-I/h2ZOPBIqgnALG2fQp6lOBsOXk51QwLDumyEayt7GRnitdP4o9D8i+YAPowrMJ8M3kU7puQUyhWuJmZLgo57A== - dependencies: - "@antfu/eslint-config-basic" "0.36.0" - "@typescript-eslint/eslint-plugin" "^5.53.0" - "@typescript-eslint/parser" "^5.53.0" - eslint-plugin-jest "^27.2.1" - -"@antfu/eslint-config-vue@0.36.0": - version "0.36.0" - resolved "https://registry.npmjs.org/@antfu/eslint-config-vue/-/eslint-config-vue-0.36.0.tgz" - integrity sha512-YuTcNlVlrEWX1ESOiPgr+e2Walfd6xt3Toa0kAKJxq2aBS1RWqIi1l3zIVGCHaX72lOrSXNmQ7bryaZyGADGDg== - dependencies: - "@antfu/eslint-config-basic" "0.36.0" - "@antfu/eslint-config-ts" "0.36.0" - eslint-plugin-vue "^9.9.0" - local-pkg "^0.4.3" - -"@antfu/eslint-config@^0.36.0": - version "0.36.0" - resolved "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-0.36.0.tgz" - integrity sha512-otZ9PfKRT3gnGMMX1gS8URTNPMPCZ69K5jHZvLkYojru0gLBZ3IO5fCvjEZpWqOyIUHtAgg6NWELf1DbEF+NDw== - dependencies: - "@antfu/eslint-config-vue" "0.36.0" - "@typescript-eslint/eslint-plugin" "^5.53.0" - "@typescript-eslint/parser" "^5.53.0" - eslint-plugin-eslint-comments "^3.2.0" - eslint-plugin-html "^7.1.0" - eslint-plugin-import "^2.27.5" - eslint-plugin-jsonc "^2.6.0" - eslint-plugin-n "^15.6.1" - eslint-plugin-promise "^6.1.1" - eslint-plugin-unicorn "^45.0.2" - eslint-plugin-vue "^9.9.0" - eslint-plugin-yml "^1.5.0" - jsonc-eslint-parser "^2.1.0" - yaml-eslint-parser "^1.1.0" + "@antfu/install-pkg" "^0.5.0" + "@clack/prompts" "^0.9.0" + "@eslint-community/eslint-plugin-eslint-comments" "^4.4.1" + "@eslint/markdown" "^6.2.1" + "@stylistic/eslint-plugin" "^2.12.1" + "@typescript-eslint/eslint-plugin" "^8.18.2" + "@typescript-eslint/parser" "^8.18.2" + "@vitest/eslint-plugin" "^1.1.20" + eslint-config-flat-gitignore "^0.3.0" + eslint-flat-config-utils "^0.4.0" + eslint-merge-processors "^0.1.0" + eslint-plugin-antfu "^2.7.0" + eslint-plugin-command "^0.2.7" + eslint-plugin-import-x "^4.6.1" + eslint-plugin-jsdoc "^50.6.1" + eslint-plugin-jsonc "^2.18.2" + eslint-plugin-n "^17.15.1" + eslint-plugin-no-only-tests "^3.3.0" + eslint-plugin-perfectionist "^4.4.0" + eslint-plugin-regexp "^2.7.0" + eslint-plugin-toml "^0.12.0" + eslint-plugin-unicorn "^56.0.1" + eslint-plugin-unused-imports "^4.1.4" + eslint-plugin-vue "^9.32.0" + eslint-plugin-yml "^1.16.0" + eslint-processor-vue-blocks "^0.1.2" + globals "^15.14.0" + jsonc-eslint-parser "^2.4.0" + local-pkg "^0.5.1" + parse-gitignore "^2.0.0" + picocolors "^1.1.1" + toml-eslint-parser "^0.10.0" + vue-eslint-parser "^9.4.3" + yaml-eslint-parser "^1.2.3" + yargs "^17.7.2" "@antfu/install-pkg@^0.4.1": version "0.4.1" @@ -88,6 +69,14 @@ package-manager-detector "^0.2.0" tinyexec "^0.3.0" +"@antfu/install-pkg@^0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.5.0.tgz" + integrity sha512-dKnk2xlAyC7rvTkpkHmu+Qy/2Zc3Vm/l8PtNyIOGDBtXPY3kThfU4ORNEp3V7SXw5XSOb+tOJaUYpfquPzL/Tg== + dependencies: + package-manager-detector "^0.2.5" + tinyexec "^0.3.1" + "@antfu/utils@^0.7.10": version "0.7.10" resolved "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz" @@ -107,7 +96,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz" integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.18.9", "@babel/core@^7.23.9", "@babel/core@^7.24.4": +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.18.9", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0": version "7.25.2" resolved "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz" integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== @@ -274,7 +263,7 @@ resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== -"@babel/helper-validator-identifier@^7.19.1", "@babel/helper-validator-identifier@^7.25.9": +"@babel/helper-validator-identifier@^7.24.7", "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== @@ -1031,7 +1020,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.25.9" "@babel/plugin-transform-typescript" "^7.25.9" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.11.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.6", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.21.5", "@babel/runtime@^7.22.3", "@babel/runtime@^7.24.4", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.11.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.4", "@babel/runtime@^7.25.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.8.4": version "7.26.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -1110,17 +1099,34 @@ resolved "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz" integrity sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ== -"@chromatic-com/storybook@^1.9.0": - version "1.9.0" - resolved "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.9.0.tgz" - integrity sha512-vYQ+TcfktEE3GHnLZXHCzXF/sN9dw+KivH8a5cmPyd9YtQs7fZtHrEgsIjWpYycXiweKMo1Lm1RZsjxk8DH3rA== +"@chromatic-com/storybook@^3.1.0": + version "3.2.3" + resolved "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-3.2.3.tgz" + integrity sha512-3+hfANx79kIjP1qrOSLxpoAXOiYUA0S7A0WI0A24kASrv7USFNNW8etR5TjUilMb0LmqKUn3wDwUK2h6aceQ9g== dependencies: - chromatic "^11.4.0" + chromatic "^11.15.0" filesize "^10.0.12" jsonfile "^6.1.0" react-confetti "^6.1.0" strip-ansi "^7.1.0" +"@clack/core@0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@clack/core/-/core-0.4.0.tgz" + integrity sha512-YJCYBsyJfNDaTbvDUVSJ3SgSuPrcujarRgkJ5NLjexDZKvaOiVVJvAQYx8lIgG0qRT8ff0fPgqyBCVivanIZ+A== + dependencies: + picocolors "^1.0.0" + sisteransi "^1.0.5" + +"@clack/prompts@^0.9.0": + version "0.9.0" + resolved "https://registry.npmjs.org/@clack/prompts/-/prompts-0.9.0.tgz" + integrity sha512-nGsytiExgUr4FL0pR/LeqxA28nz3E0cW7eLTSh3Iod9TGrbBt8Y7BHbV3mmkNC4G0evdYyQ3ZsbiBkk7ektArA== + dependencies: + "@clack/core" "0.4.0" + picocolors "^1.0.0" + sisteransi "^1.0.5" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" @@ -1128,193 +1134,247 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@dagrejs/dagre@^1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.2.tgz" - integrity sha512-F09dphqvHsbe/6C2t2unbmpr5q41BNPEfJCdn8Z7aEBpVSy/zFQ/b4SWsweQjWNsYMDvE2ffNUN8X0CeFsEGNw== +"@dagrejs/dagre@^1.1.4": + version "1.1.4" + resolved "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.4.tgz" + integrity sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg== dependencies: - "@dagrejs/graphlib" "2.2.2" + "@dagrejs/graphlib" "2.2.4" -"@dagrejs/graphlib@2.2.2": - version "2.2.2" - resolved "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.2.tgz" - integrity sha512-CbyGpCDKsiTg/wuk79S7Muoj8mghDGAESWGxcSyhHX5jD35vYMBZochYVFzlHxynpE9unpu6O+4ZuhrLxASsOg== +"@dagrejs/graphlib@2.2.4": + version "2.2.4" + resolved "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.4.tgz" + integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== -"@emnapi/runtime@^1.2.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" - integrity sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw== +"@emoji-mart/data@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz" + integrity sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw== + +"@es-joy/jsdoccomment@^0.49.0", "@es-joy/jsdoccomment@~0.49.0": + version "0.49.0" + resolved "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz" + integrity sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q== dependencies: - tslib "^2.4.0" - -"@emoji-mart/data@^1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@emoji-mart/data/-/data-1.1.2.tgz" - integrity sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg== - -"@esbuild/aix-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" - integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== - -"@esbuild/android-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" - integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== - -"@esbuild/android-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" - integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== - -"@esbuild/android-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" - integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== + comment-parser "1.4.1" + esquery "^1.6.0" + jsdoc-type-pratt-parser "~4.1.0" "@esbuild/darwin-arm64@0.24.0": version "0.24.0" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz" integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== -"@esbuild/darwin-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" - integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== - -"@esbuild/freebsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" - integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== - -"@esbuild/freebsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" - integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== - -"@esbuild/linux-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" - integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== - -"@esbuild/linux-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" - integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== - -"@esbuild/linux-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" - integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== - -"@esbuild/linux-loong64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" - integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== - -"@esbuild/linux-mips64el@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" - integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== - -"@esbuild/linux-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" - integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== - -"@esbuild/linux-riscv64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" - integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== - -"@esbuild/linux-s390x@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" - integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== - -"@esbuild/linux-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" - integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== - -"@esbuild/netbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" - integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== - -"@esbuild/openbsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" - integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== - -"@esbuild/openbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" - integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== - -"@esbuild/sunos-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" - integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== - -"@esbuild/win32-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" - integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== - -"@esbuild/win32-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" - integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== - -"@esbuild/win32-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" - integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== - -"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.3.0": - version "4.4.0" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== +"@eslint-community/eslint-plugin-eslint-comments@^4.4.1": + version "4.4.1" + resolved "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.4.1.tgz" + integrity sha512-lb/Z/MzbTf7CaVYM9WCFNQZ4L1yi3ev2fsFPF99h31ljhSEyUoyEsKsNWiU+qD1glbYTDJdqgyaLKtyTkkqtuQ== dependencies: - eslint-visitor-keys "^3.3.0" + escape-string-regexp "^4.0.0" + ignore "^5.2.4" -"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.4.1": + version "4.4.1" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.8.0": version "4.12.1" resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint-react/ast@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/ast/-/ast-1.22.1.tgz" + integrity sha512-uk44JH5RB9JytQqiHSPu89MAFlyvJ0AaSZIfQBJijjh08lswwvHOAiWLbl0iPzm7prrV4Lo3pjC3RwbVSZd+CA== + dependencies: + "@eslint-react/eff" "1.22.1" + "@eslint-react/types" "1.22.1" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/typescript-estree" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + birecord "^0.1.1" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +"@eslint-react/core@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/core/-/core-1.22.1.tgz" + integrity sha512-mzivc7X+uk19AKg+vy3EsyJoFGrhFjSCRPq1bgFDsovw67OxWP9qHNa265VIiqmRjk0iviaRmcar5tQBWhX41A== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + birecord "^0.1.1" + short-unique-id "^5.2.0" + ts-pattern "^5.6.0" + +"@eslint-react/eff@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/eff/-/eff-1.22.1.tgz" + integrity sha512-aUu5vvw9m/mv0SToTLkObdY7h6S53q673bdXiUBjwNPgIOPrfl7VBnv2dXnqd4cdVvk5e077yPKI/mwl9Vsllg== + +"@eslint-react/eslint-plugin@^1.15.0", "@eslint-react/eslint-plugin@^1.19.0": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/eslint-plugin/-/eslint-plugin-1.22.1.tgz" + integrity sha512-/+9crS1VpZk00S/oXrJG2h8BYxSB5PwGcPi8OgAXHU6TEICC/9EVqOgeRfNz+cyOLxN+Oq31+dlZA3YSN2rKsg== + dependencies: + "@eslint-react/eff" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + eslint-plugin-react-debug "1.22.1" + eslint-plugin-react-dom "1.22.1" + eslint-plugin-react-hooks-extra "1.22.1" + eslint-plugin-react-naming-convention "1.22.1" + eslint-plugin-react-web-api "1.22.1" + eslint-plugin-react-x "1.22.1" + +"@eslint-react/jsx@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/jsx/-/jsx-1.22.1.tgz" + integrity sha512-da49BHH28yAc1l5Nnf30v0G/crJN2ovz0afRfMl2dAxkZTQmp5VeiddojEbKA3lPgnaIrfrvG4UA43EITXX5ow== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + birecord "^0.1.1" + ts-pattern "^5.6.0" + +"@eslint-react/shared@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/shared/-/shared-1.22.1.tgz" + integrity sha512-nRzgOk0+fMHb1C02p4ue9Sfijkx5AVU8WL0w0V5Mk9+d4fUpxHJu12eahbwgTaLGaX5TP3KWzIfA1q1HNigPUg== + dependencies: + "@eslint-react/eff" "1.22.1" + "@typescript-eslint/utils" "^8.18.2" + fast-equals "^5.0.1" + micro-memoize "^4.1.2" + picomatch "^4.0.2" + ts-pattern "^5.6.0" + valibot "^1.0.0-beta.9" + +"@eslint-react/types@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/types/-/types-1.22.1.tgz" + integrity sha512-uLl4aDLDYzR7XTqFyUooZDocmX3Dy/3ANQDiyLVXFy055MyRhti9QjdbI+wAlkmynZiOE7oVoRtwR9JgSus/uw== + dependencies: + "@eslint-react/eff" "1.22.1" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + +"@eslint-react/var@1.22.1": + version "1.22.1" + resolved "https://registry.npmjs.org/@eslint-react/var/-/var-1.22.1.tgz" + integrity sha512-QzkS1c6XrKq8Dl6llObmIBL5KKAJZUOsugFogXwLBav1a9tf76Fc/ozqEutP4hwoOWtTWhlQR3guhwVrMHTBcA== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/types" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +"@eslint/compat@^1.1.1": + version "1.2.4" + resolved "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.4.tgz" + integrity sha512-S8ZdQj/N69YAtuqFt7653jwcvuUj131+6qGLUyDqfDg1OIoBQ66OCuXC473YQfO2AaxITTutiRQiDwoo7ZLYyg== + +"@eslint/config-array@^0.19.0": + version "0.19.1" + resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz" + integrity sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA== + dependencies: + "@eslint/object-schema" "^2.1.5" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.9.0": + version "0.9.1" + resolved "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz" + integrity sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.1.0", "@eslint/eslintrc@^3.2.0": + version "3.2.0" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.1": - version "8.57.1" - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz" - integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@eslint/js@^9.13.0", "@eslint/js@9.17.0": + version "9.17.0" + resolved "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz" + integrity sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w== -"@faker-js/faker@^7.6.0": - version "7.6.0" - resolved "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz" - integrity sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw== - -"@floating-ui/core@^1.1.0", "@floating-ui/core@^1.4.1": - version "1.4.1" - resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz" - integrity sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ== +"@eslint/markdown@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.1.tgz" + integrity sha512-cKVd110hG4ICHmWhIwZJfKmmJBvbiDWyrHODJknAtudKgZtlROGoLX9UEOA0o746zC0hCY4UV4vR+aOGW9S6JQ== dependencies: - "@floating-ui/utils" "^0.1.1" + "@eslint/plugin-kit" "^0.2.0" + mdast-util-from-markdown "^2.0.1" + mdast-util-gfm "^3.0.0" + micromark-extension-gfm "^3.0.0" + +"@eslint/object-schema@^2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz" + integrity sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ== + +"@eslint/plugin-kit@^0.2.0", "@eslint/plugin-kit@^0.2.3": + version "0.2.4" + resolved "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz" + integrity sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg== + dependencies: + levn "^0.4.1" + +"@faker-js/faker@^9.0.3": + version "9.3.0" + resolved "https://registry.npmjs.org/@faker-js/faker/-/faker-9.3.0.tgz" + integrity sha512-r0tJ3ZOkMd9xsu3VRfqlFR6cz0V/jFYRswAIpC+m/DIfAUXq7g8N7wTAlhSANySXYGKzGryfDXwtwsY8TxEIDw== + +"@floating-ui/core@^1.1.0", "@floating-ui/core@^1.6.0": + version "1.6.8" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz" + integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA== + dependencies: + "@floating-ui/utils" "^0.2.8" + +"@floating-ui/dom@^1.0.0": + version "1.6.12" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz" + integrity sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.8" "@floating-ui/dom@1.1.1": version "1.1.1" @@ -1323,41 +1383,33 @@ dependencies: "@floating-ui/core" "^1.1.0" -"@floating-ui/dom@^1.5.1": - version "1.5.1" - resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz" - integrity sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw== +"@floating-ui/react-dom@^2.1.2": + version "2.1.2" + resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== dependencies: - "@floating-ui/core" "^1.4.1" - "@floating-ui/utils" "^0.1.1" + "@floating-ui/dom" "^1.0.0" -"@floating-ui/react-dom@^2.0.1": - version "2.0.2" - resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz" - integrity sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ== +"@floating-ui/react@^0.26.25": + version "0.26.28" + resolved "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz" + integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== dependencies: - "@floating-ui/dom" "^1.5.1" + "@floating-ui/react-dom" "^2.1.2" + "@floating-ui/utils" "^0.2.8" + tabbable "^6.0.0" -"@floating-ui/react@^0.25.2": - version "0.25.2" - resolved "https://registry.npmjs.org/@floating-ui/react/-/react-0.25.2.tgz" - integrity sha512-3e10G9LFOgl32/SMWLBOwT7oVCtB+d5zBsU2GxTSVOvRgZexwno5MlYbc0BaXr+TR5EEGpqe9tg9OUbjlrVRnQ== +"@floating-ui/utils@^0.2.8": + version "0.2.8" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz" + integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig== + +"@formatjs/intl-localematcher@^0.5.6": + version "0.5.9" + resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.9.tgz" + integrity sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA== dependencies: - "@floating-ui/react-dom" "^2.0.1" - "@floating-ui/utils" "^0.1.1" - tabbable "^6.0.1" - -"@floating-ui/utils@^0.1.1": - version "0.1.1" - resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz" - integrity sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw== - -"@formatjs/intl-localematcher@^0.5.4": - version "0.5.4" - resolved "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz" - integrity sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g== - dependencies: - tslib "^2.4.0" + tslib "2" "@headlessui/react@^1.7.13": version "1.7.15" @@ -1371,29 +1423,38 @@ resolved "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz" integrity sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw== -"@hookform/resolvers@^3.3.4": - version "3.4.2" - resolved "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.4.2.tgz" - integrity sha512-1m9uAVIO8wVf7VCDAGsuGA0t6Z3m6jVGAN50HkV9vYLl0yixKK/Z1lr01vaRvYCkIKGoy1noVRxMzQYb4y/j1Q== +"@hookform/resolvers@^3.9.0": + version "3.9.1" + resolved "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.1.tgz" + integrity sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug== -"@humanwhocodes/config-array@^0.13.0": - version "0.13.0" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz" - integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== dependencies: - "@humanwhocodes/object-schema" "^2.0.3" - debug "^4.3.1" - minimatch "^3.0.5" + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.3": - version "2.0.3" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.1": + version "0.4.1" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz" + integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== "@iconify/types@^2.0.0": version "2.0.0" @@ -1421,111 +1482,22 @@ optionalDependencies: "@img/sharp-libvips-darwin-arm64" "1.0.4" -"@img/sharp-darwin-x64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz#e03d3451cd9e664faa72948cc70a403ea4063d61" - integrity sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q== - optionalDependencies: - "@img/sharp-libvips-darwin-x64" "1.0.4" - "@img/sharp-libvips-darwin-arm64@1.0.4": version "1.0.4" resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz" integrity sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg== -"@img/sharp-libvips-darwin-x64@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz#e0456f8f7c623f9dbfbdc77383caa72281d86062" - integrity sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ== - -"@img/sharp-libvips-linux-arm64@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz#979b1c66c9a91f7ff2893556ef267f90ebe51704" - integrity sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA== - -"@img/sharp-libvips-linux-arm@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz#99f922d4e15216ec205dcb6891b721bfd2884197" - integrity sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g== - -"@img/sharp-libvips-linux-s390x@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz#f8a5eb1f374a082f72b3f45e2fb25b8118a8a5ce" - integrity sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA== - -"@img/sharp-libvips-linux-x64@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz#d4c4619cdd157774906e15770ee119931c7ef5e0" - integrity sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw== - -"@img/sharp-libvips-linuxmusl-arm64@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz#166778da0f48dd2bded1fa3033cee6b588f0d5d5" - integrity sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA== - -"@img/sharp-libvips-linuxmusl-x64@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz#93794e4d7720b077fcad3e02982f2f1c246751ff" - integrity sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw== - -"@img/sharp-linux-arm64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz#edb0697e7a8279c9fc829a60fc35644c4839bb22" - integrity sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA== - optionalDependencies: - "@img/sharp-libvips-linux-arm64" "1.0.4" - -"@img/sharp-linux-arm@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz#422c1a352e7b5832842577dc51602bcd5b6f5eff" - integrity sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ== - optionalDependencies: - "@img/sharp-libvips-linux-arm" "1.0.5" - -"@img/sharp-linux-s390x@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz#f5c077926b48e97e4a04d004dfaf175972059667" - integrity sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q== - optionalDependencies: - "@img/sharp-libvips-linux-s390x" "1.0.4" - -"@img/sharp-linux-x64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz#d806e0afd71ae6775cc87f0da8f2d03a7c2209cb" - integrity sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA== - optionalDependencies: - "@img/sharp-libvips-linux-x64" "1.0.4" - -"@img/sharp-linuxmusl-arm64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz#252975b915894fb315af5deea174651e208d3d6b" - integrity sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g== - optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64" "1.0.4" - -"@img/sharp-linuxmusl-x64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz#3f4609ac5d8ef8ec7dadee80b560961a60fd4f48" - integrity sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw== - optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64" "1.0.4" - -"@img/sharp-wasm32@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz#6f44f3283069d935bb5ca5813153572f3e6f61a1" - integrity sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== dependencies: - "@emnapi/runtime" "^1.2.0" - -"@img/sharp-win32-ia32@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz#1a0c839a40c5351e9885628c85f2e5dfd02b52a9" - integrity sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ== - -"@img/sharp-win32-x64@0.33.5": - version "0.33.5" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342" - integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg== + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1767,14 +1739,6 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.9": version "0.3.25" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" @@ -1783,262 +1747,256 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@lexical/clipboard@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.16.1.tgz" - integrity sha512-0dWs/SwKS5KPpuf6fUVVt9vSCl6HAqcDGhSITw/okv0rrIlXTUT6WhVsMJtXfFxTyVvwMeOecJHvQH3i/jRQtA== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: - "@lexical/html" "0.16.1" - "@lexical/list" "0.16.1" - "@lexical/selection" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" -"@lexical/code@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/code/-/code-0.16.1.tgz" - integrity sha512-pOC28rRZ2XkmI2nIJm50DbKaCJtk5D0o7r6nORYp4i0z+lxt5Sf2m82DL9ksUHJRqKy87pwJDpoWvJ2SAI0ohw== +"@lexical/clipboard@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.18.0.tgz" + integrity sha512-ybc+hx14wj0n2ZjdOkLcZ02MRB3UprXjpLDXlByFIuVcZpUxVcp3NzA0UBPOKXYKvdt0bmgjnAsFWM5OSbwS0w== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/html" "0.18.0" + "@lexical/list" "0.18.0" + "@lexical/selection" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" + +"@lexical/code@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/code/-/code-0.18.0.tgz" + integrity sha512-VB8fRHIrB8QTqyZUvGBMVWP2tpKe3ArOjPdWAqgrS8MVFldqUhuTHcW+XJFkVxcEBYCXynNT29YRYtQhfQ+vDQ== + dependencies: + "@lexical/utils" "0.18.0" + lexical "0.18.0" prismjs "^1.27.0" -"@lexical/devtools-core@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/devtools-core/-/devtools-core-0.16.1.tgz" - integrity sha512-8CvGERGL7ySDVGLU+YPeq+JupIXsOFlXa3EuJ88koLKqXxYenwMleZgGqayFp6lCP78xqPKnATVeoOZUt/NabQ== +"@lexical/devtools-core@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/devtools-core/-/devtools-core-0.18.0.tgz" + integrity sha512-gVgtEkLwGjz1frOmDpFJzDPFxPgAcC9n5ZaaZWHo5GLcptnQmkuLm1t+UInQWujXhFmcyJzfiqDaMJ8EIcb2Ww== dependencies: - "@lexical/html" "0.16.1" - "@lexical/link" "0.16.1" - "@lexical/mark" "0.16.1" - "@lexical/table" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/html" "0.18.0" + "@lexical/link" "0.18.0" + "@lexical/mark" "0.18.0" + "@lexical/table" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/dragon@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/dragon/-/dragon-0.16.1.tgz" - integrity sha512-Rvd60GIYN5kpjjBumS34EnNbBaNsoseI0AlzOdtIV302jiHPCLH0noe9kxzu9nZy+MZmjZy8Dx2zTbQT2mueRw== +"@lexical/dragon@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/dragon/-/dragon-0.18.0.tgz" + integrity sha512-toD/y2/TgtG+eFVKXf65kDk/Mv02FwgmcGH18nyAabZnO1TLBaMYPkGFdTTZ8hVmQxqIu9nZuLWUbdIBMs8UWw== dependencies: - lexical "0.16.1" + lexical "0.18.0" -"@lexical/hashtag@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/hashtag/-/hashtag-0.16.1.tgz" - integrity sha512-G+YOxStAKs3q1utqm9KR4D4lCkwIH52Rctm4RgaVTI+4lvTaybeDRGFV75P/pI/qlF7/FvAYHTYEzCjtC3GNMQ== +"@lexical/hashtag@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/hashtag/-/hashtag-0.18.0.tgz" + integrity sha512-bm+Sv7keguVYbUY0ngd+iAv2Owd3dePzdVkzkmw9Al8GPXkE5ll8fjq6Xjw2u3OVhf+9pTnesIo/AS7H+h0exw== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/history@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/history/-/history-0.16.1.tgz" - integrity sha512-WQhScx0TJeKSQAnEkRpIaWdUXqirrNrom2MxbBUc/32zEUMm9FzV7nRGknvUabEFUo7vZq6xTZpOExQJqHInQA== +"@lexical/history@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/history/-/history-0.18.0.tgz" + integrity sha512-c87J4ke1Sae03coElJay2Ikac/4OcA2OmhtNbt2gAi/XBtcsP4mPuz1yZfZf9XIe+weekObgjinvZekQ2AFw0g== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/html@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/html/-/html-0.16.1.tgz" - integrity sha512-vbtAdCvQ3PaAqa5mFmtmrvbiAvjCu1iXBAJ0bsHqFXCF2Sba5LwHVe8dUAOTpfEZEMbiHfjul6b5fj4vNPGF2A== +"@lexical/html@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/html/-/html-0.18.0.tgz" + integrity sha512-8lhba1DFnnobXgYm4Rk5Gr2tZedD4Gl6A/NKCt7whO/CET63vT3UnK2ggcVVgtIJG530Cv0bdZoJbJu5DauI5w== dependencies: - "@lexical/selection" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/selection" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/link@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/link/-/link-0.16.1.tgz" - integrity sha512-zG36gEnEqbIe6tK/MhXi7wn/XMY/zdivnPcOY5WyC3derkEezeLSSIFsC1u5UNeK5pbpNMSy4LDpLhi1Ww4Y5w== +"@lexical/link@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/link/-/link-0.18.0.tgz" + integrity sha512-GCYcbNTSTwJk0lr+GMc8nn6Meq44BZs3QL2d1B0skpZAspd8yI53sRS6HDy5P+jW5P0dzyZr/XJAU4U+7zsEEg== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/list@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/list/-/list-0.16.1.tgz" - integrity sha512-i9YhLAh5N6YO9dP+R1SIL9WEdCKeTiQQYVUzj84vDvX5DIBxMPUjTmMn3LXu9T+QO3h1s2L/vJusZASrl45eAw== +"@lexical/list@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/list/-/list-0.18.0.tgz" + integrity sha512-DEWs9Scbg3+STZeE2O0OoG8SWnKnxQccObBzyeHRjn4GAN6JA7lgcAzfrdgp0fNWTbMM/ku876MmXKGnqhvg9Q== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/mark@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/mark/-/mark-0.16.1.tgz" - integrity sha512-CZRGMLcxn5D+jzf1XnH+Z+uUugmpg1mBwTbGybCPm8UWpBrKDHkrscfMgWz62iRWz0cdVjM5+0zWpNElxFTRjQ== +"@lexical/mark@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/mark/-/mark-0.18.0.tgz" + integrity sha512-QA4YWfTP5WWnCnoH/RmfcsSZyhhd7oeFWDpfP7S8Bbmhz6kiPwGcsVr+uRQBBT56AqEX167xX2rX8JR6FiYZqA== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/markdown@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/markdown/-/markdown-0.16.1.tgz" - integrity sha512-0sBLttMvfQO/hVaIqpHdvDowpgV2CoRuWo2CNwvRLZPPWvPVjL4Nkb73wmi8zAZsAOTbX2aw+g4m/+k5oJqNig== +"@lexical/markdown@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/markdown/-/markdown-0.18.0.tgz" + integrity sha512-uSWwcK8eJw5C+waEhU5WoX8W+JxNZbKuFnZwsn5nsp+iQgqMj4qY6g0yJub4sq8vvh6jjl4vVXhXTq2up9aykw== dependencies: - "@lexical/code" "0.16.1" - "@lexical/link" "0.16.1" - "@lexical/list" "0.16.1" - "@lexical/rich-text" "0.16.1" - "@lexical/text" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/code" "0.18.0" + "@lexical/link" "0.18.0" + "@lexical/list" "0.18.0" + "@lexical/rich-text" "0.18.0" + "@lexical/text" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/offset@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/offset/-/offset-0.16.1.tgz" - integrity sha512-/i2J04lQmFeydUZIF8tKXLQTXiJDTQ6GRnkfv1OpxU4amc0rwGa7+qAz/PuF1n58rP6InpLmSHxgY5JztXa2jw== +"@lexical/offset@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/offset/-/offset-0.18.0.tgz" + integrity sha512-KGlboyLSxQAH5PMOlJmyvHlbYXZneVnKiHpfyBV5IUX5kuyB/eZbQEYcJP9saekfQ5Xb1FWXWmsZEo+sWtrrZA== dependencies: - lexical "0.16.1" + lexical "0.18.0" -"@lexical/overflow@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/overflow/-/overflow-0.16.1.tgz" - integrity sha512-xh5YpoxwA7K4wgMQF/Sjl8sdjaxqesLCtH5ZrcMsaPlmucDIEEs+i8xxk+kDUTEY7y+3FvRxs4lGNgX8RVWkvQ== +"@lexical/overflow@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/overflow/-/overflow-0.18.0.tgz" + integrity sha512-3ATTwttVgZtVLq60ZUWbpbXBbpuMa3PZD5CxSP3nulviL+2I4phvacV4WUN+8wMeq+PGmuarl+cYfrFL02ii3g== dependencies: - lexical "0.16.1" + lexical "0.18.0" -"@lexical/plain-text@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.16.1.tgz" - integrity sha512-GjY4ylrBZIaAVIF8IFnmW0XGyHAuRmWA6gKB8iTTlsjgFrCHFIYC74EeJSp309O0Hflg9rRBnKoX1TYruFHVwA== +"@lexical/plain-text@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.18.0.tgz" + integrity sha512-L6yQpiwW0ZacY1oNwvRBxSuW2TZaUcveZLheJc8JzGcZoVxzII/CAbLZG8691VbNuKsbOURiNXZIsgwujKmo4Q== dependencies: - "@lexical/clipboard" "0.16.1" - "@lexical/selection" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/clipboard" "0.18.0" + "@lexical/selection" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/react@^0.16.0": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/react/-/react-0.16.1.tgz" - integrity sha512-SsGgLt9iKfrrMRy9lFb6ROVPUYOgv6b+mCn9Al+TLqs/gBReDBi3msA7m526nrtBUKYUnjHdQ1QXIJzuKgOxcg== +"@lexical/react@^0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/react/-/react-0.18.0.tgz" + integrity sha512-DLvIbTsjvFIFqm+9zvAjEwuZHAbSxzZf1AGqf1lLctlL/Ran0f+8EZOv5jttELTe7xISZ2+xSXTLRfyxhNwGXQ== dependencies: - "@lexical/clipboard" "0.16.1" - "@lexical/code" "0.16.1" - "@lexical/devtools-core" "0.16.1" - "@lexical/dragon" "0.16.1" - "@lexical/hashtag" "0.16.1" - "@lexical/history" "0.16.1" - "@lexical/link" "0.16.1" - "@lexical/list" "0.16.1" - "@lexical/mark" "0.16.1" - "@lexical/markdown" "0.16.1" - "@lexical/overflow" "0.16.1" - "@lexical/plain-text" "0.16.1" - "@lexical/rich-text" "0.16.1" - "@lexical/selection" "0.16.1" - "@lexical/table" "0.16.1" - "@lexical/text" "0.16.1" - "@lexical/utils" "0.16.1" - "@lexical/yjs" "0.16.1" - lexical "0.16.1" + "@lexical/clipboard" "0.18.0" + "@lexical/code" "0.18.0" + "@lexical/devtools-core" "0.18.0" + "@lexical/dragon" "0.18.0" + "@lexical/hashtag" "0.18.0" + "@lexical/history" "0.18.0" + "@lexical/link" "0.18.0" + "@lexical/list" "0.18.0" + "@lexical/mark" "0.18.0" + "@lexical/markdown" "0.18.0" + "@lexical/overflow" "0.18.0" + "@lexical/plain-text" "0.18.0" + "@lexical/rich-text" "0.18.0" + "@lexical/selection" "0.18.0" + "@lexical/table" "0.18.0" + "@lexical/text" "0.18.0" + "@lexical/utils" "0.18.0" + "@lexical/yjs" "0.18.0" + lexical "0.18.0" react-error-boundary "^3.1.4" -"@lexical/rich-text@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.16.1.tgz" - integrity sha512-4uEVXJur7tdSbqbmsToCW4YVm0AMh4y9LK077Yq2O9hSuA5dqpI8UbTDnxZN2D7RfahNvwlqp8eZKFB1yeiJGQ== +"@lexical/rich-text@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.18.0.tgz" + integrity sha512-xMANCB7WueMsmWK8qxik5FZN4ApyaHWHQILS9r4FTbdv/DlNepsR7Pt8kg2317xZ56NAueQLIdyyKYXG1nBrHw== dependencies: - "@lexical/clipboard" "0.16.1" - "@lexical/selection" "0.16.1" - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/clipboard" "0.18.0" + "@lexical/selection" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/selection@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/selection/-/selection-0.16.1.tgz" - integrity sha512-+nK3RvXtyQvQDq7AZ46JpphmM33pwuulwiRfeXR5T9iFQTtgWOEjsAi/KKX7vGm70BxACfiSxy5QCOgBWFwVJg== +"@lexical/selection@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/selection/-/selection-0.18.0.tgz" + integrity sha512-mJoMhmxeZLfM9K2JMYETs9u179IkHQUlgtYG5GZJHjKx2iUn+9KvJ9RVssq+Lusi7C/N42wWPGNHDPdUvFtxXg== dependencies: - lexical "0.16.1" + lexical "0.18.0" -"@lexical/table@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/table/-/table-0.16.1.tgz" - integrity sha512-GWb0/MM1sVXpi1p2HWWOBldZXASMQ4c6WRNYnRmq7J/aB5N66HqQgJGKp3m66Kz4k1JjhmZfPs7F018qIBhnFQ== +"@lexical/table@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/table/-/table-0.18.0.tgz" + integrity sha512-TeTAnuFAAgVjm1QE8adRB3GFWN+DUUiS4vzGq+ynPRCtNdpmW27NmTkRMyxKsetUtt7nIFfj4DvLvor4RwqIpA== dependencies: - "@lexical/utils" "0.16.1" - lexical "0.16.1" + "@lexical/clipboard" "0.18.0" + "@lexical/utils" "0.18.0" + lexical "0.18.0" -"@lexical/text@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/text/-/text-0.16.1.tgz" - integrity sha512-Os/nKQegORTrKKN6vL3/FMVszyzyqaotlisPynvTaHTUC+yY4uyjM2hlF93i5a2ixxyiPLF9bDroxUP96TMPXg== +"@lexical/text@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/text/-/text-0.18.0.tgz" + integrity sha512-MTHSBeq3K0+lqSsP5oysBMnY4tPVhB8kAa2xBnEc3dYgXFxEEvJwZahbHNX93EPObtJkxXfUuI63Al4G3lYK8A== dependencies: - lexical "0.16.1" + lexical "0.18.0" -"@lexical/utils@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/utils/-/utils-0.16.1.tgz" - integrity sha512-BVyJxDQi/rIxFTDjf2zE7rMDKSuEaeJ4dybHRa/hRERt85gavGByQawSLeQlTjLaYLVsy+x7wCcqh2fNhlLf0g== +"@lexical/utils@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/utils/-/utils-0.18.0.tgz" + integrity sha512-4s9dVpBZjqIaA/1q2GtfWFjKsv2Wqhjer0Zw2mcl1TIVN0zreXxcTKN316QppAWmSQJxVGvkWHjjaZJwl6/TSw== dependencies: - "@lexical/list" "0.16.1" - "@lexical/selection" "0.16.1" - "@lexical/table" "0.16.1" - lexical "0.16.1" + "@lexical/list" "0.18.0" + "@lexical/selection" "0.18.0" + "@lexical/table" "0.18.0" + lexical "0.18.0" -"@lexical/yjs@0.16.1": - version "0.16.1" - resolved "https://registry.npmjs.org/@lexical/yjs/-/yjs-0.16.1.tgz" - integrity sha512-QHw1bmzB/IypIV1tRWMH4hhwE1xX7wV+HxbzBS8oJAkoU5AYXM/kyp/sQicgqiwVfpai1Px7zatOoUDFgbyzHQ== +"@lexical/yjs@0.18.0": + version "0.18.0" + resolved "https://registry.npmjs.org/@lexical/yjs/-/yjs-0.18.0.tgz" + integrity sha512-rl7Rl9XIb3ygQEEHOFtACdXs3BE+UUUmdyNqB6kK9A6IRGz+w4Azp+qzt8It/t+c0oaSYHpAtcLNXg1amJz+kA== dependencies: - "@lexical/offset" "0.16.1" - lexical "0.16.1" + "@lexical/offset" "0.18.0" + "@lexical/selection" "0.18.0" + lexical "0.18.0" -"@mapbox/node-pre-gyp@^1.0.0": - version "1.0.11" - resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz" - integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== +"@mdx-js/loader@^3.1.0", "@mdx-js/loader@>=0.15.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.0.tgz" + integrity sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg== dependencies: - detect-libc "^2.0.0" - https-proxy-agent "^5.0.0" - make-dir "^3.1.0" - node-fetch "^2.6.7" - nopt "^5.0.0" - npmlog "^5.0.1" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.11" - -"@mdx-js/loader@^2.3.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@mdx-js/loader/-/loader-2.3.0.tgz" - integrity sha512-IqsscXh7Q3Rzb+f5DXYk0HU71PK+WuFsEhf+mSV3fOhpLcEpgsHvTQ2h0T6TlZ5gHOaBeFjkXwB52by7ypMyNg== - dependencies: - "@mdx-js/mdx" "^2.0.0" + "@mdx-js/mdx" "^3.0.0" source-map "^0.7.0" -"@mdx-js/mdx@^2.0.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz" - integrity sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA== +"@mdx-js/mdx@^3.0.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz" + integrity sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw== dependencies: + "@types/estree" "^1.0.0" "@types/estree-jsx" "^1.0.0" + "@types/hast" "^3.0.0" "@types/mdx" "^2.0.0" - estree-util-build-jsx "^2.0.0" - estree-util-is-identifier-name "^2.0.0" - estree-util-to-js "^1.1.0" + collapse-white-space "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + estree-util-scope "^1.0.0" estree-walker "^3.0.0" - hast-util-to-estree "^2.0.0" - markdown-extensions "^1.0.0" - periscopic "^3.0.0" - remark-mdx "^2.0.0" - remark-parse "^10.0.0" - remark-rehype "^10.0.0" - unified "^10.0.0" - unist-util-position-from-estree "^1.0.0" - unist-util-stringify-position "^3.0.0" - unist-util-visit "^4.0.0" - vfile "^5.0.0" + hast-util-to-jsx-runtime "^2.0.0" + markdown-extensions "^2.0.0" + recma-build-jsx "^1.0.0" + recma-jsx "^1.0.0" + recma-stringify "^1.0.0" + rehype-recma "^1.0.0" + remark-mdx "^3.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.0.0" + source-map "^0.7.0" + unified "^11.0.0" + unist-util-position-from-estree "^2.0.0" + unist-util-stringify-position "^4.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" -"@mdx-js/react@^2.3.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz" - integrity sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g== - dependencies: - "@types/mdx" "^2.0.0" - "@types/react" ">=16" - -"@mdx-js/react@^3.0.0": +"@mdx-js/react@^3.0.0", "@mdx-js/react@^3.1.0", "@mdx-js/react@>=0.15.0": version "3.1.0" resolved "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz" integrity sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ== @@ -2071,12 +2029,12 @@ resolved "https://registry.npmjs.org/@next/env/-/env-14.2.17.tgz" integrity sha512-MCgO7VHxXo8sYR/0z+sk9fGyJJU636JyRmkjc7ZJY8Hurl8df35qG5hoAh5KMs75FLjhlEo9bb2LGe89Y/scDA== -"@next/eslint-plugin-next@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz" - integrity sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ== +"@next/eslint-plugin-next@15.1.2": + version "15.1.2" + resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.2.tgz" + integrity sha512-sgfw3+WdaYOGPKCvM1L+UucBmRfh8V2Ygefp7ELON0+0vY7uohQwXXnVWg3rY7mXDKharQR3o7uedpfvnU2hlQ== dependencies: - glob "7.1.7" + fast-glob "3.3.1" "@next/mdx@^14.0.4": version "14.0.4" @@ -2090,46 +2048,6 @@ resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.17.tgz" integrity sha512-WiOf5nElPknrhRMTipXYTJcUz7+8IAjOYw3vXzj3BYRcVY0hRHKWgTgQ5439EvzQyHEko77XK+yN9x9OJ0oOog== -"@next/swc-darwin-x64@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.17.tgz#e29a17ef28d97c347c7d021f391e13b6c8e4c813" - integrity sha512-29y425wYnL17cvtxrDQWC3CkXe/oRrdt8ie61S03VrpwpPRI0XsnTvtKO06XCisK4alaMnZlf8riwZIbJTaSHQ== - -"@next/swc-linux-arm64-gnu@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.17.tgz#10e99c7aa60cc33f8b7633e045f74be9a43e7b0c" - integrity sha512-SSHLZls3ZwNEHsc+d0ynKS+7Af0Nr8+KTUBAy9pm6xz9SHkJ/TeuEg6W3cbbcMSh6j4ITvrjv3Oi8n27VR+IPw== - -"@next/swc-linux-arm64-musl@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.17.tgz#9a5bb809d3c6aef96c409959aedae28b4e5db53d" - integrity sha512-VFge37us5LNPatB4F7iYeuGs9Dprqe4ZkW7lOEJM91r+Wf8EIdViWHLpIwfdDXinvCdLl6b4VyLpEBwpkctJHA== - -"@next/swc-linux-x64-gnu@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.17.tgz#64e0ce01870e6dc45ae48f676d7cce82aedcdc62" - integrity sha512-aaQlpxUVb9RZ41adlTYVQ3xvYEfBPUC8+6rDgmQ/0l7SvK8S1YNJzPmDPX6a4t0jLtIoNk7j+nroS/pB4nx7vQ== - -"@next/swc-linux-x64-musl@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.17.tgz#93114164b6ccfc533908193ab9065f0c3970abc3" - integrity sha512-HSyEiFaEY3ay5iATDqEup5WAfrhMATNJm8dYx3ZxL+e9eKv10XKZCwtZByDoLST7CyBmyDz+OFJL1wigyXeaoA== - -"@next/swc-win32-arm64-msvc@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.17.tgz#4b99dea02178c112e5c33c742f9ff2a49b3b2939" - integrity sha512-h5qM9Btqv87eYH8ArrnLoAHLyi79oPTP2vlGNSg4CDvUiXgi7l0+5KuEGp5pJoMhjuv9ChRdm7mRlUUACeBt4w== - -"@next/swc-win32-ia32-msvc@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.17.tgz#f1c23955405a259b6d45c65f918575b01bcf0106" - integrity sha512-BD/G++GKSLexQjdyoEUgyo5nClU7er5rK0sE+HlEqnldJSm96CIr/+YOTT063LVTT/dUOeQsNgp5DXr86/K7/A== - -"@next/swc-win32-x64-msvc@14.2.17": - version "14.2.17" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.17.tgz#44f5a4fcd8df1396a8d4326510ca2d92fb809cb3" - integrity sha512-vkQfN1+4V4KqDibkW2q0sJ6CxQuXq5l2ma3z0BRcfIqkAMZiiW67T9yCpwqJKP68QghBtPEFjPAlaqe38O6frw== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -2138,12 +2056,12 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -2151,6 +2069,109 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@octokit/auth-token@^5.0.0": + version "5.1.1" + resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz" + integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== + +"@octokit/core@^6.1.2": + version "6.1.2" + resolved "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz" + integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== + dependencies: + "@octokit/auth-token" "^5.0.0" + "@octokit/graphql" "^8.0.0" + "@octokit/request" "^9.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.0.0" + before-after-hook "^3.0.2" + universal-user-agent "^7.0.0" + +"@octokit/endpoint@^10.0.0": + version "10.1.1" + resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz" + integrity sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q== + dependencies: + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.2" + +"@octokit/graphql@^8.0.0": + version "8.1.1" + resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz" + integrity sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg== + dependencies: + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/openapi-types@^22.2.0": + version "22.2.0" + resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz" + integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== + +"@octokit/request-error@^6.0.1", "@octokit/request-error@^6.1.5": + version "6.1.5" + resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz" + integrity sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ== + dependencies: + "@octokit/types" "^13.0.0" + +"@octokit/request@^9.0.0": + version "9.1.3" + resolved "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz" + integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== + dependencies: + "@octokit/endpoint" "^10.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.1.0" + universal-user-agent "^7.0.2" + +"@octokit/types@^13.0.0", "@octokit/types@^13.1.0": + version "13.6.2" + resolved "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz" + integrity sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA== + dependencies: + "@octokit/openapi-types" "^22.2.0" + +"@parcel/watcher-darwin-arm64@2.5.0": + version "2.5.0" + resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz" + integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw== + +"@parcel/watcher@^2.4.1": + version "2.5.0" + resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz" + integrity sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.0" + "@parcel/watcher-darwin-arm64" "2.5.0" + "@parcel/watcher-darwin-x64" "2.5.0" + "@parcel/watcher-freebsd-x64" "2.5.0" + "@parcel/watcher-linux-arm-glibc" "2.5.0" + "@parcel/watcher-linux-arm-musl" "2.5.0" + "@parcel/watcher-linux-arm64-glibc" "2.5.0" + "@parcel/watcher-linux-arm64-musl" "2.5.0" + "@parcel/watcher-linux-x64-glibc" "2.5.0" + "@parcel/watcher-linux-x64-musl" "2.5.0" + "@parcel/watcher-win32-arm64" "2.5.0" + "@parcel/watcher-win32-ia32" "2.5.0" + "@parcel/watcher-win32-x64" "2.5.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + "@pkgr/utils@^2.3.1": version "2.4.1" resolved "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.1.tgz" @@ -2244,7 +2265,7 @@ "@remixicon/react@^4.5.0": version "4.5.0" - resolved "https://registry.yarnpkg.com/@remixicon/react/-/react-4.5.0.tgz#5600d122ee4995bff2c4442cb056eeb4f11ecb5a" + resolved "https://registry.npmjs.org/@remixicon/react/-/react-4.5.0.tgz" integrity sha512-Xr20SxMpRNlgXZnoF5BCMyZuQEhXY3yJCyms8kxB/vJCCiV1nWdiO48XqRG5LBd1192iSHC4m658AIWi6rmBFg== "@rgrove/parse-xml@^4.1.0": @@ -2252,10 +2273,15 @@ resolved "https://registry.npmjs.org/@rgrove/parse-xml/-/parse-xml-4.1.0.tgz" integrity sha512-pBiltENdy8SfI0AeR1e5TRpS9/9Gl0eiOEt6ful2jQfzsgvZYWqsKiBWaOCLdocQuk0wS7KOHI37n0C1pnKqTw== -"@rushstack/eslint-patch@^1.3.3": - version "1.6.1" - resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz" - integrity sha512-UY+FGM/2jjMkzQLn8pxcHGMaVLh9aEitG3zY2CiY7XHdLiz3bZOwa6oDxNqEMv7zZkV+cj5DOdz0cQ1BP5Hjgw== +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@rushstack/eslint-patch@^1.10.3": + version "1.10.4" + resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz" + integrity sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA== "@sentry-internal/feedback@7.120.1": version "7.120.1" @@ -2343,7 +2369,7 @@ resolved "https://registry.npmjs.org/@sentry/types/-/types-7.120.1.tgz" integrity sha512-f/WT7YUH8SA2Jhez/hYz/dA351AJqr1Eht/URUdYsqMFecXr/blAcNKRVFccSsvQeTqWVV9HVQ9BXUSjPJOvFA== -"@sentry/utils@7.120.1", "@sentry/utils@^7.54.0": +"@sentry/utils@^7.54.0", "@sentry/utils@7.120.1": version "7.120.1" resolved "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.1.tgz" integrity sha512-4boeo5Y3zw3gFrWZmPHsYOIlTh//eBaGBgWL25FqLbLObO23gFE86G6O6knP1Gamm1DGX2IWH7w4MChYuBm6tA== @@ -2374,10 +2400,10 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@storybook/addon-actions@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.2.tgz" - integrity sha512-+hA200XN5aeA4T3jq8IifQq6Y+9FyNQ0Q+blM1L0Tl7WLzBc7B1kHQnKvhSj5pvMSBWc/Q/kY7Ev5t9gdOu13g== +"@storybook/addon-actions@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.7.tgz" + integrity sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA== dependencies: "@storybook/global" "^5.0.0" "@types/uuid" "^9.0.1" @@ -2385,137 +2411,137 @@ polished "^4.2.2" uuid "^9.0.0" -"@storybook/addon-backgrounds@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.2.tgz" - integrity sha512-s4uag5VKuk8q2MSnuNS7Sv+v1/mykzGPXe/zZRW2ammtkdHp8Uy78eQS2G0aiG02chXCX+qQgWMyy5QItDcTFQ== +"@storybook/addon-backgrounds@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.7.tgz" + integrity sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ== dependencies: "@storybook/global" "^5.0.0" memoizerific "^1.11.3" ts-dedent "^2.0.0" -"@storybook/addon-controls@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.2.tgz" - integrity sha512-raCbHEj1xl4F3wKH6IdfEXNRaxKpY4QGhjSTE8Pte5iJSVhKG86taLqqRr+4dC7H1/LVMPU1XCGV4mkgDGtyxQ== +"@storybook/addon-controls@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.7.tgz" + integrity sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA== dependencies: "@storybook/global" "^5.0.0" dequal "^2.0.2" ts-dedent "^2.0.0" -"@storybook/addon-docs@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.2.tgz" - integrity sha512-jIpykha7hv2Inlrq31ZoYg2QhuCuvcO+Q+uvhT45RDTB+2US/fg3rJINKlw2Djq8RPPOXvty5W0yvE6CrWKhnQ== +"@storybook/addon-docs@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.7.tgz" + integrity sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w== dependencies: "@mdx-js/react" "^3.0.0" - "@storybook/blocks" "8.4.2" - "@storybook/csf-plugin" "8.4.2" - "@storybook/react-dom-shim" "8.4.2" + "@storybook/blocks" "8.4.7" + "@storybook/csf-plugin" "8.4.7" + "@storybook/react-dom-shim" "8.4.7" react "^16.8.0 || ^17.0.0 || ^18.0.0" react-dom "^16.8.0 || ^17.0.0 || ^18.0.0" ts-dedent "^2.0.0" -"@storybook/addon-essentials@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.2.tgz" - integrity sha512-+/vfPrXM/GWU3Kbrg92PepwAZr7lOeulTTYF4THK0CL3DfUUlkGNpBPLP5PtjCuIkVrTCjXiIEdVWk47d5m2+w== +"@storybook/addon-essentials@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.7.tgz" + integrity sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw== dependencies: - "@storybook/addon-actions" "8.4.2" - "@storybook/addon-backgrounds" "8.4.2" - "@storybook/addon-controls" "8.4.2" - "@storybook/addon-docs" "8.4.2" - "@storybook/addon-highlight" "8.4.2" - "@storybook/addon-measure" "8.4.2" - "@storybook/addon-outline" "8.4.2" - "@storybook/addon-toolbars" "8.4.2" - "@storybook/addon-viewport" "8.4.2" + "@storybook/addon-actions" "8.4.7" + "@storybook/addon-backgrounds" "8.4.7" + "@storybook/addon-controls" "8.4.7" + "@storybook/addon-docs" "8.4.7" + "@storybook/addon-highlight" "8.4.7" + "@storybook/addon-measure" "8.4.7" + "@storybook/addon-outline" "8.4.7" + "@storybook/addon-toolbars" "8.4.7" + "@storybook/addon-viewport" "8.4.7" ts-dedent "^2.0.0" -"@storybook/addon-highlight@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.2.tgz" - integrity sha512-vTtwp7nyJ09SXrsMnH+pukCjHjRMjQXgHZHxvbrv09uoH8ldQMv9B7u+X+9Wcy/jYSKFz/ng7pWo4b4a2oXHkg== +"@storybook/addon-highlight@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.7.tgz" + integrity sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw== dependencies: "@storybook/global" "^5.0.0" -"@storybook/addon-interactions@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.4.2.tgz" - integrity sha512-+/NTENTApeOcONgFNQ6Olbk0GH3pTDG3w0eh00slCB+2agD1BcVKg8SSlHQV0lQF1cK3vWL/X3jeaxdFLYOjjg== +"@storybook/addon-interactions@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.4.7.tgz" + integrity sha512-fnufT3ym8ht3HHUIRVXAH47iOJW/QOb0VSM+j269gDuvyDcY03D1civCu1v+eZLGaXPKJ8vtjr0L8zKQ/4P0JQ== dependencies: "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.4.2" - "@storybook/test" "8.4.2" + "@storybook/instrumenter" "8.4.7" + "@storybook/test" "8.4.7" polished "^4.2.2" ts-dedent "^2.2.0" -"@storybook/addon-links@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.4.2.tgz" - integrity sha512-8nncReA/drR2cyAcUz484FIv+MXbyCQxYrA6yfWHthZfGu+vMIETvhh+eP4OpluVnxySoQ+hCVK/V8G2jcyAZg== +"@storybook/addon-links@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.4.7.tgz" + integrity sha512-L/1h4dMeMKF+MM0DanN24v5p3faNYbbtOApMgg7SlcBT/tgo3+cAjkgmNpYA8XtKnDezm+T2mTDhB8mmIRZpIQ== dependencies: "@storybook/csf" "^0.1.11" "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-measure@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.2.tgz" - integrity sha512-z+j6xQwcUBSpgzl1XDU+xU4YYgLraLMljECW7NvRNyJ/PYixvol8R3wtzWbr+CBpxmvbXjEJCPlF+EjF9/mBWQ== +"@storybook/addon-measure@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.7.tgz" + integrity sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw== dependencies: "@storybook/global" "^5.0.0" tiny-invariant "^1.3.1" -"@storybook/addon-onboarding@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.4.2.tgz" - integrity sha512-zWzOyRASnIPt2AcaEl1KhI+aOaKDuoIcNB7u1GoABj0YM+V9d6o3lvcsmOAQG5pgwgFyqyOnLwpTfvRSEyzGFA== +"@storybook/addon-onboarding@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.4.7.tgz" + integrity sha512-FdC2NV60VNYeMxf6DVe0qV9ucSBAzMh1//C0Qqwq8CcjthMbmKlVZ7DqbVsbIHKnFaSCaUC88eR5olAfMaauCQ== dependencies: react-confetti "^6.1.0" -"@storybook/addon-outline@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.2.tgz" - integrity sha512-oTMlPEyT4CBqzcQbfemoJzJ6yzeRAmvrAx9ssaBcnQQRsKxo0D2Ri/Jmm6SNcR0yBHxYRkvIH+2phLw8aiflCQ== +"@storybook/addon-outline@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.7.tgz" + integrity sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA== dependencies: "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-themes@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-8.4.2.tgz" - integrity sha512-SEeADvNxdkgfCEK4kxuV5w0ZFkdWQjJ3GySgLaXZM7FkEySfHyRIvkcoJml6Q0zJdChywVYNTRXonL0hmBlo7Q== +"@storybook/addon-themes@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-8.4.7.tgz" + integrity sha512-MZa3eWTz0b3BQvF71WqLqvEYzDtbMhQx1IIluWBMMGzJ4sWBzLX85LoNMUlHsNd4EhEmAZ1xQQFIJpDWTBx0nQ== dependencies: ts-dedent "^2.0.0" -"@storybook/addon-toolbars@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.2.tgz" - integrity sha512-DidzW/NQS224niMJIjcJI2ls83emqygUcS9GYNGgdc5Xwro/TPgGYOXP2qnXgYUxXQTHbrxmIbHdEehxC7CcYQ== +"@storybook/addon-toolbars@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.7.tgz" + integrity sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw== -"@storybook/addon-viewport@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.2.tgz" - integrity sha512-qVQ2UaxCNsUSFHnAAAizNPIJ/QwfMg7p5bBdpYROTZXJe+bxVp0rFzZmQgHZ3/sn+lzE4ItM4QEfxkfQUWi1ag== +"@storybook/addon-viewport@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.7.tgz" + integrity sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ== dependencies: memoizerific "^1.11.3" -"@storybook/blocks@8.4.2", "@storybook/blocks@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.2.tgz" - integrity sha512-yAAvmOWaD8gIrepOxCh/RxQqd/1xZIwd/V+gsvAhW/thawN+SpI+zK63gmcqAPLX84hJ3Dh5pegRk0SoHNuDVA== +"@storybook/blocks@^8.3.6", "@storybook/blocks@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.7.tgz" + integrity sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA== dependencies: "@storybook/csf" "^0.1.11" "@storybook/icons" "^1.2.12" ts-dedent "^2.0.0" -"@storybook/builder-webpack5@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.2.tgz" - integrity sha512-Pqa0/sqqEujzcvs+/Cwf/5qRLC+atmceROCFokMOgpIaorTXlbmiQdJ2dBhMFNugLvXfL7dVQBjBfiuzhsQ57g== +"@storybook/builder-webpack5@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.7.tgz" + integrity sha512-O8LpsQ+4g2x5kh7rI9+jEUdX8k1a5egBQU1lbudmHchqsV0IKiVqBD9LL5Gj3wpit4vB8coSW4ZWTFBw8FQb4Q== dependencies: - "@storybook/core-webpack" "8.4.2" + "@storybook/core-webpack" "8.4.7" "@types/node" "^22.0.0" "@types/semver" "^7.3.4" browser-assert "^1.2.1" @@ -2541,23 +2567,23 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.6.0" -"@storybook/components@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/components/-/components-8.4.2.tgz" - integrity sha512-+W59oF7D73LAxLNmCfFrfs98cH9pyNHK9HlJoO5/lKbK4IdWhhOoqUR/AJ3ueksoLuetFat4DxyE8SN1H4Bvrg== +"@storybook/components@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/components/-/components-8.4.7.tgz" + integrity sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g== -"@storybook/core-webpack@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.2.tgz" - integrity sha512-bzGvzrLK/oDE9YlKayDEplcECURSa1oRkvV7rxI2sOTNfwuoxHJapvxFxazEKAHMVeSwfWDf4uKK0XeG2R/arA== +"@storybook/core-webpack@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.7.tgz" + integrity sha512-Tj+CjQLpFyBJxhhMms+vbPT3+gTRAiQlrhY3L1IEVwBa3wtRMS0qjozH26d1hK4G6mUIEdwu13L54HMU/w33Sg== dependencies: "@types/node" "^22.0.0" ts-dedent "^2.0.0" -"@storybook/core@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/core/-/core-8.4.2.tgz" - integrity sha512-hF8GWoUZTjwwuV5j4OLhMHZtZQL/NYcVUBReC2Ba06c8PkFIKqKZwATr1zKd301gQ5Qwcn9WgmZxJTMgdKQtOg== +"@storybook/core@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/core/-/core-8.4.7.tgz" + integrity sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA== dependencies: "@storybook/csf" "^0.1.11" better-opn "^3.0.2" @@ -2571,20 +2597,13 @@ util "^0.12.5" ws "^8.2.3" -"@storybook/csf-plugin@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.2.tgz" - integrity sha512-1f0t6W5xbC1sSAHHs3uXYPIQs2NXAEtIGqn6X9i3xbbub6hDS8PF8BIm7dOjQ8dZOPp7d9ltR64V5CoLlsOigA== +"@storybook/csf-plugin@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.7.tgz" + integrity sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g== dependencies: unplugin "^1.3.1" -"@storybook/csf@^0.0.1": - version "0.0.1" - resolved "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz" - integrity sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw== - dependencies: - lodash "^4.17.15" - "@storybook/csf@^0.1.11": version "0.1.11" resolved "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz" @@ -2602,23 +2621,23 @@ resolved "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.12.tgz" integrity sha512-UxgyK5W3/UV4VrI3dl6ajGfHM4aOqMAkFLWe2KibeQudLf6NJpDrDMSHwZj+3iKC4jFU7dkKbbtH2h/al4sW3Q== -"@storybook/instrumenter@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.4.2.tgz" - integrity sha512-gPYCZ/0O6gRLI3zmenu2N6QtKzxDZFdT2xf4RWcNUSZyp28RZkRCIgKFMt3fTmvE0yMzAjQyRSkBdrONjQ44HA== +"@storybook/instrumenter@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.4.7.tgz" + integrity sha512-k6NSD3jaRCCHAFtqXZ7tw8jAzD/yTEWXGya+REgZqq5RCkmJ+9S4Ytp/6OhQMPtPFX23gAuJJzTQVLcCr+gjRg== dependencies: "@storybook/global" "^5.0.0" "@vitest/utils" "^2.1.1" -"@storybook/manager-api@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.2.tgz" - integrity sha512-rhPc4cgQDKDH8NUyRh/ZaJW7QIhR/PO5MNX4xc+vz71sM2nO7ONA/FrgLtCuu4SULdwilEPvGefYvLK0dE+Caw== +"@storybook/manager-api@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.7.tgz" + integrity sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ== -"@storybook/nextjs@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-8.4.2.tgz" - integrity sha512-HySwS9zfenurk+O+SX9gKskotkHo8mFRBKAIlEROIWi7iipp5GCVPyqb8gFWjvN81dKfEIAZs+fB/7ySulJ4rg== +"@storybook/nextjs@^8.3.6": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-8.4.7.tgz" + integrity sha512-6dVt6VKBndSqn91egZx2fWl44i1TnIggRgmnk5jyl2KHDRvXziFNa2ujBz1nveriAWmwRchhce0OLDx9zQ9b4w== dependencies: "@babel/core" "^7.24.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -2634,10 +2653,10 @@ "@babel/preset-typescript" "^7.24.1" "@babel/runtime" "^7.24.4" "@pmmmwh/react-refresh-webpack-plugin" "^0.5.11" - "@storybook/builder-webpack5" "8.4.2" - "@storybook/preset-react-webpack" "8.4.2" - "@storybook/react" "8.4.2" - "@storybook/test" "8.4.2" + "@storybook/builder-webpack5" "8.4.7" + "@storybook/preset-react-webpack" "8.4.7" + "@storybook/react" "8.4.7" + "@storybook/test" "8.4.7" "@types/node" "^22.0.0" "@types/semver" "^7.3.4" babel-loader "^9.1.3" @@ -2661,13 +2680,13 @@ optionalDependencies: sharp "^0.33.3" -"@storybook/preset-react-webpack@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.4.2.tgz" - integrity sha512-Gt9hQRo1ythGFzATNV4WgQDlMDzBgiq7ks+YkW2/Xu5ZkrRrM/gK75fhmbICrknZl2pPPfNFXlECPWKAeTmwFA== +"@storybook/preset-react-webpack@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.4.7.tgz" + integrity sha512-geTSBKyrBagVihil5MF7LkVFynbfHhCinvnbCZZqXW7M1vgcxvatunUENB+iV8eWg/0EJ+8O7scZL+BAxQ/2qg== dependencies: - "@storybook/core-webpack" "8.4.2" - "@storybook/react" "8.4.2" + "@storybook/core-webpack" "8.4.7" + "@storybook/react" "8.4.7" "@storybook/react-docgen-typescript-plugin" "1.0.6--canary.9.0c3f3b7.0" "@types/node" "^22.0.0" "@types/semver" "^7.3.4" @@ -2679,10 +2698,10 @@ tsconfig-paths "^4.2.0" webpack "5" -"@storybook/preview-api@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.2.tgz" - integrity sha512-5X/xvIvDPaWJKUBCo5zVeBbbjkhnwcI2KPkuOgrHVRRhuQ5WqD0RYxVtOOFNyQXme7g0nNl5RFNgvT7qv9qGeg== +"@storybook/preview-api@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.7.tgz" + integrity sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg== "@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0": version "1.0.6--canary.9.0c3f3b7.0" @@ -2697,41 +2716,52 @@ react-docgen-typescript "^2.2.2" tslib "^2.0.0" -"@storybook/react-dom-shim@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.2.tgz" - integrity sha512-FZVTM1f34FpGnf6e3MDIKkz05gmn8H9wEccvQAgr8pEFe8VWfrpVWeUrmatSAfgrCMNXYC1avDend8UX6IM8Fg== +"@storybook/react-dom-shim@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.7.tgz" + integrity sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg== -"@storybook/react@8.4.2", "@storybook/react@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/react/-/react-8.4.2.tgz" - integrity sha512-rO5/aVKBVhIKENcL7G8ud4QKC5OyWBPCkJIvY6XUHIuhErJy9/4pP+sZ85jypVwx5kq+EqCPF8AEOWjIxB/4/Q== +"@storybook/react@^8.3.6", "@storybook/react@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/react/-/react-8.4.7.tgz" + integrity sha512-nQ0/7i2DkaCb7dy0NaT95llRVNYWQiPIVuhNfjr1mVhEP7XD090p0g7eqUmsx8vfdHh2BzWEo6CoBFRd3+EXxw== dependencies: - "@storybook/components" "8.4.2" + "@storybook/components" "8.4.7" "@storybook/global" "^5.0.0" - "@storybook/manager-api" "8.4.2" - "@storybook/preview-api" "8.4.2" - "@storybook/react-dom-shim" "8.4.2" - "@storybook/theming" "8.4.2" + "@storybook/manager-api" "8.4.7" + "@storybook/preview-api" "8.4.7" + "@storybook/react-dom-shim" "8.4.7" + "@storybook/theming" "8.4.7" -"@storybook/test@8.4.2", "@storybook/test@^8.3.5": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/test/-/test-8.4.2.tgz" - integrity sha512-MipTdboStv0hsqF2Sw8TZgP0YnxCcDYwxkTOd4hmRzev/7Brtvpi4pqjqh8k98ZCvhrCPAPVIoX5drk+oi3YUA== +"@storybook/test@^8.3.6", "@storybook/test@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/test/-/test-8.4.7.tgz" + integrity sha512-AhvJsu5zl3uG40itSQVuSy5WByp3UVhS6xAnme4FWRwgSxhvZjATJ3AZkkHWOYjnnk+P2/sbz/XuPli1FVCWoQ== dependencies: "@storybook/csf" "^0.1.11" "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.4.2" + "@storybook/instrumenter" "8.4.7" "@testing-library/dom" "10.4.0" "@testing-library/jest-dom" "6.5.0" "@testing-library/user-event" "14.5.2" "@vitest/expect" "2.0.5" "@vitest/spy" "2.0.5" -"@storybook/theming@8.4.2": - version "8.4.2" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.2.tgz" - integrity sha512-9j4fnu5LcV+qSs1rdwf61Bt14lms0T1LOZkHxGNcS1c1oH+cPS+sxECh2lxtni+mvOAHUlBs9pKhVZzRPdWpvg== +"@storybook/theming@8.4.7": + version "8.4.7" + resolved "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.7.tgz" + integrity sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw== + +"@stylistic/eslint-plugin@^2.12.1": + version "2.12.1" + resolved "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz" + integrity sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ== + dependencies: + "@typescript-eslint/utils" "^8.13.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + estraverse "^5.3.0" + picomatch "^4.0.2" "@svgdotjs/svg.js@^3.2.4": version "3.2.4" @@ -2758,15 +2788,10 @@ dependencies: defer-to-connect "^2.0.0" -"@tailwindcss/line-clamp@^0.4.4": - version "0.4.4" - resolved "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.4.tgz" - integrity sha512-5U6SY5z8N42VtrCrKlsTAA35gy2VSyYtHWCsg1H87NU1SXnEfekTVlrga9fzUDrrHcGi2Lb5KenUWb4lRQT5/g== - -"@tailwindcss/typography@^0.5.9": - version "0.5.9" - resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz" - integrity sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg== +"@tailwindcss/typography@^0.5.15": + version "0.5.15" + resolved "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz" + integrity sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA== dependencies: lodash.castarray "^4.4.0" lodash.isplainobject "^4.0.6" @@ -2790,14 +2815,14 @@ dependencies: "@tanstack/query-devtools" "5.61.4" -"@tanstack/react-query@^5.60.5": +"@tanstack/react-query@^5.60.5", "@tanstack/react-query@^5.62.3": version "5.62.3" resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.62.3.tgz" integrity sha512-y2zDNKuhgiuMgsKkqd4AcsLIBiCfEO8U11AdrtAUihmLbRNztPrlcZqx2lH1GacZsx+y1qRRbCcJLYTtF1vKsw== dependencies: "@tanstack/query-core" "5.62.3" -"@testing-library/dom@10.4.0", "@testing-library/dom@^10.3.2": +"@testing-library/dom@^10.0.0", "@testing-library/dom@^10.4.0", "@testing-library/dom@>=7.21.4", "@testing-library/dom@10.4.0": version "10.4.0" resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz" integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== @@ -2811,7 +2836,20 @@ lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/jest-dom@6.5.0", "@testing-library/jest-dom@^6.4.6": +"@testing-library/jest-dom@^6.6.2": + version "6.6.3" + resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz" + integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + +"@testing-library/jest-dom@6.5.0": version "6.5.0" resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz" integrity sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA== @@ -2824,10 +2862,10 @@ lodash "^4.17.21" redent "^3.0.0" -"@testing-library/react@^16.0.0": - version "16.0.0" - resolved "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz" - integrity sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ== +"@testing-library/react@^16.0.1": + version "16.1.0" + resolved "https://registry.npmjs.org/@testing-library/react/-/react-16.1.0.tgz" + integrity sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg== dependencies: "@babel/runtime" "^7.12.5" @@ -2916,10 +2954,10 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/crypto-js@^4.1.1": - version "4.1.1" - resolved "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz" - integrity sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA== +"@types/crypto-js@^4.2.2": + version "4.2.2" + resolved "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz" + integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ== "@types/d3-array@*": version "3.2.1" @@ -3231,23 +3269,18 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.12": - version "29.5.12" - resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== +"@types/jest@^29.5.13": + version "29.5.14" + resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== dependencies: expect "^29.0.0" pretty-format "^29.0.0" -"@types/js-cookie@^2.x.x": - version "2.2.7" - resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz" - integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA== - -"@types/js-cookie@^3.0.3": - version "3.0.3" - resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz" - integrity sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww== +"@types/js-cookie@^3.0.6": + version "3.0.6" + resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz" + integrity sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ== "@types/jsdom@^20.0.0": version "20.0.1" @@ -3258,21 +3291,16 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.12" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" - integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/katex@^0.14.0": - version "0.14.0" - resolved "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz" - integrity sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA== - "@types/katex@^0.16.0": version "0.16.0" resolved "https://registry.npmjs.org/@types/katex/-/katex-0.16.0.tgz" @@ -3285,10 +3313,10 @@ dependencies: "@types/node" "*" -"@types/lodash-es@^4.17.7": - version "4.17.7" - resolved "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz" - integrity sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ== +"@types/lodash-es@^4.17.12": + version "4.17.12" + resolved "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz" + integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ== dependencies: "@types/lodash" "*" @@ -3297,13 +3325,6 @@ resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz" integrity sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg== -"@types/mdast@^3.0.0": - version "3.0.11" - resolved "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz" - integrity sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw== - dependencies: - "@types/unist" "*" - "@types/mdast@^4.0.0": version "4.0.4" resolved "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz" @@ -3321,10 +3342,10 @@ resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/negotiator@^0.6.1": - version "0.6.1" - resolved "https://registry.npmjs.org/@types/negotiator/-/negotiator-0.6.1.tgz" - integrity sha512-c4mvXFByghezQ/eVGN5HvH/jI63vm3B7FiE81BUzDAWmuiohRecCO6ddU60dfq29oKUMiQujsoB2h0JQC7JHKA== +"@types/negotiator@^0.6.3": + version "0.6.3" + resolved "https://registry.npmjs.org/@types/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-JkXTOdKs5MF086b/pt8C3+yVp3iDUwG635L7oCH6HvJvvr6lSUU5oe/gLXnPEfYRROHjJIPgCV6cuAg8gGkntQ== "@types/node@*", "@types/node@18.15.0": version "18.15.0" @@ -3343,10 +3364,10 @@ resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/papaparse@^5.3.1": - version "5.3.7" - resolved "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.7.tgz" - integrity sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg== +"@types/papaparse@^5.3.9": + version "5.3.15" + resolved "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.15.tgz" + integrity sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw== dependencies: "@types/node" "*" @@ -3355,53 +3376,53 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== -"@types/prop-types@*", "@types/prop-types@^15.0.0": +"@types/prop-types@*": version "15.7.5" resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/qs@^6.9.7": - version "6.9.7" - resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== +"@types/qs@^6.9.16": + version "6.9.17" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz" + integrity sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ== -"@types/react-dom@~18.2.0": +"@types/react-dom@^18.0.0 || ^19.0.0", "@types/react-dom@~18.2.0": version "18.2.25" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.25.tgz" integrity sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA== dependencies: "@types/react" "*" -"@types/react-slider@^1.3.1": - version "1.3.1" - resolved "https://registry.npmjs.org/@types/react-slider/-/react-slider-1.3.1.tgz" - integrity sha512-4X2yK7RyCIy643YCFL+bc6XNmcnBtt8n88uuyihvcn5G7Lut23eNQU3q3KmwF7MWIfKfsW5NxCjw0SeDZRtgaA== +"@types/react-slider@^1.3.6": + version "1.3.6" + resolved "https://registry.npmjs.org/@types/react-slider/-/react-slider-1.3.6.tgz" + integrity sha512-RS8XN5O159YQ6tu3tGZIQz1/9StMLTg/FCIPxwqh2gwVixJnlfIodtVx+fpXVMZHe7A58lAX1Q4XTgAGOQaCQg== dependencies: "@types/react" "*" -"@types/react-syntax-highlighter@^15.5.6": - version "15.5.7" - resolved "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.7.tgz" - integrity sha512-bo5fEO5toQeyCp0zVHBeggclqf5SQ/Z5blfFmjwO5dkMVGPgmiwZsJh9nu/Bo5L7IHTuGWrja6LxJVE2uB5ZrQ== +"@types/react-syntax-highlighter@^15.5.13": + version "15.5.13" + resolved "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz" + integrity sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA== dependencies: "@types/react" "*" -"@types/react-window-infinite-loader@^1.0.6": - version "1.0.6" - resolved "https://registry.npmjs.org/@types/react-window-infinite-loader/-/react-window-infinite-loader-1.0.6.tgz" - integrity sha512-V8g8sBDLVeJJAfEENJS7VXZK+DRJ+jzPNtk8jpj2G+obhf+iqGNUDGwNWCbBhLiD+KpHhf3kWQlKBRi0tAeU4Q== +"@types/react-window-infinite-loader@^1.0.9": + version "1.0.9" + resolved "https://registry.npmjs.org/@types/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz" + integrity sha512-gEInTjQwURCnDOFyIEK2+fWB5gTjqwx30O62QfxA9stE5aiB6EWkGj4UMhc0axq7/FV++Gs/TGW8FtgEx0S6Tw== dependencies: "@types/react" "*" "@types/react-window" "*" -"@types/react-window@*", "@types/react-window@^1.8.5": - version "1.8.5" - resolved "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.5.tgz" - integrity sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw== +"@types/react-window@*", "@types/react-window@^1.8.8": + version "1.8.8" + resolved "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz" + integrity sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@>=16", "@types/react@~18.2.0": +"@types/react@*", "@types/react@^18.0.0 || ^19.0.0", "@types/react@>=16", "@types/react@>=16.8", "@types/react@>=18", "@types/react@~18.2.0": version "18.2.79" resolved "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz" integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w== @@ -3409,10 +3430,10 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/recordrtc@^5.6.11": - version "5.6.11" - resolved "https://registry.npmjs.org/@types/recordrtc/-/recordrtc-5.6.11.tgz" - integrity sha512-X4XD5nltz0cjmyzsPNegQReOPF+C5ARTfSPAPhqnKV7SsfRta/M4FBJ5AtSInCaEveL71FLLSVQE9mg8Uuo++w== +"@types/recordrtc@^5.6.14": + version "5.6.14" + resolved "https://registry.npmjs.org/@types/recordrtc/-/recordrtc-5.6.14.tgz" + integrity sha512-Reiy1sl11xP0r6w8DW3iQjc1BgXFyNC7aDuutysIjpFoqyftbQps9xPA2FoBkfVXpJM61betgYPNt+v65zvMhA== "@types/resolve@^1.20.2": version "1.20.6" @@ -3426,12 +3447,12 @@ dependencies: "@types/node" "*" -"@types/semver@^7.3.12", "@types/semver@^7.3.4": - version "7.5.0" - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz" - integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== +"@types/semver@^7.3.4", "@types/semver@^7.5.8": + version "7.5.8" + resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== -"@types/sortablejs@^1.15.1": +"@types/sortablejs@^1.15.1", "@types/sortablejs@1": version "1.15.1" resolved "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.1.tgz" integrity sha512-g/JwBNToh6oCTAwNS8UGVmjO7NLDKsejVhvE4x1eWiPTC3uCuNsa/TD4ssvX3du+MLiM+SHPNDuijp8y76JzLQ== @@ -3451,17 +3472,22 @@ resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz" integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": - version "2.0.6" - resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== - -"@types/unist@^3.0.0": +"@types/unist@*", "@types/unist@^3.0.0": version "3.0.3" resolved "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz" integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== -"@types/uuid@^9.0.1", "@types/uuid@^9.0.8": +"@types/unist@^2.0.0": + version "2.0.6" + resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +"@types/uuid@^10.0.0": + version "10.0.0" + resolved "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz" + integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== + +"@types/uuid@^9.0.1": version "9.0.8" resolved "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== @@ -3478,143 +3504,97 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.53.0": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz" - integrity sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA== +"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/eslint-plugin@^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "@typescript-eslint/eslint-plugin@^8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz" + integrity sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg== dependencies: - "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.59.9" - "@typescript-eslint/type-utils" "5.59.9" - "@typescript-eslint/utils" "5.59.9" - debug "^4.3.4" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - semver "^7.3.7" - tsutils "^3.21.0" + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.18.2" + "@typescript-eslint/type-utils" "8.18.2" + "@typescript-eslint/utils" "8.18.2" + "@typescript-eslint/visitor-keys" "8.18.2" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/parser@^5.4.2 || ^6.0.0", "@typescript-eslint/parser@^5.53.0": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz" - integrity sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ== +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@^8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.2.tgz" + integrity sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA== dependencies: - "@typescript-eslint/scope-manager" "5.59.9" - "@typescript-eslint/types" "5.59.9" - "@typescript-eslint/typescript-estree" "5.59.9" + "@typescript-eslint/scope-manager" "8.18.2" + "@typescript-eslint/types" "8.18.2" + "@typescript-eslint/typescript-estree" "8.18.2" + "@typescript-eslint/visitor-keys" "8.18.2" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.59.9": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz" - integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ== +"@typescript-eslint/scope-manager@^8.1.0", "@typescript-eslint/scope-manager@^8.18.2", "@typescript-eslint/scope-manager@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz" + integrity sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g== dependencies: - "@typescript-eslint/types" "5.59.9" - "@typescript-eslint/visitor-keys" "5.59.9" + "@typescript-eslint/types" "8.18.2" + "@typescript-eslint/visitor-keys" "8.18.2" -"@typescript-eslint/scope-manager@5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz" - integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== +"@typescript-eslint/type-utils@^8.0.0", "@typescript-eslint/type-utils@^8.18.2", "@typescript-eslint/type-utils@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz" + integrity sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - -"@typescript-eslint/type-utils@5.59.9": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz" - integrity sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q== - dependencies: - "@typescript-eslint/typescript-estree" "5.59.9" - "@typescript-eslint/utils" "5.59.9" + "@typescript-eslint/typescript-estree" "8.18.2" + "@typescript-eslint/utils" "8.18.2" debug "^4.3.4" - tsutils "^3.21.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/types@5.59.9": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz" - integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw== +"@typescript-eslint/types@^8.18.1", "@typescript-eslint/types@^8.18.2", "@typescript-eslint/types@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz" + integrity sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ== -"@typescript-eslint/types@5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz" - integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== - -"@typescript-eslint/typescript-estree@5.59.9": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz" - integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA== +"@typescript-eslint/typescript-estree@^8.18.2", "@typescript-eslint/typescript-estree@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz" + integrity sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg== dependencies: - "@typescript-eslint/types" "5.59.9" - "@typescript-eslint/visitor-keys" "5.59.9" + "@typescript-eslint/types" "8.18.2" + "@typescript-eslint/visitor-keys" "8.18.2" debug "^4.3.4" - globby "^11.1.0" + fast-glob "^3.3.2" is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/typescript-estree@5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz" - integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== +"@typescript-eslint/utils@^8.1.0", "@typescript-eslint/utils@^8.13.0", "@typescript-eslint/utils@^8.18.1", "@typescript-eslint/utils@^8.18.2", "@typescript-eslint/utils@^8.8.1", "@typescript-eslint/utils@>= 8.0", "@typescript-eslint/utils@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz" + integrity sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q== dependencies: - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/visitor-keys" "5.62.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.18.2" + "@typescript-eslint/types" "8.18.2" + "@typescript-eslint/typescript-estree" "8.18.2" -"@typescript-eslint/utils@5.59.9", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.53.0": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz" - integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg== +"@typescript-eslint/visitor-keys@8.18.2": + version "8.18.2" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz" + integrity sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw== dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.59.9" - "@typescript-eslint/types" "5.59.9" - "@typescript-eslint/typescript-estree" "5.59.9" - eslint-scope "^5.1.1" - semver "^7.3.7" + "@typescript-eslint/types" "8.18.2" + eslint-visitor-keys "^4.2.0" -"@typescript-eslint/utils@^5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.59.9": - version "5.59.9" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz" - integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q== - dependencies: - "@typescript-eslint/types" "5.59.9" - eslint-visitor-keys "^3.3.0" - -"@typescript-eslint/visitor-keys@5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz" - integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== - dependencies: - "@typescript-eslint/types" "5.62.0" - eslint-visitor-keys "^3.3.0" - -"@ungap/structured-clone@^1.0.0", "@ungap/structured-clone@^1.2.0": +"@ungap/structured-clone@^1.0.0": version "1.2.0" resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vitest/eslint-plugin@^1.1.20": + version "1.1.20" + resolved "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.20.tgz" + integrity sha512-2eLsgUm+GVOpDfNyH2do//MiNO/WZkXrPi+EjDmXEdUt6Jwnziq4H221L8vJE0aJys+l1FRfSkm4QbaIyDCfBg== + "@vitest/expect@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz" @@ -3646,6 +3626,15 @@ dependencies: tinyspy "^3.0.0" +"@vitest/utils@^2.1.1": + version "2.1.4" + resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz" + integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg== + dependencies: + "@vitest/pretty-format" "2.1.4" + loupe "^3.1.2" + tinyrainbow "^1.2.0" + "@vitest/utils@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz" @@ -3656,15 +3645,6 @@ loupe "^3.1.1" tinyrainbow "^1.2.0" -"@vitest/utils@^2.1.1": - version "2.1.4" - resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz" - integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg== - dependencies: - "@vitest/pretty-format" "2.1.4" - loupe "^3.1.2" - tinyrainbow "^1.2.0" - "@vue/compiler-core@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz" @@ -3676,7 +3656,7 @@ estree-walker "^2.0.2" source-map-js "^1.2.0" -"@vue/compiler-dom@^3.2.47": +"@vue/compiler-dom@^3.2.47", "@vue/compiler-dom@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz" integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA== @@ -3684,12 +3664,35 @@ "@vue/compiler-core" "3.5.13" "@vue/shared" "3.5.13" +"@vue/compiler-sfc@^3.3.0": + version "3.5.13" + resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz" + integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ== + dependencies: + "@babel/parser" "^7.25.3" + "@vue/compiler-core" "3.5.13" + "@vue/compiler-dom" "3.5.13" + "@vue/compiler-ssr" "3.5.13" + "@vue/shared" "3.5.13" + estree-walker "^2.0.2" + magic-string "^0.30.11" + postcss "^8.4.48" + source-map-js "^1.2.0" + +"@vue/compiler-ssr@3.5.13": + version "3.5.13" + resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz" + integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA== + dependencies: + "@vue/compiler-dom" "3.5.13" + "@vue/shared" "3.5.13" + "@vue/shared@3.5.13": version "3.5.13" resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz" integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== -"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": +"@webassemblyjs/ast@^1.14.1", "@webassemblyjs/ast@1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz" integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== @@ -3790,7 +3793,7 @@ "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/wasm-parser" "1.14.1" -"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": +"@webassemblyjs/wasm-parser@^1.14.1", "@webassemblyjs/wasm-parser@1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz" integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== @@ -3825,11 +3828,6 @@ abab@^2.0.6: resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -abbrev@1: - version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -3857,7 +3855,7 @@ acorn-walk@^8.0.2, acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.0.0, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.0.0, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -3877,31 +3875,17 @@ agent-base@6: dependencies: debug "4" -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ahooks-v3-count@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz" - integrity sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ== - -ahooks@^3.7.5: - version "3.7.7" - resolved "https://registry.npmjs.org/ahooks/-/ahooks-3.7.7.tgz" - integrity sha512-5e5WlPq81Y84UnTLOKIQeq2cJw4aa7yj8fR2Nb/oMmXPrWMjIMCbPS1o+fpxSfCaNA3AzOnnMc8AehWRZltkJQ== +ahooks@^3.8.1: + version "3.8.4" + resolved "https://registry.npmjs.org/ahooks/-/ahooks-3.8.4.tgz" + integrity sha512-39wDEw2ZHvypaT14EpMMk4AzosHWt0z9bulY0BeDsvc9PqJEV+Kjh/4TZfftSsotBMq52iYIOFPd3PR56e0ZJg== dependencies: "@babel/runtime" "^7.21.0" - "@types/js-cookie" "^2.x.x" - ahooks-v3-count "^1.0.0" dayjs "^1.9.1" intersection-observer "^0.12.0" - js-cookie "^2.x.x" + js-cookie "^3.0.5" lodash "^4.17.21" + react-fast-compare "^3.2.2" resize-observer-polyfill "^1.5.1" screenfull "^5.0.0" tslib "^2.4.1" @@ -3925,7 +3909,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -3935,7 +3919,7 @@ ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.9.0: +ajv@^8.0.0: version "8.17.1" resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -3945,13 +3929,30 @@ ajv@^8.0.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ajv@^8.8.2, ajv@^8.9.0: + version "8.17.1" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" + ansi-html-community@0.0.8: version "0.0.8" resolved "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" @@ -3989,6 +3990,16 @@ ansi-styles@^6.0.0: resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +ansi-styles@^6.2.1: + version "6.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + any-promise@^1.0.0: version "1.3.0" resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" @@ -4002,18 +4013,10 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -"aproba@^1.0.3 || ^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - -are-we-there-yet@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" - integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" +are-docs-informative@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz" + integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== arg@^4.1.0: version "4.1.3" @@ -4037,49 +4040,63 @@ argparse@^2.0.1: resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@5.3.0, aria-query@^5.0.0, aria-query@^5.1.3: +aria-query@^5.0.0, aria-query@5.3.0: version "5.3.0" resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== dependencies: dequal "^2.0.3" -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" +aria-query@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== -array-includes@^3.1.5, array-includes@^3.1.6, array-includes@^3.1.7: - version "3.1.7" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz" - integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-includes@^3.1.6, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" is-string "^1.0.7" -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.findlastindex@^1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz" - integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" -array.prototype.flat@^1.3.2: +array.prototype.findlastindex@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz" + integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: version "1.3.2" resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== @@ -4089,39 +4106,39 @@ array.prototype.flat@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== +array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" -array.prototype.tosorted@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz" - integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" -arraybuffer.prototype.slice@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz" - integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-array-buffer "^3.0.2" - is-shared-array-buffer "^1.0.2" + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" asn1.js@^4.10.1: version "4.10.1" @@ -4148,10 +4165,10 @@ assertion-error@^2.0.1: resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz" - integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== ast-types@^0.16.1: version "0.16.1" @@ -4160,11 +4177,6 @@ ast-types@^0.16.1: dependencies: tslib "^2.0.1" -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - astring@^1.8.0: version "1.8.6" resolved "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz" @@ -4177,46 +4189,39 @@ async@^2.6.4: dependencies: lodash "^4.17.14" -asynciterator.prototype@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz" - integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== - dependencies: - has-symbols "^1.0.3" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -autoprefixer@^10.4.14: - version "10.4.14" - resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz" - integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== +autoprefixer@^10.4.20: + version "10.4.20" + resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz" + integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== dependencies: - browserslist "^4.21.5" - caniuse-lite "^1.0.30001464" - fraction.js "^4.2.0" + browserslist "^4.23.3" + caniuse-lite "^1.0.30001646" + fraction.js "^4.3.7" normalize-range "^0.1.2" - picocolors "^1.0.0" + picocolors "^1.0.1" postcss-value-parser "^4.2.0" -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -axe-core@^4.6.2: - version "4.7.2" - resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.7.2.tgz" - integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== - -axobject-query@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz" - integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== dependencies: - deep-equal "^2.0.5" + possible-typed-array-names "^1.0.0" + +axe-core@^4.10.0: + version "4.10.2" + resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz" + integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== babel-jest@^29.7.0: version "29.7.0" @@ -4325,6 +4330,11 @@ base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +before-after-hook@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz" + integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== + better-opn@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz" @@ -4354,7 +4364,22 @@ bing-translate-api@^4.0.2: dependencies: got "^11.8.6" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: +birecord@^0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/birecord/-/birecord-0.1.1.tgz" + integrity sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw== + +bn.js@^4.0.0: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^4.1.0: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -4384,6 +4409,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" @@ -4464,7 +4496,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.21.5, browserslist@^4.24.0, browserslist@^4.24.2: +browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.2, "browserslist@>= 4.21.0": version "4.24.2" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz" integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== @@ -4509,13 +4541,6 @@ builtin-status-codes@^3.0.0: resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz" integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== -builtins@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz" - integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== - dependencies: - semver "^7.0.0" - bundle-name@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz" @@ -4548,16 +4573,31 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: + 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== dependencies: - es-define-property "^1.0.0" es-errors "^1.3.0" function-bind "^1.1.2" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" get-intrinsic "^1.2.4" - set-function-length "^1.2.1" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" callsites@^3.0.0: version "3.1.0" @@ -4587,19 +4627,10 @@ camelcase@^6.2.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001669: - version "1.0.30001678" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001678.tgz" - integrity sha512-RR+4U/05gNtps58PEBDZcPWTgEO2MBeoPZ96aQcjmfkBWRIDfN451fW2qyDA9/+HohLLIL5GqiMwA+IB1pWarw== - -canvas@^2.11.2: - version "2.11.2" - resolved "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz" - integrity sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw== - dependencies: - "@mapbox/node-pre-gyp" "^1.0.0" - nan "^2.17.0" - simple-get "^3.0.3" +caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669: + version "1.0.30001690" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz" + integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w== case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" @@ -4622,19 +4653,6 @@ chai@^5.1.1: loupe "^3.1.0" pathval "^2.0.0" -chalk@4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz" - integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz" - integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== - chalk@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" @@ -4651,6 +4669,19 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@~5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +chalk@4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" @@ -4703,7 +4734,7 @@ chevrotain-allstar@~0.3.0: dependencies: lodash-es "^4.17.21" -chevrotain@~11.0.3: +chevrotain@^11.0.0, chevrotain@~11.0.3: version "11.0.3" resolved "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz" integrity sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw== @@ -4715,10 +4746,10 @@ chevrotain@~11.0.3: "@chevrotain/utils" "11.0.3" lodash-es "4.17.21" -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== +chokidar@^3.5.3, chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -4730,26 +4761,33 @@ chevrotain@~11.0.3: optionalDependencies: fsevents "~2.3.2" -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" -chromatic@^11.4.0: - version "11.16.5" - resolved "https://registry.npmjs.org/chromatic/-/chromatic-11.16.5.tgz" - integrity sha512-wUEKXyu3GYmUg6Jq13uyRE9iC8ph5gbfDHdyHH0vQathkGQrcjHHdoxI/GXKIjU6d+xupLon8sxRV9NuZKTWbA== +chromatic@^11.15.0: + version "11.20.2" + resolved "https://registry.npmjs.org/chromatic/-/chromatic-11.20.2.tgz" + integrity sha512-c+M3HVl5Y60c7ipGTZTyeWzWubRW70YsJ7PPDpO1D735ib8+Lu3yGF90j61pvgkXGngpkTPHZyBw83lcu2JMxA== chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -ci-info@^3.2.0, ci-info@^3.6.1: +ci-info@^3.2.0: version "3.8.0" resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== +ci-info@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz" + integrity sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" @@ -4775,16 +4813,16 @@ classcat@^5.0.3, classcat@^5.0.4: resolved "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz" integrity sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w== +classnames@^2.2.1, classnames@^2.3.2, classnames@^2.5.1: + version "2.5.1" + resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + classnames@2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== -classnames@^2.2.1, classnames@^2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== - clean-css@^5.2.2: version "5.3.3" resolved "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz" @@ -4799,35 +4837,22 @@ clean-regexp@^1.0.0: dependencies: escape-string-regexp "^1.0.5" -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== dependencies: - restore-cursor "^3.1.0" + restore-cursor "^5.0.0" -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - -cli-truncate@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz" - integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== +cli-truncate@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz" + integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA== dependencies: slice-ansi "^5.0.0" - string-width "^5.0.0" + string-width "^7.0.0" -client-only@0.0.1, client-only@^0.0.1: +client-only@^0.0.1, client-only@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== @@ -4848,16 +4873,21 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clsx@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz" - integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== - clsx@^1.1.1: version "1.2.1" resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +clsx@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +clsx@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== + co@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" @@ -4886,6 +4916,11 @@ code-inspector-plugin@^0.18.1: vite-code-inspector-plugin "0.18.2" webpack-code-inspector-plugin "0.18.2" +collapse-white-space@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz" + integrity sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw== + collect-v8-coverage@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" @@ -4911,11 +4946,6 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.2: - version "1.1.3" - resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - color@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" @@ -4924,7 +4954,7 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" -colorette@^2.0.10, colorette@^2.0.19: +colorette@^2.0.10, colorette@^2.0.20: version "2.0.20" resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -4946,16 +4976,6 @@ comma-separated-tokens@^2.0.0: resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== -commander@7: - version "7.2.0" - resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - commander@^2.20.0: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" @@ -4971,6 +4991,21 @@ commander@^8.3.0: resolved "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@~12.1.0: + version "12.1.0" + resolved "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +commander@7: + version "7.2.0" + resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +comment-parser@^1.4.0, comment-parser@1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz" + integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz" @@ -4981,6 +5016,11 @@ commondir@^1.0.1: resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +compare-versions@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz" + integrity sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -4996,11 +5036,6 @@ console-browserify@^1.2.0: resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz" @@ -5131,7 +5166,7 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -5239,11 +5274,18 @@ cytoscape-fcose@^2.2.0: dependencies: cose-base "^2.2.0" -cytoscape@^3.29.2: +cytoscape@^3.2.0, cytoscape@^3.29.2: version "3.30.3" resolved "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.3.tgz" integrity sha512-HncJ9gGJbVtw7YXtIs3+6YAFSSiKsom0amWc33Z7QbylbY2JGMrA0yz4EwrdTScZxnwclXeEZHzO5pxoy0ZE4g== +d3-array@^3.2.0, "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: + version "3.2.4" + resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + "d3-array@1 - 2": version "2.12.1" resolved "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz" @@ -5251,13 +5293,6 @@ cytoscape@^3.29.2: dependencies: internmap "^1.0.0" -"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: - version "3.2.4" - resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz" - integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== - dependencies: - internmap "1 - 2" - d3-axis@3: version "3.0.0" resolved "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz" @@ -5305,7 +5340,7 @@ d3-delaunay@6: resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz" integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== -"d3-drag@2 - 3", d3-drag@3, d3-drag@^3.0.0: +d3-drag@^3.0.0, "d3-drag@2 - 3", d3-drag@3: version "3.0.0" resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz" integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== @@ -5367,16 +5402,16 @@ d3-hierarchy@3: dependencies: d3-color "1 - 3" +d3-path@^3.1.0, "d3-path@1 - 3", d3-path@3: + version "3.1.0" + resolved "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + d3-path@1: version "1.0.9" resolved "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz" integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== -"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz" - integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== - d3-polygon@3: version "3.0.1" resolved "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz" @@ -5419,18 +5454,11 @@ d3-scale@4: d3-time "2.1.1 - 3" d3-time-format "2 - 4" -"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0: +d3-selection@^3.0.0, "d3-selection@2 - 3", d3-selection@3: version "3.0.0" resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz" integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== -d3-shape@3: - version "3.2.0" - resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz" - integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== - dependencies: - d3-path "^3.1.0" - d3-shape@^1.2.0: version "1.3.7" resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz" @@ -5438,6 +5466,13 @@ d3-shape@^1.2.0: dependencies: d3-path "1" +d3-shape@3: + version "3.2.0" + resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + "d3-time-format@2 - 4", d3-time-format@4: version "4.1.0" resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz" @@ -5468,7 +5503,7 @@ d3-shape@^1.2.0: d3-interpolate "1 - 3" d3-timer "1 - 3" -d3-zoom@3, d3-zoom@^3.0.0: +d3-zoom@^3.0.0, d3-zoom@3: version "3.0.0" resolved "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz" integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== @@ -5537,18 +5572,38 @@ data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -dayjs@^1.11.10, dayjs@^1.11.7, dayjs@^1.9.1: +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +dayjs@^1.11.10, dayjs@^1.11.13, dayjs@^1.9.1: version "1.11.13" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" @@ -5556,6 +5611,20 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@4: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.3.6: + version "4.4.0" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + debug@^4.4.0: version "4.4.0" resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" @@ -5563,6 +5632,13 @@ debug@^4.4.0: dependencies: ms "^2.1.3" +debug@~4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decimal.js@^10.4.2: version "10.4.3" resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" @@ -5575,13 +5651,6 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz" @@ -5604,30 +5673,6 @@ deep-eql@^5.0.1: resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz" integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== -deep-equal@^2.0.5: - version "2.2.1" - resolved "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz" - integrity sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ== - dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - es-get-iterator "^1.1.3" - get-intrinsic "^1.2.0" - is-arguments "^1.1.1" - is-array-buffer "^3.0.2" - is-date-object "^1.0.5" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - isarray "^2.0.5" - object-is "^1.1.5" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.0" - side-channel "^1.0.4" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" @@ -5680,7 +5725,7 @@ define-lazy-prop@^3.0.0: resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz" integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== -define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -5701,11 +5746,6 @@ delayed-stream@~1.0.0: resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== - dequal@^2.0.0, dequal@^2.0.2, dequal@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" @@ -5719,7 +5759,12 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-libc@^2.0.0, detect-libc@^2.0.3: +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== @@ -5729,7 +5774,7 @@ detect-newline@^3.0.0: resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -devlop@^1.0.0: +devlop@^1.0.0, devlop@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz" integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== @@ -5751,11 +5796,6 @@ diff@^4.0.1: resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== - diffie-hellman@^5.0.3: version "5.0.3" resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" @@ -5817,21 +5857,12 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -dom-serializer@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.2" - entities "^4.2.0" - domain-browser@^4.22.0: version "4.23.0" resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-4.23.0.tgz" integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== -domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: +domelementtype@^2.0.1, domelementtype@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== @@ -5850,13 +5881,6 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" -domhandler@^5.0.2, domhandler@^5.0.3: - version "5.0.3" - resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== - dependencies: - domelementtype "^2.3.0" - dompurify@^3.2.1: version "3.2.2" resolved "https://registry.npmjs.org/dompurify/-/dompurify-3.2.2.tgz" @@ -5873,15 +5897,6 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" -domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== - dependencies: - dom-serializer "^2.0.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - dot-case@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" @@ -5895,6 +5910,20 @@ dotenv@^16.1.4, dotenv@^16.3.1: resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz" integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + echarts-for-react@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/echarts-for-react/-/echarts-for-react-3.0.2.tgz" @@ -5903,9 +5932,9 @@ echarts-for-react@^3.0.2: fast-deep-equal "^3.1.3" size-sensor "^1.0.1" -echarts@^5.5.1: +"echarts@^3.0.0 || ^4.0.0 || ^5.0.0", echarts@^5.5.1: version "5.5.1" - resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.5.1.tgz#8dc9c68d0c548934bedcb5f633db07ed1dd2101c" + resolved "https://registry.npmjs.org/echarts/-/echarts-5.5.1.tgz" integrity sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA== dependencies: tslib "2.3.0" @@ -5944,6 +5973,11 @@ emoji-mart@^5.5.2: resolved "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.5.2.tgz" integrity sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A== +emoji-regex@^10.3.0: + version "10.4.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" @@ -5988,7 +6022,7 @@ entities@^2.0.0: resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: +entities@^4.4.0, entities@^4.5.0: version "4.5.0" resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -5998,6 +6032,11 @@ env-paths@^2.2.1: resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" @@ -6012,127 +6051,147 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.3.4" -es-abstract@^1.20.4, es-abstract@^1.22.1: - version "1.22.3" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz" - integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6: + version "1.23.7" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz" + integrity sha512-OygGC8kIcDhXX+6yAZRGLqwi2CmEXCbLQixeGUgYeR+Qwlppqmo7DIDr8XibtEBZp+fJcoYpoatp5qwLMEdcqQ== dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.2" - available-typed-arrays "^1.0.5" - call-bind "^1.0.5" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.2" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.2.6" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.12" - is-weakref "^1.0.2" - object-inspect "^1.13.1" + is-data-view "^1.0.2" + is-regex "^1.2.1" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.0" + math-intrinsics "^1.1.0" + object-inspect "^1.13.3" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.1" - safe-array-concat "^1.0.1" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.8" - string.prototype.trimend "^1.0.7" - string.prototype.trimstart "^1.0.7" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.13" + object.assign "^4.1.7" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-regex-test "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.18" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== es-errors@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-get-iterator@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz" - integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - has-symbols "^1.0.3" - is-arguments "^1.1.1" - is-map "^2.0.2" - is-set "^2.0.2" - is-string "^1.0.7" - isarray "^2.0.5" - stop-iteration-iterator "^1.0.0" - -es-iterator-helpers@^1.0.12: - version "1.0.15" - resolved "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz" - integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== - dependencies: - asynciterator.prototype "^1.0.0" - call-bind "^1.0.2" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - es-abstract "^1.22.1" - es-set-tostringtag "^2.0.1" - function-bind "^1.1.1" - get-intrinsic "^1.2.1" - globalthis "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - iterator.prototype "^1.1.2" - safe-array-concat "^1.0.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.6" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" -es-module-lexer@^1.2.1, es-module-lexer@^1.5.0: +es-module-lexer@^1.2.1, es-module-lexer@^1.5.0, es-module-lexer@^1.5.3: version "1.5.4" resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz" integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - -es-shim-unscopables@^1.0.0: +es-object-atoms@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== dependencies: - has "^1.0.3" + es-errors "^1.3.0" -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +esast-util-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz" + integrity sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + unist-util-position-from-estree "^2.0.0" + +esast-util-from-js@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz" + integrity sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw== + dependencies: + "@types/estree-jsx" "^1.0.0" + acorn "^8.0.0" + esast-util-from-estree "^2.0.0" + vfile-message "^4.0.0" esbuild-code-inspector-plugin@0.18.2: version "0.18.2" @@ -6148,7 +6207,7 @@ esbuild-register@^3.5.0: dependencies: debug "^4.3.4" -"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0": +"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", "esbuild@>=0.12 <1": version "0.24.0" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz" integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== @@ -6214,20 +6273,50 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-next@^14.0.4: - version "14.0.4" - resolved "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.4.tgz" - integrity sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ== +eslint-compat-utils@^0.5.1: + version "0.5.1" + resolved "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz" + integrity sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q== dependencies: - "@next/eslint-plugin-next" "14.0.4" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/parser" "^5.4.2 || ^6.0.0" + semver "^7.5.4" + +eslint-compat-utils@^0.6.0: + version "0.6.4" + resolved "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz" + integrity sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw== + dependencies: + semver "^7.5.4" + +eslint-config-flat-gitignore@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/eslint-config-flat-gitignore/-/eslint-config-flat-gitignore-0.3.0.tgz" + integrity sha512-0Ndxo4qGhcewjTzw52TK06Mc00aDtHNTdeeW2JfONgDcLkRO/n/BteMRzNVpLQYxdCC/dFEilfM9fjjpGIJ9Og== + dependencies: + "@eslint/compat" "^1.1.1" + find-up-simple "^1.0.0" + +eslint-config-next@^15.0.0: + version "15.1.2" + resolved "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.2.tgz" + integrity sha512-PrMm1/4zWSJ689wd/ypWIR5ZF1uvmp3EkgpgBV1Yu6PhEobBjXMGgT8bVNelwl17LXojO8D5ePFRiI4qXjsPRA== + dependencies: + "@next/eslint-plugin-next" "15.1.2" + "@rushstack/eslint-patch" "^1.10.3" + "@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" eslint-import-resolver-node "^0.3.6" eslint-import-resolver-typescript "^3.5.2" - eslint-plugin-import "^2.28.1" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + eslint-plugin-import "^2.31.0" + eslint-plugin-jsx-a11y "^6.10.0" + eslint-plugin-react "^7.37.0" + eslint-plugin-react-hooks "^5.0.0" + +eslint-flat-config-utils@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-0.4.0.tgz" + integrity sha512-kfd5kQZC+BMO0YwTol6zxjKX1zAsk8JfSAopbKjKqmENTJcew+yBejuvccAg37cvOrN0Mh+DVbeyznuNWEjt4A== + dependencies: + pathe "^1.1.2" eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: version "0.3.9" @@ -6252,236 +6341,418 @@ eslint-import-resolver-typescript@^3.5.2: is-glob "^4.0.3" synckit "^0.8.5" -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.0" - resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz" - integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== +eslint-json-compat-utils@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/eslint-json-compat-utils/-/eslint-json-compat-utils-0.2.1.tgz" + integrity sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg== + dependencies: + esquery "^1.6.0" + +eslint-merge-processors@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/eslint-merge-processors/-/eslint-merge-processors-0.1.0.tgz" + integrity sha512-IvRXXtEajLeyssvW4wJcZ2etxkR9mUf4zpNwgI+m/Uac9RfXHskuJefkHUcawVzePnd6xp24enp5jfgdHzjRdQ== + +eslint-module-utils@^2.12.0, eslint-module-utils@^2.7.4: + version "2.12.0" + resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz" + integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== dependencies: debug "^3.2.7" -eslint-plugin-antfu@0.36.0: - version "0.36.0" - resolved "https://registry.npmjs.org/eslint-plugin-antfu/-/eslint-plugin-antfu-0.36.0.tgz" - integrity sha512-qLYtjZC2y6d1fvVtG4nvVGoBUDEuUwQsS4E1RwjoEZyONZAkHYDPfeoeULDlPS0IqumSW8uGR6zGSAXi5rrVMg== +eslint-plugin-antfu@^2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/eslint-plugin-antfu/-/eslint-plugin-antfu-2.7.0.tgz" + integrity sha512-gZM3jq3ouqaoHmUNszb1Zo2Ux7RckSvkGksjLWz9ipBYGSv1EwwBETN6AdiUXn+RpVHXTbEMPAPlXJazcA6+iA== dependencies: - "@typescript-eslint/utils" "^5.53.0" + "@antfu/utils" "^0.7.10" -eslint-plugin-es@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz" - integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ== +eslint-plugin-command@^0.2.7: + version "0.2.7" + resolved "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-0.2.7.tgz" + integrity sha512-UXJ/1R6kdKDcHhiRqxHJ9RZ3juMR1IWQuSrnwt56qCjxt/am+5+YDt6GKs1FJPnppe6/geEYsO3CR9jc63i0xw== dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" + "@es-joy/jsdoccomment" "^0.49.0" -eslint-plugin-eslint-comments@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz" - integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== +eslint-plugin-es-x@^7.8.0: + version "7.8.0" + resolved "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz" + integrity sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ== dependencies: - escape-string-regexp "^1.0.5" - ignore "^5.0.5" + "@eslint-community/eslint-utils" "^4.1.2" + "@eslint-community/regexpp" "^4.11.0" + eslint-compat-utils "^0.5.1" -eslint-plugin-html@^7.1.0: - version "7.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-7.1.0.tgz" - integrity sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg== +eslint-plugin-import-x@^4.6.1: + version "4.6.1" + resolved "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.6.1.tgz" + integrity sha512-wluSUifMIb7UfwWXqx7Yx0lE/SGCcGXECLx/9bCmbY2nneLwvAZ4vkd1IXDjPKFvdcdUgr1BaRnaRpx3k2+Pfw== dependencies: - htmlparser2 "^8.0.1" + "@types/doctrine" "^0.0.9" + "@typescript-eslint/scope-manager" "^8.1.0" + "@typescript-eslint/utils" "^8.1.0" + debug "^4.3.4" + doctrine "^3.0.0" + enhanced-resolve "^5.17.1" + eslint-import-resolver-node "^0.3.9" + get-tsconfig "^4.7.3" + is-glob "^4.0.3" + minimatch "^9.0.3" + semver "^7.6.3" + stable-hash "^0.0.4" + tslib "^2.6.3" -eslint-plugin-import@^2.27.5, eslint-plugin-import@^2.28.1: - version "2.29.1" - resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== +eslint-plugin-import@*, eslint-plugin-import@^2.31.0: + version "2.31.0" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" + integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.8" + array.prototype.findlastindex "^1.2.5" array.prototype.flat "^1.3.2" array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" + eslint-module-utils "^2.12.0" + hasown "^2.0.2" + is-core-module "^2.15.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.0" semver "^6.3.1" + string.prototype.trimend "^1.0.8" tsconfig-paths "^3.15.0" -eslint-plugin-jest@^27.2.1: - version "27.2.1" - resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz" - integrity sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg== +eslint-plugin-jsdoc@^50.6.1: + version "50.6.1" + resolved "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz" + integrity sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ== dependencies: - "@typescript-eslint/utils" "^5.10.0" + "@es-joy/jsdoccomment" "~0.49.0" + are-docs-informative "^0.0.2" + comment-parser "1.4.1" + debug "^4.3.6" + escape-string-regexp "^4.0.0" + espree "^10.1.0" + esquery "^1.6.0" + parse-imports "^2.1.1" + semver "^7.6.3" + spdx-expression-parse "^4.0.0" + synckit "^0.9.1" -eslint-plugin-jsonc@^2.6.0: - version "2.8.0" - resolved "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.8.0.tgz" - integrity sha512-K4VsnztnNwpm+V49CcCu5laq8VjclJpuhfI9LFkOrOyK+BKdQHMzkWo43B4X4rYaVrChm4U9kw/tTU5RHh5Wtg== +eslint-plugin-jsonc@^2.18.2: + version "2.18.2" + resolved "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.18.2.tgz" + integrity sha512-SDhJiSsWt3nItl/UuIv+ti4g3m4gpGkmnUJS9UWR3TrpyNsIcnJoBRD7Kof6cM4Rk3L0wrmY5Tm3z7ZPjR2uGg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" + eslint-compat-utils "^0.6.0" + eslint-json-compat-utils "^0.2.1" + espree "^9.6.1" + graphemer "^1.4.0" jsonc-eslint-parser "^2.0.4" natural-compare "^1.4.0" + synckit "^0.6.0" -eslint-plugin-jsx-a11y@^6.7.1: - version "6.7.1" - resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz" - integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA== +eslint-plugin-jsx-a11y@^6.10.0: + version "6.10.2" + resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz" + integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== dependencies: - "@babel/runtime" "^7.20.7" - aria-query "^5.1.3" - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - ast-types-flow "^0.0.7" - axe-core "^4.6.2" - axobject-query "^3.1.1" + aria-query "^5.3.2" + array-includes "^3.1.8" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "^4.10.0" + axobject-query "^4.1.0" damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" - has "^1.0.3" - jsx-ast-utils "^3.3.3" - language-tags "=1.0.5" + hasown "^2.0.2" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - semver "^6.3.0" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.1" -eslint-plugin-markdown@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-3.0.0.tgz" - integrity sha512-hRs5RUJGbeHDLfS7ELanT0e29Ocyssf/7kBM+p7KluY5AwngGkDf8Oyu4658/NZSGTTq05FZeWbkxXtbVyHPwg== +eslint-plugin-n@^17.15.1: + version "17.15.1" + resolved "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.1.tgz" + integrity sha512-KFw7x02hZZkBdbZEFQduRGH4VkIH4MW97ClsbAM4Y4E6KguBJWGfWG1P4HEIpZk2bkoWf0bojpnjNAhYQP8beA== dependencies: - mdast-util-from-markdown "^0.8.5" + "@eslint-community/eslint-utils" "^4.4.1" + enhanced-resolve "^5.17.1" + eslint-plugin-es-x "^7.8.0" + get-tsconfig "^4.8.1" + globals "^15.11.0" + ignore "^5.3.2" + minimatch "^9.0.5" + semver "^7.6.3" -eslint-plugin-n@^15.6.1: - version "15.7.0" - resolved "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz" - integrity sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q== +eslint-plugin-no-only-tests@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz" + integrity sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q== + +eslint-plugin-perfectionist@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.4.0.tgz" + integrity sha512-B78pWxCsA2sClourpWEmWziCcjEsAEyxsNV5G6cxxteu/NI0/2en9XZUONf5e/+O+dgoLZsEPHQEhnIxJcnUvA== dependencies: - builtins "^5.0.1" - eslint-plugin-es "^4.1.0" - eslint-utils "^3.0.0" - ignore "^5.1.1" - is-core-module "^2.11.0" - minimatch "^3.1.2" - resolve "^1.22.1" - semver "^7.3.8" + "@typescript-eslint/types" "^8.18.1" + "@typescript-eslint/utils" "^8.18.1" + natural-orderby "^5.0.0" -eslint-plugin-no-only-tests@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz" - integrity sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw== - -eslint-plugin-promise@^6.1.1: - version "6.1.1" - resolved "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz" - integrity sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig== - -"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": - version "5.0.0-canary-7118f5dd7-20230705" - resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz" - integrity sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw== - -eslint-plugin-react@^7.33.2: - version "7.33.2" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz" - integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== +eslint-plugin-react-debug@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-debug/-/eslint-plugin-react-debug-1.22.1.tgz" + integrity sha512-dtXr9UTiWWSVkwNkaYkA04khR6xebqLeX3O8/ZJfIeFaA+58DRhwWGqzywLDjjLIM7s0V7UmuuvAGff8CVS9fA== dependencies: - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - array.prototype.tosorted "^1.1.1" + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +eslint-plugin-react-dom@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-dom/-/eslint-plugin-react-dom-1.22.1.tgz" + integrity sha512-uQg81POQCR1rDlOfvzRZQ0KoJeLkSmpsmGLU0r5unsCNJFF6hCEcqhYHapmn7oLV/6MebLF2exptsXjNc+L7rQ== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + compare-versions "^6.1.1" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +eslint-plugin-react-hooks-extra@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-hooks-extra/-/eslint-plugin-react-hooks-extra-1.22.1.tgz" + integrity sha512-9g+Cxf76nne6n9cPOzQpj4S6f8XgSqRwkDO/XbHzuU6xgaxc2Y/9lD9YX1N9Tm3d86XtdLHkWfDFBD4SigSC2Q== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +eslint-plugin-react-hooks@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz" + integrity sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw== + +eslint-plugin-react-naming-convention@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-naming-convention/-/eslint-plugin-react-naming-convention-1.22.1.tgz" + integrity sha512-KXsHYBk9x9+UYoXfLHbKrc1ntXu+TYIB5nmwEUP5PrjcmUO4GuFNFDzWSqUVileQbJPAXWBUwEBGfwCePGwJrg== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +eslint-plugin-react-refresh@^0.4.13, eslint-plugin-react-refresh@^0.4.4: + version "0.4.16" + resolved "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.16.tgz" + integrity sha512-slterMlxAhov/DZO8NScf6mEeMBBXodFUolijDvrtTxyezyLoTQaa73FyYus/VbTdftd8wBgBxPMRk3poleXNQ== + +eslint-plugin-react-web-api@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-web-api/-/eslint-plugin-react-web-api-1.22.1.tgz" + integrity sha512-g/m8c61PWqVmF2P5P9nrL7jobTCbBRdChTfL1fSMXmI9Ax3Ggl+7dWLhIFSRffEUIOOE6aAHrMT3EBWXM25uYQ== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + birecord "^0.1.1" + string-ts "^2.2.0" + ts-pattern "^5.6.0" + +eslint-plugin-react-x@1.22.1: + version "1.22.1" + resolved "https://registry.npmjs.org/eslint-plugin-react-x/-/eslint-plugin-react-x-1.22.1.tgz" + integrity sha512-+YoMnr/JLoXIhviecNYsY7kcjHaOQBOyT7wQjyaxxNrqGeTKPJI6rtk+Sb7ZGXDXVg3L8S+gyzS2VQTt9KS9gQ== + dependencies: + "@eslint-react/ast" "1.22.1" + "@eslint-react/core" "1.22.1" + "@eslint-react/eff" "1.22.1" + "@eslint-react/jsx" "1.22.1" + "@eslint-react/shared" "1.22.1" + "@eslint-react/types" "1.22.1" + "@eslint-react/var" "1.22.1" + "@typescript-eslint/scope-manager" "^8.18.2" + "@typescript-eslint/type-utils" "^8.18.2" + "@typescript-eslint/types" "^8.18.2" + "@typescript-eslint/utils" "^8.18.2" + compare-versions "^6.1.1" + is-immutable-type "^5.0.0" + string-ts "^2.2.0" + ts-api-utils "^2.0.0" + ts-pattern "^5.6.0" + +eslint-plugin-react@^7.37.0: + version "7.37.3" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz" + integrity sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.3" + array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" - es-iterator-helpers "^1.0.12" + es-iterator-helpers "^1.2.1" estraverse "^5.3.0" + hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - object.hasown "^1.1.2" - object.values "^1.1.6" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.values "^1.2.1" prop-types "^15.8.1" - resolve "^2.0.0-next.4" + resolve "^2.0.0-next.5" semver "^6.3.1" - string.prototype.matchall "^4.0.8" + string.prototype.matchall "^4.0.12" + string.prototype.repeat "^1.0.0" -eslint-plugin-storybook@^0.9.0: - version "0.9.0" - resolved "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.9.0.tgz" - integrity sha512-qOT/2vQBo0VqrG/BhZv8IdSsKQiyzJw+2Wqq+WFCiblI/PfxLSrGkF/buiXF+HumwfsCyBdaC94UhqhmYFmAvA== +eslint-plugin-regexp@^2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.7.0.tgz" + integrity sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA== dependencies: - "@storybook/csf" "^0.0.1" - "@typescript-eslint/utils" "^5.62.0" - requireindex "^1.2.0" + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.11.0" + comment-parser "^1.4.0" + jsdoc-type-pratt-parser "^4.0.0" + refa "^0.12.1" + regexp-ast-analysis "^0.7.1" + scslre "^0.3.0" + +eslint-plugin-storybook@^0.10.1: + version "0.10.2" + resolved "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.10.2.tgz" + integrity sha512-iOrFJfyLgRLIbWDLbbs3J4yrknvIB+uiZ8KGqGOEXTL7/BGuBMZLiIU9Q4Pm/VYJrHN4JqmMtwCSrAemHL2nFg== + dependencies: + "@storybook/csf" "^0.1.11" + "@typescript-eslint/utils" "^8.8.1" ts-dedent "^2.2.0" -eslint-plugin-unicorn@^45.0.2: - version "45.0.2" - resolved "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-45.0.2.tgz" - integrity sha512-Y0WUDXRyGDMcKLiwgL3zSMpHrXI00xmdyixEGIg90gHnj0PcHY4moNv3Ppje/kDivdAy5vUeUr7z211ImPv2gw== +eslint-plugin-tailwindcss@^3.17.5: + version "3.17.5" + resolved "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.17.5.tgz" + integrity sha512-8Mi7p7dm+mO1dHgRHHFdPu4RDTBk69Cn4P0B40vRQR+MrguUpwmKwhZy1kqYe3Km8/4nb+cyrCF+5SodOEmaow== dependencies: - "@babel/helper-validator-identifier" "^7.19.1" - "@eslint-community/eslint-utils" "^4.1.2" - ci-info "^3.6.1" + fast-glob "^3.2.5" + postcss "^8.4.4" + +eslint-plugin-toml@^0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/eslint-plugin-toml/-/eslint-plugin-toml-0.12.0.tgz" + integrity sha512-+/wVObA9DVhwZB1nG83D2OAQRrcQZXy+drqUnFJKymqnmbnbfg/UPmEMCKrJNcEboUGxUjYrJlgy+/Y930mURQ== + dependencies: + debug "^4.1.1" + eslint-compat-utils "^0.6.0" + lodash "^4.17.19" + toml-eslint-parser "^0.10.0" + +eslint-plugin-unicorn@^56.0.1: + version "56.0.1" + resolved "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.1.tgz" + integrity sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + "@eslint-community/eslint-utils" "^4.4.0" + ci-info "^4.0.0" clean-regexp "^1.0.0" - esquery "^1.4.0" + core-js-compat "^3.38.1" + esquery "^1.6.0" + globals "^15.9.0" indent-string "^4.0.0" - is-builtin-module "^3.2.0" + is-builtin-module "^3.2.1" jsesc "^3.0.2" - lodash "^4.17.21" pluralize "^8.0.0" read-pkg-up "^7.0.1" - regexp-tree "^0.1.24" - regjsparser "^0.9.1" - safe-regex "^2.1.1" - semver "^7.3.8" + regexp-tree "^0.1.27" + regjsparser "^0.10.0" + semver "^7.6.3" strip-indent "^3.0.0" -eslint-plugin-unused-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz" - integrity sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A== - dependencies: - eslint-rule-composer "^0.3.0" +eslint-plugin-unused-imports@^4.1.4: + version "4.1.4" + resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz" + integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== -eslint-plugin-vue@^9.9.0: - version "9.14.1" - resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.14.1.tgz" - integrity sha512-LQazDB1qkNEKejLe/b5a9VfEbtbczcOaui5lQ4Qw0tbRBbQYREyxxOV5BQgNDTqGPs9pxqiEpbMi9ywuIaF7vw== +eslint-plugin-vue@^9.32.0: + version "9.32.0" + resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.32.0.tgz" + integrity sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug== dependencies: - "@eslint-community/eslint-utils" "^4.3.0" + "@eslint-community/eslint-utils" "^4.4.0" + globals "^13.24.0" natural-compare "^1.4.0" - nth-check "^2.0.1" - postcss-selector-parser "^6.0.9" - semver "^7.3.5" - vue-eslint-parser "^9.3.0" + nth-check "^2.1.1" + postcss-selector-parser "^6.0.15" + semver "^7.6.3" + vue-eslint-parser "^9.4.3" xml-name-validator "^4.0.0" -eslint-plugin-yml@^1.5.0: - version "1.7.0" - resolved "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.7.0.tgz" - integrity sha512-qq61FQJk+qIgWl0R06bec7UQQEIBrUH22jS+MroTbFUKu+3/iVlGRpZd8mjpOAm/+H/WEDFwy4x/+kKgVGbsWw== +eslint-plugin-yml@^1.16.0: + version "1.16.0" + resolved "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.16.0.tgz" + integrity sha512-t4MNCetPjTn18/fUDlQ/wKkcYjnuLYKChBrZ0qUaNqRigVqChHWzTP8SrfFi5s4keX3vdlkWRSu8zHJMdKwxWQ== dependencies: debug "^4.3.2" + eslint-compat-utils "^0.6.0" lodash "^4.17.21" natural-compare "^1.4.0" yaml-eslint-parser "^1.2.1" -eslint-rule-composer@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz" - integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" +eslint-processor-vue-blocks@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/eslint-processor-vue-blocks/-/eslint-processor-vue-blocks-0.1.2.tgz" + integrity sha512-PfpJ4uKHnqeL/fXUnzYkOax3aIenlwewXRX8jFinA1a2yCFnLgMuiH3xvCgvHHUlV2xJWQHbCTdiJWGwb3NqpQ== eslint-scope@^7.1.1: version "7.2.0" @@ -6491,88 +6762,105 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - eslint-visitor-keys "^1.1.0" + esrecurse "^4.3.0" + estraverse "^4.1.1" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: version "3.4.3" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.36.0: - version "8.57.1" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" - integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + +eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "eslint@^7.0.0 || ^8.0.0 || ^9.0.0", "eslint@^7.23.0 || ^8.0.0 || ^9.0.0", "eslint@^8.50.0 || ^9.0.0", "eslint@^8.57.0 || ^9.0.0", "eslint@^9.0.0 || ^8.0.0", eslint@^9.10.0, eslint@^9.13.0, eslint@^9.5.0, "eslint@>= 8.57.0", eslint@>=6, eslint@>=6.0.0, eslint@>=8, eslint@>=8.0.0, eslint@>=8.23.0, eslint@>=8.40, eslint@>=8.40.0, eslint@>=8.44.0, eslint@>=8.56.0: + version "9.17.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz" + integrity sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.1" - "@humanwhocodes/config-array" "^0.13.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.9.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.17.0" + "@eslint/plugin-kit" "^0.2.3" + "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" - cross-spawn "^7.0.2" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" -espree@^9.0.0, espree@^9.3.1, espree@^9.6.0, espree@^9.6.1: +espree@^10.0.1, espree@^10.1.0, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + +espree@^9.0.0: + version "9.6.1" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +espree@^9.3.1: + version "9.6.1" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +espree@^9.6.1: version "9.6.1" resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -6586,10 +6874,10 @@ esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0, esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== +esquery@^1.4.0, esquery@^1.5.0, esquery@^1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -6610,43 +6898,52 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-util-attach-comments@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz" - integrity sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w== +estree-util-attach-comments@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz" + integrity sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw== dependencies: "@types/estree" "^1.0.0" -estree-util-build-jsx@^2.0.0: - version "2.2.2" - resolved "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz" - integrity sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg== +estree-util-build-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz" + integrity sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ== dependencies: "@types/estree-jsx" "^1.0.0" - estree-util-is-identifier-name "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" estree-walker "^3.0.0" -estree-util-is-identifier-name@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz" - integrity sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ== +estree-util-is-identifier-name@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz" + integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== -estree-util-to-js@^1.1.0: - version "1.2.0" - resolved "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz" - integrity sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA== +estree-util-scope@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz" + integrity sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ== + dependencies: + "@types/estree" "^1.0.0" + devlop "^1.0.0" + +estree-util-to-js@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz" + integrity sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg== dependencies: "@types/estree-jsx" "^1.0.0" astring "^1.8.0" source-map "^0.7.0" -estree-util-visit@^1.0.0: - version "1.2.1" - resolved "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz" - integrity sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw== +estree-util-visit@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz" + integrity sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" estree-walker@^2.0.2: version "2.0.2" @@ -6670,6 +6967,11 @@ event-target-shim@^5.0.0: resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" @@ -6698,7 +7000,7 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.0.0, execa@^7.1.1: +execa@^7.1.1: version "7.1.1" resolved "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz" integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== @@ -6713,6 +7015,21 @@ execa@^7.0.0, execa@^7.1.1: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +execa@~8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" @@ -6739,7 +7056,12 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0: +fast-equals@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz" + integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== + +fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -6750,6 +7072,17 @@ fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.0: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-parse@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz" @@ -6791,12 +7124,12 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" filesize@^10.0.12: version "10.1.6" @@ -6832,7 +7165,20 @@ find-cache-dir@^4.0.0: common-path-prefix "^3.0.0" pkg-dir "^7.0.0" -find-up@^4.0.0, find-up@^4.1.0: +find-up-simple@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz" + integrity sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw== + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -6864,10 +7210,18 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.1.0, flatted@^3.2.9: + version "3.3.2" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== for-each@^0.3.3: version "0.3.3" @@ -6876,6 +7230,14 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + fork-ts-checker-webpack-plugin@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz" @@ -6908,10 +7270,10 @@ format@^0.2.0: resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz" integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== -fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== fs-extra@^10.0.0: version "10.1.0" @@ -6922,13 +7284,6 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - fs-monkey@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz" @@ -6944,41 +7299,28 @@ fsevents@^2.3.2, fsevents@~2.3.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -function-bind@^1.1.1, function-bind@^1.1.2: +function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" @@ -6989,16 +7331,26 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== +get-east-asian-width@^1.0.0: + version "1.3.0" + resolved "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz" + integrity sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: + 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== 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" get-package-type@^0.1.0: version "0.1.0" @@ -7012,27 +7364,38 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" -get-stream@^6.0.0, get-stream@^6.0.1: +get-stream@^6.0.0: version "6.0.1" resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-tsconfig@^4.5.0: - version "4.6.0" - resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.0.tgz" - integrity sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg== +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +get-tsconfig@^4.5.0, get-tsconfig@^4.7.3, get-tsconfig@^4.8.1: + version "4.8.1" + resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz" + integrity sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg== dependencies: resolve-pkg-maps "^1.0.0" -glob-parent@^5.1.2, glob-parent@~5.1.2: +glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -7046,24 +7409,31 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.6: - version "7.1.6" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== +glob@^10.3.10: + version "10.4.5" + resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" -glob@7.1.7, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.3, glob@^7.1.4: version "7.1.7" resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -7080,36 +7450,30 @@ globals@^11.1.0: resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0: +globals@^13.24.0: version "13.24.0" resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" -globals@^15.13.0: - version "15.13.0" - resolved "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz" - integrity sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g== +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" +globals@^15.11.0, globals@^15.13.0, globals@^15.14.0, globals@^15.9.0: + version "15.14.0" + resolved "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz" + integrity sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig== -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" + define-properties "^1.2.1" + gopd "^1.0.1" globby@^13.1.3: version "13.1.4" @@ -7122,12 +7486,10 @@ globby@^13.1.3: merge2 "^1.4.1" slash "^4.0.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== got@^11.8.6: version "11.8.6" @@ -7151,11 +7513,6 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" @@ -7166,7 +7523,7 @@ hachure-fill@^0.5.2: resolved "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz" integrity sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg== -has-bigints@^1.0.1, has-bigints@^1.0.2: +has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== @@ -7183,34 +7540,24 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== dependencies: - has-symbols "^1.0.2" + dunder-proto "^1.0.0" -has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - function-bind "^1.1.1" + has-symbols "^1.0.3" hash-base@^3.0.0, hash-base@~3.0, hash-base@~3.0.4: version "3.0.4" @@ -7228,54 +7575,43 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" -hast-util-from-dom@^4.0.0: - version "4.2.0" - resolved "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz" - integrity sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ== +hast-util-from-dom@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz" + integrity sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q== dependencies: - hastscript "^7.0.0" + "@types/hast" "^3.0.0" + hastscript "^9.0.0" web-namespaces "^2.0.0" -hast-util-from-html-isomorphic@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz" - integrity sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw== +hast-util-from-html-isomorphic@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz" + integrity sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw== dependencies: - "@types/hast" "^2.0.0" - hast-util-from-dom "^4.0.0" - hast-util-from-html "^1.0.0" - unist-util-remove-position "^4.0.0" + "@types/hast" "^3.0.0" + hast-util-from-dom "^5.0.0" + hast-util-from-html "^2.0.0" + unist-util-remove-position "^5.0.0" -hast-util-from-html@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz" - integrity sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A== +hast-util-from-html@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz" + integrity sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw== dependencies: - "@types/hast" "^2.0.0" - hast-util-from-parse5 "^7.0.0" + "@types/hast" "^3.0.0" + devlop "^1.1.0" + hast-util-from-parse5 "^8.0.0" parse5 "^7.0.0" - vfile "^5.0.0" - vfile-message "^3.0.0" - -hast-util-from-parse5@^7.0.0: - version "7.1.2" - resolved "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz" - integrity sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw== - dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" - hastscript "^7.0.0" - property-information "^6.0.0" - vfile "^5.0.0" - vfile-location "^4.0.0" - web-namespaces "^2.0.0" + vfile "^6.0.0" + vfile-message "^4.0.0" hast-util-from-parse5@^8.0.0: version "8.0.1" @@ -7291,26 +7627,18 @@ hast-util-from-parse5@^8.0.0: vfile-location "^5.0.0" web-namespaces "^2.0.0" -hast-util-is-element@^2.0.0: - version "2.1.3" - resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz" - integrity sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA== +hast-util-is-element@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz" + integrity sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g== dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" hast-util-parse-selector@^2.0.0: version "2.2.5" resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== -hast-util-parse-selector@^3.0.0: - version "3.1.1" - resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz" - integrity sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA== - dependencies: - "@types/hast" "^2.0.0" - hast-util-parse-selector@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz" @@ -7337,27 +7665,49 @@ hast-util-raw@^9.0.0: web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-to-estree@^2.0.0: - version "2.3.3" - resolved "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz" - integrity sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ== +hast-util-to-estree@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz" + integrity sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw== dependencies: "@types/estree" "^1.0.0" "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" comma-separated-tokens "^2.0.0" - estree-util-attach-comments "^2.0.0" - estree-util-is-identifier-name "^2.0.0" - hast-util-whitespace "^2.0.0" - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdxjs-esm "^1.0.0" + devlop "^1.0.0" + estree-util-attach-comments "^3.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" property-information "^6.0.0" space-separated-tokens "^2.0.0" - style-to-object "^0.4.1" - unist-util-position "^4.0.0" + style-to-object "^0.4.0" + unist-util-position "^5.0.0" zwitch "^2.0.0" +hast-util-to-jsx-runtime@^2.0.0: + version "2.3.2" + resolved "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.2.tgz" + integrity sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + comma-separated-tokens "^2.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + hast-util-whitespace "^3.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^1.0.0" + unist-util-position "^5.0.0" + vfile-message "^4.0.0" + hast-util-to-parse5@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz" @@ -7371,20 +7721,22 @@ hast-util-to-parse5@^8.0.0: web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-to-text@^3.1.0: - version "3.1.2" - resolved "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz" - integrity sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw== +hast-util-to-text@^4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz" + integrity sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A== dependencies: - "@types/hast" "^2.0.0" - "@types/unist" "^2.0.0" - hast-util-is-element "^2.0.0" - unist-util-find-after "^4.0.0" + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + hast-util-is-element "^3.0.0" + unist-util-find-after "^5.0.0" -hast-util-whitespace@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz" - integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng== +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" hastscript@^6.0.0: version "6.0.0" @@ -7397,17 +7749,6 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" -hastscript@^7.0.0: - version "7.2.0" - resolved "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz" - integrity sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw== - dependencies: - "@types/hast" "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-parse-selector "^3.0.0" - property-information "^6.0.0" - space-separated-tokens "^2.0.0" - hastscript@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz" @@ -7419,6 +7760,17 @@ hastscript@^8.0.0: property-information "^6.0.0" space-separated-tokens "^2.0.0" +hastscript@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/hastscript/-/hastscript-9.0.0.tgz" + integrity sha512-jzaLBGavEDKHrc5EfFImKN7nZKKBdSLIdGvCwDZ9TfzbF2ffXiov8CKE445L2Z1Ek2t/m4SKQ2j6Ipv7NyUolw== + dependencies: + "@types/hast" "^3.0.0" + comma-separated-tokens "^2.0.0" + hast-util-parse-selector "^4.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + he@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" @@ -7429,6 +7781,11 @@ highlight.js@^10.4.1, highlight.js@~10.7.0: resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== +highlightjs-vue@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz" + integrity sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" @@ -7487,6 +7844,11 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" +html-url-attributes@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz" + integrity sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ== + html-void-elements@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz" @@ -7513,16 +7875,6 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" -htmlparser2@^8.0.1: - version "8.0.2" - resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz" - integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - entities "^4.4.0" - http-cache-semantics@^4.0.0: version "4.1.1" resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz" @@ -7550,7 +7902,7 @@ https-browserify@^1.0.0: resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz" integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== -https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -7568,24 +7920,29 @@ human-signals@^4.3.0: resolved "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz" integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== -husky@^8.0.3: - version "8.0.3" - resolved "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz" - integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== -i18next-resources-to-backend@^1.1.3: - version "1.1.4" - resolved "https://registry.npmjs.org/i18next-resources-to-backend/-/i18next-resources-to-backend-1.1.4.tgz" - integrity sha512-hMyr9AOmIea17AOaVe1srNxK/l3mbk81P7Uf3fdcjlw3ehZy3UNTd0OP3EEi6yu4J02kf9jzhCcjokz6AFlEOg== - dependencies: - "@babel/runtime" "^7.21.5" +husky@^9.1.6: + version "9.1.7" + resolved "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== -i18next@^22.4.13: - version "22.5.1" - resolved "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz" - integrity sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA== +i18next-resources-to-backend@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz" + integrity sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw== dependencies: - "@babel/runtime" "^7.20.6" + "@babel/runtime" "^7.23.2" + +i18next@^23.16.4, "i18next@>= 23.2.3": + version "23.16.8" + resolved "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz" + integrity sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg== + dependencies: + "@babel/runtime" "^7.23.2" iconv-lite@0.6, iconv-lite@0.6.3: version "0.6.3" @@ -7604,10 +7961,10 @@ ieee754@^1.2.1: resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.0.5, ignore@^5.1.1, ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1, ignore@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== image-size@^1.0.0: version "1.1.1" @@ -7621,15 +7978,15 @@ immediate@~3.0.5: resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== -immer@^9.0.19: +immer@^9.0.19, immer@>=9.0.6: version "9.0.21" resolved "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz" integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== -immutable@^4.0.0: - version "4.3.0" - resolved "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz" - integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== +immutable@^5.0.2: + version "5.0.3" + resolved "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz" + integrity sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw== import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -7665,7 +8022,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4, inherits@2: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -7675,25 +8032,30 @@ inline-style-parser@0.1.1: resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -internal-slot@^1.0.4, internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== - dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" - side-channel "^1.0.4" +inline-style-parser@0.2.4: + version "0.2.4" + resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz" + integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== -"internmap@1 - 2": - version "2.0.3" - resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" - integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" internmap@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + intersection-observer@^0.12.0: version "0.12.2" resolved "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz" @@ -7725,7 +8087,7 @@ is-alphanumerical@^2.0.0: is-alphabetical "^2.0.0" is-decimal "^2.0.0" -is-arguments@^1.0.4, is-arguments@^1.1.1: +is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -7733,14 +8095,14 @@ is-arguments@^1.0.4, is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-arrayish@^0.2.1: version "0.2.1" @@ -7759,12 +8121,12 @@ is-async-function@^2.0.0: dependencies: has-tostringtag "^1.0.0" -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== dependencies: - has-bigints "^1.0.1" + has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" @@ -7773,44 +8135,49 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== +is-boolean-object@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz" + integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-builtin-module@^3.2.0: +is-builtin-module@^3.2.1: version "3.2.1" resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz" integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== dependencies: builtin-modules "^3.3.0" -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.15.1: + version "2.16.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== +is-data-view@^1.0.1, is-data-view@^1.0.2: + 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== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-decimal@^1.0.0: version "1.0.4" @@ -7837,12 +8204,12 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -7854,6 +8221,13 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== +is-fullwidth-code-point@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz" + integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA== + dependencies: + get-east-asian-width "^1.0.0" + is-generator-fn@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" @@ -7883,6 +8257,15 @@ is-hexadecimal@^2.0.0: resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz" integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== +is-immutable-type@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-immutable-type/-/is-immutable-type-5.0.0.tgz" + integrity sha512-mcvHasqbRBWJznuPqqHRKiJgYAz60sZ0mvO3bN70JbkuK7ksfmgc489aKZYxMEjIbRvyOseaTjaRZLRF/xFeRA== + dependencies: + "@typescript-eslint/type-utils" "^8.0.0" + ts-api-utils "^1.3.0" + ts-declaration-location "^1.0.4" + is-inside-container@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz" @@ -7890,10 +8273,10 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" -is-map@^2.0.1, is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== is-nan@^1.3.2: version "1.3.2" @@ -7903,28 +8286,19 @@ is-nan@^1.3.2: call-bind "^1.0.0" define-properties "^1.1.3" -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-number@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-plain-obj@^4.0.0: version "4.1.0" resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" @@ -7935,32 +8309,27 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-reference@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz" - integrity sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w== +is-regex@^1.2.1: + 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== dependencies: - "@types/estree" "*" + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.1, is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" @@ -7972,46 +8341,49 @@ is-stream@^3.0.0: resolved "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: - has-symbols "^1.0.2" + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.12" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15, is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - which-typed-array "^1.1.11" + which-typed-array "^1.1.16" -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-weakset@^2.0.1: +is-weakmap@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz" + integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bound "^1.0.2" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-wsl@^2.2.0: version "2.2.0" @@ -8035,6 +8407,11 @@ isexe@^2.0.0: resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isomorphic.js@^0.2.4: + version "0.2.5" + resolved "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz" + integrity sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw== + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" @@ -8088,16 +8465,26 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== +iterator.prototype@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.4.tgz" + integrity sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA== dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" + reflect.getprototypeof "^1.0.8" + set-function-name "^2.0.2" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" jest-changed-files@^29.7.0: version "29.7.0" @@ -8317,7 +8704,7 @@ jest-resolve-dependencies@^29.7.0: jest-regex-util "^29.6.3" jest-snapshot "^29.7.0" -jest-resolve@^29.7.0: +jest-resolve@*, jest-resolve@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== @@ -8480,7 +8867,7 @@ jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -jiti@^1.20.0, jiti@^1.21.0: +jiti@*, jiti@^1.20.0, jiti@^1.21.6: version "1.21.6" resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== @@ -8490,12 +8877,7 @@ js-audio-recorder@^1.0.7: resolved "https://registry.npmjs.org/js-audio-recorder/-/js-audio-recorder-1.0.7.tgz" integrity sha512-JiDODCElVHGrFyjGYwYyNi7zCbKk9va9C77w+zCPMmi4C6ix7zsX2h3ddHugmo4dOTOTCym9++b/wVW9nC0IaA== -js-cookie@^2.x.x: - version "2.2.1" - resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz" - integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== - -js-cookie@^3.0.1: +js-cookie@^3.0.5: version "3.0.5" resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz" integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== @@ -8520,7 +8902,7 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsdoc-type-pratt-parser@^4.0.0: +jsdoc-type-pratt-parser@^4.0.0, jsdoc-type-pratt-parser@~4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz" integrity sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg== @@ -8604,10 +8986,10 @@ json5@^2.1.2, json5@^2.2.2, json5@^2.2.3: resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonc-eslint-parser@^2.0.4, jsonc-eslint-parser@^2.1.0: - version "2.3.0" - resolved "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.3.0.tgz" - integrity sha512-9xZPKVYp9DxnM3sd1yAsh/d59iIaswDkai8oTxbursfKYbg/ibjX0IzFt35+VZ8iEW453TVTXztnRvYUQlAfUQ== +jsonc-eslint-parser@^2.0.4, jsonc-eslint-parser@^2.4.0: + version "2.4.0" + resolved "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz" + integrity sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg== dependencies: acorn "^8.5.0" eslint-visitor-keys "^3.0.0" @@ -8623,27 +9005,29 @@ jsonfile@^6.0.1, jsonfile@^6.1.0: optionalDependencies: graceful-fs "^4.1.6" -"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: - version "3.3.3" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz" - integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: + version "3.3.5" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: - array-includes "^3.1.5" - object.assign "^4.1.3" + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" jwt-decode@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz" integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== -katex@^0.16.0, katex@^0.16.10, katex@^0.16.9: - version "0.16.10" - resolved "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz" - integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== +katex@^0.16.0, katex@^0.16.11, katex@^0.16.9: + version "0.16.18" + resolved "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz" + integrity sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ== dependencies: commander "^8.3.0" -keyv@^4.0.0: +keyv@^4.0.0, keyv@^4.5.4: version "4.5.4" resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -8660,16 +9044,16 @@ kleur@^3.0.3: resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -kleur@^4.0.3: - version "4.1.5" - resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz" - integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== - kolorist@^1.8.0: version "1.8.0" resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz" integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== +ky@^1.7.2: + version "1.7.4" + resolved "https://registry.npmjs.org/ky/-/ky-1.7.4.tgz" + integrity sha512-zYEr/gh7uLW2l4su11bmQ2M9xLgQLjyvx58UyNM/6nuqyWFHPX5ktMjvpev3F8QWdjSsHUpnWew4PBCswBNuMQ== + lamejs@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/lamejs/-/lamejs-1.2.1.tgz" @@ -8688,17 +9072,17 @@ langium@3.0.0: vscode-languageserver-textdocument "~1.0.11" vscode-uri "~3.0.8" -language-subtag-registry@~0.3.2: - version "0.3.22" - resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== +language-subtag-registry@^0.3.20: + version "0.3.23" + resolved "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== -language-tags@=1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz" - integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ== +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== dependencies: - language-subtag-registry "~0.3.2" + language-subtag-registry "^0.3.20" launch-ide@1.0.0: version "1.0.0" @@ -8731,10 +9115,17 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lexical@0.16.1, lexical@^0.16.0: - version "0.16.1" - resolved "https://registry.npmjs.org/lexical/-/lexical-0.16.1.tgz" - integrity sha512-+R05d3+N945OY8pTUjTqQrWoApjC+ctzvjnmNETtx9WmVAaiW0tQVG+AYLt5pDGY8dQXtd4RPorvnxBTECt9SA== +lexical@^0.18.0, lexical@0.18.0: + version "0.18.0" + resolved "https://registry.npmjs.org/lexical/-/lexical-0.18.0.tgz" + integrity sha512-3K/B0RpzjoW+Wj2E455wWXxkqxqK8UgdIiuqkOqdOsoSSo5mCkHOU6eVw7Nlmlr1MFvAMzGmz4RPn8NZaLQ2Mw== + +lib0@^0.2.98: + version "0.2.99" + resolved "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz" + integrity sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w== + dependencies: + isomorphic.js "^0.2.4" lie@3.1.1: version "3.1.1" @@ -8743,10 +9134,10 @@ lie@3.1.1: dependencies: immediate "~3.0.5" -lilconfig@2.1.0, lilconfig@^2.0.5, lilconfig@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== +lilconfig@^3.0.0, lilconfig@^3.1.3, lilconfig@~3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== line-clamp@^1.0.0: version "1.0.0" @@ -8758,45 +9149,49 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -lint-staged@^13.2.2: - version "13.2.2" - resolved "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz" - integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== +lint-staged@^15.2.10: + 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== dependencies: - chalk "5.2.0" - cli-truncate "^3.1.0" - commander "^10.0.0" - debug "^4.3.4" - execa "^7.0.0" - lilconfig "2.1.0" - listr2 "^5.0.7" - micromatch "^4.0.5" - normalize-path "^3.0.0" - object-inspect "^1.12.3" - pidtree "^0.6.0" - string-argv "^0.3.1" - yaml "^2.2.2" + chalk "~5.3.0" + commander "~12.1.0" + debug "~4.4.0" + execa "~8.0.1" + lilconfig "~3.1.3" + listr2 "~8.2.5" + micromatch "~4.0.8" + pidtree "~0.6.0" + string-argv "~0.3.2" + yaml "~2.6.1" -listr2@^5.0.7: - version "5.0.8" - resolved "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz" - integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== +listr2@~8.2.5: + version "8.2.5" + resolved "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz" + integrity sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ== dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.19" - log-update "^4.0.0" - p-map "^4.0.0" - rfdc "^1.3.0" - rxjs "^7.8.0" - through "^2.3.8" - wrap-ansi "^7.0.0" + cli-truncate "^4.0.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^9.0.0" loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0, loader-utils@^2.0.4: +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loader-utils@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== @@ -8810,11 +9205,6 @@ loader-utils@^3.2.1: resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz" integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== -local-pkg@^0.4.3: - version "0.4.3" - resolved "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz" - integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g== - local-pkg@^0.5.1: version "0.5.1" resolved "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz" @@ -8851,7 +9241,7 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" -lodash-es@4.17.21, lodash-es@^4.17.21: +lodash-es@^4.17.21, lodash-es@4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== @@ -8876,20 +9266,21 @@ lodash.merge@^4.6.2: resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21: +lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" longest-streak@^3.0.0: version "3.1.0" @@ -8928,6 +9319,11 @@ lowlight@^1.17.0: fault "^1.0.0" highlight.js "~10.7.0" +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" @@ -8935,19 +9331,12 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - lz-string@^1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== -magic-string@^0.30.5: +magic-string@^0.30.11, magic-string@^0.30.5: version "0.30.12" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz" integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw== @@ -8963,7 +9352,7 @@ magicast@^0.3.4: "@babel/types" "^7.25.4" source-map-js "^1.2.0" -make-dir@^3.0.2, make-dir@^3.1.0: +make-dir@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -8994,10 +9383,10 @@ map-or-similar@^1.5.0: resolved "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz" integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== -markdown-extensions@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz" - integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== +markdown-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz" + integrity sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q== markdown-table@^3.0.0: version "3.0.3" @@ -9009,6 +9398,11 @@ marked@^13.0.2: resolved "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz" integrity sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA== +math-intrinsics@^1.0.0, math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" @@ -9018,201 +9412,180 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -mdast-util-definitions@^5.0.0: - version "5.1.2" - resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz" - integrity sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA== +mdast-util-find-and-replace@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz" + integrity sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" - -mdast-util-find-and-replace@^2.0.0: - version "2.2.2" - resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz" - integrity sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw== - dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" escape-string-regexp "^5.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" -mdast-util-from-markdown@^0.8.5: - version "0.8.5" - resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz" - integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== +mdast-util-from-markdown@^2.0.0, mdast-util-from-markdown@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz" + integrity sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-string "^2.0.0" - micromark "~2.11.0" - parse-entities "^2.0.0" - unist-util-stringify-position "^2.0.0" - -mdast-util-from-markdown@^1.0.0, mdast-util-from-markdown@^1.1.0: - version "1.3.1" - resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz" - integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== - dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" decode-named-character-reference "^1.0.0" - mdast-util-to-string "^3.1.0" - micromark "^3.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-decode-string "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-stringify-position "^3.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + mdast-util-to-string "^4.0.0" + micromark "^4.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-decode-string "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-stringify-position "^4.0.0" -mdast-util-gfm-autolink-literal@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz" - integrity sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA== +mdast-util-gfm-autolink-literal@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz" + integrity sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" ccount "^2.0.0" - mdast-util-find-and-replace "^2.0.0" - micromark-util-character "^1.0.0" + devlop "^1.0.0" + mdast-util-find-and-replace "^3.0.0" + micromark-util-character "^2.0.0" -mdast-util-gfm-footnote@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz" - integrity sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ== +mdast-util-gfm-footnote@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz" + integrity sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" - micromark-util-normalize-identifier "^1.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" -mdast-util-gfm-strikethrough@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz" - integrity sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ== +mdast-util-gfm-strikethrough@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz" + integrity sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-table@^1.0.0: - version "1.0.7" - resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz" - integrity sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg== +mdast-util-gfm-table@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz" + integrity sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" markdown-table "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.3.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm-task-list-item@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz" - integrity sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ== +mdast-util-gfm-task-list-item@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz" + integrity sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-markdown "^1.3.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-gfm@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz" - integrity sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg== +mdast-util-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz" + integrity sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw== dependencies: - mdast-util-from-markdown "^1.0.0" - mdast-util-gfm-autolink-literal "^1.0.0" - mdast-util-gfm-footnote "^1.0.0" - mdast-util-gfm-strikethrough "^1.0.0" - mdast-util-gfm-table "^1.0.0" - mdast-util-gfm-task-list-item "^1.0.0" - mdast-util-to-markdown "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-gfm-autolink-literal "^2.0.0" + mdast-util-gfm-footnote "^2.0.0" + mdast-util-gfm-strikethrough "^2.0.0" + mdast-util-gfm-table "^2.0.0" + mdast-util-gfm-task-list-item "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-math@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-2.0.2.tgz" - integrity sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ== +mdast-util-math@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz" + integrity sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w== dependencies: - "@types/mdast" "^3.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" longest-streak "^3.0.0" - mdast-util-to-markdown "^1.3.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.1.0" + unist-util-remove-position "^5.0.0" -mdast-util-mdx-expression@^1.0.0: - version "1.3.2" - resolved "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz" - integrity sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA== +mdast-util-mdx-expression@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz" + integrity sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-mdx-jsx@^2.0.0: - version "2.1.4" - resolved "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz" - integrity sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA== +mdast-util-mdx-jsx@^3.0.0: + version "3.1.3" + resolved "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz" + integrity sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" ccount "^2.0.0" - mdast-util-from-markdown "^1.1.0" - mdast-util-to-markdown "^1.3.0" + devlop "^1.1.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" parse-entities "^4.0.0" stringify-entities "^4.0.0" - unist-util-remove-position "^4.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" + unist-util-stringify-position "^4.0.0" + vfile-message "^4.0.0" -mdast-util-mdx@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz" - integrity sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw== +mdast-util-mdx@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz" + integrity sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w== dependencies: - mdast-util-from-markdown "^1.0.0" - mdast-util-mdx-expression "^1.0.0" - mdast-util-mdx-jsx "^2.0.0" - mdast-util-mdxjs-esm "^1.0.0" - mdast-util-to-markdown "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-mdx-expression "^2.0.0" + mdast-util-mdx-jsx "^3.0.0" + mdast-util-mdxjs-esm "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-mdxjs-esm@^1.0.0: - version "1.3.1" - resolved "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz" - integrity sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w== +mdast-util-mdxjs-esm@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz" + integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== dependencies: "@types/estree-jsx" "^1.0.0" - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - mdast-util-to-markdown "^1.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + devlop "^1.0.0" + mdast-util-from-markdown "^2.0.0" + mdast-util-to-markdown "^2.0.0" -mdast-util-newline-to-break@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-1.0.0.tgz" - integrity sha512-491LcYv3gbGhhCrLoeALncQmega2xPh+m3gbsIhVsOX4sw85+ShLFPvPyibxc1Swx/6GtzxgVodq+cGa/47ULg== +mdast-util-newline-to-break@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz" + integrity sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-find-and-replace "^2.0.0" + "@types/mdast" "^4.0.0" + mdast-util-find-and-replace "^3.0.0" -mdast-util-phrasing@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz" - integrity sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg== +mdast-util-phrasing@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz" + integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== dependencies: - "@types/mdast" "^3.0.0" - unist-util-is "^5.0.0" - -mdast-util-to-hast@^12.1.0: - version "12.3.0" - resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz" - integrity sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw== - dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-definitions "^5.0.0" - micromark-util-sanitize-uri "^1.1.0" - trim-lines "^3.0.0" - unist-util-generated "^2.0.0" - unist-util-position "^4.0.0" - unist-util-visit "^4.0.0" + "@types/mdast" "^4.0.0" + unist-util-is "^6.0.0" mdast-util-to-hast@^13.0.0: version "13.2.0" @@ -9229,31 +9602,27 @@ mdast-util-to-hast@^13.0.0: unist-util-visit "^5.0.0" vfile "^6.0.0" -mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: - version "1.5.0" - resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz" - integrity sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A== +mdast-util-to-markdown@^2.0.0, mdast-util-to-markdown@^2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz" + integrity sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA== dependencies: - "@types/mdast" "^3.0.0" - "@types/unist" "^2.0.0" + "@types/mdast" "^4.0.0" + "@types/unist" "^3.0.0" longest-streak "^3.0.0" - mdast-util-phrasing "^3.0.0" - mdast-util-to-string "^3.0.0" - micromark-util-decode-string "^1.0.0" - unist-util-visit "^4.0.0" + mdast-util-phrasing "^4.0.0" + mdast-util-to-string "^4.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-decode-string "^2.0.0" + unist-util-visit "^5.0.0" zwitch "^2.0.0" -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: - version "3.2.0" - resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz" - integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== +mdast-util-to-string@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz" + integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== dependencies: - "@types/mdast" "^3.0.0" + "@types/mdast" "^4.0.0" memfs@^3.4.1, memfs@^3.4.12: version "3.5.3" @@ -9310,254 +9679,253 @@ mermaid@11.4.1: ts-dedent "^2.2.0" uuid "^9.0.1" -micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz" - integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== +micro-memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz" + integrity sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g== + +micromark-core-commonmark@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz" + integrity sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w== dependencies: decode-named-character-reference "^1.0.0" - micromark-factory-destination "^1.0.0" - micromark-factory-label "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-factory-title "^1.0.0" - micromark-factory-whitespace "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-html-tag-name "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-factory-destination "^2.0.0" + micromark-factory-label "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-factory-title "^2.0.0" + micromark-factory-whitespace "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-html-tag-name "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-autolink-literal@^1.0.0: - version "1.0.5" - resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz" - integrity sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg== +micromark-extension-gfm-autolink-literal@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz" + integrity sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw== dependencies: - micromark-util-character "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-footnote@^1.0.0: - version "1.1.2" - resolved "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz" - integrity sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q== +micromark-extension-gfm-footnote@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz" + integrity sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw== dependencies: - micromark-core-commonmark "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-strikethrough@^1.0.0: - version "1.0.7" - resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz" - integrity sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw== +micromark-extension-gfm-strikethrough@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz" + integrity sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-classify-character "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-classify-character "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-table@^1.0.0: - version "1.0.7" - resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz" - integrity sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw== +micromark-extension-gfm-table@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz" + integrity sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-tagfilter@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz" - integrity sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g== +micromark-extension-gfm-tagfilter@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz" + integrity sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg== dependencies: - micromark-util-types "^1.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm-task-list-item@^1.0.0: - version "1.0.5" - resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz" - integrity sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ== +micromark-extension-gfm-task-list-item@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz" + integrity sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-gfm@^2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz" - integrity sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ== +micromark-extension-gfm@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz" + integrity sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w== dependencies: - micromark-extension-gfm-autolink-literal "^1.0.0" - micromark-extension-gfm-footnote "^1.0.0" - micromark-extension-gfm-strikethrough "^1.0.0" - micromark-extension-gfm-table "^1.0.0" - micromark-extension-gfm-tagfilter "^1.0.0" - micromark-extension-gfm-task-list-item "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" + micromark-extension-gfm-autolink-literal "^2.0.0" + micromark-extension-gfm-footnote "^2.0.0" + micromark-extension-gfm-strikethrough "^2.0.0" + micromark-extension-gfm-table "^2.0.0" + micromark-extension-gfm-tagfilter "^2.0.0" + micromark-extension-gfm-task-list-item "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-math@^2.0.0: - version "2.1.2" - resolved "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.1.2.tgz" - integrity sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg== +micromark-extension-math@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz" + integrity sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg== dependencies: "@types/katex" "^0.16.0" + devlop "^1.0.0" katex "^0.16.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-mdx-expression@^1.0.0: - version "1.0.8" - resolved "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz" - integrity sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw== +micromark-extension-mdx-expression@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz" + integrity sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ== dependencies: "@types/estree" "^1.0.0" - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-extension-mdx-jsx@^1.0.0: - version "1.0.5" - resolved "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz" - integrity sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA== +micromark-extension-mdx-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.1.tgz" + integrity sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg== dependencies: "@types/acorn" "^4.0.0" "@types/estree" "^1.0.0" - estree-util-is-identifier-name "^2.0.0" - micromark-factory-mdx-expression "^1.0.0" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" + devlop "^1.0.0" + estree-util-is-identifier-name "^3.0.0" + micromark-factory-mdx-expression "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" -micromark-extension-mdx-md@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz" - integrity sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA== +micromark-extension-mdx-md@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz" + integrity sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ== dependencies: - micromark-util-types "^1.0.0" + micromark-util-types "^2.0.0" -micromark-extension-mdxjs-esm@^1.0.0: - version "1.0.5" - resolved "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz" - integrity sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w== +micromark-extension-mdxjs-esm@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz" + integrity sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A== dependencies: "@types/estree" "^1.0.0" - micromark-core-commonmark "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.1.0" - uvu "^0.5.0" - vfile-message "^3.0.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" -micromark-extension-mdxjs@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz" - integrity sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q== +micromark-extension-mdxjs@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz" + integrity sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ== dependencies: acorn "^8.0.0" acorn-jsx "^5.0.0" - micromark-extension-mdx-expression "^1.0.0" - micromark-extension-mdx-jsx "^1.0.0" - micromark-extension-mdx-md "^1.0.0" - micromark-extension-mdxjs-esm "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-types "^1.0.0" + micromark-extension-mdx-expression "^3.0.0" + micromark-extension-mdx-jsx "^3.0.0" + micromark-extension-mdx-md "^2.0.0" + micromark-extension-mdxjs-esm "^3.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-destination@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz" - integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== +micromark-factory-destination@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz" + integrity sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-label@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz" - integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== +micromark-factory-label@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz" + integrity sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-mdx-expression@^1.0.0: - version "1.0.9" - resolved "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz" - integrity sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA== +micromark-factory-mdx-expression@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.2.tgz" + integrity sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw== dependencies: "@types/estree" "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-events-to-acorn "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - unist-util-position-from-estree "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" + devlop "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-events-to-acorn "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + unist-util-position-from-estree "^2.0.0" + vfile-message "^4.0.0" -micromark-factory-space@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz" - integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== +micromark-factory-space@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz" + integrity sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg== dependencies: - micromark-util-character "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-title@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz" - integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== +micromark-factory-title@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz" + integrity sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-factory-whitespace@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz" - integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== +micromark-factory-whitespace@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz" + integrity sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ== dependencies: - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - -micromark-util-character@^1.0.0: - version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz" - integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== - dependencies: - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" micromark-util-character@^2.0.0: version "2.1.0" @@ -9567,98 +9935,84 @@ micromark-util-character@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" -micromark-util-chunked@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz" - integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== +micromark-util-chunked@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz" + integrity sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-classify-character@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz" - integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== +micromark-util-classify-character@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz" + integrity sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q== dependencies: - micromark-util-character "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-character "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-combine-extensions@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz" - integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== +micromark-util-combine-extensions@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz" + integrity sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-types "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-types "^2.0.0" -micromark-util-decode-numeric-character-reference@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz" - integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== +micromark-util-decode-numeric-character-reference@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz" + integrity sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-decode-string@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz" - integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== +micromark-util-decode-string@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz" + integrity sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ== dependencies: decode-named-character-reference "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-symbol "^1.0.0" - -micromark-util-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz" - integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== + micromark-util-character "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-symbol "^2.0.0" micromark-util-encode@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz" integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== -micromark-util-events-to-acorn@^1.0.0: - version "1.2.3" - resolved "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz" - integrity sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w== +micromark-util-events-to-acorn@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz" + integrity sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA== dependencies: "@types/acorn" "^4.0.0" "@types/estree" "^1.0.0" - "@types/unist" "^2.0.0" - estree-util-visit "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - vfile-message "^3.0.0" + "@types/unist" "^3.0.0" + devlop "^1.0.0" + estree-util-visit "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + vfile-message "^4.0.0" -micromark-util-html-tag-name@^1.0.0: - version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz" - integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== +micromark-util-html-tag-name@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz" + integrity sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA== -micromark-util-normalize-identifier@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz" - integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== +micromark-util-normalize-identifier@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz" + integrity sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q== dependencies: - micromark-util-symbol "^1.0.0" + micromark-util-symbol "^2.0.0" -micromark-util-resolve-all@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz" - integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== +micromark-util-resolve-all@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz" + integrity sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg== dependencies: - micromark-util-types "^1.0.0" - -micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: - version "1.2.0" - resolved "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz" - integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== - dependencies: - micromark-util-character "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-symbol "^1.0.0" + micromark-util-types "^2.0.0" micromark-util-sanitize-uri@^2.0.0: version "2.0.0" @@ -9669,68 +10023,50 @@ micromark-util-sanitize-uri@^2.0.0: micromark-util-encode "^2.0.0" micromark-util-symbol "^2.0.0" -micromark-util-subtokenize@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz" - integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== +micromark-util-subtokenize@^2.0.0: + version "2.0.3" + resolved "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz" + integrity sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg== dependencies: - micromark-util-chunked "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.0" - uvu "^0.5.0" - -micromark-util-symbol@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz" - integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== + devlop "^1.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" micromark-util-symbol@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz" integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== -micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: - version "1.1.0" - resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz" - integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== - micromark-util-types@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz" integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== -micromark@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz" - integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== +micromark@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz" + integrity sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw== dependencies: "@types/debug" "^4.0.0" debug "^4.0.0" decode-named-character-reference "^1.0.0" - micromark-core-commonmark "^1.0.1" - micromark-factory-space "^1.0.0" - micromark-util-character "^1.0.0" - micromark-util-chunked "^1.0.0" - micromark-util-combine-extensions "^1.0.0" - micromark-util-decode-numeric-character-reference "^1.0.0" - micromark-util-encode "^1.0.0" - micromark-util-normalize-identifier "^1.0.0" - micromark-util-resolve-all "^1.0.0" - micromark-util-sanitize-uri "^1.0.0" - micromark-util-subtokenize "^1.0.0" - micromark-util-symbol "^1.0.0" - micromark-util-types "^1.0.1" - uvu "^0.5.0" + devlop "^1.0.0" + micromark-core-commonmark "^2.0.0" + micromark-factory-space "^2.0.0" + micromark-util-character "^2.0.0" + micromark-util-chunked "^2.0.0" + micromark-util-combine-extensions "^2.0.0" + micromark-util-decode-numeric-character-reference "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-normalize-identifier "^2.0.0" + micromark-util-resolve-all "^2.0.0" + micromark-util-sanitize-uri "^2.0.0" + micromark-util-subtokenize "^2.0.0" + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" -micromark@~2.11.0: - version "2.11.4" - resolved "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz" - integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== - dependencies: - debug "^4.0.0" - parse-entities "^2.0.0" - -micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8, micromatch@~4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -9773,16 +10109,16 @@ mimic-fn@^4.0.0: resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz" @@ -9803,37 +10139,60 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: +minimatch@^10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.3: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^5.0.0: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "5.0.0" resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" +minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mitt@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== mkdirp@^0.5.6: version "0.5.6" @@ -9842,11 +10201,6 @@ mkdirp@^0.5.6: dependencies: minimist "^1.2.6" -mkdirp@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - mlly@^1.7.2, mlly@^1.7.3: version "1.7.3" resolved "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz" @@ -9857,12 +10211,12 @@ mlly@^1.7.2, mlly@^1.7.3: pkg-types "^1.2.1" ufo "^1.5.4" -mri@^1.1.0: - version "1.2.0" - resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz" - integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== +"monaco-editor@>= 0.21.0 < 1", "monaco-editor@>= 0.25.0 < 1": + version "0.52.2" + resolved "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz" + integrity sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ== -ms@2.1.2, ms@^2.1.1: +ms@^2.1.1, ms@2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -9881,26 +10235,21 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.17.0: - version "2.22.0" - resolved "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz" - integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== - nanoid@^3.3.6, nanoid@^3.3.7: version "3.3.8" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +natural-orderby@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz" + integrity sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg== + negotiator@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" @@ -9911,7 +10260,7 @@ neo-async@^2.6.2: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -next@^14.2.10: +"next@^13.5.0 || ^14.0.0 || ^15.0.0", next@^14.2.10: version "14.2.17" resolved "https://registry.npmjs.org/next/-/next-14.2.17.tgz" integrity sha512-hNo/Zy701DDO3nzKkPmsLRlDfNCtb1OJxFUvjGEl04u7SFa3zwC6hqsOUzMajcaEOEV8ey1GjvByvrg0Qr5AiQ== @@ -9947,12 +10296,10 @@ node-abort-controller@^3.0.1: resolved "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== -node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== node-int64@^0.4.0: version "0.4.0" @@ -9995,13 +10342,6 @@ node-releases@^2.0.18: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz" integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== -nopt@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" - integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== - dependencies: - abbrev "1" - normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" @@ -10046,17 +10386,7 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" -npmlog@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - -nth-check@^2.0.1: +nth-check@^2.0.1, nth-check@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== @@ -10078,10 +10408,10 @@ object-hash@^3.0.0: resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.3, object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== object-is@^1.1.5: version "1.1.5" @@ -10096,60 +10426,55 @@ object-keys@^1.1.1: resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.3, object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" object-keys "^1.1.1" -object.entries@^1.1.6: - version "1.1.6" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz" - integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== +object.entries@^1.1.8: + version "1.1.8" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -object.fromentries@^2.0.6, object.fromentries@^2.0.7: - version "2.0.7" - resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz" - integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== +object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" -object.groupby@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz" - integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== +object.groupby@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" -object.hasown@^1.1.2: - version "1.1.3" - resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz" - integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== +object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== dependencies: - define-properties "^1.2.0" - es-abstract "^1.22.1" - -object.values@^1.1.6, object.values@^1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz" - integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" objectorarray@^1.0.5: version "1.0.5" @@ -10163,7 +10488,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -10177,6 +10502,13 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + open@^8.0.4: version "8.4.2" resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz" @@ -10260,29 +10592,27 @@ p-locate@^6.0.0: dependencies: p-limit "^4.0.0" -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - p-try@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -package-manager-detector@^0.2.0: - version "0.2.7" - resolved "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.7.tgz" - integrity sha512-g4+387DXDKlZzHkP+9FLt8yKj8+/3tOkPv7DVTJGGRm00RkEWgqbFstX1mXJ4M0VDYhUqsTOiISqNOJnhAu3PQ== +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +package-manager-detector@^0.2.0, package-manager-detector@^0.2.5: + version "0.2.8" + resolved "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.8.tgz" + integrity sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA== pako@~1.0.5: version "1.0.11" resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== -papaparse@^5.3.1: +papaparse@^5.4.1: version "5.4.1" resolved "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz" integrity sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw== @@ -10340,6 +10670,19 @@ parse-entities@^4.0.0: is-decimal "^2.0.0" is-hexadecimal "^2.0.0" +parse-gitignore@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-2.0.0.tgz" + integrity sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog== + +parse-imports@^2.1.1: + version "2.2.1" + resolved "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz" + integrity sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ== + dependencies: + es-module-lexer "^1.5.3" + slashes "^3.0.12" + parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" @@ -10370,7 +10713,7 @@ path-browserify@^1.0.1: resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== -path-data-parser@0.1.0, path-data-parser@^0.1.0: +path-data-parser@^0.1.0, path-data-parser@0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz" integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== @@ -10405,6 +10748,14 @@ path-parse@^1.0.7: resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -10444,26 +10795,37 @@ pdfjs-dist@4.4.168: canvas "^2.11.2" path2d "^0.2.0" -periscopic@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz" - integrity sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^3.0.0" - is-reference "^3.0.0" - -picocolors@^1.0.0, picocolors@^1.1.0: +picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidtree@^0.6.0: +picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pidtree@~0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== @@ -10473,10 +10835,10 @@ pify@^2.3.0: resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== -pinyin-pro@^3.23.0: - version "3.24.2" - resolved "https://registry.npmjs.org/pinyin-pro/-/pinyin-pro-3.24.2.tgz" - integrity sha512-5tPyLhxT4CZ9dWqQRqm3X5ADdS18Sb2w0ranNBgr6jCrqO4O8gtfuyqG7Y6+1Mre+0n2VlhKDz+3P5oqSLrkOw== +pinyin-pro@^3.25.0: + version "3.26.0" + resolved "https://registry.npmjs.org/pinyin-pro/-/pinyin-pro-3.26.0.tgz" + integrity sha512-HcBZZb0pvm0/JkPhZHWA5Hqp2cWHXrrW/WrV+OtaYYM+kf35ffvZppIUuGmyuQ7gDr1JDJKMkbEE+GN0wfMoGg== pirates@^4.0.1, pirates@^4.0.4: version "4.0.5" @@ -10518,7 +10880,7 @@ pnp-webpack-plugin@^1.7.0: dependencies: ts-pnp "^1.1.6" -points-on-curve@0.2.0, points-on-curve@^0.2.0: +points-on-curve@^0.2.0, points-on-curve@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz" integrity sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A== @@ -10547,6 +10909,11 @@ portfinder@^1.0.28: debug "^3.2.7" mkdirp "^0.5.6" +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + postcss-import@^15.1.0: version "15.1.0" resolved "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz" @@ -10563,13 +10930,13 @@ postcss-js@^4.0.1: dependencies: camelcase-css "^2.0.1" -postcss-load-config@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz" - integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA== +postcss-load-config@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz" + integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== dependencies: - lilconfig "^2.0.5" - yaml "^2.1.1" + lilconfig "^3.0.0" + yaml "^2.3.4" postcss-loader@^8.1.1: version "8.1.1" @@ -10608,14 +10975,22 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-nested@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz" - integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== +postcss-nested@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== dependencies: - postcss-selector-parser "^6.0.11" + postcss-selector-parser "^6.1.1" -postcss-selector-parser@6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.9: +postcss-selector-parser@^6.0.15: + version "6.1.2" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@6.0.10: version "6.0.10" resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz" integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== @@ -10623,10 +10998,18 @@ postcss-selector-parser@6.0.10, postcss-selector-parser@^6.0.2, postcss-selector cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-selector-parser@^6.0.11: - version "6.0.13" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz" - integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== +postcss-selector-parser@^6.1.1: + version "6.1.2" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-selector-parser@^6.1.2: + version "6.1.2" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -10636,6 +11019,15 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^ resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +"postcss@^7.0.0 || ^8.0.1", postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.4, postcss@^8.4.47, postcss@^8.4.48, postcss@>=8.0.9: + version "8.4.49" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.1" + source-map-js "^1.2.1" + postcss@8.4.31: version "8.4.31" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" @@ -10645,15 +11037,6 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.2.14, postcss@^8.4.23, postcss@^8.4.31, postcss@^8.4.33, postcss@^8.4.38: - version "8.4.47" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz" - integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== - dependencies: - nanoid "^3.3.7" - picocolors "^1.1.0" - source-map-js "^1.2.1" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -10676,7 +11059,16 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^29.0.0, pretty-format@^29.7.0: +pretty-format@^29.0.0: + version "29.7.0" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -10713,7 +11105,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.8.1: +prop-types@^15.5.8, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10774,15 +11166,15 @@ pure-rand@^6.0.0: resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== -qrcode.react@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz" - integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== +qrcode.react@^4.1.0: + version "4.2.0" + resolved "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz" + integrity sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA== -qs@^6.11.1, qs@^6.12.3: - version "6.13.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz" - integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== +qs@^6.12.3, qs@^6.13.0: + version "6.13.1" + resolved "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz" + integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg== dependencies: side-channel "^1.0.6" @@ -10833,10 +11225,10 @@ range-parser@^1.2.1: resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc-input@~1.3.5: - version "1.3.11" - resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.3.11.tgz" - integrity sha512-jhH7QP5rILanSHCGSUkdoFE5DEtpv8FIseYhuYkOZzUBeiVAiwM3q26YqZ6xBB0QFEZ/yUAgms4xW4iuub3xFQ== +rc-input@~1.6.0: + version "1.6.4" + resolved "https://registry.npmjs.org/rc-input/-/rc-input-1.6.4.tgz" + integrity sha512-lBZhfRD4NSAUW0zOKLUeI6GJuXkxeZYi0hr8VcJgJpyTNOvHw1ysrKWAHcEOAAHj7guxgmWYSi6xWrEdfrSAsA== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" @@ -10852,14 +11244,14 @@ rc-resize-observer@^1.0.0: rc-util "^5.38.0" resize-observer-polyfill "^1.5.1" -rc-textarea@^1.5.2: - version "1.5.3" - resolved "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.5.3.tgz" - integrity sha512-oH682ghHx++stFNYrosPRBfwsypywrTXpaD0/5Z8MPkUOnyOQUaY9ueL9tMu6BP1LfsuYQ1VLpg5OtshViLNgA== +rc-textarea@^1.8.2: + version "1.8.2" + resolved "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.2.tgz" + integrity sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.1" - rc-input "~1.3.5" + rc-input "~1.6.0" rc-resize-observer "^1.0.0" rc-util "^5.27.0" @@ -10911,7 +11303,7 @@ react-docgen@^7.0.0: resolve "^1.22.1" strip-indent "^4.0.0" -"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", react-dom@~18.2.0: +"react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", "react-dom@^16 || ^17 || ^18", "react-dom@^16.13.1 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom@^18.0.0 || ^19.0.0", react-dom@^18.2.0, "react-dom@>= 16.3.0", react-dom@>=16.0.0, react-dom@>=16.14.0, react-dom@>=16.3.0, react-dom@>=16.4.0, react-dom@>=16.8.0, react-dom@>=16.8.1, react-dom@>=16.9.0, react-dom@>=17, react-dom@>=17.x, react-dom@>=18.0.0, react-dom@~18.2.0: version "18.2.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -10927,10 +11319,10 @@ react-draggable@4.4.6: clsx "^1.1.1" prop-types "^15.8.1" -react-easy-crop@^5.0.8: - version "5.0.8" - resolved "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.0.8.tgz" - integrity sha512-KjulxXhR5iM7+ATN2sGCum/IyDxGw7xT0dFoGcqUP+ysaPU5Ka7gnrDa2tUHFHUoMNyPrVZ05QA+uvMgC5ym/g== +react-easy-crop@^5.1.0: + version "5.2.0" + resolved "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.2.0.tgz" + integrity sha512-gjb7jN+WnwfgpbNUI2jSwyoIxF1sJ0PVSNVgEysAgF1rj8AqR75fqmdvqZ6PFVgEX3rT1G4HJELesiQXr2ZvAg== dependencies: normalize-wheel "^1.0.1" tslib "^2.0.1" @@ -10942,29 +11334,41 @@ react-error-boundary@^3.1.4: dependencies: "@babel/runtime" "^7.12.5" -react-error-boundary@^4.0.2: - version "4.0.9" - resolved "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.9.tgz" - integrity sha512-f6DcHVdTDZmc9ixmRmuLDZpkdghYR/HKZdUzMLHD58s4cR2C4R6y4ktYztCosM6pyeK4/C8IofwqxgID25W6kw== +react-error-boundary@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz" + integrity sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag== dependencies: "@babel/runtime" "^7.12.5" -react-hook-form@^7.51.4: - version "7.51.5" - resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz" - integrity sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q== +react-fast-compare@^3.2.2: + version "3.2.2" + resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + +react-headless-pagination@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/react-headless-pagination/-/react-headless-pagination-1.1.6.tgz" + integrity sha512-t7L/Q4xpyZszw8iC8ALERs/G2644JESmssahUkRp65WFWvw2k9HXVmfI6VbXvTXrqy+a8fbKT6BQ6SgS2ULNOA== + dependencies: + clsx "^2.1.0" + +react-hook-form@^7.0.0, react-hook-form@^7.53.1: + version "7.54.2" + resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz" + integrity sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg== react-hotkeys-hook@^4.6.1: version "4.6.1" resolved "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.6.1.tgz" integrity sha512-XlZpbKUj9tkfgPgT9gA+1p7Ey6vFIZHttUjPqpTdyT5nqQ8mHL7elxvSbaC+dpSiHUSmr21Ya1mDxBZG3aje4Q== -react-i18next@^12.2.0: - version "12.3.1" - resolved "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz" - integrity sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA== +react-i18next@^15.1.0: + version "15.2.0" + resolved "https://registry.npmjs.org/react-i18next/-/react-i18next-15.2.0.tgz" + integrity sha512-iJNc8111EaDtVTVMKigvBtPHyrJV+KblWG73cUxqp+WmJCcwkzhWNFXmkAD5pwP2Z4woeDj/oXDdbjDsb3Gutg== dependencies: - "@babel/runtime" "^7.20.6" + "@babel/runtime" "^7.25.0" html-parse-stringify "^3.0.1" react-infinite-scroll-component@^6.1.0: @@ -10994,39 +11398,34 @@ react-is@^18.2.0: resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-markdown@^8.0.6: - version "8.0.7" - resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz" - integrity sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ== +react-markdown@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz" + integrity sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg== dependencies: - "@types/hast" "^2.0.0" - "@types/prop-types" "^15.0.0" - "@types/unist" "^2.0.0" - comma-separated-tokens "^2.0.0" - hast-util-whitespace "^2.0.0" - prop-types "^15.0.0" - property-information "^6.0.0" - react-is "^18.0.0" - remark-parse "^10.0.0" - remark-rehype "^10.0.0" - space-separated-tokens "^2.0.0" - style-to-object "^0.4.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - vfile "^5.0.0" + "@types/hast" "^3.0.0" + devlop "^1.0.0" + hast-util-to-jsx-runtime "^2.0.0" + html-url-attributes "^3.0.0" + mdast-util-to-hast "^13.0.0" + remark-parse "^11.0.0" + remark-rehype "^11.0.0" + unified "^11.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" -react-multi-email@^1.0.14: - version "1.0.16" - resolved "https://registry.npmjs.org/react-multi-email/-/react-multi-email-1.0.16.tgz" - integrity sha512-dgg4TY3P5FWz6c4ghgxH1bjZOgYL3S/HN+EUNe6dqHbLMVzeyud1ztDUlqvft4NX1sUxKx2IF2zDq1yAJQA5yQ== +react-multi-email@^1.0.25: + version "1.0.25" + resolved "https://registry.npmjs.org/react-multi-email/-/react-multi-email-1.0.25.tgz" + integrity sha512-Wmv28FvIk4nWgdpHzlIPonY4iSs7bPV35+fAiWYzSBhTo+vhXfglEhjY1WnjHQINW/Pibu2xlb/q1heVuytQHQ== -react-papaparse@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/react-papaparse/-/react-papaparse-4.1.0.tgz" - integrity sha512-sGJqK+OE2rVVQPxQUCCDW2prLIglv9kTdizhNe2awXvKo0gLShmhpRN3BwA+ujw5M2gSJ/KGNEwtgII0OsLgkg== +react-papaparse@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/react-papaparse/-/react-papaparse-4.4.0.tgz" + integrity sha512-xTEwHZYJ+1dh9mQDQjjwJXmWyX20DdZ52u+ddw75V+Xm5qsjXSvWmC7c8K82vRwMjKAOH2S9uFyGpHEyEztkUQ== dependencies: - "@types/papaparse" "^5.3.1" - papaparse "^5.3.1" + "@types/papaparse" "^5.3.9" + papaparse "^5.4.1" react-pdf-highlighter@^8.0.0-rc.0: version "8.0.0-rc.0" @@ -11037,7 +11436,7 @@ react-pdf-highlighter@^8.0.0-rc.0: react-rnd "^10.4.11" ts-debounce "^4.0.0" -react-refresh@^0.14.0: +react-refresh@^0.14.0, "react-refresh@>=0.10.0 <1.0.0": version "0.14.2" resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -11051,10 +11450,10 @@ react-rnd@^10.4.11: react-draggable "4.4.6" tslib "2.6.2" -react-slider@^2.0.4: - version "2.0.5" - resolved "https://registry.npmjs.org/react-slider/-/react-slider-2.0.5.tgz" - integrity sha512-MU5gaK1yYCKnbDDN3CMiVcgkKZwMvdqK2xUEW7fFU37NAzRgS1FZbF9N7vP08E3XXNVhiuZnwVzUa3PYQAZIMg== +react-slider@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/react-slider/-/react-slider-2.0.6.tgz" + integrity sha512-gJxG1HwmuMTJ+oWIRCmVWvgwotNCbByTwRkFZC6U4MBsHqJBmxwbYRJUmxy4Tke1ef8r9jfXjgkmY/uHOCEvbA== dependencies: prop-types "^15.8.1" @@ -11066,13 +11465,14 @@ react-sortablejs@^6.1.4: classnames "2.3.1" tiny-invariant "1.2.0" -react-syntax-highlighter@^15.5.0: - version "15.5.0" - resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz" - integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== +react-syntax-highlighter@^15.6.1: + version "15.6.1" + resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz" + integrity sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg== dependencies: "@babel/runtime" "^7.3.1" highlight.js "^10.4.1" + highlightjs-vue "^1.0.0" lowlight "^1.17.0" prismjs "^1.27.0" refractor "^3.6.0" @@ -11090,15 +11490,15 @@ react-window-infinite-loader@^1.0.9: resolved "https://registry.npmjs.org/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz" integrity sha512-5Hg89IdU4Vrp0RT8kZYKeTIxWZYhNkVXeI1HbKo01Vm/Z7qztDvXljwx16sMzsa9yapRJQW3ODZfMUw38SOWHw== -react-window@^1.8.9: - version "1.8.9" - resolved "https://registry.npmjs.org/react-window/-/react-window-1.8.9.tgz" - integrity sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q== +react-window@^1.8.10: + version "1.8.11" + resolved "https://registry.npmjs.org/react-window/-/react-window-1.8.11.tgz" + integrity sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ== dependencies: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@~18.2.0: +"react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^15.0.0 || >=16.0.0", "react@^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", "react@^16 || ^17 || ^18", "react@^16.11.0 || ^17.0.0 || ^18.0.0", "react@^16.13.1 || ^17.0.0 || ^18.0.0", "react@^16.3.0 || ^17.0.0 || ^18.0.0", "react@^16.3.0 || ^17.0.1 || ^18.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react@^18 || ^19", "react@^18.0.0 || ^19.0.0", react@^18.2.0, "react@>= 0.14.0", "react@>= 16", "react@>= 16.3.0", "react@>= 16.8.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16, react@>=16.0.0, react@>=16.13.1, react@>=16.14.0, react@>=16.3.0, react@>=16.4.0, react@>=16.8, react@>=16.8.0, react@>=16.8.1, react@>=16.9.0, react@>=17, react@>=17.x, react@>=18, react@>=18.0.0, react@>=18.2.0, react@~18.2.0, "react@15.x || 16.x || 17.x || 18.x": version "18.2.0" resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -11156,7 +11556,16 @@ readable-stream@^2.3.8: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -11176,6 +11585,11 @@ readable-stream@^4.0.0: process "^0.11.10" string_decoder "^1.3.0" +readdirp@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz" + integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" @@ -11194,6 +11608,46 @@ recast@^0.23.5: tiny-invariant "^1.3.3" tslib "^2.0.1" +recma-build-jsx@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz" + integrity sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew== + dependencies: + "@types/estree" "^1.0.0" + estree-util-build-jsx "^3.0.0" + vfile "^6.0.0" + +recma-jsx@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz" + integrity sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q== + dependencies: + acorn-jsx "^5.0.0" + estree-util-to-js "^2.0.0" + recma-parse "^1.0.0" + recma-stringify "^1.0.0" + unified "^11.0.0" + +recma-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz" + integrity sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ== + dependencies: + "@types/estree" "^1.0.0" + esast-util-from-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +recma-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz" + integrity sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g== + dependencies: + "@types/estree" "^1.0.0" + estree-util-to-js "^2.0.0" + unified "^11.0.0" + vfile "^6.0.0" + recordrtc@^5.6.2: version "5.6.2" resolved "https://registry.npmjs.org/recordrtc/-/recordrtc-5.6.2.tgz" @@ -11207,17 +11661,26 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reflect.getprototypeof@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz" - integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== +refa@^0.12.0, refa@^0.12.1: + version "0.12.1" + resolved "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz" + integrity sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" + "@eslint-community/regexpp" "^4.8.0" + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.8, reflect.getprototypeof@^1.0.9: + version "1.0.9" + resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz" + integrity sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + dunder-proto "^1.0.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + which-builtin-type "^1.2.1" refractor@^3.6.0: version "3.6.0" @@ -11257,24 +11720,28 @@ regex-parser@^2.2.11: resolved "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz" integrity sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg== -regexp-tree@^0.1.24, regexp-tree@~0.1.1: +regexp-ast-analysis@^0.7.0, regexp-ast-analysis@^0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz" + integrity sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A== + dependencies: + "@eslint-community/regexpp" "^4.8.0" + refa "^0.12.1" + +regexp-tree@^0.1.27: version "0.1.27" resolved "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz" integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== -regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: - version "1.5.1" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz" - integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== +regexp.prototype.flags@^1.5.3: + version "1.5.3" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - set-function-name "^2.0.0" - -regexpp@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + call-bind "^1.0.7" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.2" regexpu-core@^6.1.1: version "6.1.1" @@ -11293,6 +11760,13 @@ regjsgen@^0.8.0: resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz" integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== +regjsparser@^0.10.0: + version "0.10.0" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz" + integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA== + dependencies: + jsesc "~0.5.0" + regjsparser@^0.11.0: version "0.11.2" resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz" @@ -11300,24 +11774,18 @@ regjsparser@^0.11.0: dependencies: jsesc "~3.0.2" -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== +rehype-katex@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz" + integrity sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA== dependencies: - jsesc "~0.5.0" - -rehype-katex@^6.0.2: - version "6.0.3" - resolved "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz" - integrity sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA== - dependencies: - "@types/hast" "^2.0.0" - "@types/katex" "^0.14.0" - hast-util-from-html-isomorphic "^1.0.0" - hast-util-to-text "^3.1.0" + "@types/hast" "^3.0.0" + "@types/katex" "^0.16.0" + hast-util-from-html-isomorphic "^2.0.0" + hast-util-to-text "^4.0.0" katex "^0.16.0" - unist-util-visit "^4.0.0" + unist-util-visit-parents "^6.0.0" + vfile "^6.0.0" rehype-raw@^7.0.0: version "7.0.0" @@ -11328,66 +11796,88 @@ rehype-raw@^7.0.0: hast-util-raw "^9.0.0" vfile "^6.0.0" +rehype-recma@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz" + integrity sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw== + dependencies: + "@types/estree" "^1.0.0" + "@types/hast" "^3.0.0" + hast-util-to-estree "^3.0.0" + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== -remark-breaks@^3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/remark-breaks/-/remark-breaks-3.0.3.tgz" - integrity sha512-C7VkvcUp1TPUc2eAYzsPdaUh8Xj4FSbQnYA5A9f80diApLZscTDeG7efiWP65W8hV2sEy3JuGVU0i6qr5D8Hug== +remark-breaks@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz" + integrity sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-newline-to-break "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-newline-to-break "^2.0.0" + unified "^11.0.0" -remark-gfm@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz" - integrity sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig== +remark-gfm@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz" + integrity sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-gfm "^2.0.0" - micromark-extension-gfm "^2.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-gfm "^3.0.0" + micromark-extension-gfm "^3.0.0" + remark-parse "^11.0.0" + remark-stringify "^11.0.0" + unified "^11.0.0" -remark-math@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/remark-math/-/remark-math-5.1.1.tgz" - integrity sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw== +remark-math@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz" + integrity sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-math "^2.0.0" - micromark-extension-math "^2.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-math "^3.0.0" + micromark-extension-math "^3.0.0" + unified "^11.0.0" -remark-mdx@^2.0.0: - version "2.3.0" - resolved "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz" - integrity sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g== +remark-mdx@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz" + integrity sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA== dependencies: - mdast-util-mdx "^2.0.0" - micromark-extension-mdxjs "^1.0.0" + mdast-util-mdx "^3.0.0" + micromark-extension-mdxjs "^3.0.0" -remark-parse@^10.0.0: - version "10.0.2" - resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz" - integrity sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw== +remark-parse@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz" + integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== dependencies: - "@types/mdast" "^3.0.0" - mdast-util-from-markdown "^1.0.0" - unified "^10.0.0" + "@types/mdast" "^4.0.0" + mdast-util-from-markdown "^2.0.0" + micromark-util-types "^2.0.0" + unified "^11.0.0" -remark-rehype@^10.0.0: - version "10.1.0" - resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz" - integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== +remark-rehype@^11.0.0: + version "11.1.1" + resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.1.tgz" + integrity sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ== dependencies: - "@types/hast" "^2.0.0" - "@types/mdast" "^3.0.0" - mdast-util-to-hast "^12.1.0" - unified "^10.0.0" + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + mdast-util-to-hast "^13.0.0" + unified "^11.0.0" + vfile "^6.0.0" + +remark-stringify@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz" + integrity sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw== + dependencies: + "@types/mdast" "^4.0.0" + mdast-util-to-markdown "^2.0.0" + unified "^11.0.0" renderkid@^3.0.0: version "3.0.0" @@ -11410,11 +11900,6 @@ require-from-string@^2.0.2: resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -requireindex@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz" - integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" @@ -11468,7 +11953,7 @@ resolve.exports@^2.0.0: resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -11477,7 +11962,7 @@ resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.4: +resolve@^2.0.0-next.5: version "2.0.0-next.5" resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== @@ -11493,23 +11978,23 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" + onetime "^7.0.0" + signal-exit "^4.1.0" reusify@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rimraf@^3.0.2: version "3.0.2" @@ -11560,28 +12045,15 @@ rw@1: resolved "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz" integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== -rxjs@^7.8.0: - version "7.8.1" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: - tslib "^2.1.0" - -sade@^1.7.3: - version "1.8.1" - resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz" - integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== - dependencies: - mri "^1.1.0" - -safe-array-concat@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz" - integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - 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" safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: @@ -11589,26 +12061,24 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@~5.1.0: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz" - integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== +safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== dependencies: - regexp-tree "~0.1.1" + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" @@ -11622,14 +12092,16 @@ sass-loader@^13.2.0: dependencies: neo-async "^2.6.2" -sass@^1.61.0: - version "1.62.1" - resolved "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz" - integrity sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A== +sass@^1.3.0, sass@^1.80.3: + version "1.83.0" + resolved "https://registry.npmjs.org/sass/-/sass-1.83.0.tgz" + integrity sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw== dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" + chokidar "^4.0.0" + immutable "^5.0.2" source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" saxes@^6.0.0: version "6.0.0" @@ -11638,14 +12110,23 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -scheduler@^0.23.0: +scheduler@^0.23.0, scheduler@>=0.19.0: version "0.23.0" resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz" integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== dependencies: loose-envify "^1.1.0" -schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.1.1: + version "3.3.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -11669,28 +12150,40 @@ screenfull@^5.0.0: resolved "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz" integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== +scslre@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz" + integrity sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ== + dependencies: + "@eslint-community/regexpp" "^4.8.0" + refa "^0.12.0" + regexp-ast-analysis "^0.7.0" -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.0.0: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: - version "7.6.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" +semver@^6.3.0: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.6.2, semver@^7.6.3: +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3: version "7.6.3" resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + serialize-javascript@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz" @@ -11703,12 +12196,7 @@ server-only@^0.0.1: resolved "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz" integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-function-length@^1.2.1: +set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -11720,14 +12208,15 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.0, set-function-name@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz" - integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== dependencies: - define-data-property "^1.0.1" + define-data-property "^1.1.4" + es-errors "^1.3.0" functions-have-names "^1.2.3" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.2" setimmediate@^1.0.4: version "1.0.5" @@ -11742,7 +12231,7 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sharp@^0.33.2, sharp@^0.33.3: +sharp@^0.33.3, sharp@^0.33.5: version "0.33.5" resolved "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz" integrity sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw== @@ -11788,34 +12277,65 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4, side-channel@^1.0.6: - 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== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" +short-unique-id@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/short-unique-id/-/short-unique-id-5.2.0.tgz" + integrity sha512-cMGfwNyfDZ/nzJ2k2M+ClthBIh//GlZl1JEf47Uoa9XR11bz8Pa2T2wQO4bVrRdH48LrIDWJahQziKo3MjhsWg== -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + 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== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + 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" + +side-channel@^1.0.6, side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -simple-get@^3.0.3: - version "3.1.1" - resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz" - integrity sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-swizzle@^0.2.2: version "0.2.2" @@ -11844,23 +12364,10 @@ slash@^4.0.0: resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" +slashes@^3.0.12: + version "3.0.12" + resolved "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz" + integrity sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA== slice-ansi@^5.0.0: version "5.0.0" @@ -11870,24 +12377,24 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -sortablejs@^1.15.0: - version "1.15.0" - resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz" - integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w== +slice-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz" + integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1: +sortablejs@^1.15.3, sortablejs@1: + version "1.15.6" + resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz" + integrity sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A== + +source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1, "source-map-js@>=0.6.2 <2.0.0": version "1.2.1" resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -11896,7 +12403,20 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -11906,6 +12426,21 @@ source-map@^0.7.0, source-map@^0.7.3: resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== +source-map@~0.6.0: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz" @@ -11937,6 +12472,14 @@ spdx-expression-parse@^3.0.0: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" +spdx-expression-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz" + integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + spdx-license-ids@^3.0.0: version "3.0.13" resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz" @@ -11947,6 +12490,11 @@ sprintf-js@~1.0.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +stable-hash@^0.0.4: + version "0.0.4" + resolved "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz" + integrity sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g== + stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" @@ -11964,19 +12512,12 @@ state-local@^1.0.6: resolved "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz" integrity sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w== -stop-iteration-iterator@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz" - integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== +"storybook@^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0", storybook@^8.3.6, storybook@^8.4.7: + version "8.4.7" + resolved "https://registry.npmjs.org/storybook/-/storybook-8.4.7.tgz" + integrity sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw== dependencies: - internal-slot "^1.0.4" - -storybook@^8.3.5: - version "8.4.2" - resolved "https://registry.npmjs.org/storybook/-/storybook-8.4.2.tgz" - integrity sha512-GMCgyAulmLNrkUtDkCpFO4SB77YrpiIxq6e5tzaQdXEuaDu1mdNwOuP3VG7nE2FzxmqDvagSgriM68YW9iFaZA== - dependencies: - "@storybook/core" "8.4.2" + "@storybook/core" "8.4.7" stream-browserify@^3.0.0: version "3.0.0" @@ -12001,70 +12542,6 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -string-argv@^0.3.1: - version "0.3.2" - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" - integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@4.2.3, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.0.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.matchall@^4.0.8: - version "4.0.10" - resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz" - integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - regexp.prototype.flags "^1.5.0" - set-function-name "^2.0.0" - side-channel "^1.0.4" - -string.prototype.trim@^1.2.8: - version "1.2.8" - resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz" - integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimend@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz" - integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - -string.prototype.trimstart@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz" - integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" @@ -12079,6 +12556,137 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +string-argv@~0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-ts@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/string-ts/-/string-ts-2.2.0.tgz" + integrity sha512-VTP0LLZo4Jp9Gz5IiDVMS9WyLx/3IeYh0PXUn0NdPqusUFNgkHPWiEdbB9TU2Iv3myUskraD5WtYEdHUrQEIlQ== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string-width@^7.0.0: + version "7.2.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + +string.prototype.includes@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz" + integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + +string.prototype.matchall@^4.0.12: + version "4.0.12" + resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" + set-function-name "^2.0.2" + side-channel "^1.1.0" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + 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== + dependencies: + 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.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + +string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + stringify-entities@^4.0.0: version "4.0.3" resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz" @@ -12087,6 +12695,13 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -12094,7 +12709,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.1.0: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -12145,19 +12760,19 @@ style-loader@^3.3.1: resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz" integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== -style-to-object@^0.4.0, style-to-object@^0.4.1: +style-to-object@^0.4.0: version "0.4.1" resolved "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz" integrity sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw== dependencies: inline-style-parser "0.1.1" -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== +style-to-object@^1.0.0: + version "1.0.8" + resolved "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz" + integrity sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g== dependencies: - client-only "0.0.1" + inline-style-parser "0.2.4" styled-jsx@^5.1.6: version "5.1.6" @@ -12166,19 +12781,26 @@ styled-jsx@^5.1.6: dependencies: client-only "0.0.1" +styled-jsx@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz" + integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== + dependencies: + client-only "0.0.1" + stylis@^4.3.1: version "4.3.4" resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz" integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now== -sucrase@^3.32.0: - version "3.32.0" - resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz" - integrity sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ== +sucrase@^3.35.0: + version "3.35.0" + resolved "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== dependencies: "@jridgewell/gen-mapping" "^0.3.2" commander "^4.0.0" - glob "7.1.6" + glob "^10.3.10" lines-and-columns "^1.1.6" mz "^2.7.0" pirates "^4.0.1" @@ -12215,6 +12837,13 @@ symbol-tree@^3.2.4: resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +synckit@^0.6.0: + version "0.6.2" + resolved "https://registry.npmjs.org/synckit/-/synckit-0.6.2.tgz" + integrity sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA== + dependencies: + tslib "^2.3.1" + synckit@^0.8.5: version "0.8.5" resolved "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz" @@ -12223,61 +12852,57 @@ synckit@^0.8.5: "@pkgr/utils" "^2.3.1" tslib "^2.5.0" -tabbable@^6.0.1: +synckit@^0.9.1: + version "0.9.2" + resolved "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz" + integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + +tabbable@^6.0.0: version "6.2.0" resolved "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz" integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== -tailwind-merge@^2.4.0: - version "2.5.2" - resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz" - integrity sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg== +tailwind-merge@^2.5.4: + version "2.6.0" + resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz" + integrity sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA== -tailwindcss@^3.4.4: - version "3.4.9" - resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.9.tgz" - integrity sha512-1SEOvRr6sSdV5IDf9iC+NU4dhwdqzF4zKKq3sAbasUWHEM6lsMhX+eNN5gkPx1BvLFEnZQEUFbXnGj8Qlp83Pg== +tailwindcss@^3.4.0, tailwindcss@^3.4.14, "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20": + version "3.4.17" + resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz" + integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" - chokidar "^3.5.3" + chokidar "^3.6.0" didyoumean "^1.2.2" dlv "^1.1.3" - fast-glob "^3.3.0" + fast-glob "^3.3.2" glob-parent "^6.0.2" is-glob "^4.0.3" - jiti "^1.21.0" - lilconfig "^2.1.0" - micromatch "^4.0.5" + jiti "^1.21.6" + lilconfig "^3.1.3" + micromatch "^4.0.8" normalize-path "^3.0.0" object-hash "^3.0.0" - picocolors "^1.0.0" - postcss "^8.4.23" + picocolors "^1.1.1" + postcss "^8.4.47" postcss-import "^15.1.0" postcss-js "^4.0.1" - postcss-load-config "^4.0.1" - postcss-nested "^6.0.1" - postcss-selector-parser "^6.0.11" - resolve "^1.22.2" - sucrase "^3.32.0" + postcss-load-config "^4.0.2" + postcss-nested "^6.2.0" + postcss-selector-parser "^6.1.2" + resolve "^1.22.8" + sucrase "^3.35.0" tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.1.11: - version "6.2.1" - resolved "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz" - integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - terser-webpack-plugin@^5.3.1, terser-webpack-plugin@^5.3.10: version "5.3.10" resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz" @@ -12308,11 +12933,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" @@ -12332,11 +12952,6 @@ throttle-debounce@^2.1.0: resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz" integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ== -through@^2.3.8: - version "2.3.8" - resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - timers-browserify@^2.0.12: version "2.0.12" resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz" @@ -12344,17 +12959,17 @@ timers-browserify@^2.0.12: dependencies: setimmediate "^1.0.4" -tiny-invariant@1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== - tiny-invariant@^1.3.1, tiny-invariant@^1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== -tinyexec@^0.3.0: +tiny-invariant@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz" + integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + +tinyexec@^0.3.0, tinyexec@^0.3.1: version "0.3.1" resolved "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz" integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== @@ -12391,6 +13006,13 @@ toggle-selection@^1.0.6: resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz" integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== +toml-eslint-parser@^0.10.0: + version "0.10.0" + resolved "https://registry.npmjs.org/toml-eslint-parser/-/toml-eslint-parser-0.10.0.tgz" + integrity sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g== + dependencies: + eslint-visitor-keys "^3.0.0" + tough-cookie@^4.1.2: version "4.1.4" resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz" @@ -12408,11 +13030,6 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - trim-lines@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz" @@ -12423,11 +13040,28 @@ trough@^2.0.0: resolved "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz" integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== +ts-api-utils@^1.3.0: + version "1.4.3" + resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz" + integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== + +ts-api-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz" + integrity sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ== + ts-debounce@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/ts-debounce/-/ts-debounce-4.0.0.tgz" integrity sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg== +ts-declaration-location@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.5.tgz" + integrity sha512-WqmlO9IoeYwCqJ2E9kHMcY9GZhhfLYItC3VnHDlPOrg6nNdUWS4wn4hhDZUPt60m1EvtjPIZyprTjpI992Bgzw== + dependencies: + minimatch "^10.0.1" + ts-dedent@^2.0.0, ts-dedent@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz" @@ -12438,7 +13072,7 @@ ts-interface-checker@^0.1.9: resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -ts-node@^10.9.2: +ts-node@^10.9.2, ts-node@>=9.0.0: version "10.9.2" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== @@ -12457,6 +13091,11 @@ ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +ts-pattern@^5.6.0: + version "5.6.0" + resolved "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.6.0.tgz" + integrity sha512-SL8u60X5+LoEy9tmQHWCdPc2hhb2pKI6I1tU5Jue3v8+iRqZdcT3mWPwKKJy1fMfky6uha82c8ByHAE8PMhKHw== + ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz" @@ -12490,28 +13129,21 @@ tsconfig-paths@^4.0.0, tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.6.2, tslib@^2.6.3, tslib@2: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== -tslib@2.6.2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0: +tslib@2.6.2: version "2.6.2" resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - tty-browserify@^0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz" @@ -12554,74 +13186,90 @@ type-fest@^0.8.1: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-fest@^2.14.0, type-fest@^2.19.0: +type-fest@^2.14.0, type-fest@^2.19.0, "type-fest@>=0.17.0 <5.0.0": version "2.19.0" resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== -typed-array-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz" - integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - is-typed-array "^1.1.10" + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" -typed-array-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz" - integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.8" for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" -typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-length@^1.0.4: +typed-array-byte-offset@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== dependencies: - call-bind "^1.0.2" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - is-typed-array "^1.1.9" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" -typescript@4.9.5: +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + +"typescript@^4.9.5 || ^5.3.3", "typescript@>= 4.2.x", "typescript@>= 4.3.x", "typescript@>= 4.x", typescript@>=2.7, typescript@>=3.3.1, typescript@>=4.0.0, typescript@>=4.2.0, typescript@>=4.7.4, typescript@>=4.8.4, "typescript@>=4.8.4 <5.8.0", typescript@>=4.9.5, typescript@>3.6.0, typescript@4.9.5: version "4.9.5" resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +"typescript@>= 5.0.0": + version "5.7.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== + +typescript@>=5: + version "5.7.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== + ufo@^1.5.4: version "1.5.4" resolved "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz" integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== -uglify-js@^3.17.4: - version "3.17.4" - resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz" - integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== +uglify-js@^3.19.3: + version "3.19.3" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" undici-types@~6.19.8: version "6.19.8" @@ -12651,38 +13299,26 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -unified@^10.0.0: - version "10.1.2" - resolved "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz" - integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== +unified@^11.0.0: + version "11.0.5" + resolved "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz" + integrity sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA== dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" bail "^2.0.0" + devlop "^1.0.0" extend "^3.0.0" - is-buffer "^2.0.0" is-plain-obj "^4.0.0" trough "^2.0.0" - vfile "^5.0.0" + vfile "^6.0.0" -unist-util-find-after@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz" - integrity sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw== +unist-util-find-after@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz" + integrity sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ== dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - -unist-util-generated@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz" - integrity sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A== - -unist-util-is@^5.0.0: - version "5.2.1" - resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz" - integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== - dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" unist-util-is@^6.0.0: version "6.0.0" @@ -12691,19 +13327,12 @@ unist-util-is@^6.0.0: dependencies: "@types/unist" "^3.0.0" -unist-util-position-from-estree@^1.0.0, unist-util-position-from-estree@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz" - integrity sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww== +unist-util-position-from-estree@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz" + integrity sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ== dependencies: - "@types/unist" "^2.0.0" - -unist-util-position@^4.0.0: - version "4.0.4" - resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz" - integrity sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg== - dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" unist-util-position@^5.0.0: version "5.0.0" @@ -12712,27 +13341,13 @@ unist-util-position@^5.0.0: dependencies: "@types/unist" "^3.0.0" -unist-util-remove-position@^4.0.0: - version "4.0.2" - resolved "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz" - integrity sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ== +unist-util-remove-position@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz" + integrity sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q== dependencies: - "@types/unist" "^2.0.0" - unist-util-visit "^4.0.0" - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== - dependencies: - "@types/unist" "^2.0.2" - -unist-util-stringify-position@^3.0.0: - version "3.0.3" - resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz" - integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== - dependencies: - "@types/unist" "^2.0.0" + "@types/unist" "^3.0.0" + unist-util-visit "^5.0.0" unist-util-stringify-position@^4.0.0: version "4.0.0" @@ -12741,14 +13356,6 @@ unist-util-stringify-position@^4.0.0: dependencies: "@types/unist" "^3.0.0" -unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: - version "5.1.3" - resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz" - integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents@^6.0.0: version "6.0.1" resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz" @@ -12757,15 +13364,6 @@ unist-util-visit-parents@^6.0.0: "@types/unist" "^3.0.0" unist-util-is "^6.0.0" -unist-util-visit@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz" - integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^5.0.0" - unist-util-visit-parents "^5.1.1" - unist-util-visit@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz" @@ -12775,6 +13373,11 @@ unist-util-visit@^5.0.0: unist-util-is "^6.0.0" unist-util-visit-parents "^6.0.0" +universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz" + integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== + universalify@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz" @@ -12829,17 +13432,17 @@ url@^0.11.0: punycode "^1.4.1" qs "^6.12.3" -use-context-selector@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/use-context-selector/-/use-context-selector-1.4.1.tgz" - integrity sha512-Io2ArvcRO+6MWIhkdfMFt+WKQX+Vb++W8DS2l03z/Vw/rz3BclKpM0ynr4LYGyU85Eke+Yx5oIhTY++QR0ZDoA== +use-context-selector@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/use-context-selector/-/use-context-selector-2.0.0.tgz" + integrity sha512-owfuSmUNd3eNp3J9CdDl0kMgfidV+MkDvHPpvthN5ThqM+ibMccNE0k+Iq7TWC6JPFvGZqanqiGCuQx6DyV24g== use-strict@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/use-strict/-/use-strict-1.0.1.tgz" integrity sha512-IeiWvvEXfW5ltKVMkxq6FvNf2LojMKvB2OCeja6+ct24S1XOmQw2dGr2JyndwACWAGJva9B7yPHwAmeA9QCqAQ== -use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: +use-sync-external-store@^1.2.0, use-sync-external-store@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -12865,20 +13468,20 @@ utila@~0.4: resolved "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== -uuid@^9.0.0, uuid@^9.0.1: +uuid@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz" + integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== + +uuid@^9.0.0: version "9.0.1" resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== -uvu@^0.5.0: - version "0.5.6" - resolved "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz" - integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== - dependencies: - dequal "^2.0.0" - diff "^5.0.0" - kleur "^4.0.3" - sade "^1.7.3" +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-compile-cache-lib@^3.0.1: version "3.0.1" @@ -12894,6 +13497,11 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +valibot@^1.0.0-beta.9: + version "1.0.0-beta.9" + resolved "https://registry.npmjs.org/valibot/-/valibot-1.0.0-beta.9.tgz" + integrity sha512-yEX8gMAZ2R1yI2uwOO4NCtVnJQx36zn3vD0omzzj9FhcoblvPukENIiRZXKZwCnqSeV80bMm8wNiGhQ0S8fiww== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" @@ -12902,14 +13510,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vfile-location@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz" - integrity sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw== - dependencies: - "@types/unist" "^2.0.0" - vfile "^5.0.0" - vfile-location@^5.0.0: version "5.0.3" resolved "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz" @@ -12918,14 +13518,6 @@ vfile-location@^5.0.0: "@types/unist" "^3.0.0" vfile "^6.0.0" -vfile-message@^3.0.0: - version "3.1.4" - resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz" - integrity sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw== - dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz" @@ -12934,16 +13526,6 @@ vfile-message@^4.0.0: "@types/unist" "^3.0.0" unist-util-stringify-position "^4.0.0" -vfile@^5.0.0: - version "5.3.7" - resolved "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz" - integrity sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g== - dependencies: - "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^3.0.0" - vfile-message "^3.0.0" - vfile@^6.0.0: version "6.0.3" resolved "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz" @@ -13004,10 +13586,10 @@ vscode-uri@~3.0.8: resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz" integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== -vue-eslint-parser@^9.3.0: - version "9.3.0" - resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.0.tgz" - integrity sha512-48IxT9d0+wArT1+3wNIy0tascRoywqSUe2E1YalIC1L8jsUGe5aJQItWfRok7DVFGz3UYvzEI7n5wiTXsCMAcQ== +vue-eslint-parser@^9.4.3: + version "9.4.3" + resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz" + integrity sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg== dependencies: debug "^4.3.4" eslint-scope "^7.1.1" @@ -13044,11 +13626,6 @@ web-namespaces@^2.0.0: resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" @@ -13072,7 +13649,7 @@ webpack-dev-middleware@^6.1.2: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-hot-middleware@^2.25.1: +webpack-hot-middleware@^2.25.1, webpack-hot-middleware@2.x: version "2.26.1" resolved "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz" integrity sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A== @@ -13081,7 +13658,7 @@ webpack-hot-middleware@^2.25.1: html-entities "^2.1.0" strip-ansi "^6.0.0" -webpack-sources@^3.2.3: +webpack-sources@^3, webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== @@ -13091,7 +13668,7 @@ webpack-virtual-modules@^0.6.0, webpack-virtual-modules@^0.6.2: resolved "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz" integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ== -webpack@5: +webpack@^5.0.0, webpack@^5.1.0, webpack@^5.11.0, webpack@^5.20.0, "webpack@>= 4", "webpack@>=4.43.0 <6.0.0", webpack@>=5, webpack@5: version "5.97.1" resolved "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz" integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg== @@ -13140,63 +13717,57 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== - dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" is-generator-function "^1.0.10" - is-regex "^1.1.4" + is-regex "^1.2.1" is-weakref "^1.0.2" isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" -which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" -which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.2, which-typed-array@^1.1.9: - version "1.1.13" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== +which-typed-array@^1.1.16, which-typed-array@^1.1.18, which-typed-array@^1.1.2: + version "1.1.18" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz" + integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + gopd "^1.2.0" + has-tostringtag "^1.0.2" which@^2.0.1: version "2.0.2" @@ -13205,22 +13776,15 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.2: - version "1.1.5" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" string-width "^4.1.0" @@ -13235,6 +13799,24 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrap-ansi@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz" + integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" @@ -13278,15 +13860,10 @@ yallist@^3.0.2: resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml-eslint-parser@^1.1.0, yaml-eslint-parser@^1.2.1: - version "1.2.2" - resolved "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.2.tgz" - integrity sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg== +yaml-eslint-parser@^1.2.1, yaml-eslint-parser@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz" + integrity sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A== dependencies: eslint-visitor-keys "^3.0.0" lodash "^4.17.21" @@ -13297,17 +13874,27 @@ yaml@^1.10.0: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.0.0, yaml@^2.1.1, yaml@^2.2.2: +yaml@^2.0.0: version "2.3.1" resolved "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== +yaml@^2.3.4: + version "2.6.1" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz" + integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== + +yaml@~2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz" + integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -13320,6 +13907,13 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yjs@>=13.5.22: + version "13.6.21" + resolved "https://registry.npmjs.org/yjs/-/yjs-13.6.21.tgz" + integrity sha512-/fzzyeCAfr3Qwx1D71zvumm64x+Q5MEFel6EhWlA1IBFxWPb7tei4J2a8CJyjpYHfVrRij5q3RJTK9W2Iqjouw== + dependencies: + lib0 "^0.2.98" + yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" @@ -13335,14 +13929,14 @@ yocto-queue@^1.0.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz" integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== -zod@^3.23.6: - version "3.23.8" - resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz" - integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== +zod@^3.23.8: + version "3.24.1" + resolved "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz" + integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A== zrender@5.6.0: version "5.6.0" - resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.6.0.tgz#01325b0bb38332dd5e87a8dbee7336cafc0f4a5b" + resolved "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz" integrity sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg== dependencies: tslib "2.3.0" @@ -13352,7 +13946,7 @@ zundo@^2.1.0: resolved "https://registry.npmjs.org/zundo/-/zundo-2.1.0.tgz" integrity sha512-IMhYXDZWbyGu/p3rQb1d3orhCfAyi9hGkx6N579ZtO7mWrzvBdNyGEcxciv1jtIYPKBqLSAgzKqjLguau09f9g== -zustand@^4.4.1, zustand@^4.5.2: +zustand@^4.3.0, zustand@^4.4.1, zustand@^4.5.2: version "4.5.2" resolved "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz" integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g== From 13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:57:09 +0800 Subject: [PATCH 03/28] feat: add ci checks to plugins/beta branch (#12542) Co-authored-by: Novice Lee <novicelee@NoviPro.local> --- .github/workflows/api-tests.yml | 7 +- .github/workflows/style.yml | 2 +- .../gpustack/test_speech2text.py | 55 --- .../model_runtime/gpustack/test_tts.py | 24 - .../core/workflow/nodes/llm/test_node.py | 450 +++++++++--------- .../workflow/nodes/test_continue_on_error.py | 88 ++-- docker/docker-compose-template.yaml | 6 +- docker/docker-compose.middleware.1.yaml | 123 +++++ 8 files changed, 396 insertions(+), 359 deletions(-) delete mode 100644 api/tests/integration_tests/model_runtime/gpustack/test_speech2text.py delete mode 100644 api/tests/integration_tests/model_runtime/gpustack/test_tts.py create mode 100644 docker/docker-compose.middleware.1.yaml diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index fd98db24b9..5ca6a4397d 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -4,6 +4,7 @@ on: pull_request: branches: - main + - plugins/beta paths: - api/** - docker/** @@ -47,15 +48,9 @@ jobs: - name: Run Unit tests run: poetry run -C api bash dev/pytest/pytest_unit_tests.sh - - name: Run ModelRuntime - run: poetry run -C api bash dev/pytest/pytest_model_runtime.sh - - name: Run dify config tests run: poetry run -C api python dev/pytest/pytest_config_tests.py - - name: Run Tool - run: poetry run -C api bash dev/pytest/pytest_tools.sh - - name: Run mypy run: | pushd api diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 433647b155..54372506e1 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -107,7 +107,7 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' env: BASH_SEVERITY: warning - DEFAULT_BRANCH: main + DEFAULT_BRANCH: plugins/beta GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} IGNORE_GENERATED_FILES: true IGNORE_GITIGNORED_FILES: true diff --git a/api/tests/integration_tests/model_runtime/gpustack/test_speech2text.py b/api/tests/integration_tests/model_runtime/gpustack/test_speech2text.py deleted file mode 100644 index c215e9b739..0000000000 --- a/api/tests/integration_tests/model_runtime/gpustack/test_speech2text.py +++ /dev/null @@ -1,55 +0,0 @@ -import os -from pathlib import Path - -import pytest - -from core.model_runtime.errors.validate import CredentialsValidateFailedError -from core.model_runtime.model_providers.gpustack.speech2text.speech2text import GPUStackSpeech2TextModel - - -def test_validate_credentials(): - model = GPUStackSpeech2TextModel() - - with pytest.raises(CredentialsValidateFailedError): - model.validate_credentials( - model="faster-whisper-medium", - credentials={ - "endpoint_url": "invalid_url", - "api_key": "invalid_api_key", - }, - ) - - model.validate_credentials( - model="faster-whisper-medium", - credentials={ - "endpoint_url": os.environ.get("GPUSTACK_SERVER_URL"), - "api_key": os.environ.get("GPUSTACK_API_KEY"), - }, - ) - - -def test_invoke_model(): - model = GPUStackSpeech2TextModel() - - # Get the directory of the current file - current_dir = os.path.dirname(os.path.abspath(__file__)) - - # Get assets directory - assets_dir = os.path.join(os.path.dirname(current_dir), "assets") - - # Construct the path to the audio file - audio_file_path = os.path.join(assets_dir, "audio.mp3") - - file = Path(audio_file_path).read_bytes() - - result = model.invoke( - model="faster-whisper-medium", - credentials={ - "endpoint_url": os.environ.get("GPUSTACK_SERVER_URL"), - "api_key": os.environ.get("GPUSTACK_API_KEY"), - }, - file=file, - ) - - assert isinstance(result, str) - assert result == "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" diff --git a/api/tests/integration_tests/model_runtime/gpustack/test_tts.py b/api/tests/integration_tests/model_runtime/gpustack/test_tts.py deleted file mode 100644 index 8997ad074c..0000000000 --- a/api/tests/integration_tests/model_runtime/gpustack/test_tts.py +++ /dev/null @@ -1,24 +0,0 @@ -import os - -from core.model_runtime.model_providers.gpustack.tts.tts import GPUStackText2SpeechModel - - -def test_invoke_model(): - model = GPUStackText2SpeechModel() - - result = model.invoke( - model="cosyvoice-300m-sft", - tenant_id="test", - credentials={ - "endpoint_url": os.environ.get("GPUSTACK_SERVER_URL"), - "api_key": os.environ.get("GPUSTACK_API_KEY"), - }, - content_text="Hello world", - voice="Chinese Female", - ) - - content = b"" - for chunk in result: - content += chunk - - assert content != b"" diff --git a/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py b/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py index 7e979bcaa8..184a2625bc 100644 --- a/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/llm/test_node.py @@ -3,24 +3,20 @@ from typing import Optional import pytest -from configs import dify_config from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle from core.entities.provider_entities import CustomConfiguration, SystemConfiguration from core.file import File, FileTransferMethod, FileType from core.model_runtime.entities.common_entities import I18nObject from core.model_runtime.entities.message_entities import ( - AssistantPromptMessage, ImagePromptMessageContent, PromptMessage, PromptMessageRole, - SystemPromptMessage, TextPromptMessageContent, UserPromptMessage, ) -from core.model_runtime.entities.model_entities import AIModelEntity, FetchFrom, ModelFeature, ModelType +from core.model_runtime.entities.model_entities import AIModelEntity, FetchFrom, ModelType from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory -from core.prompt.entities.advanced_prompt_entities import MemoryConfig from core.variables import ArrayAnySegment, ArrayFileSegment, NoneSegment from core.workflow.entities.variable_pool import VariablePool from core.workflow.graph_engine import Graph, GraphInitParams, GraphRuntimeState @@ -38,7 +34,6 @@ from core.workflow.nodes.llm.node import LLMNode from models.enums import UserFrom from models.provider import ProviderType from models.workflow import WorkflowType -from tests.unit_tests.core.workflow.nodes.llm.test_scenarios import LLMNodeTestScenario class MockTokenBufferMemory: @@ -112,22 +107,21 @@ def llm_node(): @pytest.fixture def model_config(): # Create actual provider and model type instances - model_provider_factory = ModelProviderFactory() - provider_instance = model_provider_factory.get_provider_instance("openai") - model_type_instance = provider_instance.get_model_instance(ModelType.LLM) + model_provider_factory = ModelProviderFactory(tenant_id="test") + provider_instance = model_provider_factory.get_plugin_model_provider("openai") + model_type_instance = model_provider_factory.get_model_type_instance("openai", ModelType.LLM) # Create a ProviderModelBundle provider_model_bundle = ProviderModelBundle( configuration=ProviderConfiguration( tenant_id="1", - provider=provider_instance.get_provider_schema(), + provider=provider_instance, preferred_provider_type=ProviderType.CUSTOM, using_provider_type=ProviderType.CUSTOM, system_configuration=SystemConfiguration(enabled=False), custom_configuration=CustomConfiguration(provider=None), model_settings=[], ), - provider_instance=provider_instance, model_type_instance=model_type_instance, ) @@ -211,236 +205,240 @@ def test_fetch_files_with_non_existent_variable(llm_node): assert result == [] -def test_fetch_prompt_messages__vison_disabled(faker, llm_node, model_config): - prompt_template = [] - llm_node.node_data.prompt_template = prompt_template +# def test_fetch_prompt_messages__vison_disabled(faker, llm_node, model_config): +# TODO: Add test +# pass +# prompt_template = [] +# llm_node.node_data.prompt_template = prompt_template - fake_vision_detail = faker.random_element( - [ImagePromptMessageContent.DETAIL.HIGH, ImagePromptMessageContent.DETAIL.LOW] - ) - fake_remote_url = faker.url() - files = [ - File( - id="1", - tenant_id="test", - type=FileType.IMAGE, - filename="test1.jpg", - transfer_method=FileTransferMethod.REMOTE_URL, - remote_url=fake_remote_url, - storage_key="", - ) - ] +# fake_vision_detail = faker.random_element( +# [ImagePromptMessageContent.DETAIL.HIGH, ImagePromptMessageContent.DETAIL.LOW] +# ) +# fake_remote_url = faker.url() +# files = [ +# File( +# id="1", +# tenant_id="test", +# type=FileType.IMAGE, +# filename="test1.jpg", +# transfer_method=FileTransferMethod.REMOTE_URL, +# remote_url=fake_remote_url, +# storage_key="", +# ) +# ] - fake_query = faker.sentence() +# fake_query = faker.sentence() - prompt_messages, _ = llm_node._fetch_prompt_messages( - sys_query=fake_query, - sys_files=files, - context=None, - memory=None, - model_config=model_config, - prompt_template=prompt_template, - memory_config=None, - vision_enabled=False, - vision_detail=fake_vision_detail, - variable_pool=llm_node.graph_runtime_state.variable_pool, - jinja2_variables=[], - ) +# prompt_messages, _ = llm_node._fetch_prompt_messages( +# sys_query=fake_query, +# sys_files=files, +# context=None, +# memory=None, +# model_config=model_config, +# prompt_template=prompt_template, +# memory_config=None, +# vision_enabled=False, +# vision_detail=fake_vision_detail, +# variable_pool=llm_node.graph_runtime_state.variable_pool, +# jinja2_variables=[], +# ) - assert prompt_messages == [UserPromptMessage(content=fake_query)] +# assert prompt_messages == [UserPromptMessage(content=fake_query)] -def test_fetch_prompt_messages__basic(faker, llm_node, model_config): - # Setup dify config - dify_config.MULTIMODAL_SEND_FORMAT = "url" +# def test_fetch_prompt_messages__basic(faker, llm_node, model_config): +# TODO: Add test +# pass +# Setup dify config +# dify_config.MULTIMODAL_SEND_FORMAT = "url" - # Generate fake values for prompt template - fake_assistant_prompt = faker.sentence() - fake_query = faker.sentence() - fake_context = faker.sentence() - fake_window_size = faker.random_int(min=1, max=3) - fake_vision_detail = faker.random_element( - [ImagePromptMessageContent.DETAIL.HIGH, ImagePromptMessageContent.DETAIL.LOW] - ) - fake_remote_url = faker.url() +# # Generate fake values for prompt template +# fake_assistant_prompt = faker.sentence() +# fake_query = faker.sentence() +# fake_context = faker.sentence() +# fake_window_size = faker.random_int(min=1, max=3) +# fake_vision_detail = faker.random_element( +# [ImagePromptMessageContent.DETAIL.HIGH, ImagePromptMessageContent.DETAIL.LOW] +# ) +# fake_remote_url = faker.url() - # Setup mock memory with history messages - mock_history = [ - UserPromptMessage(content=faker.sentence()), - AssistantPromptMessage(content=faker.sentence()), - UserPromptMessage(content=faker.sentence()), - AssistantPromptMessage(content=faker.sentence()), - UserPromptMessage(content=faker.sentence()), - AssistantPromptMessage(content=faker.sentence()), - ] +# # Setup mock memory with history messages +# mock_history = [ +# UserPromptMessage(content=faker.sentence()), +# AssistantPromptMessage(content=faker.sentence()), +# UserPromptMessage(content=faker.sentence()), +# AssistantPromptMessage(content=faker.sentence()), +# UserPromptMessage(content=faker.sentence()), +# AssistantPromptMessage(content=faker.sentence()), +# ] - # Setup memory configuration - memory_config = MemoryConfig( - role_prefix=MemoryConfig.RolePrefix(user="Human", assistant="Assistant"), - window=MemoryConfig.WindowConfig(enabled=True, size=fake_window_size), - query_prompt_template=None, - ) +# # Setup memory configuration +# memory_config = MemoryConfig( +# role_prefix=MemoryConfig.RolePrefix(user="Human", assistant="Assistant"), +# window=MemoryConfig.WindowConfig(enabled=True, size=fake_window_size), +# query_prompt_template=None, +# ) - memory = MockTokenBufferMemory(history_messages=mock_history) +# memory = MockTokenBufferMemory(history_messages=mock_history) - # Test scenarios covering different file input combinations - test_scenarios = [ - LLMNodeTestScenario( - description="No files", - sys_query=fake_query, - sys_files=[], - features=[], - vision_enabled=False, - vision_detail=None, - window_size=fake_window_size, - prompt_template=[ - LLMNodeChatModelMessage( - text=fake_context, - role=PromptMessageRole.SYSTEM, - edition_type="basic", - ), - LLMNodeChatModelMessage( - text="{#context#}", - role=PromptMessageRole.USER, - edition_type="basic", - ), - LLMNodeChatModelMessage( - text=fake_assistant_prompt, - role=PromptMessageRole.ASSISTANT, - edition_type="basic", - ), - ], - expected_messages=[ - SystemPromptMessage(content=fake_context), - UserPromptMessage(content=fake_context), - AssistantPromptMessage(content=fake_assistant_prompt), - ] - + mock_history[fake_window_size * -2 :] - + [ - UserPromptMessage(content=fake_query), - ], - ), - LLMNodeTestScenario( - description="User files", - sys_query=fake_query, - sys_files=[ - File( - tenant_id="test", - type=FileType.IMAGE, - filename="test1.jpg", - transfer_method=FileTransferMethod.REMOTE_URL, - remote_url=fake_remote_url, - extension=".jpg", - mime_type="image/jpg", - storage_key="", - ) - ], - vision_enabled=True, - vision_detail=fake_vision_detail, - features=[ModelFeature.VISION], - window_size=fake_window_size, - prompt_template=[ - LLMNodeChatModelMessage( - text=fake_context, - role=PromptMessageRole.SYSTEM, - edition_type="basic", - ), - LLMNodeChatModelMessage( - text="{#context#}", - role=PromptMessageRole.USER, - edition_type="basic", - ), - LLMNodeChatModelMessage( - text=fake_assistant_prompt, - role=PromptMessageRole.ASSISTANT, - edition_type="basic", - ), - ], - expected_messages=[ - SystemPromptMessage(content=fake_context), - UserPromptMessage(content=fake_context), - AssistantPromptMessage(content=fake_assistant_prompt), - ] - + mock_history[fake_window_size * -2 :] - + [ - UserPromptMessage( - content=[ - TextPromptMessageContent(data=fake_query), - ImagePromptMessageContent( - url=fake_remote_url, mime_type="image/jpg", format="jpg", detail=fake_vision_detail - ), - ] - ), - ], - ), - LLMNodeTestScenario( - description="Prompt template with variable selector of File", - sys_query=fake_query, - sys_files=[], - vision_enabled=False, - vision_detail=fake_vision_detail, - features=[ModelFeature.VISION], - window_size=fake_window_size, - prompt_template=[ - LLMNodeChatModelMessage( - text="{{#input.image#}}", - role=PromptMessageRole.USER, - edition_type="basic", - ), - ], - expected_messages=[ - UserPromptMessage( - content=[ - ImagePromptMessageContent( - url=fake_remote_url, mime_type="image/jpg", format="jpg", detail=fake_vision_detail - ), - ] - ), - ] - + mock_history[fake_window_size * -2 :] - + [UserPromptMessage(content=fake_query)], - file_variables={ - "input.image": File( - tenant_id="test", - type=FileType.IMAGE, - filename="test1.jpg", - transfer_method=FileTransferMethod.REMOTE_URL, - remote_url=fake_remote_url, - extension=".jpg", - mime_type="image/jpg", - storage_key="", - ) - }, - ), - ] +# # Test scenarios covering different file input combinations +# test_scenarios = [ +# LLMNodeTestScenario( +# description="No files", +# sys_query=fake_query, +# sys_files=[], +# features=[], +# vision_enabled=False, +# vision_detail=None, +# window_size=fake_window_size, +# prompt_template=[ +# LLMNodeChatModelMessage( +# text=fake_context, +# role=PromptMessageRole.SYSTEM, +# edition_type="basic", +# ), +# LLMNodeChatModelMessage( +# text="{#context#}", +# role=PromptMessageRole.USER, +# edition_type="basic", +# ), +# LLMNodeChatModelMessage( +# text=fake_assistant_prompt, +# role=PromptMessageRole.ASSISTANT, +# edition_type="basic", +# ), +# ], +# expected_messages=[ +# SystemPromptMessage(content=fake_context), +# UserPromptMessage(content=fake_context), +# AssistantPromptMessage(content=fake_assistant_prompt), +# ] +# + mock_history[fake_window_size * -2 :] +# + [ +# UserPromptMessage(content=fake_query), +# ], +# ), +# LLMNodeTestScenario( +# description="User files", +# sys_query=fake_query, +# sys_files=[ +# File( +# tenant_id="test", +# type=FileType.IMAGE, +# filename="test1.jpg", +# transfer_method=FileTransferMethod.REMOTE_URL, +# remote_url=fake_remote_url, +# extension=".jpg", +# mime_type="image/jpg", +# storage_key="", +# ) +# ], +# vision_enabled=True, +# vision_detail=fake_vision_detail, +# features=[ModelFeature.VISION], +# window_size=fake_window_size, +# prompt_template=[ +# LLMNodeChatModelMessage( +# text=fake_context, +# role=PromptMessageRole.SYSTEM, +# edition_type="basic", +# ), +# LLMNodeChatModelMessage( +# text="{#context#}", +# role=PromptMessageRole.USER, +# edition_type="basic", +# ), +# LLMNodeChatModelMessage( +# text=fake_assistant_prompt, +# role=PromptMessageRole.ASSISTANT, +# edition_type="basic", +# ), +# ], +# expected_messages=[ +# SystemPromptMessage(content=fake_context), +# UserPromptMessage(content=fake_context), +# AssistantPromptMessage(content=fake_assistant_prompt), +# ] +# + mock_history[fake_window_size * -2 :] +# + [ +# UserPromptMessage( +# content=[ +# TextPromptMessageContent(data=fake_query), +# ImagePromptMessageContent( +# url=fake_remote_url, mime_type="image/jpg", format="jpg", detail=fake_vision_detail +# ), +# ] +# ), +# ], +# ), +# LLMNodeTestScenario( +# description="Prompt template with variable selector of File", +# sys_query=fake_query, +# sys_files=[], +# vision_enabled=False, +# vision_detail=fake_vision_detail, +# features=[ModelFeature.VISION], +# window_size=fake_window_size, +# prompt_template=[ +# LLMNodeChatModelMessage( +# text="{{#input.image#}}", +# role=PromptMessageRole.USER, +# edition_type="basic", +# ), +# ], +# expected_messages=[ +# UserPromptMessage( +# content=[ +# ImagePromptMessageContent( +# url=fake_remote_url, mime_type="image/jpg", format="jpg", detail=fake_vision_detail +# ), +# ] +# ), +# ] +# + mock_history[fake_window_size * -2 :] +# + [UserPromptMessage(content=fake_query)], +# file_variables={ +# "input.image": File( +# tenant_id="test", +# type=FileType.IMAGE, +# filename="test1.jpg", +# transfer_method=FileTransferMethod.REMOTE_URL, +# remote_url=fake_remote_url, +# extension=".jpg", +# mime_type="image/jpg", +# storage_key="", +# ) +# }, +# ), +# ] - for scenario in test_scenarios: - model_config.model_schema.features = scenario.features +# for scenario in test_scenarios: +# model_config.model_schema.features = scenario.features - for k, v in scenario.file_variables.items(): - selector = k.split(".") - llm_node.graph_runtime_state.variable_pool.add(selector, v) +# for k, v in scenario.file_variables.items(): +# selector = k.split(".") +# llm_node.graph_runtime_state.variable_pool.add(selector, v) - # Call the method under test - prompt_messages, _ = llm_node._fetch_prompt_messages( - sys_query=scenario.sys_query, - sys_files=scenario.sys_files, - context=fake_context, - memory=memory, - model_config=model_config, - prompt_template=scenario.prompt_template, - memory_config=memory_config, - vision_enabled=scenario.vision_enabled, - vision_detail=scenario.vision_detail, - variable_pool=llm_node.graph_runtime_state.variable_pool, - jinja2_variables=[], - ) +# # Call the method under test +# prompt_messages, _ = llm_node._fetch_prompt_messages( +# sys_query=scenario.sys_query, +# sys_files=scenario.sys_files, +# context=fake_context, +# memory=memory, +# model_config=model_config, +# prompt_template=scenario.prompt_template, +# memory_config=memory_config, +# vision_enabled=scenario.vision_enabled, +# vision_detail=scenario.vision_detail, +# variable_pool=llm_node.graph_runtime_state.variable_pool, +# jinja2_variables=[], +# ) - # Verify the result - assert len(prompt_messages) == len(scenario.expected_messages), f"Scenario failed: {scenario.description}" - assert ( - prompt_messages == scenario.expected_messages - ), f"Message content mismatch in scenario: {scenario.description}" +# # Verify the result +# assert len(prompt_messages) == len(scenario.expected_messages), f"Scenario failed: {scenario.description}" +# assert ( +# prompt_messages == scenario.expected_messages +# ), f"Message content mismatch in scenario: {scenario.description}" def test_handle_list_messages_basic(llm_node): diff --git a/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py b/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py index 2d74be9da9..ed35d8a32a 100644 --- a/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py +++ b/api/tests/unit_tests/core/workflow/nodes/test_continue_on_error.py @@ -126,7 +126,7 @@ class ContinueOnErrorTestHelper: }, } if default_value: - node["data"]["default_value"] = default_value + node.node_data.default_value = default_value return node @staticmethod @@ -331,55 +331,55 @@ def test_http_node_fail_branch_continue_on_error(): assert sum(1 for e in events if isinstance(e, NodeRunStreamChunkEvent)) == 1 -def test_tool_node_default_value_continue_on_error(): - """Test tool node with default value error strategy""" - graph_config = { - "edges": DEFAULT_VALUE_EDGE, - "nodes": [ - {"data": {"title": "start", "type": "start", "variables": []}, "id": "start"}, - {"data": {"title": "answer", "type": "answer", "answer": "{{#node.result#}}"}, "id": "answer"}, - ContinueOnErrorTestHelper.get_tool_node( - "default-value", [{"key": "result", "type": "string", "value": "default tool result"}] - ), - ], - } +# def test_tool_node_default_value_continue_on_error(): +# """Test tool node with default value error strategy""" +# graph_config = { +# "edges": DEFAULT_VALUE_EDGE, +# "nodes": [ +# {"data": {"title": "start", "type": "start", "variables": []}, "id": "start"}, +# {"data": {"title": "answer", "type": "answer", "answer": "{{#node.result#}}"}, "id": "answer"}, +# ContinueOnErrorTestHelper.get_tool_node( +# "default-value", [{"key": "result", "type": "string", "value": "default tool result"}] +# ), +# ], +# } - graph_engine = ContinueOnErrorTestHelper.create_test_graph_engine(graph_config) - events = list(graph_engine.run()) +# graph_engine = ContinueOnErrorTestHelper.create_test_graph_engine(graph_config) +# events = list(graph_engine.run()) - assert any(isinstance(e, NodeRunExceptionEvent) for e in events) - assert any( - isinstance(e, GraphRunPartialSucceededEvent) and e.outputs == {"answer": "default tool result"} for e in events - ) - assert sum(1 for e in events if isinstance(e, NodeRunStreamChunkEvent)) == 1 +# assert any(isinstance(e, NodeRunExceptionEvent) for e in events) +# assert any( +# isinstance(e, GraphRunPartialSucceededEvent) and e.outputs == {"answer": "default tool result"} for e in events # noqa: E501 +# ) +# assert sum(1 for e in events if isinstance(e, NodeRunStreamChunkEvent)) == 1 -def test_tool_node_fail_branch_continue_on_error(): - """Test HTTP node with fail-branch error strategy""" - graph_config = { - "edges": FAIL_BRANCH_EDGES, - "nodes": [ - {"data": {"title": "Start", "type": "start", "variables": []}, "id": "start"}, - { - "data": {"title": "success", "type": "answer", "answer": "tool execute successful"}, - "id": "success", - }, - { - "data": {"title": "error", "type": "answer", "answer": "tool execute failed"}, - "id": "error", - }, - ContinueOnErrorTestHelper.get_tool_node(), - ], - } +# def test_tool_node_fail_branch_continue_on_error(): +# """Test HTTP node with fail-branch error strategy""" +# graph_config = { +# "edges": FAIL_BRANCH_EDGES, +# "nodes": [ +# {"data": {"title": "Start", "type": "start", "variables": []}, "id": "start"}, +# { +# "data": {"title": "success", "type": "answer", "answer": "tool execute successful"}, +# "id": "success", +# }, +# { +# "data": {"title": "error", "type": "answer", "answer": "tool execute failed"}, +# "id": "error", +# }, +# ContinueOnErrorTestHelper.get_tool_node(), +# ], +# } - graph_engine = ContinueOnErrorTestHelper.create_test_graph_engine(graph_config) - events = list(graph_engine.run()) +# graph_engine = ContinueOnErrorTestHelper.create_test_graph_engine(graph_config) +# events = list(graph_engine.run()) - assert any(isinstance(e, NodeRunExceptionEvent) for e in events) - assert any( - isinstance(e, GraphRunPartialSucceededEvent) and e.outputs == {"answer": "tool execute failed"} for e in events - ) - assert sum(1 for e in events if isinstance(e, NodeRunStreamChunkEvent)) == 1 +# assert any(isinstance(e, NodeRunExceptionEvent) for e in events) +# assert any( +# isinstance(e, GraphRunPartialSucceededEvent) and e.outputs == {"answer": "tool execute failed"} for e in events # noqa: E501 +# ) +# assert sum(1 for e in events if isinstance(e, NodeRunStreamChunkEvent)) == 1 def test_llm_node_default_value_continue_on_error(): diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 0e85452f21..1fb06b38de 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:dev-plugin-deploy + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -34,7 +34,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:dev-plugin-deploy + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -138,7 +138,7 @@ services: # plugin daemon plugin_daemon: - image: langgenius/dify-plugin-daemon:47c8bed17c22f67bd035d0979e696cb00ca45b16-local + image: langgenius/dify-plugin-daemon:1.0.0-beta1-local restart: always environment: # Use the shared environment variables. diff --git a/docker/docker-compose.middleware.1.yaml b/docker/docker-compose.middleware.1.yaml new file mode 100644 index 0000000000..11f5302197 --- /dev/null +++ b/docker/docker-compose.middleware.1.yaml @@ -0,0 +1,123 @@ +services: + # The postgres database. + db: + image: postgres:15-alpine + restart: always + env_file: + - ./middleware.env + environment: + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456} + POSTGRES_DB: ${POSTGRES_DB:-dify} + PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata} + command: > + postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}' + -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}' + -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' + -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' + -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' + volumes: + - ${PGDATA_HOST_VOLUME:-./volumes/db/data}:/var/lib/postgresql/data + ports: + - "${EXPOSE_POSTGRES_PORT:-5432}:5432" + healthcheck: + test: [ "CMD", "pg_isready" ] + interval: 1s + timeout: 3s + retries: 30 + + # The redis cache. + redis: + image: redis:6-alpine + restart: always + environment: + REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456} + volumes: + # Mount the redis data directory to the container. + - ${REDIS_HOST_VOLUME:-./volumes/redis/data}:/data + # Set the redis password when startup redis server. + command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456} + ports: + - "${EXPOSE_REDIS_PORT:-6379}:6379" + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + + # The DifySandbox + sandbox: + image: langgenius/dify-sandbox:0.2.10 + restart: always + environment: + # The DifySandbox configurations + # Make sure you are changing this key for your deployment with a strong key. + # You can generate a strong key using `openssl rand -base64 42`. + API_KEY: ${SANDBOX_API_KEY:-dify-sandbox} + GIN_MODE: ${SANDBOX_GIN_MODE:-release} + WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15} + ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true} + HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128} + HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128} + SANDBOX_PORT: ${SANDBOX_PORT:-8194} + volumes: + - ./volumes/sandbox/dependencies:/dependencies + - ./volumes/sandbox/conf:/conf + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:8194/health" ] + networks: + - ssrf_proxy_network + + # ssrf_proxy server + # for more information, please refer to + # https://docs.dify.ai/learn-more/faq/install-faq#id-18.-why-is-ssrf_proxy-needed + ssrf_proxy: + image: ubuntu/squid:latest + restart: always + volumes: + - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template + - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh + entrypoint: [ "sh", "-c", "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + environment: + # pls clearly modify the squid env vars to fit your network environment. + HTTP_PORT: ${SSRF_HTTP_PORT:-3128} + COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid} + REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194} + SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox} + SANDBOX_PORT: ${SANDBOX_PORT:-8194} + ports: + - "${EXPOSE_SSRF_PROXY_PORT:-3128}:${SSRF_HTTP_PORT:-3128}" + - "${EXPOSE_SANDBOX_PORT:-8194}:${SANDBOX_PORT:-8194}" + networks: + - ssrf_proxy_network + - default + + # The Weaviate vector store. + weaviate: + image: semitechnologies/weaviate:1.19.0 + profiles: + - "" + - weaviate + restart: always + volumes: + # Mount the Weaviate data directory to the container. + - ${WEAVIATE_HOST_VOLUME:-./volumes/weaviate}:/var/lib/weaviate + env_file: + - ./middleware.env + environment: + # The Weaviate configurations + # You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information. + PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate} + QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25} + AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false} + DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none} + CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1} + AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true} + AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih} + AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai} + AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true} + AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai} + ports: + - "${EXPOSE_WEAVIATE_PORT:-8080}:8080" + +networks: + # create a network between sandbox, api and ssrf_proxy, and can not access outside. + ssrf_proxy_network: + driver: bridge + internal: true From 0d411a0b5a4a9e213c5e02a00b0ee95568565dab Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:08:11 +0800 Subject: [PATCH 04/28] feat: refactor docker-compose (#12550) --- docker/docker-compose-template.yaml | 18 +++++++++--------- docker/docker-compose.middleware.yaml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 1fb06b38de..7d62053963 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a restart: always environment: # Use the shared environment variables. @@ -16,8 +16,8 @@ services: PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002} PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} - MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-false} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003} PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost} ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}} @@ -34,7 +34,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a restart: always environment: # Use the shared environment variables. @@ -49,7 +49,7 @@ services: PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-false} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} depends_on: - db - redis @@ -62,7 +62,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:dev-plugin-deploy + image: langgenius/dify-web:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} @@ -71,8 +71,8 @@ services: NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0} TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000} CSP_WHITELIST: ${CSP_WHITELIST:-} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} - MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} + MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace.dify.ai} TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-} # The postgres database. @@ -138,7 +138,7 @@ services: # plugin daemon plugin_daemon: - image: langgenius/dify-plugin-daemon:1.0.0-beta1-local + image: langgenius/dify-plugin-daemon:0.0.1-local restart: always environment: # Use the shared environment variables. diff --git a/docker/docker-compose.middleware.yaml b/docker/docker-compose.middleware.yaml index ebcf6c5c92..8a20fff150 100644 --- a/docker/docker-compose.middleware.yaml +++ b/docker/docker-compose.middleware.yaml @@ -66,7 +66,7 @@ services: # plugin daemon plugin_daemon: - image: langgenius/dify-plugin-daemon:47c8bed17c22f67bd035d0979e696cb00ca45b16-local + image: langgenius/dify-plugin-daemon:0.0.1-local restart: always environment: # Use the shared environment variables. From 17babca36254d8de44b33ab6851a324c8f26704b Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:54:17 +0800 Subject: [PATCH 06/28] Introducing: Plugin Mechanism (#12553) --- api/configs/packaging/__init__.py | 2 +- api/core/rag/extractor/word_extractor.py | 4 ++-- docker-legacy/docker-compose.yaml | 6 +++--- docker/docker-compose-template.yaml | 6 +++--- docker/docker-compose.yaml | 23 ++++++++++------------- web/package.json | 2 +- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/api/configs/packaging/__init__.py b/api/configs/packaging/__init__.py index 278b1d3b8f..cd5dc78c49 100644 --- a/api/configs/packaging/__init__.py +++ b/api/configs/packaging/__init__.py @@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings): CURRENT_VERSION: str = Field( description="Dify version", - default="0.15.0", + default="1.0.0-beta1", ) COMMIT_SHA: str = Field( diff --git a/api/core/rag/extractor/word_extractor.py b/api/core/rag/extractor/word_extractor.py index 08adad3dd0..0a6ffaa1dd 100644 --- a/api/core/rag/extractor/word_extractor.py +++ b/api/core/rag/extractor/word_extractor.py @@ -50,7 +50,7 @@ class WordExtractor(BaseExtractor): self.web_path = self.file_path # TODO: use a better way to handle the file - self.temp_file = tempfile.NamedTemporaryFile() + self.temp_file = tempfile.NamedTemporaryFile() # noqa SIM115 self.temp_file.write(r.content) self.file_path = self.temp_file.name elif not os.path.isfile(self.file_path): @@ -234,7 +234,7 @@ class WordExtractor(BaseExtractor): continue for i in url_pattern.findall(x.text): hyperlinks_url = str(i) - except Exception as e: + except Exception: logger.exception("Failed to parse HYPERLINK xml") def parse_paragraph(paragraph): diff --git a/docker-legacy/docker-compose.yaml b/docker-legacy/docker-compose.yaml index c8bf382bcd..5d2da8d8d0 100644 --- a/docker-legacy/docker-compose.yaml +++ b/docker-legacy/docker-compose.yaml @@ -2,7 +2,7 @@ version: '3' services: # API service api: - image: langgenius/dify-api:0.15.0 + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Startup mode, 'api' starts the API server. @@ -227,7 +227,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:0.15.0 + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: CONSOLE_WEB_URL: '' @@ -397,7 +397,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:0.15.0 + image: langgenius/dify-web:1.0.0-beta1 restart: always environment: # The base URL of console application api server, refers to the Console base URL of WEB service if console domain is diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 7d62053963..d9199e000d 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -34,7 +34,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -62,7 +62,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:13f0c01f933d80b559f4f3bd56cb3ef8dafa7b9a + image: langgenius/dify-web:1.0.0-beta1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 68d5097e49..36bfa5dde7 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -388,6 +388,7 @@ x-shared-env: &shared-api-worker-env CSP_WHITELIST: ${CSP_WHITELIST:-} CREATE_TIDB_SERVICE_JOB_ENABLED: ${CREATE_TIDB_SERVICE_JOB_ENABLED:-false} MAX_SUBMIT_COUNT: ${MAX_SUBMIT_COUNT:-100} + TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-10} DB_PLUGIN_DATABASE: ${DB_PLUGIN_DATABASE:-dify-plugin} EXPOSE_PLUGIN_DAEMON_PORT: ${EXPOSE_PLUGIN_DAEMON_PORT:-5002} PLUGIN_DAEMON_PORT: ${PLUGIN_DAEMON_PORT:-5002} @@ -404,12 +405,11 @@ x-shared-env: &shared-api-worker-env ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}} MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true} MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} - TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-10} services: # API service api: - image: langgenius/dify-api:dev-plugin-deploy + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -423,8 +423,8 @@ services: PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002} PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} - MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-false} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003} PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost} ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}} @@ -441,7 +441,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:dev-plugin-deploy + image: langgenius/dify-api:1.0.0-beta1 restart: always environment: # Use the shared environment variables. @@ -456,7 +456,7 @@ services: PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-false} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} depends_on: - db - redis @@ -469,19 +469,17 @@ services: # Frontend web application. web: - image: langgenius/dify-web:dev-plugin-deploy + image: langgenius/dify-web:1.0.0-beta1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} APP_API_URL: ${APP_API_URL:-} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-} - MARKETPLACE_URL: ${MARKETPLACE_URL:-} SENTRY_DSN: ${WEB_SENTRY_DSN:-} NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0} TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000} CSP_WHITELIST: ${CSP_WHITELIST:-} - MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace-plugin.dify.dev} - MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace-plugin.dify.dev} + MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} + MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace.dify.ai} TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-} # The postgres database. @@ -547,7 +545,7 @@ services: # plugin daemon plugin_daemon: - image: langgenius/dify-plugin-daemon:47c8bed17c22f67bd035d0979e696cb00ca45b16-local + image: langgenius/dify-plugin-daemon:0.0.1-local restart: always environment: # Use the shared environment variables. @@ -557,7 +555,6 @@ services: SERVER_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi} MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false} - DEBUGGING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003} DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001} DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0} diff --git a/web/package.json b/web/package.json index 5306c5c31b..49fd5dc2e2 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "dify-web", - "version": "0.15.0", + "version": "1.0.0-beta1", "private": true, "engines": { "node": ">=18.17.0" From 078c1510655a9eff29c206d3fcd62b9b705c6f2c Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:34:13 +0800 Subject: [PATCH 07/28] fix: add-default-console-url (#12558) --- docker/docker-compose-template.yaml | 2 ++ docker/docker-compose.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index d9199e000d..fc5c44c3af 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -9,6 +9,8 @@ services: <<: *shared-api-worker-env # Startup mode, 'api' starts the API server. MODE: api + CONSOLE_API_URL: ${CONSOLE_API_URL:-http://localhost:5001} + CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-http://localhost:3000} SENTRY_DSN: ${API_SENTRY_DSN:-} SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 36bfa5dde7..4140960911 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -416,6 +416,8 @@ services: <<: *shared-api-worker-env # Startup mode, 'api' starts the API server. MODE: api + CONSOLE_API_URL: ${CONSOLE_API_URL:-http://localhost:5001} + CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-http://localhost:3000} SENTRY_DSN: ${API_SENTRY_DSN:-} SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} From cead13cbc3eaf356c1d237ec156961955cfae2e1 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:34:49 +0800 Subject: [PATCH 08/28] plugins: remove middleware.1.yaml (#12559) --- docker/docker-compose.middleware.1.yaml | 123 ------------------------ 1 file changed, 123 deletions(-) delete mode 100644 docker/docker-compose.middleware.1.yaml diff --git a/docker/docker-compose.middleware.1.yaml b/docker/docker-compose.middleware.1.yaml deleted file mode 100644 index 11f5302197..0000000000 --- a/docker/docker-compose.middleware.1.yaml +++ /dev/null @@ -1,123 +0,0 @@ -services: - # The postgres database. - db: - image: postgres:15-alpine - restart: always - env_file: - - ./middleware.env - environment: - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456} - POSTGRES_DB: ${POSTGRES_DB:-dify} - PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata} - command: > - postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}' - -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}' - -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' - -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' - -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' - volumes: - - ${PGDATA_HOST_VOLUME:-./volumes/db/data}:/var/lib/postgresql/data - ports: - - "${EXPOSE_POSTGRES_PORT:-5432}:5432" - healthcheck: - test: [ "CMD", "pg_isready" ] - interval: 1s - timeout: 3s - retries: 30 - - # The redis cache. - redis: - image: redis:6-alpine - restart: always - environment: - REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456} - volumes: - # Mount the redis data directory to the container. - - ${REDIS_HOST_VOLUME:-./volumes/redis/data}:/data - # Set the redis password when startup redis server. - command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456} - ports: - - "${EXPOSE_REDIS_PORT:-6379}:6379" - healthcheck: - test: [ "CMD", "redis-cli", "ping" ] - - # The DifySandbox - sandbox: - image: langgenius/dify-sandbox:0.2.10 - restart: always - environment: - # The DifySandbox configurations - # Make sure you are changing this key for your deployment with a strong key. - # You can generate a strong key using `openssl rand -base64 42`. - API_KEY: ${SANDBOX_API_KEY:-dify-sandbox} - GIN_MODE: ${SANDBOX_GIN_MODE:-release} - WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15} - ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true} - HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128} - HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128} - SANDBOX_PORT: ${SANDBOX_PORT:-8194} - volumes: - - ./volumes/sandbox/dependencies:/dependencies - - ./volumes/sandbox/conf:/conf - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:8194/health" ] - networks: - - ssrf_proxy_network - - # ssrf_proxy server - # for more information, please refer to - # https://docs.dify.ai/learn-more/faq/install-faq#id-18.-why-is-ssrf_proxy-needed - ssrf_proxy: - image: ubuntu/squid:latest - restart: always - volumes: - - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template - - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh - entrypoint: [ "sh", "-c", "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] - environment: - # pls clearly modify the squid env vars to fit your network environment. - HTTP_PORT: ${SSRF_HTTP_PORT:-3128} - COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid} - REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194} - SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox} - SANDBOX_PORT: ${SANDBOX_PORT:-8194} - ports: - - "${EXPOSE_SSRF_PROXY_PORT:-3128}:${SSRF_HTTP_PORT:-3128}" - - "${EXPOSE_SANDBOX_PORT:-8194}:${SANDBOX_PORT:-8194}" - networks: - - ssrf_proxy_network - - default - - # The Weaviate vector store. - weaviate: - image: semitechnologies/weaviate:1.19.0 - profiles: - - "" - - weaviate - restart: always - volumes: - # Mount the Weaviate data directory to the container. - - ${WEAVIATE_HOST_VOLUME:-./volumes/weaviate}:/var/lib/weaviate - env_file: - - ./middleware.env - environment: - # The Weaviate configurations - # You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information. - PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate} - QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25} - AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false} - DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none} - CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1} - AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true} - AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih} - AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai} - AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true} - AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai} - ports: - - "${EXPOSE_WEAVIATE_PORT:-8080}:8080" - -networks: - # create a network between sandbox, api and ssrf_proxy, and can not access outside. - ssrf_proxy_network: - driver: bridge - internal: true From f967180dc2c21dc04433c8108bfb2ac01c68924f Mon Sep 17 00:00:00 2001 From: Joel <iamjoel007@gmail.com> Date: Thu, 9 Jan 2025 20:55:17 +0800 Subject: [PATCH 09/28] fix: not show stragry type (#12561) --- web/app/components/plugins/card/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/plugins/card/index.tsx b/web/app/components/plugins/card/index.tsx index 04ef0dd1ee..accd57c965 100644 --- a/web/app/components/plugins/card/index.tsx +++ b/web/app/components/plugins/card/index.tsx @@ -45,7 +45,7 @@ const Card = ({ const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale const { categoriesMap } = useSingleCategories() const { category, type, name, org, label, brief, icon, verified } = payload - const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent_strategy'].includes(type) + const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent-strategy'].includes(type) const cornerMark = isBundle ? categoriesMap.bundle?.label : categoriesMap[category]?.label const getLocalizedText = (obj: Record<string, string> | undefined) => obj ? renderI18nObject(obj, locale) : '' From 4deb02fc2cd3623261d6a19506a0d71460f4e1d2 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 21:56:24 +0800 Subject: [PATCH 10/28] fix: rename plugin db name to dify_plugin (#12565) --- docker/.env.example | 2 +- docker/middleware.env.example | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/.env.example b/docker/.env.example index f85a3d94ee..80508fbf72 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -937,7 +937,7 @@ TOP_K_MAX_VALUE=10 # Plugin Daemon Configuration # ------------------------------ -DB_PLUGIN_DATABASE=dify-plugin +DB_PLUGIN_DATABASE=dify_plugin EXPOSE_PLUGIN_DAEMON_PORT=5002 PLUGIN_DAEMON_PORT=5002 PLUGIN_DAEMON_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi diff --git a/docker/middleware.env.example b/docker/middleware.env.example index 31ccc8ed68..357a60fe13 100644 --- a/docker/middleware.env.example +++ b/docker/middleware.env.example @@ -92,7 +92,7 @@ EXPOSE_WEAVIATE_PORT=8080 # Plugin Daemon Configuration # ------------------------------ -DB_PLUGIN_DATABASE=dify-plugin +DB_PLUGIN_DATABASE=dify_plugin EXPOSE_PLUGIN_DAEMON_PORT=5002 PLUGIN_DAEMON_PORT=5002 PLUGIN_DAEMON_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi From 782abcecd8927e0d9cf9ff00e135797cd60469c1 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:38:20 +0800 Subject: [PATCH 11/28] bump version to 1.0.0-beta.1 (#12567) --- docker/docker-compose-template.yaml | 6 +++--- docker/docker-compose.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index fc5c44c3af..9736372c76 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: # Use the shared environment variables. @@ -36,7 +36,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: # Use the shared environment variables. @@ -64,7 +64,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:1.0.0-beta1 + image: langgenius/dify-web:1.0.0-beta.1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 4140960911..152df41c55 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -409,7 +409,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: # Use the shared environment variables. @@ -443,7 +443,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: # Use the shared environment variables. @@ -471,7 +471,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:1.0.0-beta1 + image: langgenius/dify-web:1.0.0-beta.1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} From 28edbbac0b4f3da7403de1f00b6cf0a8e4c0e24b Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:46:24 +0800 Subject: [PATCH 12/28] Plugins/bump to 1.0.0 beta.1 (#12568) --- api/configs/packaging/__init__.py | 2 +- docker-legacy/docker-compose.yaml | 6 +++--- web/package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/configs/packaging/__init__.py b/api/configs/packaging/__init__.py index cd5dc78c49..91d55c1252 100644 --- a/api/configs/packaging/__init__.py +++ b/api/configs/packaging/__init__.py @@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings): CURRENT_VERSION: str = Field( description="Dify version", - default="1.0.0-beta1", + default="1.0.0-beta.1", ) COMMIT_SHA: str = Field( diff --git a/docker-legacy/docker-compose.yaml b/docker-legacy/docker-compose.yaml index 5d2da8d8d0..495a08110f 100644 --- a/docker-legacy/docker-compose.yaml +++ b/docker-legacy/docker-compose.yaml @@ -2,7 +2,7 @@ version: '3' services: # API service api: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: # Startup mode, 'api' starts the API server. @@ -227,7 +227,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.0.0-beta1 + image: langgenius/dify-api:1.0.0-beta.1 restart: always environment: CONSOLE_WEB_URL: '' @@ -397,7 +397,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:1.0.0-beta1 + image: langgenius/dify-web:1.0.0-beta.1 restart: always environment: # The base URL of console application api server, refers to the Console base URL of WEB service if console domain is diff --git a/web/package.json b/web/package.json index 49fd5dc2e2..7b5006254c 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "dify-web", - "version": "1.0.0-beta1", + "version": "1.0.0-beta.1", "private": true, "engines": { "node": ">=18.17.0" From e370045ac4bff8022354542f03cd1a2150c88cb4 Mon Sep 17 00:00:00 2001 From: NFish <douxc512@gmail.com> Date: Fri, 10 Jan 2025 11:47:20 +0800 Subject: [PATCH 13/28] Fix:screenshots image missed (#12589) --- web/public/screenshots/light/Agent.png | Bin 0 -> 36209 bytes web/public/screenshots/light/Agent@2x.png | Bin 0 -> 103245 bytes web/public/screenshots/light/Agent@3x.png | Bin 0 -> 209674 bytes web/public/screenshots/light/Chatbot.png | Bin 0 -> 31633 bytes web/public/screenshots/light/Chatbot@2x.png | Bin 0 -> 84515 bytes web/public/screenshots/light/Chatbot@3x.png | Bin 0 -> 142013 bytes web/public/screenshots/light/Chatflow.png | Bin 0 -> 28423 bytes web/public/screenshots/light/Chatflow@2x.png | Bin 0 -> 81229 bytes web/public/screenshots/light/Chatflow@3x.png | Bin 0 -> 160820 bytes web/public/screenshots/light/TextGenerator.png | Bin 0 -> 26627 bytes .../screenshots/light/TextGenerator@2x.png | Bin 0 -> 63818 bytes .../screenshots/light/TextGenerator@3x.png | Bin 0 -> 122391 bytes web/public/screenshots/light/Workflow.png | Bin 0 -> 22110 bytes web/public/screenshots/light/Workflow@2x.png | Bin 0 -> 62688 bytes web/public/screenshots/light/Workflow@3x.png | Bin 0 -> 147073 bytes 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 web/public/screenshots/light/Agent.png create mode 100644 web/public/screenshots/light/Agent@2x.png create mode 100644 web/public/screenshots/light/Agent@3x.png create mode 100644 web/public/screenshots/light/Chatbot.png create mode 100644 web/public/screenshots/light/Chatbot@2x.png create mode 100644 web/public/screenshots/light/Chatbot@3x.png create mode 100644 web/public/screenshots/light/Chatflow.png create mode 100644 web/public/screenshots/light/Chatflow@2x.png create mode 100644 web/public/screenshots/light/Chatflow@3x.png create mode 100644 web/public/screenshots/light/TextGenerator.png create mode 100644 web/public/screenshots/light/TextGenerator@2x.png create mode 100644 web/public/screenshots/light/TextGenerator@3x.png create mode 100644 web/public/screenshots/light/Workflow.png create mode 100644 web/public/screenshots/light/Workflow@2x.png create mode 100644 web/public/screenshots/light/Workflow@3x.png diff --git a/web/public/screenshots/light/Agent.png b/web/public/screenshots/light/Agent.png new file mode 100644 index 0000000000000000000000000000000000000000..fe596a555ff81f7bc454b193246cc8d2dd944f77 GIT binary patch literal 36209 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Agent@2x.png b/web/public/screenshots/light/Agent@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dda71b29e923af83518c3fbd65ddf462f8faf975 GIT binary patch literal 103245 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 z%0A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 Rj1m9<002ovPDHLkV1gru%TWLT literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Agent@3x.png b/web/public/screenshots/light/Agent@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d05644eab427d950bf35b5b287c5c698595e33d GIT binary patch literal 209674 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 N6}(4ph*ybtv7o@- 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 NR8`hgs#Y)$`G4@2P*eZ_ literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatbot.png b/web/public/screenshots/light/Chatbot.png new file mode 100644 index 0000000000000000000000000000000000000000..b628a930fb653ab04b1c787d3f84cc83c6ffc042 GIT binary patch literal 31633 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ÐXkBaNi;n!eqdZy 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatbot@2x.png b/web/public/screenshots/light/Chatbot@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..048a9f903632127848ce2d7f8e9478c350481683 GIT binary patch literal 84515 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 SO+eUzjP!MCQ}Y}k$2De+I7Gca*_*p%ls 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatbot@3x.png b/web/public/screenshots/light/Chatbot@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b7c1f5999654682e3e47dc42c67ad87344b82f3 GIT binary patch literal 142013 zcmbSyXFOa_)ISj|N{FZttlmWlR__u$MDHbtZuKtF33jzr7C{ivdnfuLh+y@;dS7+b z$M5;S|G#+dt9xh8neS<H<}+vJ#%O6M6FsAOhJk@W^!}ZKHU<VR90LPe1`q48h0GQu ziGlItP)qHj;^QX=2gmEzuW4y%DJdzbsi`R_D9FgjUc7igN=mx5v$wIiy@uReSX>?$ z99l<it*os_MMrP%>~3xEEiSJvF0UYFW>IIC4-XGFw|D64n~O{ICHng01a)?Cb$)Sm zcXxkua)vs+I6QkeL7l&q(YA99+u1!JH#*wf-o3iIIy^er-9Oqpxg()s-#<LrIlA@@ zg#fINW5M6Ib`MwAclHmC%4<3(iw}66PO|bU=NH#k);2jmpICxU-F)K4Cgx}7SIerK zH}@~q_3f6H*Lns<KRNr88y@rz{rg^6Ro~o~ocTl7Wasb1450i_R@IbTf2+NFn6>io z{YM*qmlJY>y)V%jh8DXEYlji)$6+c*BV&`Oi+les$$??u+J^SE-8;3mlW)oSQCi1M zZN2X+!#SKEev~wHbPtb?BY1@5*LO}cbAQ^q1=TioEpHqnH@4|qj{HKCXc7;pQxCIT zPoK7LC8hsl{BA!rJ@1@;{yN(xuKbcJ?|?JtgfH|&E9~@D%wZqmCOyA~%Wj9>{@6P( zs<`{=3dX#%fA%FhDKIQi^@AyO)*+|O>TACvLo4?m#pPF-^mLv_y3n)e#LTJXo1VVG z)vc4Lxa9cc><jb*ZSYY>)5WXsL#>q4&hCCU--zEmgFh>pp^hgOiI=orj?7&T+kX!Z zE<DKiqUc%Q*8aKvQBt3p@jam6A|eJ-Tw1q&b{7_#mGbYD)@YgO*ADmRgW=IhD6GUc z?9kBM5m<BJ_vff=<q}eP*gbfO-Ll?Ug3>WUwsw!3#2$6@jU|sXS#=%Bcy5$8pt%G0 z3QLdje^$|(Z4K_<_|{z*T5Qm<zSaDDn37eZrf+NKyvf<W8&$Lo&N}_>d;F*A>YMSt zO>^49*iGodsRwMgIP9b*=@bQ}*9%)$2zfXkN&*&pOGF*&m7I#^K8DIJDwFN}yTBc4 z{jykU2)TH^K2kC@9NPN}RcnPR)jIA7xao9L^_y?^p_X}!cuG%g4IPZ9xJ39QFDYNW zUTFz4=A8DV`wlLKW>MZaX<|HKvwN=~`_Xr9zw65*Jx1vFyAsNhC;z?v-yVyL6`B9# zgg?}ie$@RxKM~nC)9SCHu|!?;zTvAxo{a*H72oMs)q2XvaVD;Q;SYcYM8aQWEr)Jd z{OMgO6l9WLE};CU7mCL)$9#2rhc_DCx72ZsrvLwI;f9`*-P)Y%bP&!`%Iyi9z`!se zwocx>xmRbi52$eT3@j)YdY>{SuACq6U)Lv=K`rC{=QKI3G&}`5<nK>3aZE8Weq%qg zPIU-6*f((ztdO%L1!07i{`l9j(fl*0kc{Ig02iZ4opaICjs3YA%`;gzCdOf$4w-Ml z=bgNl;j|c91fcD?o%1w3IT8?tj46Ag3Y|R*9uVWZQi}KXzW+QS_TvDPLw}n*28;z$ z|6|}2Xh+eG|Ep#|VuWVmn>MR0AyoGLVdWH`3@Iu(hjZhm_90*_3{Eb7m$r&?Bh~7S z`_HDwx9M9s(vtsSynQdCgz7((k>ZLAlo}GasUEgJYnwZ`-m;&U;2Yw2g!`BbvSNOI zmOWEfM?F>(A4o667t8WryY^3UvvYLGOdTi6X<{2(eYe>c`yUj?dHb%QgB{%%!pzpa zl}>Op?vXsSCCQR@V6oBmk{`VGpwnO4c7dq1n<!79S4CfG4%&s&{>FujJ6BHMe4B`F zoiE5|e|Dr1Z+jbbm!flz7y?zpG^{wx0LdNI*Ecf{^)%7#jHY+c?x$ieLnKoaFV?~h z18)Na>Bu)E0l3Gcaxa3-;E8cRL|xt(BF#J7p!8^m7l+cs6GuauxVKhEhe64B>lg{c zzv9L>{6_VBX&@k~cY#3bPz5q`UVZ?t@Qy`(SR6SSD^dR!l7GCBy?wIXa%=goxj%P* z1b_L0{es#pEbk%exzED+Ve|S%#X|P<tyJMO!8F^ao6SqDQ1e73HJuJ`oTcJ(tEaj4 zsYe`u;zpJqYyeG>A)ZHn{tjBe!6c4=wZu~5>%CelDpi^KzBAnAS4RSkvm~=y>0IP> zlwabJ)Q6Lyzh)K}v+(%<kQf-#?r##rNk9ZF&l~&?y-gNg2Jl!9Vq@|slKhbiM#Gj( zNveJsxUiEJH%9ye4ec!X7np=UdSn6TwGRW5LM6Cxj;v4JC&sFBsP?oeG>y5psw-Y~ z>-JENkV|eVIs04@89q@^W)ktpW8$5Pp)9XazB=1<khJ%@7(l5yzkj-J|M>%5t<`<V zT?Q-Cw=8_YNvB=wuYw6$PhKkWKcqg=6*o8s@z_gR*JgT<5vp8+#8FYSPDsj*u=zn6 z^WauY&r4<3xP^KjP-jOwn3@EA)Cc1?;~Q|mm;=0WC8HrApAA46;98ACuSlT){9_;; zGCFqjkH$hS*d!ktYQ+06$^KmnkKFS$REL+#>(MHq5i8W7v2n0*nBD3{gTynmo~rTs zj986@{0br9(tQ9c*;wWk%H=(eXemj)5FnR${Sh%#KN>M#U}@|sx=XfV0Y_Kc0qD)U zIC;C72%6aK1RyuQti_3v;E5=h-h!uN`-%9=IY)MK{eE}<&_^{Tx=7<cwBF@RxzLji z^no}C^6_oU+e<HI@qkfwcyw_&;V>~`D{`oO8j=t&hHhTh9%P!X`el-jpBtEAzpAAw z4pzn0Eg}3b8#u(nsNmFg^|-x;)i(Y4HgdIyL){xaYE*oM9pK2N><x07Q7BT1ZfIv6 z5e3s&7gSm5HXv>mh#NlqFMYUJ%Lo7Pgl!zF<-qN<8)L8`HmtdS%j*56Is~ae_h*1h z=bmCsh#){DP;2N?Q`eAm-O6jXwXU9+>@f`GW%ETpic4*G%A9X%>7ZEMH5hX#qZQ?( z=yectE&gJ{avenhb^!-zo@2G(OGI^SoDm_=6|XsW%l#DWxOGCW=;ZJaRo6`XsEKbV zQ8UdU=`Z?(%=2rDH(G}@FSeKkpH!>CnN#Z<DsmFa!H!v%4-qgCd~|)-V$|w!&mt7g z?jQ`g0U|Mlk$;M=r7AwUDf)ml+^QiBl8|Zd+`wSe25HXTbfq~J21Xj5UuXHBb$jNA z?`GeMn9#zO?W1%OtVtiu<XBN`(Pk>mQIIO=)JN9-vi9supH$P<&~xx|$o1LiFS+2; z=J1^A%jL=3hna_tlD@KPdXy7I-dyeRq`dV|LE9|C|2I^p`4)_|FWtK1$th3<v_O|7 z7ww1Nj%+nKQI5%nVDgpdmEwCmtRclPR?0reFMX6Vb5&{G`zcLDocWV4>K42mbVF9` zZKnD@QPsQV?AF6X@hqp;CpyEPRnDm?dywDJH7Na2EXQ0w_>o!hVFf!f7mS=@E9#*C z@FAolv13;(!K|Dex%%dsg1A%s`=ylc`vKJc3&5r6?@yS88(;j${7MD7N^ng++|^T~ zpwjEHRTkpN{mRkTM?PyOG&m14tzpv*<)XwZ^Y<|v^Ol|&3M#_n^M?Ijqx5wY2_hh> zY01BVNXFIFY$Mu0JX_JIXnyl2M94R?dA%`N=`zo8w(2~71AQA!FGBWjf;F|xa>$jv zlZjF<)w$Y>**K)mCvwl2OMkYxqSZ2Y5z|5@TGA6OP%A%PO`rL<?RO*U0Tz1rpjM;u z!+=exIr}@yi>lt}^j{f-z@haW_Pc6dFQ=0xE%p=@18(xZasGiK6@PfA@V7#io~!!` zhUJ;r+0XWKUB2)S5Z6UYq;Al;&~A3c?hOZnvVnR|b3QD{#s+yJh!1)KOPlPDZ5%Cb zt#j!*xlo;c=5#!-11|mfbAc4uQ!z0eImWl0bWLr1d%!Hy;k2t@>HLOW0ABi|WK`_w z%^_Z(;@IiYbJP>UE&gZk!L0+p9s^v|B@SB0dS^Wm`mOlqAHNPi5%{YG2j>6@Bz#fk zeh?3Ny}Mp|xUSm{5=SzN0&@5V4V3^;P7vVO7>@QN2i{&ZweYDQmVPocc*^S|g|~?f z-!k3R{)_MP?D89N^-N3|`dIDsUq%%<xbcl=y`iGwMiAT!ezUmB!f-?k@NFC$La82r zUV@g(6jRYIc)%K0UN(6RaReh=#Cf@rf{ekO9ZFcRl7Ify<Cammv~WR?+e2b9tweZe z9GDP4J|1Ds^yfsbh#}X}-gOft{xQw<$cc0b?O#xxn#d5+*D$)VryO5UP6Dd)K^%T( zoDQkfE9r6s1)ZN71ESVv8E<=h<HvI7KtshxctH6^@`j*^GrxAHx9Ss0wG+am%drfu zH6876>PEu>0=wT{p2_D%o)UdUWH@Z1Qc}rgdFJvbw&35-L%zhus$6&wp#YPcU~}*6 z)l+~=3Y)B%P{0SrT5oK>DT#J`6pb+2?A`V6OZ7_OXXus>>;;}?N)aR2d{lK|mMK-7 z(BZv)_vU?8`THkqCQ`v#bP<7;i_x_mU>cOU!%5V`wKu$T3yO%?aq+=KC+M-k1`l3$ z2WZL*qX0;+1}|rM4`HEl4KTgJx<r(*J9dburDDS4vLwA%+$gJ|%Ttn`ktC6sB|-<X zxJ#2gjF$dD5AIY9u!0*ib82GfP~xwV5%cRwU`D|%F$KTYh~XH|)H2DsoZe-P`>KYT zh?WTy<mV@$O~P(n4}ej(Yil(D{0haTd0eu@C6^Iqgv~)7iieo)%j<LViu(e`pWv2m z8D1VN_^9cAg0Q`I8<O8K;PvOD;HN+zi2?nHIxwH!Q2pN%(5F@D-2HyQ@<anOyuQ7s zxrfL>860*~ATbdb;6k)M?=k;MCY$ZZ9t@*DDpMD5%x07c{w1PgW~5wmmC(o!MZ6yH z3pf<jdes%%xCVQO?dt{W?7ZG2Rq(=J^KSLiwuEPmsQi_u@5nMhmnTrRB-GOz@RW(Q zRfIG*&E!djg?@Q$0CR$s^o&j(8t{sfWz~)nKQpPDu}pKcuFdSL$WOXsme=qZsJ{pE zjHfY3Z-6Kr-vuVpipo1+qB50Nb+0}@ZI=Fd!jmO{1Xf%QX`j#_x4EeX8s+XYz04Ek z5_n!tZ|s5QVi$PiL7=w%BEQ@Hy<*MI+=~-Ig-BRs-CJr<(Mdzm1~&ZF9G6~zwM~3t zXO~tWD=#piEHUtN>{GP;Q#k#u=0A1s8wUC0#qAz#CL&}?=RGiy2KPA7A8vUNBZ^-x zr|QbT-(lmJy-gf<r0ksE`Zc?|8RYzH!|T^k)@#-D{Y~Y|<*;Nk774@))>icX$9Ku) zx*tE*(2;`VBwCd31Gh=m>_+jBy1b3fj8b97mqF$tvUPZV<3)dAqTKTE5wnkzs$gX! zkJdQur+%dK1cfJHXqvrZE4%=RW#|JCtXEmJR~Z~U2?z%K(ZmOf$M@&-9H%mD$+?Ce zQh~UImz?5~7aRDQRp`W|Sdh;PlxW~RDiVSs!#f`TG{xZ0gM;F17n(fa#${XDcWQ*W zZt%rYnx+1VaeVH5PHk?vC5RmyS060>^)ygCi?8xA7|%^|_czZ<aD4Dkyo-VZ=G3T9 z+Uay}Uy&fOJ}%w!&Zu_OxdhbXp=jdAjlQ<or&KbCbbr75^K*5#MVta<%`{pqVI%;i z4GYXR`hTL|L`tB6APeFg7I?J`&0HFWU$C-#0)iQiJxE4NkJ}8tAiEpvIRhszQG;%c zoO5tc(kEu;(j_O0jrLl*I<hWt;N)8Oc9T_~o=@4D`SZ&yWB*vkgIbQ4%HZGuvYmy5 z#h#c-S-L7~15ehL$CQC!lGBKmKbA_f_W`bL!;=?rIz$iRdCPT@0F|h%p>tU;GTfOu zXTO)AYDT_hJfxy{)J5zEDuQOmUiYKje_~J=ttLV9ZBpY77s|kj8pTB1tOc2na!q)% zdY~04k!Auii8RUCR|<~0i^@YL>X;fS3!GiePL*1?RKoWFbK7)UScwVrZ3Ia5JgSDD z+X(>I_^<`R0uqE?qDZ?6Bl6T9aM1A7?<IC~?9dI#4iFT-^i;5I+sw@59hl%`WaNtR z<^X(@`C+BActCJL5f0G?OrFk3q6TmZ>lkFDg3Veaj8^770?FfxQfL#3!%cE7y?wxr zer4XGNR6f)t#FCn_8dH*H{$?XDLhN)y<`%tW{&Qe?NF>loMw_>|HLAb^i?hITRhZk z4B)waeuik6X}C!zDJXkHpFn=VI6Fs!+~);SIO_}nqLict@!_qH{`~pVMsga^IXTm6 z7}X@b)K2TYJ}_<rcf_hx@~V$IF9%aPzFaJwS~GOX(WlL>zt7D326TOb{M{Pay1~_7 zn*|u~2Jrpk&*kN%)qMV+b<e;|gJ33NYv1`*a6!DKFON)z^67XYGdyC_{jUwU=ODM< z0L7WQo%)g74`&&#XIWVU2Q@ou_z_v_PU|r6YPZvhp93lMP&SyAhMSKKHx-a-Q|6U- z5iBVDORb^AKq>5tl0;p6i;W!$NG65PGT8+QJ7+WCZrz3J*Xf<O4&4Wj(ZZx2{Z6&a z)Y#s2xLK0Wy8i;nuwdYS=k(ep4!ni<T=tO)3mt3xru(Iy!^1FvWjJM*!cpY==V(o9 zfb`$GcFFQCfU9VHSY%QA3xM?RiS_eHoKY5dAv_^5>^4sKPRM0q!cJ2NAElXOhDXMc zLp_X+`jIF_hnfu+)sau|R9jJfwkI?oVMPI0M@PmI`mu0M2X%fPsdH-Y5tF2aU^GVv zo_Z1bDZ&W#PXfxR$;ng8l*4J=w-2wVjYTO#+m1Y=ULaFwLii_9VfcUnh%hnjZ+Co9 zU7Ep28%id8;nOEE>JB$Sq<spZN=dp<tY87>*z1C}Q3j+FZ`LVm=Kh5PmZT`J4DleO zf7QeR9zsO`WJzBmFaHR(J3e>0vP5sQ!b5Hj8ePZiT-EM)ywhnx_Rnksg!OuPqa=iv zh&iRK4ZgxIP*1qN%eKfY*KiX;{yI<W*Dp|k=G+9N>3spn{qGtP#DZBBQ(aYGO%z#f zAPf($Sb*I_C_(PG<%z_yyv0o>SxNH#uVEO?Gw*{`GIn8KkZx-atExIl=BP9}kRb?& zep~GmodfIXxm|b)7#NUE*f)Rpm+~u(7^Eb6Hxj;a8}j;t4ZN?H9IY=G*0`q=d^5{5 zPdIV-&ipe<fCgU)(Ac)k-tbmRIoUh!F$G0E_g^hBE?Xz)#IXDL;lp5{6?_Z>2+BL> zi#lT|I@|T)#zWnQ-3;+b^Qw8wK&7RASQo~8{<ocOz0BexF&odoHgqK2>q`T#=e(gq z4KUoC*_kd+|C7xrw1Za$sRW`<z#)oX7Uja;<kEnecFEvP3cPX}OmvXFQ8<{1Vqm_p z2~GEYF=n&dn&B%fa=wmB`04nP^EI~Eox`~p6?tmNY-<R8VV7va`o-D<LlB87BwR~~ zwcqoEcf3mh8fW^BR?YJ*vA00;6v-mZ!xv+i`nUeb_nJ7kFB)GZsN>w@iO_c(P}0%Q zf!wCG+r~=&t^s@&m;7?>S3=$ppp)5=AeDB;*IYdwpO1S-RqfhWPZooqQmu!rc1h%* zj=}k70KPipb0$-cNx2HhvOHbDZC(u(2;y(o$RjG}!d{6q<D-X!#MY{l7PDMK11qRO zYr$ZjkLt{wD}UZj1Zph@o{Sy&et(ei*AH6GzWW^b>DljxuA14wy_u7f6DZ$uNXVTW zG&z|}oGoR__+rTAV0mM#;{0$Hwnt>y%?p)y$dtA*{fy3D%xMqei`sCN7U8l%N5izJ zKLLiN+FjhnJ{Lp7Z?{H1N(;&pV}R);k;}N1b{ZWaB@%_RUIJGRTg4u3RiHuF*R)Ny zv-L}oS%Q&mbCdGClHA%p{K#OI2^F0^r5!$2=*`czXt9oDa@0~{7RS>0<DP!zXQ}Y& z#G+^5FXNnru)9`~ee#9bMQOLxu?qCzH3F~sjm~7GS>sBI57Uxc4t2Ey{H_mtbnF|* z#X8MY8_;7H0V7;qR6BETiUMQ(X8i!4Jz;2GAMoy2XuaWTng8&go%h7IzyXVlI!p17 z3sHkVToDy5VblQFJi!b_S|fWx<U7~~kjdluC(JW(XOA@nMkIz7yCqi#5l$R6{cVHC zR)dfJicj5G#pU7ks30;vW`Jd^dCN4FO+AIQ+2Adb@h!4$Ho;Z!ZGQcNO$5w%NwY>| zx>)(K=pa)aUha>&u{o|xcI9&x4S<gbA!f36{TJ6Bw@`1rCzBTyK4EL9a%+?;15@^D z*aC$qieqcD&%j6OxrQk@xMYvj!q}-g%VYqha?VGSA&zzC+rnOh1$#ZcziyQBE+i^f z6ol~Rb<q13z@M>DGL1wI^jC@qDca8XM{D4i)B+yB`Xe7J<@gXAER=M7+<{i3F-om9 zU%i<u6<ok5bDyI3glJI%s`v>p|Gb^j%CG!##29@qgpu?hK~v{7j;3ZHw@!|giQtyP zln-Yy>zsxId_CdS27TITp&h99O?@zxTOa;ZmYyLN$e)z<Kg+!tj%<@Rdpi+x^Q95L zD@b{fpm;}LW5iW-Qx3lMdO6lrTF`br+!}c<A{!#bSR6VbW+=S`&p4lNUm<z~FaA=1 z1j6}{wm2VNMVOs*e^5_<wpzC^#L>*7oW8>Z5}PldG`Dp)W;Ln<CtD^8R=kvG-3UCV zeq>c7WA_^chzJ5*##x@XzoD(Cbrva03z$nVPRJlZy_TBg`Q>NGRdJa5&z%RUTnj+| zn^^D_)yP`Gdn|RX#Y7UJBNhZ|@k=G2$r<XS*=0n7a0(hajPo7p13wrJoqQTl)P~1X zVb?4~4HRVR^sa9uP@wie?<%&k%<LK^sHBwPm=<IeR$4j6@XE~LXr;X+<{!WRb#p1E zBW!qUuQl(aPb!hhRQG<9HQ~($sLW*-u~fqR@e4;i-SiT`mLOauM3ZW+_G&@GSwVw1 zjP4U`6S1SH*Snr{`PGN@QNb)g8P^CaD7XU9>0Qp5+z2Bf^0^$hzh%SgZo}@%9o+77 z8F=yj#`3L0`9;N1WAar;=U$@&5nW=jxw4cg6dgAh?>j=xCjJuC_bv@KraLy7%L?;f zB2fBoa5qf+Qa#6;=ZEz67aK_~=JP|8+;?o3^b+>1Z(XX*Km!i%)X`woAG0ZyEZ5ba zIH)xrXmozrygzCf)xmCK^oI|otMCfaRYH-s4f|I!3XgRz-XEW39bZp-8P6^tc1?7P zbtd{J{f9~uHbm2g+<m$5@9lR7UB(%yStM7TJCp-MO$dOmuu<O{`^J5S_Wk+5>+X;7 zztSBW*`v*4hFlkN7?j@Vb1-<8VdLN~1{txLh30;s9nNsiHx2ZTk+1L*A@sj16bW1X zh8y+28s*_ziPgDpcg=si4j8gSe;!h-*a7IHzk|)!lAvC1Mtw&^-QiwiiIHC>hhLmM z0eMdRC-uth<a#01NLsaZm2Z>r=)|IZBeT@A-=fG&k*M|D<kdIt-qI4Yt@rHQEj%VL z3{hz>e~NIqillPxJD=jeW}~=BoQOc@$AU2itg^+#UiWFHk-mvQ!#YJdGcWMb&=@S* zTV8-OF!YKOB#>qN7&RE*f9%%16k!yZOd6I+yW}lbI(uWUjwCXAJc+<yPZg7llbBW4 zmNP@dmflk*F+CQQwK%<+ZHjKYHOfybN=|pvjc_qSK_$wiBd~o|GQ*2x1W_});NJf> zCzVi&wrT*NJw}S}D;bN!$vR43B|xw+WT-#%#qBoHfo6vU#wtz?U=EK&W5fT+or13m z%WW<IyAH^L!WvIc5gQ%m{n5940hg#fxt9Z&CVfLU)#*DWR!ZW@{JI}?OP+d>CNd}} ztnrAPsIa>*hCjupz+0<EvE#?|bN!3xV-bGQ>bM^ATYA-J^h{r{pxj#swsRNM`zHe` zPH=KA?y*S-2q(#y%!NGER-8vi{W&e~DPL`gY(d}y!r`nI!MGuJe{><k53?`ZnvK3q zScu5s0eZ52!j%!y7SEV9K*g%r4@r59x#+xW^y$jVN`Ii^*4Ngh<}aOYH3Ym*kE_(j zj9Qk9UcGKztX?;DFR{*0vvn*)?M!6gQranFS@27eYT66KN#(lp>rC3>4svGH=Q0*U zr3W9(74I$0JJh%CyE_Nn&!z!%+;Dnrun!O1RLV5Qo0THhnoEZo!0aRxhwJw=!oo^q zi<N)iVd9UAd>FbdMOK3xi0x-un9QClrJOa22eABMC_%7TfcSKOn-R*t6s%ZLDdzt( zOIGSMDCbq6`Q01O{h4PGB%jNge2&%!a4V%hHBHyfm-l<nOs$27lRpJsk*_B`_l}EJ zj4D8km_}Oe3$#)oUHvMr(=K1GC|F%So{N0w5SdF*NU(x|k6)PXc?pEv5H^`f-MoFj zm&+Dz=m-<_@19vMX9yW?o#N<^*+0zwEI4SWVI2-WUNhZu(M~iPaNqkm!eIoZv7Ho3 zQz}pzF~>%$<*e&QknBi?GD}O}Bm!Oj^|;H)@g$Hp>ujmqy`I3UFbP9E1c5t?Y1sgI z=Bs0a4+e>2R^i|`amJ$duLn)Q)=54W-vT?U_qKVhoqbvm(pm}0$188qibL*l{#m|C z2_JY5g!U5V4uC#$vWhM_p`5o0P@GoTfor=6FxZzUanN|v*TgOy>_%3AXs2g}`nP3q zjf!7=+sP{^Jv(d*#=%CfkUo+cRI?}hkveM>ySs#k=eWwHlcFxl<K}<$T~)?Ppc3u8 z=W($R<Z^QB+<#6GYnA>9k6ur}ZGPyndr{Ox5ZwEc3l&0xtX;(ik|UWF^nUB0n#XN7 zwFdl;vVO5SiQ7GiJ8NMnP)?*1wEdG3v)->NQEl97C=`;|R{nnJD=u0~s#6odtibuV zQ3D%YMLuQ-%NU+z(C~+yb`_++&-m9_<H3eD3coA7U`QT&a4qL~Su%yE>9~8BKJmhf zR`;k{WufDrS!>I`liec%6bUHRBU>e-g)JvuAtjxE;gGtpSqZr=R|$G$x@4uj^}EHR zZdNMCMPE~EpeRJ)(i5$AKVrfSjkIg-OSMaEM#e)zunq|0gq5)UG{dMGi}?kd`kaPo z#O3tBYd_m#7k-wE5s`_)Ez9O{Bf!hsMTKKp51odaD(WY`kU<IO7s!eAZ)aucpEs<& z5jv7=6clm|F|CQXkt1Is6`uHWRH%GSby^IvqqNLKM9NBq_3bR9mkNzpb=SjpHj~_$ zY{E?Us__2RCnUFF6QK;>y#C`IK_ac1Nvl6a&7$t!3?2Mfr1Z*Cn5kW*R_)rA29sZB z=+KLM&{!W?&gMs80?`2{<9JSdWa(DHHwOz+IERkgypdF`-TaFuvX;(dm^3X&oA%`^ z?ISHM(ir7;9n5i}nv%{*CSDw1#%wNBda~@{udq~FWavQ!IA@0b^m)DZ3j4rF`AaL} z6x}8l4XrTz_0iVwFi9eLPzWECNmQiV$DK_2wJ1~d$E%abDN&7m;az$hU;zVL=Y&oJ zCzJ)hJ)R*~!xeJLo}80N)|d{o40m!9qk@q}euX_vGCG_!DypmbD?{+AO*ThsL;GKw zEM1)NZ%>-3g)E`CYoq7^p+UOjQ~!mV`wUvy9G;i3hypFR*q)WUuAUHybW$IV*^Xlw z=LLPYsn=E1SErC_`i58LL3qJG{zV7*k0i4lr4^@G+QpOzxw)0N57h&g(;Hb0z<c<P zEpzbsqumhge{<VLc4E3nNe<ibJ-lAFMunEo(|+%Hjlt&XtmL0`1^lK5k8Eo2N{LF7 z7yRwz2+E^QX-f%wSwfX^4JwyYo(A1MXJ;jqMnD&M7z0Gi2oY?_cU3QnQMZQ!aUr#q znjdCrW%0`=Yd&!}@&2r*;5OcrTJQ$*z4_+1XEMK+M$`YKFfWX1<y=PkXVYf{cRgfx zaO>CD-@jna{Xk<ZzXxx&L)89qGgN2KqQ@{Vd+nv{d5zGcRTFi<m(26|30`Yt$>q$6 z3cKxlOdABCoFXbDHr`Zasik|PB{)p|)vYWsSBE)lS`<zYwD#1!8V{vzNC?{cS}9^# zjWAERl>aI}WH_9c*_i4kW)X^&-|UpbZ{B+nh=m2Lr&@0)XE3+t)@!49#b>O$PH=b7 z63z$riM64-4n`pdk8<v&_OP(9q<?W<fs$I?R-=9eM`2&yuJ$zU#@US>68vrJS`0qR zPg@^Iqz@t98)7*#YELSe-FuD-uXJp$W#ALn{!?A>P5a!MiyGREV{FK~l@4w>-_)Ib z!0qTZ^=+u?IbT1%mZL657MJ&OIm~k$9sGXc`Xlr*)2e6gBPV?D$Z1Cf^dV8z2*P$# zbIxGSQ&W$DeFospB*?E;p@mmO)XY&L88ckFyL5wYX}>6o{bq>5@~K^0>nIbIL{o*q z==axyjzyBQURK_((WsNwz3vNUNg<}1N0es`BuijJc)tdANm!rQ&NONuj{}_=NRe*W z-J9cw(p4nEO!fhMQ+MQkUf+kTU)9XvI}3@val6A+K--Zbv80=hB;b63?zm_X*{8rV z*X51_X0#z5s<x^_r$i>rHKGs?75jICL36sy+v?1Srb}2j`PKlK9o!Q>wc{!Kw88^r z+3~8dw_{lCcWp#Z;}uH|{UvMsQk8yZg-X%Hr{J>vme(_)Fpao{U~GNC-#&z=4AVTj zpV5O$vvs0Gik1eAEu^M(ld<eY+JsnzQ<$~eLUlyCq@=y-!;=x;y+2hm#Kt~LATWjr z2v*$w<b7I#5QxSrIDG0e6#5{0!xnhd3>1FvI#ps`GE#utTlvJSjl$inDjM;Cbo z%Q?VKvf-q`weVW)>c~$Ux{PcS0g5i~q$j$PRFG`wGYsNzco!x`v!zH*U0I5FrAtTm zh1~rIoYt?vwAu6a>Tu$yVr&0x`~AQ#3T6zKqrC}Hav274o+`!D%&0$SXN2C@T@wXy zv=i_}#s`BN`(gw%8@fE{;Hn~b+I>n7G+=|62dt3*&7<Io4EKJknAyP<!4+oJSxbwd z|1cHkSc5$rf`$M(^>A77EmA*?cg@`+X{z%^*pk`$=?Nr2oxx_sigo?{P}+FX2>4b} zQRZ2!_t@IxM@fO%eS)GKZ1$OU_v}uK)VPHf^G!%Cd~0x=8^wgv$fX$UsD)(f%kIrH zEQH&gkVuUTVdMlyD&)N2?|9N42#Tr#Hif3Qna~X&{aN2%t64F(YT=E5;m=hHpGA!^ zb5KYpY`%@Y6(#bew12$R!T4~9CT@g7U&Z&=s1>&IPCIpm0H<G(_*MRR2|S>nc+_`_ z^WKbJ9l0AFcm=Jt=z&2T4UsA}KT6f3y|BA#<dEb-jbKwBzgD8sg0TLr1@Y;KV6S(X zW#*IH5Ys%{A`Lzau>}OEQ$y7RSLgTd4vu@rH?vPO&M~}Pg0fv1qQun>#UWV~j1Dh= z?}f#)G>IsIYDeVgq@r_It(d?ZU7nVIuC${L6vYUhTV&qtcdU_bSF_12X1sA%v|{we zFQVaJUIO=EMBkz%s*9rAs-&q^57h^fM5%R=;)|qyJ6;7J0!*I;_!*b-cznoGMw<Iy zN<V{0Q!sXlv!lpnBrDB``1JVVsUXTJjPx`R4}<yMFDgixfu$^?;#Yb$PupYhG5~LV zHiAZ%>ReSISV3OD)=2%5J@#l^v|>zLH9!B``nPiRpvW&U?nJbigZ*=c{Bkk>&ECxw zcfCt~_W>Zr<QIiOksMMLFTrxrun~@SYJvmJpRc%u3HvT!8YBDV)!#UVo4g!p3Oa-L zDv1!}xqqS||I7^%Q&-E4ioIFio{;81{aDmdt~S|k3)BNWg#`RUsM7lrY3;SY{%KkH z7PjN_Eten%4-%sA<{p^^Kf=$cfvZwdN)7+HZa;3{O~r(mzgW2apg;_Hj>3X?C`f!n za)psLvo<J9)VML1tfW~fa?Z|XDJ*`1=!hPX0wosHGQ6&g03fk(CV16j>5%IzTE(Vj zmil=bE}mA^BK=-n#ny=b+`G6Nmv0M%uYX4>5PxHd+a1GI<jv5GXFwTN!sS(eTChRF zZui@8{*d%svlfus<Yl4Rg^Fl<Wq@%oZ$^<EslpJQ{S$h<^4gP$fZ6Q}LBY=yXWNV+ zr!}&ZG*l#)v29TYQ8^aWjJWWUP6kMn^wLqP0kW4dCeZz)D>Wh_OQ1HG(L~N=kqfl8 z7z+3C>xV1H!8vrwDS$Y|!)B1-H$h<HABp_`5jgCeDJHPzC?0OlBpr=^jHA_j(^r^U z(bUXN_jYza7S~)AUyI~iwSL~eIimN@xSrTrYBJ&P7v@jecg_09(=^46O{O1+t(|bC zVdt#knmLI$S}Io11xG5J|6GmU5t5t0@~)E`CCANQV0W>ep00HITyfNNg4!4vNG7m9 z7Ho)w^3AjAN4EhK5+Xge(j-a!L~mE_p<U6m-0u>ZYVWBh`YQEuA8Zsl_I!RI-hcD3 z85J8ZY!FV+E8g9R)<>!&g6d676A7bDDu4gs1_coZB-QJ&(OR!~o!LQJ&Dq$*wvPi< z>)u8n*r4q9`!UK-p1kaBEITElh0fDm7Ql6s>onIGQpYa$#>lOa6xkP3cUsY~f5_gX zx1}UNuPq(bSlHo^_LRTb5KMJ5{cFiEeVWJLwV#&ssx#}{pvhk&?<lPYMjX}3HJS45 zq}f8`tLNvZiDZxD-y>&rt&#Mj*<8&7Z~#ht`Y?o=mMH{<ET975>i<fzX4#-Z=f=Vd zt@lP%Jf#pVVH0CU4R9`dpQnfsUBh)VC-NJ{BcUvhZT&oY!}5>4lFs^5{?aOA;{<-C z2y|mzH2zqD9h;Rp3R%m3kE6JU*)!Abm#ukhgRlfG$3s*#<HCB}P;QV3#M)<@nk>Z! z0=PEYLitPJp+7vsD_N1aJ*>?aVR?gV;?c)9LpBO(cCB|^e;286@Y0V_iSl9~fm7nX z$4cbF_uD;CiO+kU^pc|Wtr^sY#0+HOI=OUw>^s8+I%^Lx*WK4^si|U5D4kN2t@l6W zi-jqg4y3W`WFekVNQjX@wo(|6WTu_fczQfG+a|``$bDw*6*=}&d1WQH_GMZJ8GSm5 zy=1s6S2KKfhI%!n;`Zk$@gHZ@^V6}wdUitXJ;ILQ&B|Zr;Bs9ZQFL@n+-cRX8iydg z{l7#-Qr5`YCS`v~#~gm*Ra^OHhClM@60S(--$dM@t~L^&;$~gux1iKjd^<MHA>E}R z>*f`I)_A8TW8{0I2Sv?Z+nIGoGBlxtR6Bj#(4SjgNZ6-u$$S&C&v$K+Pf;6gJ0r~= zuDA-sBwzx_vR4dkg_(iO^&O)F0y}Q1uag5L@Dub6#!K-SJmk-i9zdY?h|ceGMxk;h z+rzlFCwgKn`&zETJpL&G-(VhlDTey-kT8MZck=XYj;*3Q$z%EB(R9%gGCZI_%n?4$ zsGddsW=$#U-4}i;DzlT!$CcVhcDKgunvoaEbG@YR^jT0ZVd^$S6hO(ioI#OOo<Ekg ze-q(x)-4QbVrlQ5JsaJztG=5ku4;Srnyz^B4~+s{*nm45-d)9x-Ad4U``@dqNQ1tE za*sT!HQF|3%GNKgjOHDzioDHt;R?i3Ow4?`A8L7<^xHpx9@n)O<>DcUaIQB$Rgl~Z zu-cBr@6K_$L}O&11U$%Cl?wu{GXz7Pk2HFiL9pC2*y>9ZDheRHM?KcPUA-?-@h2^4 z9&ct#zCxfe@Y+K5xA;N7f!=Z70_|rcQ1T6bOXiEQ7M#r%Y^ZmwL@aD~N;r5;w<4BM z3z7dC!BNSZrIILnO-nVXeS|BEGVU)#gnlCE^iiQ;x6bV#|A+gqf*6x_#PxhX0jDEV zhv+N+CYg9<lp`@DjFK3#d>D6&F9)(gyq|h=9Uq_qdB})1Ny{x!bol^pcerU`w{|CM zg~5~)JQymyeuQtZBrHoZ7VGMfGY&LIs5(GASWM@o(ys>XzQC~pc~Ivr1+@crH4J}9 zw4+Y@HNC{0nl$1kpI^V~nMXyDiyX;x`LiZ)3rT&A)Lpt~I%^M5zW%nuVQ-vw0ny&G zBd1sIB5pp*DOiZ73_}z2UixlADh-jTtPbOP?}u&RMG9NOHr<1Lrtdr}K6&fks21vp zm7`!mqaIx&(MucH=2N7=?=QSx_$0G~T(T8L{+lh^--8qzG#+RE&jlqc2=0{u@&_oP z-+jB*O60*~hW24BJ)!q_EWOAymtWl?12JBTNDVCMS`VT2atJC{trI}HPp@s-TZ?HA zKIQs2eFZC2FZyKE!vxayUTjB*<(>5CI+lkqPEXZuTUf<t&-z!%IsU%v2-!@u1ko{? zA2l995;6TZrwWuK2p)7rrE1`^vcdSNKzh|&x|U2BrEB&4MO9McQO`qUEzF4iEhF2U z*Dpn#xV9QARqEkiSVTBpInyOmexJQ~i^tiUjF4>!3!(5GImaeAN4x9UbJk>bT;%vw z!#kPKug)ju4`!?2#`(>L!65B@iZ_uqp3}2FMU?@-149y9{TXxE>%19f&oe##E#S1I zX>7R(^NJ?v!9%<YkpkTtH6*zBdAGYiw$U_CG`zFM2d6o{TML87BSvXO!%+bjyUd&H zle}JPK5bss!gsDo`6{dAS5=AOGg}lU_WQ06(P~+f)VeWo52_fg!ga0Ft{u+Z0N+f_ z1uIK7&|ITGvy23>vJxX(LR?_FgE!09pq%+H16VJB?w@?6vPBj3P{vtz@b}1quly8> zfEbvlRNbMR0-Xh>2{EIOtt?fy`5H4HJu5GyXfO}X6bm09oR9@#CDW6mYv$K4e*ru4 zmm#>k%&i<zJ<{YtbsD1be<skqfbLH@GYUxHfe(;^st0`QTVs4$w{=kZBdY&YeNlOE zaWW>9cD!IOWnZaD?oaM;YmA^o%GZGh1tdTbSrDbTOBNIc7m*qppyyLTCj4k!ZQ$5; zx4U3s3uIkAjSxh;SY~X}D`=3Se_HNh<nO1z8{=)&881mVK-hR^nNP!1zq<#066t=P zWReos8$r2YXjb&5O2crEu1gN*L^MuA85sp>G7#C*bjY{g(DqZzQ$dw!>HmE8c0Zx# z$V#-m>cr<}CihA7LW~bGAZp@Fup6+JzIE!^VvsUXs+~66=b3Ywu5d`IW-f!|ZfPV( zgQiMlFXH*#iR2GopG^q);_~K{rnR{STz$Y=q>rCyHJfrUr(8#KY)6|UI*3<yXWbgx z+h@Dse@5LJzWe8yHu|#0V(6NX&FPD^uv4UW5CLu2{P$m7#a7E$+JN4`du~Zy#Yg#< zep3Yk7#b<jDCefS!{OvSDISzcr^T|xC8F+$u|V@gD4d_LBfl@~Zc<S9M>NbWMs!tW zlOCR%h}r%Cy@fLYHMQ1zq9uO#APW?Y0^igG``fqwwZB1(_%rd9SLiBM@1#~KPLwn# z1u~+FJ9b;#I0&Zv7eD*B+Egl)`JjrxZd8HFhj?G;Xudy=9xJNBOsl1TMf|R6qpCt` zP!_AfO0a?DhA;H_8{GRf<6bLSsu$>Y7KCqIp!H_IFOEsl!%7v6y=>>_9Kib*G4R5s zJd8#0?Sy*Wjgy48(8#eWp>@01g?L@dKjGfaC&`S7JPZ)B<@emp@p;VBTH|c?0=O4F zwx(|z*T^E<Nq%-wmWI7r>B4Jgx{L`L^{4pMz_{Gyf=V))0+UnShQsxnfbm-Tm<Op6 z6LqJ<-R8@7{p&}Sw`!1Oleg}#$%(PEcI+~+Q|dLo(HW80-oA^Gm&sYoeTnuiBz16| z888|TE0C`)(Mznkjev`j^|?CATtIcbj63%-!A*GIkEAU?+y=3?P<epgcPXl*331TZ zD<dRndA*cT`jF>v%^$+@hlY3FSZ|qDwi}|fT{%#gHTPC@7fORJP)zIus2~%FlJ&c# zfs2C1DIEVvUY?iq_@Im7(*@(WHfO>oHGlUm3b)IcP&ng>hu)INS~5yZ^#nR;LB>w} ziq1P~hug?BdzR?V{p=CvZW)pYfG+bM`S*7n1{6eBX<`eq&rSxRo-5C^4m}}}HR5}X z{0dLjv8*eXi=z#`P!Ye&wcT<}f@8)lzQAbJE{krX;sEX7i$FXox4*zGotXOosC1^z zO{CiBN3=)i;OYskqEzA{N6-UxA_AY93p8q^nX=-Ze7=9l#MYYqmmATbPOZ9(QiVYO zaqtF5!9OreM{m#92DAXTyefT)26M60h!ZtQn)3%gR7r^%+1*eB9#&=2Q!T9DnVm7x zXE5;<CbsPwz0BE4Em`1;zMX-6txnuJy6`23_}qJ$o}Y7s95-(N`n5WKEjg*!;q}LQ zsf8+VCZs<I8U9AOL$8b+Vz+WK=pvo^GKavK#E)Zas@l5za{-)m>=N0Od~6AK-UQWE zNY9LzyD4x1oTQmBk5Jnui&utw`6q7x?e}NX#p$$Tio<yfcU$u&v9z^_MM0KBq`hBN zFx2m5D^U0sx$934kHk4u9RbHB;wa#LD<ksRWnZA6@Om`j4FA-y@LxFzgo%+}etL?f zV$Y3e=$F9PWnXXXhTI7KmCoinr>Fi0b|h$8vA@Vg_dIII5h0O=?O4~oZ(WY?3{?9& zLR~>a+YTi|RW+W3_I4weQhb->7`>pqZbM4T9k-~BLpN5I2roo9D?=(nW0;K0H~+p% zxFn{F>L<tPPS=;C_?icw=#T8PTUuvC`NReisTpUkNfLidL`beO{oH`>xYsa$i-z^N zyl13F{SjLm7h?i}1R10HbbCNf{C$Hh-Q!}C8Wa(h2@;=rR~xF{K?E7uL==dVFKMRV zC9T^v34OY`EjWJ!!k!=d*N2n**qx||WEY+&_1SA36Xw+2dkHk8{RW@t6Km`5y3c;( z1|dUOb7gTeLoi+f0WZ-G&FQ=SRw5uiM*T{k8!oSTB{M1rS$DyC>WiW-g?K?_jefmy z*U84*^Sv?OIt@70OmG^nffc7DGUHNI@qTz|_D35L7G@n!yL^|BxjToEr{k9{s=8kk z9ifdl1!R9TwodSCPGvoFN52WkzRwa$kz4RJGcJH%o3<x#4-YYsqFcA-ZYS%Nkg+HR zkwp8cBgn(0*1P*`YZM<dN`$-_l@2#t(KIz4qa42qSgfyLzy1~o{oCyFR2d1M&x$o^ zW&+s|m<y1{K$XiwCZkP09Dc{`ZsX3yH#AaCwN|)4D1tj?mGB9chC~WA0j?V=Qc5r3 zxj|}sH>e1ZsgeH6#r*~kBv#Q@^zE=SBp~_o@E^p-2MX5)8<Y(~g#(HZsd9ep7jpg< zMBbcluh5|nk}!keoL-#gz{A+CU&k!q#KQ?7A-Bh#5#~Xd2j6n`i`ad}k06~wAcjAb zatguv)#5LjL2Qg6hhN?t#aS<Uem4E^5!o7X*|Om#A<gt~c78w#kw0Eh8e?n}Y)Uu^ zpT#WBtQz&qO0Tl`t|0kkRf3hJ&4B87t|yk#iDh<yKrh3Y<qSVWyB*`)bJroG{H*WC zmm6G%<k*2{F}32Ubl0<P6kD6IT)w+RdTQ?zH{2|Vh^yYyk&UuyIyJ*)K2G`tRpdaV z1D3CE*2>OD+LZ6_zO!p?wjLTSQ|D^tGEqV&D$bP^Tx{_$)tDiPVf26AbqEdOhSIR4 zUtPpzgc%-tN0p4fkF{4<=Mh8kHO#j{9B#k2<#qk&VYYt#w2bnnih~@%s8#73;f{@t zblbEkOag<pyhy#UgLgZH2V4rE_haz|kc0&$AG)!gLc||D)!(c<KKoFKYHB0yoo1vA zOB_dsL<Af^AvPDc{LuB#M&!Jy2D4+CqPau)KJz6%(A^yA$gE`_sb<iskVH`S*I){( zkkOEMw6T4m|7D4gMQqFubnk_eEd?in%I+6t%2PD~#~LSx3y!!T+c*#it%&T>n#O+> z#e6_G1H}ldvs_fj*`#ya4NO_B5aJv~K0&CZuW^YEJF5)JkQMw34DvES8XFiur!cN- z%cF0<v%ivILM;LU7HvM?<-n;yx$ny~SKygETcv7aj9c?q77&Psv+3Iyoqe<SqR(}7 z3tlief_e5wI0wJ>nkvR@L<Rb|b&@ti|F%j)BUKDM`U-|AyvfFfx99>Kl$~7XOcpo0 zB~n3FZaFjDr+!`)3ilFFC;;7%U@yr&g!9*QPh4IPK|fzl$MfOSa16Y(7QW6OpP(oe zeI(i^nvTyz{d2&6-`#fIUyzK6&G2`bcM<U-;pS}!4krW7^P&z4KO$R+id$>e-!pPZ zMcyd^HwUeIf+v1p7hc7sCKx^?nX0bRZu-Y|F-qL-Dy7^@#%5m=x+GWRo*k~@ECwek z=mafzx1KJMTX%o)+qTh|F;{&8J46*}yH91#Z*$_^>$r&dHe0M{%S;7Q+3yvn$q4FT zav<(Ei=pkR!QsB&7WkxKwyCFUw`pb8Zpamy@L3g7th0I2NXE6>CiVg%eeNV;sNZ={ zgT7IR?R#sb5PetOyIDK6^Lux%$cU;8;X+M?!#IOPMmKtPlI9|8yGo-XoL<MVoxETb ze1n*z@F8a*q_3F}*CDO>8j_MbUT9Uv2rA+B6{O;m+~gM$SlBD{DuSh_AUO`hwUK2y z_cs#4O|u7&j$N@;sHn_sXNGQdRl%P>0tMc1GP(i<<;skdIRbi1;nNDuh(oyKQ{qv> zM1yAE3&I5if7a`)(VH=bm|v#q(nNaFIgDpwP~wi4z)g)LNB5MNT{LaF&(<npz#!U$ z0=MWKWOd?TRrzo&9v3K>2tS>>?jJRh{?D;YMwby~Wy6MhA<>W7W$j3jPJQ>_DU`7i zv(0ohWp^E3Wb@TMFygi#&RYQM{D~<&P|ucT%Nh3C=dDH%Y-e<ZAthcB3xGkzDRl15 z|7Gp8aDWx6jr`;iRbQ@JOczkb6b4f_kA_A49oU$TIp65@c1s|NrJWu6@<w`AJcP33 z3wuKA+Ji-sc>4!gn+=-}vU(b23RRS^u#6sme91Ne41ZnxIugUJ2a3njugDgrm^U^s zx(c~M*>(oF+9s<boYZ)4q_XI1lWhb_q}nnDd*k6d#f<td<23MU{Ve3t%WpFlxf8V& zH3s$dD?9vmuM!d#^0{0Vm39X^@Df5$sflF>a~2klz&6dn8$P$W12)f<3GS9HCX=%; z=9unn15oI0QaX)3+xe=mSuE^{{ZM;y)5GlTU3Dcpv?w`m_;V7KG7?Icr-rtW&c+Rx zx^EowjYZT}^f}TVMDkt}7lbXo+&EJ}F1q+QDjU*6GYHsB_)e%N?%GrSsNOUxa%Q!+ ztD3!dxZoSH$)=6@{!g;8YQ72ik1mOw?M8_zKCvxAW%Co`)V*69f7qg}g-WJXWp4by zx+uBWcd~AFo`U)9=)hLhH9#^!`JRz~Vfm-xR(YYT0Hp9$6nwfj^3O(1f6@6|XXd~6 z6yX~ROM7<fzKxA3iw4E^x<(3(gSq?%Nxe*D?0bDrBk|>h{C>hy)gU5kr5u9sl(77_ ztU8z8_)9-n;2YJ!cWR%-<4Mq?2}ZOZ*W8Q786W&9Iq0%FgfDguybA5<(X-dmN;$$S zJgUfX-hj5K^4uzMqmM|H;m@J)#*gdYX&}n9kf;xhU5xs>*o>~BgW_%Z(7-{HJyK(u zR}e7Ap8wsql7B9{lxPk8w`N4PO6eAi<jpl|$dMCKafycl4*i+&G6xZWHc3mY$>+C@ zr0A9DBk749_V}H%u_M>8Pjrb-`rlz~C}n2YQA-(MSnJo`MzXTe`*?UOAzm8JD(aoz zDk&i?C-;lIHt6lm>HP*i>ufo1?%5gt^@Nz0G3w9#p|SP8NoNmCSI<9f%%FQtgjpgd zjk(p;(AMW35UpRrZT_A8MU>Y6aCDUcZ9GpKD!3MR2=>EWg1cLxK=I;k!J49l;u3-s zcPs9$MT1*$YazG?_m}^BpYF@;&F(%o^Nj3V=D6bb=j0X@L#UwA);CU~zns5Xo#u); zPS`)V*e8p3W5Eoz$f0bia_jEv^d;(4QrpJwRkh3cp(K35GN5C6{bjZNg-O$AQf%g@ zA-SBN5?l@LsWA$YrV93+d8|rmgGpMIgdBRP9w4dIm7!Xy6Br9+LJFDYV^3~zT^wRL zEnlZBBHaB%cl<*3#vBHKe1^ZiZU6v6yLy@Zhdpl%pt;fG0lQY<x6W9M1UwyWd-8*^ z7MDA&$l{9anKpQ5V(<W~a3j0}S?<_qzYPF^-sPsT2F8<g#*aTD7{yNilpZsj@w~Tw zQP5dR+y9FD<!(JWdFSLVx~MK+#oul3|9p_P#^w9Oeo|?L_)HHf8c2$P`Oe}~h#Azk zro7vpUC$pX_=2xAH5uBZcQk=g+Quid82Wqv?na=Mr~+|^9U;uL@Y`hs@$nElbqV`s zEDLY&hkg_pWm|VXK;KYp__s?p9z+&yz}hWD_7p{omUO`Fk(@Z#7p93;@F#`_y0F+3 z_c^mUtzbTHKVP!ob?a1HBObTygcF518j4vmh5Ft2BaEBg7ODJo7qv5yuYzNFA0m0` zEGVLi>>3tDtSYIlSldrjT|?P8ijC!-egBwI$I9+7Af9EEs8LixNpGI`UiS$@5neG( zz6aw^Unn&t!*6|5o>8k(KU9fkVMgq8*9u!8Vidd#7q|QD8K%RoqIep5w&VyMXj-+8 z3Ru`b8am`zHiHRzh0`S@RQ@dj<>jjyQndl6v0?U4TR9NP8~+yPCosd*Yt`gnQ2Z3S zc@mMSWO;caCF>9_@?GmT;045y{2hBl;B`qfS)jNIiAl(ZuA8*a?1pppeQKE+AZ%Fq zpwxDS`>Uu3xpm~LPL=iFrdWn0j3xHsvT!r2!?ypQU=nO20ft_!`;@xs&MqH-3m~~@ zx5ou<lLia@b82}dwZpNn!yFeX+2bAcL-afRyImnj^_t(sAb#uX^As}5(3^kmzb~U& zc^g0Egl_pq7#q#MFf&a>7_&T6gNGjMR64m5qFD?li6ddSzKRQR-@>b4jS%A{ES1Q| zm0vkC4H9IjzvX^xH8iu*`0GG-wbbRP$)4<@>a=I?)5uG_`+m;%;)A<jSK|MJ5+RV` zBucCSU>kA)Ig_h0fhSw;g+~}~(Ch1^EyXe#9`;<tIT=+qKss7r?Iea8LRuOujPfTP zUfyTcJx5{fZ%27rGqs=#NSga)>W3q&)j0xRim$AG+bBRIC@Yu&8)}g9VNEV;c}}$e zQcjR?tD==)<yIffgwXGp8*u{4K6f(r<$-3BI1$^Z>evY`g1e4I#O{j*PK1NS6`$O2 zozpp)Hl<wK=5BcZv6fI)zV0v)n80wJY}XRr-@5ur?BBe+CMMGW-8IPXM)rTmb?Iur z{|Zy`(Vdd1Q1xtL0#dU1-#7{#xqS%GqS_s=)6lS_<*QaA{Lx_kqfUOl0!uix2gm-i zuEhK22=d6~JFu=~H!@|+p`uQb7*rLqz^_=|QJsp<#0=1sTle+%yli5=TZk~0uga7d z!S#Oowk0FN&h?IW*ujuQCZy0Wo&)E%b-Z3#j62@K=w{J~HL$cXJ}sa1S=<kE^jq}d zli16hHKTq&z?Ouh(i?=GJTzRzH{z>K4W#2*`Vf>#;jF($e=6SPecU1>bdwL0C2Ec8 z=uDzIn)i{THm5rZh-XA-MGU2+WYC48&QxxXs9W6{Cf%lW=|8Cm+uU%SA97464XbvC zn2ETIsP0@uuZ&9Op}{aCGc`84zM9(OlQidZvy(y>p5;MZ%xZC8I}$0NvhWMFSePz6 zLvFv=iv^VP2^vCpchcGI^78Q@*s%}u^ybY)5JdK?_VP8B6%2_8JrknFIkiI{bM4F` zGWqexS@9(&hcMZ$i2UZH%q_>HG>%Kuw}N1pJEubSWwX)jUCCsW96T@b&!)50%8zn& zv_6^2$?fZF+T%l8AmD$i*`=K1Y}iamMX9C)KVM{~R>Q%Gn~|p`HM7BW?Z}CY&_O01 z0sCxa@zA(*GzXeX+>U3T|EAF%jBZF*|L5t8<+80qHJwkXacgmH9lLV=v@QPezmm+i zOzJ!T;ox$O4sQMZwE?8fp&>63!1t^zzS0s{H*D%NhCUEiqjuagiFd_C7^AkA!d5W5 z6iqeYsOMi_HGQPj+rbcXN*XKvN>pM?9Xz0Kyf$nbix?~g*rjxWqq(qwVm7mlh<r0c zsiHG=S`?gqNLs&#T1OMv0&tP}q{xAI{0Ru;kNe=(lZ%3MgUQMAo5wu{2p}ZhuN5|a z4K8XlHs%3Td&rP>1x|lFB!`y6gsAx|Q;5J~kJQYR&jF(kX5Bd891cWJ_|<VSQnXkQ zOvfBb@~$Lh;5N_$KfjvNV@7qtqkTJS_0jqi%Wy?FU)VGdqtdul?Fdbq%`}Q9^vj*r z95nOGCz3>|Tp3VLO4;pOLJ&qT@K40;7Yc$mUb*24f0OVkWRe6^r2Ixo<BdFE;d_;? z8#^@JRL2fJ*1&|KJLd+`*Q;F>N3uID%YYybR|qN>_uKXfd)OSrq)h{q_5G|y(~5tG zhOY`|aUN2H4~;KxG_>kFQdcKOq?8bVtvxJ7%cK1)d_599LdM11TUx;|dDaI4gEFgN z3@0bOj)8EB_sNjJJw{t71q8xv4mb^zl3<clqCT(mGK2b1K_QR~baSlTIGt<gAz-7@ z#NeyyijO|ALkS7E$$=o&xf&LoX;kTncV`}=S>dL>GNB=m(G>ag@dMD@oVFFi*-$gx z`|2O_<{2MO#6y4T*_|RpF$N|YM=zw)Kn}s>5+?$l!$)FGmLH$L{!`xn1E^kpAec8z zo{@nsITY}k>;5OC1($DEL1l{_d^ZQb6?<59A#5qzM2pOP<|#ZsOIu6WLhm~x5C{1D zlmHmb+oStCJ~a!DElgq+$X3fq==uT&Dk{&5;d_~a42V)v0M}7_p$VAAP;P!b0kDxv zSgY774VZMPhYL|Tle8qDuT0GBOs!MXLD{zX7TWAT)7VQu{zFXO!x21AU(NTLdUp)F zefQ~K8CBRv203_X1Ry6E=4CoxyczNMPWxQ1&te9f1>rDf(R37v1PxIy`T85X_xK>3 zm!1K139TQb1I^Y*EEfWzI&!4;pxuhkbBP;%UxT;K?_sep>|MyZ9DMv+Cm93cTPN|W zRj3&C82TMMh@#V2&kV?sV$eAEu7Ta)2xaR#>%*7uiCQz)j^Vy=CR!Tjt~~}s*JLA3 zbiqd?eDL2hKK5rApxAzmyI<I~GRK7y=q4x8Cuur<=CEV!f!u#W-%K%wiw3nl4wgUD z_%eI{(^-F(Vp7ov9x;R;??c$SPe(%pxPjj6S9+x#+|G*}l2u(N3rF=6+_m7h{#$iF zh@j**o4_k{K`AYr0O%8IX~R{BrXs2?-Qi@uqa0oTVqwYL7h#=g-wz5RjLq3*&clC< zVkG?xWq8rKM^4*(BXI|lZHhyDqI-+@?=?pjkj))~lB0+RY=b=@v2%(H%Vx|kEh!Dl zpQK8F`tW8&p^};BTc$OzbD#!kxUIKkG>iVek+%Zyfea{LzU*MtqSp8?%R6~2=B8m5 zdt%u$DiM~&A8B0M$+N~1y}EXuVP*0n!{QCZygAI`)YCYOqW_#HQDI*oDLMa(G$nc0 zq9D*q-B`xvpKkLRi(z81wg0ErB}G2FO{EMZ7JF1<EO{)X>QGB7_Ij0OoUoDw0{i_y zCK*TaMt*`Rp$2B6?(Q(T?lxj|j9o+vQl(nX_z9YMFOoWJ({Fs}M%KPQq9+c}|MB13 z5`y`48$F&jntuu~Q<cnSm~7Z0;HCdi=1NQWFFy`u$)TCV00tS1m@}pI$bCTlkPe_p zs_=vBjl2X3w4J;}x4TEl`yHG#fQdzVZTe>deye#z<g#LRg1u7_j3m9<+tzd5RN$?A zRS={61ew--n2Gr6x~niwIE+etg(7^#bB{H7vBaq=Xgp>aXYE2FD)S4}=)XRE@VAiC z|H>Um@X%y);>&8>+CBYoe)!4gO44Q>+T-=8*ck)54~j9VB7!p01OY;xAAmfAm-?F> zy_i0Q=RqunG;+}cwPM@=AuOH}2gB|m0P6U?Z|uv#%+~n5xCvY;%DDJCOL=vMXd54F zGt1Oe6$QcrE;dI#`Rl{==|Bcy37i@eKmC7^X%{@L6iB1O^@IXy+Mpq_Z&Xvd*vsj; z&>*tgcwnK^Huag{q<?<1%5Y00nPb!z@2Q1JsRkuVbZa>mQVWrZ#_TA1L}(~m!`_bw zv7}8?y+-H~n+;+8oR$<@ZOX^#VT>08XVp^xNR^H9en|SO+=;$nFR`XK1ynQO;b`Dk z?{JU4a{h2((uEOgH)Se<GDm&?aCh=6)qkLdN<|k_F2>hyRd&o?!ZN+h$Q1)3$~0uS zXB6>R#RR%@cZDDTvtKzgqmsfFl3IS@#5ttdQbLWyV`1AjGuuOxZ7zo0SNC>v;RPhk zYE}U*`?Lt@^gJ)DT>H*g7CW)kT|Q-cP#?EPnLFI^Dm?~fQq@r2F)UF%*Zo2KNEu?x zp-N7?#2dTt8yr$m(a9meEY6{`IL+H1++|}tG$Rlr(%3D*01MYxdFy&)9!j6RyHFj( zPMO5HK&+r678sW)gV?|2YFC$VtVEgm_LDnPCtslQW*TnySy3(y-P}T`Du*Fa0Unme zWJ&`bF)4``tMZQ*Hk{u#qrKWn`o&oKMT<@dhE9?6eGiU4;qA&64Yk~K7ASOMItU(w z?gn}MHOY)Ld0O*AFZ-}LF!#@N9T44P5=oEHBy&D8+Pi2URTiXHlXze3MW3ul1QZKs zAcsMD?!ZNfu!k2a9iD|Yi8!&YVQVpJaFiY&UCh77=~9Rok=Qf)w#)jwq-Wek_1pUK z(4~7(h{%unzq~i$dpd>~BaSqqvFZ;SZw&h(e1Em+lt1HxEegphV){O7NsZ7L3ICKr z38>354h+y3#dyr#h`RV6BanQ=q84J3gs5qFGlL)l5292te}v^uWQQejZcb7Xc;u?a zj1R*+l$fEa+Q?aOfe%1bc$b80lzL?s6PxM?*<4N7#-(3YB0!ok7#FkCVd1;uHcK7p z$n77<t?2D021O|O<ozAd7wAwN%(YQZbcXi{9s(<r?KP1n26ib*pdkazexBxTy`q<e zot#TtiPt7duMbZap!q(E@*Zc$xpV2CwU@BpPx0sZa-2~&o1SYtV1}5fT)_E&16nn6 z?C`^IpT3X{S7W{0%TG>@afyH{yccPAdeDE5vnzgT83jbhK)I9A5Y!?hYN^d)$SU`0 z{~o=jIpgiYBG{dZ^OW|&=IOTlJPH4<L?(*TqkRDX4qjO>hZh&1LV7=VvZdO^p5?Yb zcw#jc(eYAU3Hdkl0w=6I|2SOus&p9kyl=_=ba@+B%SQ}5UTrnH6F>uHrYt#ajUe<0 z+wwdyK78=TVkbWQJVVG;MAEk2)3UieWz9JGy4sm43r?#BXZ?a~JKrE7ZqDroC~k+q z`jjg>%NCaAesktj&K;iqJI{_X9$*c>Jj(_6$7Pa1m=V#{odx6TVvQ9u8G){&t0W{| ziIbJP^ScDL{eJ(xOfWw<xzb%+G%7-#A9p|&JuUdT=S!lFjL}P-eC-XF!g_KN-ZC4^ z-djdJqb{TY#ORDq>#tfv%!O2}xSa@m=6J~Ke%hk(=dm=gKQjEAb*WWu+@Jj<CY_I3 zCMMXDxtm>}-5fn}{{TQ~QmT`97%a5TDA0iBP8Gh<m75`WthLuVvb#$aa#}chNcY|y zbK7)HrZ&Nnb)aABoEx^)K9AmRg$Q>CAinbenSMl)LfKkjYxORMIozZYbmI1gn&+A# zVxdRvf!)4=e#ST3w@>ZOJ|DH>8{opM5qN!_(9-yaJpQ`NJZt9-T<L5?CL^bmTeh&W zIfnu$FS8fJ;NFf$0q2LJHqAsFX6E_Dp&31d1ZvhXC31eHqk4AP53j^bq>kiFka@}5 zP^lfF)-3Uu*a@Ix0GwWNSj`XrC5#EY!w$Vm>qk0g&GmhZV{EN&xMXdDNpHw&u%)2+ z!&RR90(|iQM*_^H_J5z%$1hUaKs2-i4BGtz^hj}*$Ys3lrBxYnEz|NQRjTyO8>`u& zVGmbr1M`UPd@aGa%(aUU2INFdA4Y`UFhZ-1iWZcxH(_jX@=c`kD-!@0wYf&E8EH2s z>}s_U)8(KSxAp2(7UA4LzlDT~HRCqvt*QLzju&E@t@p~nII+4x{GS;StK3$XdzDvz zJCoF8_W(hfcaf`g9c4-N>41F`I8Nb^q${xVoqilvp4z)v5KWqJH0EAtr~cU|<R4vE z-Kg<1IXQa+7nZ<r<HN*6lDOQ%lAnV*!p|^zgt18H82XG|wxGu-YUo>Hw=QFi3L3(Z zi%-9dvpxP8b0(75S8LsVwrH&xV|M>3Cg~$Je)UOWa@XN%r^WP%xXJ^dzpkwHkLu=D zjBymq+^A!kv+>*d7s?Zp6weKFW#EM5eVE_^DCAF@1O+W<RCfO%qdqaxMef-kusg_` zmoE0Jqj=r0`m0^j(3n-M!lXz)K`}7W)+cuN;wlIqm!9UG*G?u!78uU-KBYsJchC>@ zxcX*LzmCz!qTeZS>T0F+na{6(ck;-3fU?dI$ieh-zfjH%_Jel2wGSFq+FtthiN4%N zJ<@jao|30>j90EwlGU5dy7>A?WZ8s>R^_m@Fz$eJzV(bE3O6wly4@_6Sok&XT%Zqi zrXzzKT1|Z_ZSlDTBtCATasdOCVO!U{`r5?}lj=dE$yb<h<B>TmOx2%Iez}YHY;72s zc6GPDgDO%42>xd#>ETLiG27<ZLJg&WQiO%S=1B;&pD)@`0wKme)Pf>)nVb&YmS+_& zcZQ_6{3+q)q0|$IUES(sZ~0Jq=c-!U(`NrO0VO!(NOEzjHhrEBw6MmpH1=%cb=B?- z-C*{4)3iNuB?fNl2{SgBNCtNH7K^zVZj2@wjd6g`70X8tBW1qvNah&1d$ubL0~F^6 zym*}gvgIf4fF<ixA6*T)--B*3Dl@mhH*FVe`wxfU4_?`>#{nnzfFgg_H-3p8fb+-u z?a^cm#;C%J?{sCbl%Kz>pZo+WRi~P$JMFXdwfFx=zxgkBDzB1C?p7sDao6REn|=du zh4NiCs-P!|DvHf5&kHh2T~2Rz6+6lz`kqpoNjVW^$BypzPa}YwlPdeHxu;9fr3q62 zq#nkn{h>+|d01#yu>NI_6d_WC8E5Qcx4q|wD!u_uayt&}IbokUxEHfcBKU6@Fxg5c zz66e&$<(}FaQR+6n&%fcIs+DUslNMec_go~yPw`Agd70#PjdsqlUg&|f0B~sE5b?I zDHJujpEa5|6>|PnUUA2&`fugz(+gqYz7iO7gqF6UOoSvm0K$H5YEjCE0)VKT(T7D- zGN2RRdA^2)+E4Ye1}se5Ph1SJwnbqPl(mAniz%YTRKOjj#42NhH1H7OV&dRi9Bp!2 z921Vx0FZTb>?yTChaakQ2o4^Pu5Wq2=8M@f&z0{)=P#+Kg%l@Avh&}vYd1QQKf#jY zNwiC=V&wPV`fwqCdFoy3W@)f(79Pi;<#hUd?Ht@i&gC|z^8yUbjMx+oehHa7kUF-& zG1LymGG!tOKaL#vplJMFng_#Fa4In9??+HPB@?PMJ=(#v6rKTbp3hCwYa_Wt+ZVzO z-(*)GXD{3Pq2SpqxTs{pr_OIzyqFLB`lV%$W(^duzHOV^_s$atl7F!Bz4t(?W#x~+ z11hV5!k=aCSs-w+JU4rk9#;LbmNS)4#UYlC18Xu1O<B77(5Kyd2P5$;!mN_Ex%@U_ z)V*YKAmr+^NFGK3UE8m*RBWAvw^;=;y}g}Ex>nI5iKYXeWIU^4rPbiW$+8CH6Jj}U zK&!q2Kd)me4++g7yT2LdZd1St&pXAm-5Rva__cwjOfBbg;%)JHUZogP0rVn$rHcAu zt0>09M@A#i$<$Fi_OmZfgX)8>053XN;(z#kNN{PiG2hZ44qfSl9r^~J4%&Mu4b@50 zPC{BUU_+O$LcqswD2WSnI2AN-ByT0pOqq=CLC-}zn<>+S<g5kg+kSC_Ce*J}<obDq zgIqM`QTj+A!s1xQ?U-WW<_g2xIR!t7S&v2wJGKQ=PQ&lDjelHZ8X6eQ6!qM)cD09C zV~y+cydB8<)=D-d@#*b986F#Jw5A$`Bo!xd^BJ+3xZ{0sGM)(0BealJ2rK&>87<>w z4zKlC^Smy@6z7fZR#nyQ(%gS{vu@Qwf3Pw3W$QgNEpyUK0})IfcSmRLxBFGk93G5{ zG3aEkW+jOcs37Rq@(z(9w?KilW2q4)Uph3E=$feG@_PE<<yu(%Cm-m$N83Bl52Qk7 zZDb=(VQ++V7cbi0@s_@ck_-0oD1W%WYXcoj^3iSA7EU6AaLdq(v>LY(Lh>b=_8EnR za~Pr?7tA|P-}j2dhhGlLBOO~~`fV*UOG?F!8|-0`0nG-~6UlV(4U#9E%{?hU7Nsx$ z64tWkgb}VR?)<S+3B&3r7N63!jMYwy#rY#G9i)pd8j1eZDu-9Wh(eu3l(=VCT_TpO zNJeYd$AYgCBZE}@wJn{lJy1KSqqOup$c!M;nV1Ji_3D1>1@B0q*HONnXh2J}EJ}LY z`or9T;-j*<DRwwDUtvM&w6SHRp@qkR_CBmFV^So(1az9__vj{j_#yts+RXcnUOTbT zV^^cDr=$Bfa0sCiPF%TS6%!1m`SlI?&m8x%43XP_e<8*-D$I%&fq)9s0(W;$;w)`n z79gh7gzU9RNaFv%HPm}W*mUVe`79n^jrHa};qL@FWY=TkTER$+eghjWwI7Pcps29k zEq~a$)MAXorB3Ea<T)`V(zD`gT+3Z48HuZ(21(WK5$s#F{-ZR*j1wjBw$vf{tX8YP z+Sp!VEPiY#+3Gx0y-~#pnG(}e+4<nMoYja|*2u;)o5DrHGBK0FLAbt1+jtV}*I!a* zMUUKy0%N4)e+|Wv2W9dnAFXb0ZWS}kVCV{<veGVKf%3pdGS#;Vi6;U0ZDl*(8J+S5 zm<0skI_R*W3*X&b4$-&)h#**Y&ZW>?j+Qy@E!@Zoo{vfk6ps5rNgMuw990syX|O4& z%9>3%qXm?nM{P|VUgjo4E7|nPpIxaDE>w1tIpsqIJwKJ+-V^4ELp^Ta!%}2h=!jNj zN1AvWW5uSo+-cyW(qDUn>$$qz+B>X$8~)uBk4|!~O^M7yL*S0Qpc;yBH~BjxgtWet zIPC%qCbT$NsR&ziC;t@Nt83!`h0cN#3y2fDbTWjM5*m>7$-S7=WL+i~$S4}$cuAim zY0NRuto-zF^qv9LzI9r6Bly*T8bzDN{lqtp!^(>YpVyUvFK{x{Ce(|(yBotO9A1v^ z{t(?|qQEJ8xEgB{dmKaQwl{K~CZqp6<L%O)!YA?HdFc|~jTtP5quE$X$@7g5LTA|Y zkOQ~U6&=Kfde=D_Y@%?&A$3yZD>IB1T^IVh#I__U9+h@C3g+A+Lp)3tLPnhFn)Bp0 za>Wea*<}EYG1B+e@U<=7sq24#Jj0@EiJGOD-Z1gOy6GR-3K7HV)gQU|1BC{5+)(s# z!z9sjpsw|FWA)D>2+VO<Z5S1$Sq8LvCLW60CL+R2Zw8+izPMZC`x*D4;mG<Kjk_PI z9R=3PZ_~np)tOP2Dj%!<&QsfFbf9>5)|+><vNGv|ig$xh>o~J6J2;SlC5u^vtFe~P z#t&#dPI?BOVA2?y`l(nl3v>q#Y&T?<r!~zCTPS~1^h!pCQ^n~1QIiAOjutuFIJ5fj zO~P8M$JPQ9MdP=og~BDuHwT_X;~yl>BL~++!{uphXVbg{@dvaQR}dS<VP5bR>`K|M zwix`?UtbK*kgk~u9xr$Dj43bVK?q|sL?2p@+T<5b;>~|a(d*D1zurk0BXUUr>2I!& z0!U!e;7^p1B>Ev={o)CRQ-aT$?VkEt_%5ykoTu9m+qUlzlS$R5>knrO<2g{tc1_vC zXP8JJGF<$>z{freacbUIK*>8^8{+=M%D*|SkNfsHXwUD=QNfTSlFxy8kQoaN)D+1i zAT<Gq@2hJNgrJS+qKc6Yyw{A*AQj=LP%iDVQya8t92X^uk~%>JO(mJ&7j;iaO1(xA zRFh>ZGL=$@fQmPF9k^XZQL-$Sp(u!R>5f*+-Ea8cqNfb(;15=^r|Tu!qk`M3Oj|b5 z+qN<Y5<yhp?%LE-cTx#>T)h5WWWgUx^QdT3s%&<H!cRYT!ZBqD^Yiu5kbg*uU~C!C zyz`7@s_4Gs<)G87w_M(KhFsR{>cW4k>PYw<{u89VA;~ep8k&A(`tu82kjLxF<Zm7& zS!*cqxNUxh^{+Klyx!jpE^@`JIvn@99yg&PG;qH6x`LaVx61JaKbd{dkD$=L2&=jo zjlx`KXSMMCLSGF|LKJy}|Ng5?t7E&>F6DTPF;;!g04XtWMgma@9H6J!Td2~&xtW)g zj8XF@oydYR{Z*2<`#XJUZ}MkDS0r4LoS$MI?^Th2ss1k$A*epj__={`y_5T7cM{Rk z&q*o}u4zZL{bSoeiF5MV>V1LYg`9S$#I<bq4T`QOEZP@y<z|<);xcnP|0&(6Rx<EQ zmowc=-?Y!~Yu<@Yl#3WjOE^;N&x8)1H<zqgd^ohb-;C<0_7qr=K!rm9XY!o}dmHQ0 zeJ!}PkaL`M(uq{ndEXfGqGPyCKJ6Cqerq-zy{#pZ@dUF=u+gZr?yCRv+Q@hKodw0x zXG5P(1VAVf>Vn06LhVmc>q^dfzQ-=ns`ijW%<qL0@Ax7cRV)RkGoQh(l<a;rlWOYW z++)v?=?h}_FCmYu`Wug1DQ4@>pz4|P3)8^sU45z%$-AR+$-8aab`9^hpI$u7|B>NP z1pBqRA>HMc7kH7~MYEA4-=&DxFUZc;+@U3|uJWudRW`k+Vd^hBF+hwl;drted3$Hd zuo*a*+KY7&7t}?rRe*RL3Qg?E8jVvx7s?uIJlbh~UopQD2oy0<@x!H{TYh7$&U8Oc zctP)!VT^3bE6(F?u`xfiJ#wMZjypTB;RX=B0Z7O(t1pce4A7vejXjadcH3ihL7ZrY zOyXo~q9W>eqOd$%%IO^$jxs4S#AYa0Q=eIeyu*iG7EU_a4NoV50XGvwNOxTa?YQ4i z7B-9`grC>0vep&j_H9V=-0b{c=O?Y%{OANkAL_XyHoOM7C_Hz;M`?wiSq-}O^rpRY z4Z21<g3}T((MCbn@-}3cfE4F82Z^IR$x#}v%vnQiVpJBU_H+?uQO%zpy1*gN0lLMy z|0p6gMUX9~pDG@5<4F<~>O4$T<tMgv&>8FA+s;^N+wbf4{zVvK!d{J?@!qTQOclNG zV-=L!eFLgu*Jdd%;vu4Iab{{acY1ngKdqWxgIrU>UmUOEGqpImcl(UG1DMh8ik9=Q zB60El-rCSgl1fSJl^tZ}dF^;_fZSZ|m(njgTo>k{VU!g$ag@A~j6`7$b(s?*_DG<q zZkzV>9B6y&nE5A<@?x(Ervd?DJvI@R*0?OuLI73Dp!(2W6cwBkfJ3Jl*>s^%^G?0O z0lCJaS)FZHZd(2&EpuL_*V(DGQ2)m?$ktS$%4<%*i%vNO6o-Kq7;rj!g1aM>z4CHB z%SkJgQ~maip3m(OaJAKEW@a`F8oV>A4m>*>I{bT!L)%?*WlP)Ay>zcY8wdo81^G=8 z5%D4z(P7e-Q-(OmogWE|f7hHgvJ`L<4IvvEr`kL0RPV)n#3G<va&hP&_futC?4b_! zcyC0Bb{%QlgG@NY`DufCjZ`CkAT9D^%ubCmN%mOp@2}}q9f6lvr9?M{eZE3G<k33Q z$7bt)!7dpglx^43YjkwoP5@9hL)&0C+LmZ=CSJff7q3aYA76Z+$Km`IGCZWJcwUTN zaYx-O#>4IDG41eQkt5-!SU)BdrxTJz$kw&?6Q?|Z=-PZN2put7c2o3AvjktNYo8BP z2>1D>6!&Uci*`|tb0RjfwCYx@nlTIR_=0X91&TAUD{0hzz$IYe+qNN95rS`k478^# zKR@J&Rnb<5;rt8Z&K0g{L@{Fx0)LLJ-u^J@|K*hNM%UTH_)_(~x@>#_imeu&E}pp^ z6*)WD%$eMCpuJ+YdzYAY$WzGU<pfCC{jwY%e_HzP-($Tf?EBdZ`F4-6Ue5VsF|7{+ z%`0YD4>Fr`z@q~_7LV_?f8W=ytNA^|h`~()6{>m<yBLIyMtqVDG9VxS>@Gm&QNh)2 zDaeVkcg@=ws3_8(#fxipIx9)HSFkF#lHo6PK7%dJeOjanLF;+i)44E0Vcx$*dr3vI zuJMeHnp4^N`u|ONyvqg!u>*Bjmd&1Sz7wi5|AgQAgPbA(@?}&KVhQ<rxQBjXU2TXU zzv8K)fOy#MRQq~JzoShh*GarjB`g`26SNB_B?RgzERq{%=&<^FBNFGgDz31E?J>G| zl1x-@L~mcbey?!RfAuRr&xdj7>#se{e#@%4y?^kJ7!s$IRIdZzs)^e_S=hQ86g08| ze4wJXu(M$9&qlT#d9Dpq+`~bu0-=9sLALLfk&wX#aPO>n7x2s3<&!&yn1qD*<L&18 z?LKeEyvX_O<?Pz$<w}Q`Rpxe}?XZ-bi|8~I_(6y;C7e#o2MR$WuRb(X+@|}_jN`S> z^5M4EUym0eoRC3(zei891H+u~;kW(-I2nyy5yow>EDsAQc$1k);G53;TK;b-^-1(^ zO%4d1*zV&fp6peYa#^e$kI*Yw%`}0sd9B!?I=g}^s;4xYf!1DfRgP7tDL&<ap5;}C z##_wlwT|K<o(LjCM|w~;eRuRD2r9bU|98YCa-rCXuxjgH<^oA(p3^XiP^)o!J)If* z=*-zP*qPF4=IufA*Ton2D7G}#KR>lasJA{(J+gi@Y;(j=SF+b%md5ZM>JC(+)}{W1 z2R!@2tI2$GyLYQxzp-UIEAETZMmyI2q~}dx0vAe&<6{+?do5g<fc{Yv?5L;(CO{~b zhSkzFy!)h5F)MD!b;<V;P|!9~+wb%s=Gcj%Z^|W9ci$Lu#%Hu9NpCj7DxZO%a*+3Z zw;P;X(isE5%#Z_$cmz0!IQ!E;`z-oK<xZ%5c1F~l7uv34DMYt?wBL*OuG}@w`?z5I zrAsC%wZp1Bf18BirmgX@3hOGBW-ZUb5UV9yTcJ;HhJH0rb>o{6ajOUC(QKo{lA}(; z#M%RF_kJcxb%-o$xysAW*~}&k7CEp@`Ne-9%1qDq*HD*Y0>I)bXXo@?%__Z&(Mk3i zM@w|kL1{R5H^ca+<%T33koZ*o`89hAmy-x7ne6{Zo-lds4^N5Hu>e80>>Zuhsr=*q zNFQs`O*mG;t%Tx^k!muN|JirNZ18gh_D>RXs0~Kg*fI<Fse3F=8-BoCv<p#e2^@qq zv))9kvP4lb1wO}ktyz>~ycS8O^t{$4DYMEyn*!V-tDs&M|E>bwDmQ7??!O*j<+6~& zaq?Vy*B=RJ^ZZeXD5SLqq0fBhjaS)qh-7irW^4bFA>R8$kH8k9hKfE!8YhWhlQ@OG zH~)L58N7R)%V=l<pQtFMreAP(G0n(V*^N*m)QYShqM`X|r#>;k6g&Qln<rIGqprX; zG<u&gzNRvU?Yuy~XbBDva!OeE$sFkM`0y%oDdAni?0n?F(vlo}%uq7^K6%X;K9M;* zVfYds4b#zCKI*Mh%A(f`u9sh8WOBt{(F+k-Q5^_>REkf`MP&+4C+!be)MWjcpZ5E- z@cVQNRn}zl#o|phTf4L3@T-XNFfJQzC2Gfc<-_Ui@W@qq&@Q%iw;UVa*hi6qO_bv1 z`jF0TzRMZHC!(9$@V|1&f_4)_)!Ltq?K)jXKW4;^3_Q+g@p>@W9}$Q~CqTZvObs^9 zo4_@$Rwg$W7L`h#Uod-HU{t$328Z{ogaOhaUZ(mQ3{|1Rn(iMYnp&4uCl2uiy8OfK z7bRL@S$U1~yJsi$$Mvovw&H(H4&yHBctC_yl6wY>xM-$ykP`$YII79$(OCF>FeLiL z<=<@y$k+GbcwYYGwWj6B%c%J`cMNf7xG>5LxpQ7wDaNM{o>*w_ty~581%ft*Lxd>y zX2yg5{yy6jJ=>X%{?}t!o$KgY$|bquMJkUlOP6!Lqh86sy?}0#W&1J6>jkfp8tAiE z_KDgVHwDnaj>EY1UVyLtLhFs7Fd2jlmWi7}8kn?CSR;W3=?-@zaLwT}mCoVLuBPHc zrM!D<29;s6h`((!u0cZ;+n|1PFg4gj+C|yrYQ0U|z1k~Ev>m_uc8?of1CTM@-@dmU zP=%Pw0mTRU%+`pgOZwTiY!yA(bOq1%OSac%%$3r<`~rgJhuM@(X9ryL^aQ4BvCYp| zXxoH?x^RgV*0wFPb1eqnQvKYjo{eqZZ5awEzl0f$J03!fs50oQe-pNrrP5RxR3B5e zChMwuy4hus7At`U-4`jl@zN&Q<%F(2Raw-ojQe1h&tB~x_C3uns|s^6NK(N~8*sns zpO*i6A{Ou-taeJ)_Zoc&jMPY_f8h?yjQjd;F{!P}u(_@*GLG6(MQ}9PNia=qsJ-Sh z6<~eXQ)MkB=<)u>rtiSBv8!8R)m4cve17r*)~-?UwwA!86LP!I*WYS+X4OmGd?31} z-#8A*Src(C2w+P2^QifBeikV56hr?8LRfuzX#2len?pL3gEDNB(myizp2xbc(-pxN zleFW_HUc(kL=-m;?;@EVDnG!d?qm<?OA0u}@ebGixQkrERwfL7R1&LS&6GDI0cF)V z=O4-CCtj0Y$OtZphYE?&`S&}%;T=`cYZVm-c_AKfE8aDi=lH*#ZNok?=>}*XBM}_P zcMFpI6%*6ALNk%cPxB6984Qvh(R!1(@3o%id?RVYpTY66#PD!wm$-_+LdA({{&$4U zw9R#Gi}c+eXcLDEJqBu7P_|UPK>}M~ACpz(<NKYJusPtpp_J*I>+0i`HiWWE*l+O< z8Cy@7GH>Lko>SJI+fM)DDNUJV1fI8S=s)+=%dI{1aaNOUjlTcX9v9p5+m!G#N+C&d z$!WJ5Z)U|M+YkgpHw9JI4vO#YP8$77s$V-K)$wC=X0u)(#b3|#E6yqe%xHSeda6>Z z=Y418O;)mZ{qYyJ;vu5$&o3kIAXnlKm#bTpi(>N1*g;1mT@6tY%hP-Pmy~|jL2%ih zTKutoiLzjW3D;>cgf}an;em9<+HaUl;uq`C3n7e%_XeQ7p=*;ogA!M16mMi;asW*^ zx&z!QRDc68sx`^Tq#acGqj@MaC4E5@lKykAduA5UCh^CW<FVZ@&R7_ZY!-Z}WnNWo zVl%7bbeM!@rT+M_y&Q0&(4{F6mlcqH{SocmrJ_$Q!3i+?vQeGz+%k(dE{jy~gqv*x zCreOakzknSfqhOh2}-K2q);ZXuiK1mca1dPC8=`GtT3Yxc5OMURjR0CVFk}Edk1Yf zcGS5ne+r0F=!qZ{0`)Qh`sA!*sdViuf;vLJeR>K=ZJ3QrEPHgaDsv>3|H5mblkR;# zGZ^_PU$$+dH=b&a0+{HH%J|?jGX!ACQqd@#@tFw(#dV<6!?hcYg{xe|L2Tut(i+BW z=PDZ+78s?IX4;RD@DBP3qxS-mYl3RnVQ;BOaVTCI;xal45B~kd&Zx`mhJ7uUJ|TKg zSJs4f57Lu-9_+;>v%0wtK!+)^4uG{H4wY4mFq-yjREOcxP*x&52~ez{Y;jCx#11lu zi0xW8z!kDm%l=t4EABA@8^=LZiUKQQmz=qb5!VTl`XSz@5Nz_8&uCd7uAQxp{s8I2 zA0x95D7*KaiP9LJYU9$VgNQJjG*JrZbVe42JISFIw?Xofo{9rxnUh5Zk9MJ#(pUv} zZ%R31S#|q57#>TcaQxxs@E<KWq#p3AwWaZqGA5BDsH|rN;~y*I&}P%s3-vnU@HMt| zde?v(N~PBJDP$o>O8mUQI^G+8zlr!$E9|wU>98!bP{A5B;{_8E(E2xP+DVflTAC)) zMh6qiPq#B~TYglpy@8c7%%91jKg#fE*}-z+?Zp>^BAos%>cA}J@ZnM>Dt>IC1ST6H z-0nwm?||+qB}6~HEZ}6cDGD-)Kcsbu+}WF{cKY>u)E=@4FvAVDFyl2p*Xxahe=SB= zR~=PQrX##AQgMbnt?q159F!5}^bxskLANf<C4hmAsxJDKuYkq@eaMh}@4~0o+b>9e zEvfc}f3)jes}B%Xa+04-o6|O{|4F*w7P~lFAXpyK(Xe3y&bB?-L5EA-$s09%i_~oX zy!F5c6SZH}%uE$aW60A^5YxmR=4Yu!XC?D58GY4dZ?n<^3?sRUGCzN23V4lknUY%; zukqa41ZC1{P~kQc(b{SdUuAl}EJRfwYWB_yxKxa^Q{-U}%GOwaHBJvB<$Z`9F2g_C zh57X2FUxx=BnALzAusmv3+A;H8)CkoVaE>n@?>3c&o8wU(+`x>SVXjwY{+JX63oN) z)1MpH|4I}P!*vyW5PsjS#4$j_qOet<ubw$&4rY@bw(Lyl8#w(CWQA%230%==Yxkk~ z^pQ7S)8eB5Y<Lw$cAB;Xk+-z}G3$$ra7j>8*x&mPR$xhc!`$|(Z2cXW-GSx}7|u+$ ztc7$(D$diEG3AL2KWd&<jo;$UW{9JyjVBn~zr~h%9@rIF#0%qIAmMnmU<REowHc9? zoF;52(TA%M-v*@y*+msss$2iW+B%xiT*FA}X-ARkbenqDM06tSopM_#Tcn%bcNQDe z3^Quv+x8jMEafY46TGYXVkyo5OIbqc_Ha&Fo`?sVYkA*){+cp=L8};G^VwR}`YQ{; zB6l4<%*(RqkD7o}XxK5YKDpqSH>@4M4Y!|P+C>bY=6WtV>5ZM_QBO$#f6Lp=-C%l$ zipQx$xl`5{waMCGVEhggQ%cZy3;Lqpq8tHb{uYtCdE|`_^F_0xLTODwGW@v2_N7)* zxdQ-`J<~{`qN_y%-CvXHNxlK`*&=B9x2M|nkYFE~c&URC583wV^LaAep%U%uly^#0 z_V1Zb3!2Yh>M5CB=c1#Fm?$(H?Th0h2fC+F8gao;ADf0}#jX^p4DDLFu@c!=KuSw^ zgjid$wDkX|Md%5kVN9(#3A*wN!hZbC{T;kyv(wi8rI_AF$+Z2qmK08LFZq!Qr3|1I zd-aYQ4zBs>Fijccw($8ER$9BZ!2&n?PT2Q$16#`b;*W(Dx_!jIF#6VRqe7^D30C%h zty#CCm@!B%IoL$%TOFs+ksI?C@!z)@$h%UBAEgi8`ps1@S#PHI_p3LA>G2yrtkbG6 zQX15pBehPy6+a^XxhL*1L2i09&udw2$R>(Y1LYe;oqKPISV5scNiPJf{P+g$f9KUw z$bK+tA;jy+KBpMqM+j%}7}@lvvwv;R_3?%bMw1=l2XKzqrnAcq#JLUIr_QaAwY<7K zYSvPe;P9p>(KbEuIC)VQLy)t3`$~w%aRuOH2YCAiv%@N%FGP?KoAYHLSwDTs44I~j zasFq#;}}W%I5D$`RW)f2o%I$A^S?N56z{O5ylinQ>A@UgaJ!~65Hq9gmkYNhvR@UV zd6a+K-hXEF>QX%WM&IlhY@ATS3RKiGShy2n6{N@wDswIl_!6)8ZsKD6r|jX%_@@|- zk2K3a5HsJNhTcm{*qWfg#?S9{|GGdpy)C;d1%G4MlbWH9*Z&<l+<&@kx|`hr#J{CJ zcJX1T$~_fZ9iWpwVSLi~b3qXN@uO=+UEF^7eb%onX8CwWZtr}-J-cGLujr$*p2v9r zDqPE?-G{ATvx?u~ni2in%B@k9O*1aGN&iI?5FO3_v3&dRObS)@#Dd#QRBaU$eN{5) z7F3B>ooH|j?ucEFnnJNUfL+vB=4+%LsXqiTKy8%nIWAuZ3|HD;Z&%8WG+||Gw;MMa zhc3Vu3BT<qhR=6PNE5^LUcgi+K%PgZ<Mb{E28wlIW#=!MLh>|Ea`8H8Eolt!iL9;i z01rR)*Z;J6BdIvhNwJ>BOFQPBq4iipj?C=7gp?);KfP;ZKvkNsmo9^S%3>R^6S9qs z_UBpTOrtkz_rL+X<8)!14I<bGV>Uqoa#;H<TT-{$)jK!-JZXDh8DPM#e*?Z~0zXp% z#m$G5d)y7c+drtj$dw<`o2%iHAS@K?()aC$r$hkp@c!&H0MVNGj2C<l-`|{uDD=NS zr)OC;Q#Xamc|pl@;q;2{&5_W$@>%S^Fzna(62iyOulz_4Fa!%Cd6z8%B)0nB0n22S zg||SHsB!lZ{@iMcHjGC?o#c{GE0c@2iDLm5zOFb3h~Ep=Mz4j?YdfUmxq(-@Da2VQ z5{Y%L(s8;qe(sI0&aL9FiFD_}3F14qL2m~dAB@|e$=G~vT~zN;Cj_aPy1}qQ<l}1H zun|2bjv*OjggqVee$5ka-ojN)K|U^4Fs$Y@oX&q@?JiBGSUFM>pSLOgh}mY3t*z`# zwVg*W(%N?AE1KRfuVb7-xsv$026`lto_L*~Q`b=I_gzV7ESF<haS(gn?ye(;a;P&9 zCiwvZ#mANzKZ8U-F&~?H8gytN(`kSBif?i>y`5?jrbUJ!i(=pQ**3f~Z{5c3$#Q6c z1~_p6`=7%x2h}|s2gMU?;@LaJBzYucvb21-x_9hP*h@(JS8poWC&D#|9XyW2K526% zgh@Mz6YPiPSM8&N4eI&IhO*FVr<@KLjXJYx<ZFB3g^G{rPfB<3OLH3TP}KM-$Gh@` zXII-W!IsqY%*8gF2;pwqn(u)aqn^@^-yP&v4tLx{+Phz_HhidC)90Vf&}jopU&i-s zjjK746IO#)M-J2=nZb%K6S3W%9XY_Y7+wf7^K6>avgnOC=x?mtz~q}0lNt*Y86x_> z2^-Ey!G7B(UvpYj$8>Oka1A<lKJG}dM2FB;a=2<|(gYGPd>%Nff$ei*7?NoNB7lD@ zT=Oe&db*5QzPu)b?T&)t%~C=r-`5k94`G|jMRz|t)1H?448E9^y@!3DhKR;f(%f%( zZQ$)(4~`s+d-(!kU^@)dVeBA!t=vZAw9t;9pZff5GoL$<?(!BUg<r%7`KzspD5TWh zfx5`~b`vsRM>pfiz)XYs)`y>d8$$Q2{SxHIRLd<FzZ?9S0G_F0R=-F)37qZv5RxV; z<zy3_*;vuCIPNFMp!~f0Ijwt54-DUa5)6GU_6(*2sa=?RT<v~1^m(~${w@|<tAF>R zYTwR&-Ki=00PCCluc^3e7itt|)EVt!)>^;v{Heb83lLbfh3+R~nx7iU(-F#WCkCOc zSgk1jE{DCnRxd5(;!wBq`2)@+hxb{7s&t%IlOdc_8YfZoPcUpQ<|y2?(@>4?EquwQ zO}6nJ&|!^E78&kAnl&M)Q0rGa5+9dDtM7O*A3eatEzOy$*Hpxkk4^J&E@2zFLdmUi z&12ZdQ<hZYp_~lN?vbeY%t&EceWJVfynzB@+k297X@k>v0DumKlCO6HCP&_u)>oY0 zu1pViNLwTA-uThT@0<p1%OFlM`9@o5X@YuOaxDcD0H=N*MZuMh!m><G)7m(oM_RAi z*QVE6?K<8*Z>#Jl|ExB(E^^57s(Hlum7kEjj~CJ-W1qYk2y@g=Nf7ag{ob~*%>>h} zisc;uf+RM7HXeO33`UTS(u#s>Gqkxgnseo^N4dJk!blBsP;PE+_%K1`1aUl1TH%=w zzkf|_<*|5O!CWgUMlN}1UG;)8XD+RkqL1_>llnbUvuMLfzZ4qB;Z%|ce8#~o!qFV& z=TbF6d`U#K?&S|`gR~q98<+&0glUo_W^&8?XPEeeNhvevxyl#~IlJu-lo8vA5~J4_ z%D!^<r2<{u|94sRec^)@LdaumeS_htLR6kVe_G9!RvR|Dc%`EuY`nUOAUwKljkL{W z0Z$b;<@2pXF<tZiagVQ%HMxwE)#>_k<nQhj^)8ixMmuxqYqAr&bvldW;N`47cDcvp zc8R0>ep!GHCG+s~#;buS$q7&he+(%!>VaM@pEL$oTI*J|f#Jbsycyg=1Y@-qCI7W@ zWTzv>eg~o>Xu6y~XBAWjw*1d&#GrLGfUF+;Qp9lxxV1UN*d+hA1G^`gr*FQOJQSel zCA`sCpe@#P!D~Y-5=L4zxU-lYd0)u(9Z){G(Hk}BU9IR$n!=$zgZigzT)eCh9irJd zG9S79U*!nRK~sAWe|q6iY>Y1!*xvIhXU={X8i+S+Q2xj4;kD5IbvtxvAdf2C74q7$ zJJilQd%&VuxXfvWWDK-Dh4$s(;eWpUv!0ack}HRbZ~!OFAJs{$7{=G92%>_z@7OM& z58WrZXx;{V>g<|D4%}j3uiVh=y<D`+)z0~y%?I4(ikp4dy=q$Dzp7uR%s`|)&-==z zQm~ct&SAhWvoOQs_(sG82YMbQ2<WL*NxxKoZVY(vFE{sUOYiQR(@Uz_YbFkTQNQYR z&i1lX;SzVHsDrhZPk1rG6uYD*$S(Mkw^XRVqNzxWJwD!A#@vMGeLZ%uHf`E#v8z;J zrU4_esez2bPk8QjCgz!maI-%ib8TyQg9j#_59tFgo(*7uNx&S>0OJ8-8`azcCu?8V zxALu$P!73XV7-rEt45y|A#sE_(sl_N9X%}p8wQlUkU<HnY>bt`mCpK=z<=rauqd0- zn=afnA>B+@7+S{vOTvHB>*&yt+4ZdRu>XAj+nx87+jHCb2udaO^SL<U@VnS)!O*>@ z({))S@p-_3Jzl2}F5>Vg9i*rT&onSQ>T`*NE2k`gtL+$JR}J@HQ`}i1w#O<0x}Bpe z#NVOB5^fHlDwiCf+sp%#&#eR*NMc@iU^hW4gMvksnMb5;u85J88%EJT3r)O&G-H*e zPSI+Z^_+dp&Tq1u70Q2^nCgP@$y)%zR(Tut@uJ$m`!%ZoF2*Lg5_$UqOm8N+u_0P6 zk<{a0p-WdGb_L6guo!0}M=>m`AdQJ~?9St9O>Qnq%0HWBigD84xai5nShQ>zA1?k) z?M@qEx_TLyf5m>xlZ;!j{v|!hT=0mX?S6jvQoP>OwOTTtm_VGrRO+=pNnMR?i!{O7 zo36;O<#9Bftq^_#8>WaC6F<F1r8FBiYqq72@0Or~#}G9$O*T(_&Yjt5k`?T(zW$B! z(RoSXLf!WM!=J;Lm9~)(M?u^#YqL@2K3&evx<9VF9J5#~&5f4*KENq#DVf^ZSt*)i z%4092YVg{vYzb&l8AkWIkH@<h!m`jy@E_miZ8GDyG4JYH{<qCE!AY36o`DULdYRV` ziO!0N$nH3B70wZ15alOyJ#+Ol4c-kBA#bP|XiRXoEvi-_%_$xY@nbm+`7U+-LJQDT zF$}X=KT;s&>mVL(wh&AV`Jip&`elNv_zi+*c!6u9Q%Pt9a=3J%&$WOCv#mDzmGBPl zHMHm|b@DDHw}9wPqfLR71W%)B#!q`}BinjeHvK63Xv(sWx}mZp809=L$5|yq)i&&H zL3r@wn9&;9>YXr}@b)dHw9W5Qual^ePmhGjTS!~rw1nM+0tuWN?Bn|Es>40Yy$;H& z6uQznnapV;8bn4{yjxbRn?JEYV}L8VtKD2X^u<`QYf-;}iIGFD8v@G-X<^L`BTXcL zu@htJ{U@4l^8WOI=N3I)(yucBaec8nS)H(RdAGKkGI@TQ^6kH;t4ptkic6gPv;X7h zDg&Zwx-f`<G)PK!NQZQHBT~{LNJz<&OLwy@Al)sotVl^C2rOMnH;Z&Fx#YL+_kZr0 zIdRX-y>rg<3^GFF-q6GuTsAOrWCikjPMSC5wy71o!qy^wN5$0*W`X7E=D2pUi56>a z27H}+7gzkIP56s9!*};1c3XzC8bij+;?pVd28Ul{uySF?h+s3NXm0S1v4oxTMT^Qu zOYB-_cQQU)J-XyZeq6Y3ai0`??&Y<%gbcI0Y|>Zx0xyG{kh!*CL!Gs2`)4|CJ`_{D z)?Q3UNGZW4U1rGK1W~^&z2&<DjtR=jxN~c$wOlI4ELW?W9+CN}qHOVM2k`tVS;2}} zx!GZl2X_9ND0T0+_L(+HE2*7wi$yIWOSqZy{CTL{8Yei@2<ts1VDxxCJN@6Z=|5~o zF?*%1&tP+I9c_MaJ_gV=kPv7m>>Su4fhNKK0-GqjkCr;z70LhMIil9P^^K@k%V^9B z#rGtq7ky8G*9|5NgSR;-1+;F*3=SrGB>_TNB;L|R#`n9Hla9k!O4$Wz9QSX2U20Yh zLeoH>RX{Z%VeHR0wc4;y#H<dX(n77*=Zx30agt1>T!V}!iN2qL&;UbDU@_O855@tb zuH0W*PFV&~BuL<zai0nv#Z3C1e9TtTbdJytU*>GJ6NPofh&;+N5$T8JI8gvvnjlQ9 z0<h9-EdV1Q!mOD4x_EauJ|)&3bSpla>6I+Km!S;S(}tw={T5I*9%SI69s7~&T6}gl z-^ze&Ec3KU2)rRBWs{)h(XSzOg(;QYf449~@Cmh-*4*?<9;r$FsY}nNM=R%1efMv0 zf<Y;#&CQm;&03CmcFrMmS*vOy?t36E{F#5X2;t;k<Bsyc7l>Iq|Ic&?P{ZPH`!6p! z+MPev8|OdVemA#YjGdOzi`c3Jh2}lsyv-eU0?!zn{8jWJzg}{|2k@(mmn2zA!l2C{ z3+#XRs4hlAM8wv~PH14de8I(<)3J@1;$3JD4}k=QYE_ZN-!K32T^FcXa}<E;;J%bV zg?FsvqcAo6kVOKZF##`Ijq@(;$0g3TL<pyyX)k*z1G{a(u%P*OG>IfDpOL9Tz~cl+ z-B)7W`fV^FEXqpfgOk;#;<xh0YK-nI8d7DLoc0P*u10utxk}(U5?>!gl{Zx%)Q_)b zmwD&Z=g?)p%Dd?6mOdjtw?t{(4KM6kI#c{gCxPn$^n~#(jWfo1%PZtGPs501l^mww zKjJa?#%;XdHn;_qg<iE65>T0NcH=z=!e;*XPxJ20=dN6g%w9%s)%Ik@w;`3x8U(}Y zO!DNk+G^?Fu_8+w<lT<y=I7;Wj5EL*%B$I_9?r%KytSPxZ@d}&+>sU%wTn5bUD1>T zfW|$Yr9Z2B5wtq%nZC;rS_e55q{=@UaKL?a(1ag=L)O;~#c^UWjJ`%xMc$i$rQgD< zR3?<JpD?mUDt1Rfvf5Poq87w$Zm-QpJR$?QW^l+m6@X3L`+iDmCRES0BNk-WX}fm3 zqGIp&?@|(8Amoz%uY#)+J^Zbm7;u!If_Myn%9f3^zU1;I1F6CD(QvpY3zO%sv9^($ zouDPRn^V8$WxsX39nH}@lO!$g>Xkw&<1Jy2M=w>KR@%ozk}YUV=shiX2O`K$>Eb<L zD247Zn;TEivm=w3ui%QejF;C|EuS4jo}{=$0&AG8SkAdKJRwW>oo##<+ebxoH;*Be z(9}99GXJe^RF+1vIG(ng!k8LP#mKPfT)T&Tam+LE(^iaF?YUlk&S%F0bJpxJ+iX(z zL*NO|V1C2}V1MDk&56-LIhd{fPU;UA3G&)K!io*dv6Ax~?s=DD5c%_CqyNYJZgu+> z9R*CSiYXMB^nUorgqy2Pu2rCq7jmJar@WT$k1@k2s70sv)tlze)c?3p`*m2z>OTsV zkZ}azo1oqCLn~tEw}La|xuXQ%v#6YB@yi=u1(f`~Zx(t(G%%OCE!=i52?!0u8JS@2 zCI5YrC))J5y;Y=#1J`J&$o7VpwFI{%dHqB0bC!to>-nhTb<g=z54+6WN=A=AQbKFy zE=!0<4iEmM+f<LJGnnD-%0XPaORjAT{umUxE)$+j;ot6e^Sx-F)q9Q%P=)I}15QJn zP*icxyGo_j@P}>LUuR4+Q@pJXy2-atdlc$)d3eUSQ^EB_1Unm@*S$G>fnbNa2x1`k z$m|LAD%kStL4i0YJ{Z4ktKCy81K=7OAvk~%U-C50p@VEdXZ1btB{TK+{&-E=?#2QF zPHUMoa-W^BK<m}+3hFs>j4ew~xxG|_16Jf;UtOlble~-XOWdz{QSmP^78=MXRJK>k z4r9|YcE->bdCNLiRv4&qkd{f5$|uwSnyA+?NOe;YHaO7wbwhMDZZ+pbh2IzY6I=0y zTp;isABG{t^94ioBWyiAX<_(-cabj`oy#_Z^POsBmT4=SY{<CzGVydHEhlletHof* znS_JixO00mhlHr_dA_D6N|j327Z_^vye3QLafGTEJ5$TzubHsjTa||5W+qm*O{b%% z5j^zf6Qr=T3`s=jv@nj|4tHWL0}cWXOPj4IjJP)wu_MG8txVRzQFJm?R^<d~$EjIQ z_SP?=o|OcIY*5XhMk=@L&?3{(w;aylXZR9V5vDgX2y-Ir6-|(|lWWc^Gi=W-1wdfv zJd^Fuw}v9Jl)P@*veCSY&$nN8XA-h>zfEfH>@1)KPBVd(if$G_x^Z*0l_-!$jqc}& z9@|hVG19?`M36fAkZEi&PUNV&;|Jsxw&`>~A!KXrK(HWsHjOas-hE+SNA<6*T9=<v zmL3L7Ze(1*$x+6MEoW(g;Ft#eCyzp)i{@cV>0fsbqsFhv(X%W$a_wnsmPMO%YX~LK z{Z&($_wE2b?1>r_5Uus)kQO<D4lijLO5uPg3o|CqRU$c2RF{;e(yO@aK5IV}w5xT) z@AWCF1f)KhnmTyC9<Jd3k!CllH|?7KVElJ`v&7OJ<lZfC-CgM6?^nN+<g9TpIfgPQ z^oAN`A)H?%0g&!kI^+lugYI+Sf68}PBB6!ounoE?s+Q7H9n-r>wb1aFSYEVf$Y{oV zBjpCpnXXAE<{aIVs<Gg-#4~h#wkgcdRimJc@*_tjs(&{$=*Y4<Hi#0kmPPKVK%mcH ztN3!}AM6!;@1mhB-ElSrW9Y1&t0*86uui7{!X;gT9a2lfVM$HRO#L<!puh|}n$HQF z;R<et>~}iTjh=8&2Dqc)pE6hp`CX;vjth2TrDYc7HW7Y*2%>d9gg4D-Frq4qQ3Vls zEJQs87AqMMtDH<EjI?FRT*-KD4{BgJ67ZnVNa9rnPYg%Iy`I)q3K~)ck1_emaqLsP zg?z!ltO<lhOFnq-kfs+6KJpJ%I5<g|utG1iT*v`N*_|GaY-CB^m5~hy{NQcZbWK^k zWxr|e;75lEIGXR>ubUlqW$XL=*G)l5Me{ni!ot8@D_#`Dx>VU*-K0t_sOw~|9QO=R zYJPUvw!!^vSaK!Crx7>U@8BjbKjW%gyoDU_TFh%?x4<BuOS9@X<dS@@THoqT-n<ht zBxorQDn9H~F_>Ixx%~}SE*=veaGZ?en!dm{c52}7=JTypf&cSLdNqk!LAG%NznFEP zaY1gfwG3>g?eYz`H5`VaF~KM={ZG96p8{y?gQ`DJh5+(kEP<raXy0O0*|d1rEJ_Kj zu{09_PdAG?X(7B52*Fu=*n@)xzJ{8iXIsg@XHZ;D#@8C*zC&jbiL(yvIzrM>h<6#@ zTC7`Z*ODIVNrG5J6r_<-pWH&WrNYwj2Rt4`{Y*paT@s6tU^aQHDiU7_WH$Edwc(<A zGWjJvw9G~6z6eB`M`~^5(dZp@(&{WC_xASNa`fF!?H2ooI<YR-zr%XTjjCr5Hr<Pr zlfXL!H&+mUZRmZl*7iz!y8m|9?wq&VGA+#AO6&H?duxZW`&JAeLbN%kM$>zGhX!Nl zx=-0UVW`MoNu4dpmOwa0ORo`yopu)c!fil-l9tahuqCW|5txh|TN~eSK|-Pl&1*Df zEzeAMl%kpcjdIW7gU8iB)O?#~n?;8=6&c%RweJAXfZy~9oM&FIJ@>Z{WMTqvM2(^# zPZhv}E~nOm(HO3Q561LgnY`>K&r8a6c3Flmlj0O~^FxXr2@x)S@_M2_uSO%+(g>5> zFa}TdO^kw9952a~4)$mqYyRfngIQw6?S}YIWGU%wab-fJrq3Ihw5R<=8dRL|-F}~E zP1h4phMh>He%MJ#HVj#bBF+2|#zJY45JZ7cL~B*6`uRaX;$<2G3b)L4ATH`1z8=;3 zq8b|FH6zK)=@<B}!W<I2L{N!v47WtAOv!lS^5E^-{R@O*yvH6^kVu&}7CIbq-^!_Z zo>Wxwjj{JU2nzWUcs_g!El7v90MUTd7S>P%5d35mQ<y}D^w5-QXM<>*C#>|i#DO@v zwl8J)&;f!_kP9&42texNu-(!P|HlYxK~E5hud{Ia2*y(>|AreF5x*#@6Sly(E<WX9 z#y{5Qi~+}Zxm^`1Vun7=R>dNPj=(aNX#$o1T%>~En8^Db^J{R-`Q9=5zH@#FACC!| zsYXM%au#W<eR8#S8k~lX(7|R*CXK7_(O?tF9(t!|a}#`pxCjxof<}rlULU-}bhKVe zc`4cO&2z)IBn#-PH(6Fqk1k9wt?^wtoETeh%ll~hh-HCsm$j2Hi<h~a9({t4w_U>( z@?CUc9ZT3K_?u^NQ9B8~liF`N&svid_!dR+x0~M+A_~4XT++j`;hmu!O(lHz5RO!+ zG17xkj&jVmvO+ngf>o{HBB`@M&5b(t*_ZW~@8k0wLtiBpe=vOOfyT!uNiO@WX+UKl z$-QX2oQ6oa>!sMnk#M0y6Gg+jO-7ql%K6xpznbFxnJuVlf<ajBK*sZ?Lib_KPPf4d zN2`z&hDKlNC^rOfFRsI@_~$L{ir{*Zs~)r52+w(mkE_5yFdu?|$a?C~xUkuae9u{q zwDr;aWJNRRh4T2*JLeI$KLN*a3Cm6T!=IGk+^_PVHri&1j(7HAV=caWAP%-=li~w! z=*+AIB<t2lT2<iDXYW%g_mHo@D7y0-^laN$)V+FNDD+NWYzZ`^k~!qoYNof`vdH_2 zOs!2f-uy4;vn!>YYA%Gp%w?dKXiH0M$LRSY7ikJqCGXZeg4<(j8S{s0tc8$e3XR6x zX`AHNIwK8YWX>NMtQ2Ssq|4AZWzNh(Ou1`l7LoGF9gdmCYH2j0LQT^8VPpuJ?nF)6 zDsVsG1_^*HQMKAg?@f|1z37Q+yu{TAAm@DhO|jl&ucf=;n0XC_YF>A~IG%81&yn2) zI|#ILtp@(`5*jYsS6U?oW>rP=ftr#n*AL#p(;#0DJGULuMe2u}l<S%Us#Zl8c%jAt zuD3<Wc_)p#8%3_pZbq7&9jQVlI;2jV)~?3P>*LJ)=g40xQ)EE)LemV_?%~oJXp}Ns zE+3||{lwrKHefq4Ax<7hh2nw9J+!Avre{%ug_b{1<rR3w$Bm*Vi@m99X}B1DFe)A# zgb|$s>nxW`-jW<lleWI4w3F=q_3Kj|H8YWLlts>49EOER=FAvaDxzt5vnAIV*1>zx zw5V(axk&fh?s#qarplUriO;v~<I&*R7>UHI1NyX;&(|+=pQSW3EJe_;uaQ}I2L-&3 zhsnjkwzS<(o*#Vbes)aT64t*JQ?ZOc+di)JFyuy&LNh?xHY*4a@J@OjhJl%tvo5`B zw^L?tDK4Z24^hQ5nytLtut0u=WFLGIG3cZT<2rvkyWBex84ClJ+e1F>(Y^B-EymAi zq~~y<7gC>Yd-Re-;Xw?vgO-0$Nic`lq^;m@;YhU$PVmywxxarkeNK(Ly_nOo&}K#( z*A7kgNRgw=oi}yZwwX}(6C*~3+7%W4h+7V=8_XgsM|}5PVFvX1^-@VFh!aP*BqhZR zR=`Yziz?B!8e%O-lVB&<#1b48b*1&FgHG#;@e@~yo-VboH6CdzN&ca#yzIL1fwnKr zQnWxqwhjJhNjGdl^pjSfmG?`EBJ_YBeKyCchsm!*?kq7t<|VC$x)PlODq#J=b<OV| zC6A1Dzu|EoNm{2mor7*#-M*nf675kubx9=OcRN+MQz@h|?*=P43u-X=nbmf3NUsJe z-?OtY7Y1cfQG#HCz|WQksuO|;^qsaTXmBYzgVx;bsDP^c(~w(|twGVl{MSa3Z?<lX zYu%Ovd^l^V{daL58uzi%IxkUcCq=#xHRqr($(33*e;6BbtBPBu5)NWPd|03=_U@au zXk^G$9RGuj^!$KZ6)T-fH6gsfJNAz9t1l_=qXkhFyQT8u=JqLtoJ@x0N6Z$bgSF*_ zF=e;JoK+GDK`}xi2dG$gv479ry7!n?a4yWDkYix`)PFWjWRE&UtFwxisr&V@n}G#= z{-G#H#|$%RaPW<DkUbSkQ6<b;FA7%AWdprK-U@dX?%$Klmyjpn@mb|jQL;othD!4x zSR0OJp{Y(8zg1+bAuDcf1I<jM|5scPpsq2lI@YQ>v!eymXauc&eD;dZdbzs=={7-} zBCJVI3H(UiZC0TXBZ$~=Xm3?tHdh7>yCyCR&~pGnf+bb2-th^D#uFv${Mz_xbGOy( zrm3nP{B%5GPQ%$v95#@q;zb7(4f<rk>uaej8{T!9I|=94fk%@R9$pQ0&hq=X#QVxQ z9Voe<IGl8aJUy=7^sl~Rks`pbp`toI#gd2<ewC9|5MO{d3C@Wx-XI(OLgc0}D3~Sk zh2+pkw$WHLp1|&K{UMD*YcbtrDzLT;_9V~HWEB+nx9SA~60`NxQWqYGl{;IyiJ|PB zyv^v_`sg*+h6P~$dA3NV;Zc(GuA8#=+HcmshSwTrSgd`eZuM1l`{HaoY_>Y@)g7;Z z$B=f@F#g|)_o8i3;cJ?G;9bijgp%K?BM=Gb_5ty~R{{I}&g*kFP)48$2P9Q7yx7VK z%c*ylv(=@u406@{dA~^3wco_W0ro_^&pr472{14+nu%16d#7T?wNzd6vJkhO%(g1k z%q+FE$6G}M*(|xz8t=4Pr@1icU+Xu0!?XEoOO>YN)io()o|9_pG(o*@VGj1Euc-xz zkfyo=ojc!f|1uytd?L{5;c4#sTo&NRlHuJfTlQL=H%F_p|HCg5$oH&IUqld1Tv=gK zN6%NozYL|QDL7nwitUw`+op*3K{U&JXsiD42gWB{m%pgF`x<ywVy0Oyk3sEQQWrP0 z7sBj4Q~jw86L5U7e*5&s<@3Xo*VNC)GgHYjZwl<*pB4>9HlI6_w+}x*-zt(?aN?1e zFR+-YmCVfem&!cUWVD~a)HY+$@mrCu>0_mK0d4+Sah|d}P-dly&=2b{d&xNIrHPBh zcdD(ODZxqKTa&%=dP=4a7Zb{gIbK-M$Dpa|0T-X#*zJAtiU!G&zuP$wT#{D7hJvnt z&IZQYa}|?V-Opcth-021Pp+!K>e$d}O)p{833$@#(LcQLEancpwEb;HeaXPvhS2Eb z+7;6M9aMWJ%)0-kTLW??On*dClB0VWd_;OMGW(ekR$2N}{jF@nT1xwWdL>!t#N~2t zpepsh^((%u>-Bp+Ud(^?x#V?~I%!t??*KM}_xG%COmQ~O3@4^`SouVVrv%@d5TJF@ z)7AFBj*|$k;z=y5gC;SkBw}y);Q@$XnUJwi3>*6VX(trVdiNVZrgPov&}DJ73Wkp( z4629dd8M^99qnHog-!Ttqf%!(8hR!8T1_zrzkt6<X7+M$Ssw@g(-W>q*+_6yV4v%L z)lG&28zE_hg85aH#M*U8(;6fh3V*QxG7sG6V1EHEoFhB9*#-hspbxSlZS^0DUAexx zxTku&US6qwRKxwYbQp}<5{zYjW)y#h*^8B&alJ3tx*xL8_3>=Auh}Gl6dN^b78uzj zip>ov&0@HmjK-NRv>`Z4T#?-KLslFYep4Wl_boqs`&WGKofz)-HI*Mn9cD92m|+~N z&3xDJe_YHV(q!<1Yt4XUm}P=KI{drI%iJ{+>)hUFQmS2K1oY)>yZAmlKDl<wscC^B zA->&Z!UI>rvO56>qdI%+Z!bq>Rv2l&b^g84|3IT;kS_nYZWfEeQskp8q}|r9yh~1m zT|?J6gDj<BmRkBYpJlK`l>aGazl52PW6d<^_RJXbVi|-R80u$Z7FjqIWoH$qS@kee zJSYUs-D6$&G@s{1^12vqlmaJ6SM2UN#~>&<m|(dvMFdW=S*G2^32Z}r@juy9>9Nvz zkR)^GmC>xiQY(+nwfJGQ&~Z*2`+D2B_=POul+WvIj_(#QIE`0Ap8n1I;lC#JCy0+H z;%%KK_pY|;5~B_wL?G%eV^Vz}x=z;~D-Bp`@U$rSdf@LrlC)1>H3<Q8;fBvzWm-V< zEg&{eF+Zr;YX?j*A!LU*T$`1gZTHo|pPt&x=?XoaF{3E0ZRpC4u&mz{O?v9vX&gQ8 zv@_3CS}JIczn5~?-Tl!{=GNI4@eZk2(BO$&SCHSA6)3I)MDIx$Vf=aSwx?ls<3<i0 z_yyd4tXJMJYm%u>ck=;#-0%Ig&pn0$a@*Q)FMDq}hH?J=<M`6&@adNrKBPrx)F~s( zh(Dzg63Oe{&}5n<IXu{tUDEy0b)S?{Od$wy_xBUnInkFaUz|}*8EztROw#IH)z+cf zC47~)BQj9SXIJbshv(|V%;lplt3ArKBr4ML&WG)SZvBx`c6rx+i-Xo7E|3=Hy9PSp z+r1fcm_IS<o|h_|osAbrthu3kS-JN&lHKo5!bjXNS|+N+GEFY>MiuC^xyZ%lKtDQV z3g7Rj61TSc_;;s@?X531>o#?NYFT=FLto%N(8`|c7WxQf(@tpAXe<F2^G1O?6B4DH z&=aXAp`%05;!B5%K^^9$aX0u+JcN7U3wq$BcZysi;ZQMGSsjP5F8%p_Ec-R1;ki~t z!w-P`Z^K&%L-^?ExR05T@py!lfSAD%-ie$inI*te(@Yecw&gV_(?+fyZ2E>8ZXo28 zU+iu1BYM{1mj^a{Et<e4ye|2j17t@^G-|sO-FFoRwTu&)Xll%zz4u3PQcIM}bc-{~ zQv7l1?0GD#W8vQ;u=x?5N2_PRi1ey{Cm>9E9uXKnTR6owv7RCfe(Z0Vba!x!5yWLA zYGc=2DM?Sc+)x_z+wKqfR`u?leeLKU3@FMX-%3nCBx9}eDM6HzMWRv0#PLDr_urX| z!Q7}KE<?<m+#1Jxjz-xqCP2)_&wuDZ5xWDQQZz)-LGe_>EO%txAkydkQS^NFMcZM# zN;(wnzyoas_>wKV*-y<h8DY9Y%YMXRdG$E4OY}T=?dO@@2G-+~Y%U$#Go<sH-=Ek5 z5%>Azk%nLPXexELKj8X07IDwWG4SM@A-A7>oIwMpeRHB}lPJCG&&k$!T$y#GA<U!^ z5)Rn;No2J^ODbAx0Zs|8%f`y76`Bom;cGl%)^*?ycybUK2|LT?PyoF6QfG&a%#8@U ze30wrer%N!*M0;tBH@hzCwuy2)_rOh18($Sxnn>0O?DAhGE0aw18nF_V1aixhqIrB z@?#>ZFu>j#3y9a|Qce};TR7YyGO)-|MkG-`P8`zK9kg(#7n8?0$23>V=&J_1?&elp zBLLq+1T<wOj=BWnx17OURH-Hd=P-`-#JiS=4Uhm*UKfPA(kjd*z(pNpUU?$3pLhT? z(a{<3f$uP_?dV9;!4c7a;%J{<_kX%N7w2|aV3XaPzFxc8x_L45=~M&*_R3TaL*iWs z>X-X8>#g&6mB^a&^`>I**r3M%fb6w}J5ZvIWq&F6giNJ<iJy;mrN$7|$4K2AL6U#Z zCFtXrPs`w&DE&p+@%Cc$XJw)Oo}CwZ32lSa$k?NIf>8f!D}hDM3;!t}Cz^t<a&1TU z)>n_tW8f_`2@AxbEqoh0^5-|l3p#uR%Ob;b;4<X1E8O7_(6s-4({I(F&OpXMI{b1D z<1B#X{*2N$f$S||>PeD}s_fpRWbnXq35nn-#zK_l-v%&RGg-Cq18O=xRiJ%!s>FPX zJ?8|*?j(P?LqAkuKj19!;Iu{sj&n?2+DZ??f*x3YKWHBAa=%aX<T)ia5Pl*zOrG0` z_jiAP{Bu*ACpsh4ICBsK*lyNI$l5LU48EjdzT~WR&7Cf73pem^#Qm+{pLDj&$T8?J zhzF@bMeyDqAbUHPoUvgBj*T6SU}e@9x{vO8e&U=*fV9Y~X%E)W^p$Uw9QSP(4~5zF z(ttR~#J^_}AI1_e0fMnu3XkOL&PB_2dh)uwhV6(Th(fUY@0%O9so8&v(=-bTgdlT1 zBwPm2(fgiWLgLYtOd3(dU4Eu;?C{Fw_t#+&J{@_axYTdaU}1CM+kZ7GyRD<;3&TwM zD_mQDjCP+!_i8UW&b57NM$_HH{(Qv%?9Vp%xOAFZ3aqX86o0RuiW6(|O_|<z>2bV~ z><(;cpOO*|AukN=Adn(iUJAADo)Yb!ipPe#RI?nZk8LMy_nN#oSzGye%XtlzGB@WY z+|6%lqC9h#A%azI&6Ck=z10PWd=`K7M*~j&otDs(^Q2M;MmF5TJ!3-E3Z0L|yL7t_ zOe%#<2+noNPggw>`9q$xDvK{klRNUr;py6p45zS@Udm>f{ixTh!Izmvkf{0JYfW83 z!9Tz8a<!VKV`VkybJo`WxFLpRx8RpR_kXyqe0AzF__>e3o}IJeCfsjoD%X7EHItZe z(Ue9EBEs)?_)E_7f+^(bMaro|X4^(c7PAE8N>2yP-F|JtO+R=O8G0;H)7jEj<XwAb zsb`-JJm=5sd=gfc*lDxrgL=pZpH~n7mXQjpQ-|AS-ev8bqTd$<v#j=bV*5bO?wHXg z=vJ0xEpILJ=h%!hmuPZUN~m0am1AG&cVOHh1YjvG5fyNvFq1RddHwcMf_!AJkqIH# zWFV(WRuGi70iYXUsbuqmE0}28(%V*l^;K+gEg9=0$5W4}6}C8E{{zH5FrDBYe3)mO zdux|BVHd9&g5R;6;PQBuef7cT&q*f#kEdLY*ZQf;k35}EhaXT$QUFC^+_sGeF)8T$ z1l)Sws$t5=!Nw!!U&+fz=`vVD-G;ZRKN!lZ_B}HNuYqiem4a4S+&w8J<Wsya`W+Lv zB`KjhOv<vPCbtVk%(|c;n<>*ssH65_1?HcL3izUsOPE?{-l%#UX{C0FeTBCTXb?s# zD`W=TJ}@z6uG~|tF|J{wqscHUAYGW|h(2ff#7f;%5uxe8-Tc!kB4;Y<64i*VoGU`_ z;#$qn+#KtrHmqZR{FE3<`)ruRlpmhmRDc0DTs}4~t_!{4CUvv^TW|}YF@x}J1uJl% z?;?Rex5w>T_$|S{f*7kk$RKQZ>RhyF+3SL^f6ytrmZx5pkmZ7X(QFoNqy-=A1gV)X zx#EF>iOyDX3aKn%5-sx`rN4x1d0INfSn%<|l4_@EyJP39^r3I6*~GtYgy+{yFOR~{ z1a`_vj;Cz-b^Q?I(lz(l)ZLO>BJdNZf0$}$$3^cI{X0cZ<1@`)1@%wD#J)ZwElk?| zm`LAO@_hS;FCzN;Gp5cIp_;CtU53jFDTZLYhLe37uKn=9O3gT1!c^-@(*vM10+m$K zk|F0*Ucj)!!K_E2(KG7-i(m@TNSqv98DT5O6*UXrP9Z&Z@1cQYg2CFfnLk=BdY1}i zS(Vgi&{=)nj~k5@_ny<SCKhObZJQS1*ZHi7#-B!VAx}66+nqP)08eai`_eGi+N58_ zBgTe<R4<vEbR6vVJ!7|N;3<W#PryOnW(6iff@XtGY0^k%jnwz94ohO%RUi9W%C!_J zjsf%Salt@<u;G@XY#9GIN#%q2!0jpC$oyD%{erGsX~}hrh}6Gmf!8im)FMgDgXjM6 zJ+)Zi1VVi&hE^k_0<UL*$jzL!P=*&wn~nPk?PuBTrSSo0cx$0@QkfC9TkgTTy5LC4 zFsIH+8g2j1vS@)@Jx<SW;I*ojmxesQmNos$IVE_Q+Chh1ip-{mOs%k%gFhesiY1vb z2!=^{bT+LLM;OMPe(Nhs9LP;kl$4xSg)^}0cmAc?ms6;7T##LroPQ4c`|m8doB`C* z3`*APyQ&(jm{e_Wub~FtyTr`Wp!^`=oOo|@HrMiVPSTCujIo7NkblZ6yg5Fh%omsS zssrC2n!_5#kN5YUk+QG4N=3XOXlTjCV3EmM{!g%M=rRVPcRp=}J;p<I_LVsYs@x_| zjowS=;)K!n<4|NIcLuBx@%qhj@HgB2iSaHA&TFt)ajUgdV~%9)-vCCp+7EKozB!OG zi~X=Bc@Kh!-LXZze0vBe6T${5q+a)&jwrScx3)eh`q=tMt$J#%U%wJ_6{=Nj485k7 zw0?ChC$Se|s&<j)JLlc5Lsh03PVwuuls)kPB&cxE^@s;sxJ+(tmX#EL^m8VijhH6F zHaEw{HeP3ZVEA<V1v6PND0O6_=WM}48i7r{eiuT~eMf5DzuDCUTE4n!JMGxPJ2Sa? z7Q5Y+STkyq&<{D@U>@mT&%&7C*~Dyp+r<(>`#anX1+{EoKVad4HMBHmbGGmT47Ds$ zdxVLg8aFmB8ve@~^{CB2RPO9<c395Br5I0+FQ#_D(kZZ;2ZepE?f}tsoqGM%(Jf<+ zl;DOPa98xD)f*eKQl-LKQ$zRJojPLaTM%dZ32m>dyW_fM@EEI<BQF<=DRvhNI)DNB zk9_VRu)i#>D3p&UMBw|dq?Puf(=JCXjqSU4A1|&MY~h7YLGNA%HG6m9Km$iY^K9W< zgB5=Ly>9id?$NeX#c+YTax?T2Z*?>8|8+54KkA6XTcl}vzgUV<CfZ*4dwUyAr%tUX zEIyy2Z2ResS6B{<=5Jh0|GOo0(HWs9jSqm=a|xpdzv^cd_(B(m(5LC`*a{8gnur!i z)}8PXNS2gEW-$^CW?@;9mWNrC6FJ@qKd_gp@+@CTZ;4(slL5^+CgkY_#fwBr^`5PT zx~=_QLf^~4IwpB*CTGL%7^G&hH!lp=b}H9ZpvNmTVz5q8@JldQn2MxOARNwJp8t(~ z`tF7&$H$^{<q2wSBPZ@`8F4oVnP{BC0^Z75U9IuARLCq447bj;p^J7s&ht<(1izTO zpF4@q4T;sbumXOWmYl4njGV}wyb(fu=Gb{P1!4HC`zTZ{@$mP{FeZncw7<)Ph%-8@ z>gr{rI7j9tiq>}a8qLM_O;|1QEG}A_w~5VK9gs>1_50Tb-I%_BU}GlHm~kLqtZ83V zy!W)rIH*{nmnhp<o{L*WgPAt!bF(mAkb$|g!|T!#2Kwrpn|eIw`+cEoI;1%#Pk$`j z<BSFty-82!j5P44H@Ujgkqz=Gs{ri32j7_W-Vc(FC1m@|@|LbZ9NgFV1PH((B~3MR z`A2{sGz!5agB9|$ObqkRL2i85Fn9F%+Z_t^NAOdt^gYJ)$EZ=OgJxsNvjwW_Kxw_Z zz!;|tkFmP9cV##6&==<)lP@LnLVQAgGa^rmxg=0fX<MYSZ~805r{UuN9lnY@kDHFM zf0hVBEO7VY@{4oRms*xkz-?}Uo-9m_Toma9uykhFU!3pezM5mo6**!m1h$lg_ncL1 zU-AXBR$MOnHIpsA9fVuZf65C~kE<aRR;a@sP)VSG(V={o$?PyIIhW5x1J{&4CeEg| zTB?}FIDw1LrI`E!(B}LgGQ<16-S$M>wK^6<^o4_>Rl0|&RqZ)&GNiJTgz+h8ooZ%n zF5_xodBHWDbapR^<rRB7CT6}^V?nRgr*ebkW05L-RTQt8sg{*&(8rp(Q(pD-EXn7w zBQb_<jn98ELN=+S4+D*#6VbhJa7yb3i{tjIFVai=rjpIU%1)1*J@aNY8qGCjw2stQ zF69o-vwUzoz<%(SegVLqI1E{==L*i<Mp;Y@kRN<C$E()QY+#3s0H7huyxhr#TJ+vN zj{mzladwuz=iz`cWUtqH6Q(THUp|q;Ux!NXPIG;NdJC`^u_jRGt_&BRr?LZ=0&gAe zzFzB=!cz+7*dGDR0w&KT1PD&4_e<b<_2HI&wb1G=D@n51X%?|5;JMf{GbLUOK)FI4 z*<6ZNQbkwF#;H;jplpQhYIq+Xj;s1Yl^>Q)01!OXkbV$eqmp<4Udb(aVOG2{+p#*3 ze&CUUg)~(Kr9HJSH$u9xP<4Ur?tTh&4t0gNF<HmPxY-J_m`d=_7M*heXBp1jWn1`g z%Q;NoXHZM<J8o*S?tJF^-ZtU=Am_5KI5vlv_bY#u9;}XZY1hz`d6Q|Y=U#>drFv}! zcQ&g_v8N2`W00;5LoS2=R3$V;DMl}Mnl&(JI0I@L)yBnTGh!J&dS{<XE41rZMmc1? zPMY=K!-wyWaxz|DSr5R7l-u{Cwjf(aN4)-UNm%grBl_GD>A?!SMH`0!*?S&$#|IjI znDuvv`$s2($>++cclvxhgWgU@^b!SfjeL(czngt9dU;b(Kj4ds5=_+!j<MSsulZFy z5e68CQ^RxC-3VO2U`Ge9mxumVCtBrL(-8WXS5y+}xTIus#dhJt!}CU^QJa#$ZwKDL z+p_-T45aaS&*#vX#gv=Q7>x|*yYGs{j$2jmjEXY(5AL3Hhc54umJyvkyc&dgB=g!> z!5V9LRbbrKOwQA{X;F%z$$1A8SMCo9kG%tK3TZQ|4*~qQ>U?G>P=UJu&vZcrz8Cq= z2hOy|JsTt*9jRD|aH)M0m!so`n+4<Eb&aj5(@?-V5?#;kpxCbZhO(|+f|?2QnRink zjz3z6?md3Y7Hu4mgxQ<=a$f?-m_FU`9sR(i`EkcExNY$eVsrg({l)E=_F#oNGvrD7 zVYG;rrg0VaQ-#|SA-1Nqa}(g65uqe&Sq-y7_w?LG(Ej!tde0ccz6)0B1z;eE%}}dB zeOW}jVK7*B@6SD}Xf6LS)Xl!aFg5XrHf!AXaB(5$WL5n*!!+SZFJXjwHN3!2w=Q2` zm3rh5iPq__<ZzIZ?5nS78&_d)8#>_INgxVTZ@pD>hip$hO-bfo0LulTz3H!^qBHBb zs(0+GJ0+0R;`5O|ApuHMk+bJv9q)o4PeedZ4}mC|@5t{LsTcxgC4<>HNG*xdR>H$+ zw`G%;_2i#`Ifjz7rs6XdrF&B8)r~=0jtF66pu9$v*N-)1OsD6ND@}9>=d=#h&r~cS z+~?n)J8t^ptVHZA<d|%JBFna8D~AjCi+-C^6AV?qE)cD{t#<|yu4Z<RNIs2i{iRAd z@%?9c(4{GBu|{#eKSzpzP@FnuxptvU8gVwbue52PVX7INpf8K)2Xatlv_f*<Sbt%y zO>^r}I!x+WlIJAe+}1<&7ZgyoFF3;=u^N5ELn38@C5R5axXG6kv&J$ShgZETW^puJ zeGDiQHHzjjiBrBeaz{F15(5%DM1Maq<2Y0o-~M^h*xM-#SYb~xcb7|JKe;`>oY;QQ ziQGKNOg?}HJ4*N)zt&=&fK$vYY|zTFz|DOi&cO};zFy{t&^BR4239uu<i3rvx<%G3 zy`y4CUD|<_55>$>o!rgMZJmh+U4mvN>t(I@5}1AclHARiu4!zt%s5zOn&>k~wYz?m zbbWt4g})>fiH|y3zu(9Ve%v460nGK-Q?{A_mwZ4Q33Z-*I{1Tl6_J11+?#Db=My_C zgTBMaU0Hv3zcrhz?V+0J6<Ckz7ycUjSpCu#t_x48@`eJ`q|Rm@zH}G&<EfFh;tz>! zH>@2Ok|0-mTH@{}iGK*jlxZ3CZm-Qx3Q3Aaz1BtAJ$QXj=sG-~J5>QNfNQoKP@s#~ z$_bg{fH{9r*Mpgm<Lh7FnB}P6r<hd^YShuDD)WVXEMWBpg6$QunsATY6XZg?yIn0Q zC6LzNM^oI(0MOGIW*~djWi%K+mO_G}0`iy7`TE5Y+iRaC#h@@m!J`y&Bf%5o=6tT{ z^rrE1kX{O@K~kWmn|pZXO-IR_OlqK#I@WKo_PzY6D=LEtBNp#n$-^=D^c87dH+A+7 z?3zGD7oWLMyX{Pq>N*VtktD-R)Q%zOhI50<g>(G1T7=o!4CNHFWwl`LRN*Gn*tN+G z{>_mfP_1#JXrx`J4!ppPfo<4ptJlrGM{YieTF%(`9+}^F;G|R&!OWpQ=C<ThH-a}5 z0{=l=!NiJT3@X$pGIS@E`pLLDb0{lcjX(7{S|}uXdV*i9J&E2SDeoKeM42kz%exl8 zyfL@P+By^)^~k`p=I{*_$vp+pXVrw3N)_GudpiuI2PNvV@g3!`xaI}k!q9uS$HXdc z#c5O+GtntOnk#p`3?p}*+~0cdW3#a1yR27uG=Hd?NP_gi4MF<D+*O=Wrcq9?_}%o@ zy!rdOqWlZ*&P6ciL^|&$)EhCiiE=cEnImLD%9pmqh7rH7l31~i>m9Lrk-hwjXY+3t z*#-W*!tx5oEF-J(j^G7EF8|_yy}Hug0Ow>aUINC_ZHFkHe&g!A3pBL07pL!{ITVec zg*<I8+xy;`YQG?TgAqjIsVe)pJBOj+Q@!}~vXh2Pd!SdSdHL~ih;fh%qJbK8NeIKf zy7{UGH_T#X!bdULmHw+C;WCRLa_<xAeMi{ibaOK77W{Nz1@nMV9a4A~IOjVCd*=pT zGP7tiG<W61ILo~L+>Bt0Jll%M->b9da2W!(+*d8k7Y!^?wN09@JqiA8lVM4w0DdKc zH^h3IZwykvXp^r~)KrqNTL({Qf(v(RsO7}_0M$aOGtm#6x%oauYrh`pz#N5rC9^Y$ znx^}Pl&+ilOYE6sIt+{xvWrJjGd#+&U_FK-)nM<2NMJrn)|l~0XdY(KQFmOue#3W9 z?s@Q7OV^Wk;oMl;Y+6sG04BeG@7Zz{mX$x%FXZ;n=qDjnse&oljsy(gZ3y~x<+(g4 zq$2H?IB>QUrO>d^%_|A1gH3@JFW&KbB9Zzc54VsfiY-oQCZYs0z4Y%<(d{Bj#-+Td zcH7WA3d-i{JdW#1PlHBXn+)hK)B`fX!=!Ea$AvtQL4t-L?*LyQ7#=X+y=DINGOMIX zzltqS{h5d@m_y@vD+9bvMmAkTm*haSWw|z3jh_6Cc_#sabyDkSIHZu%HX`GTV|~r( z{p|Hbt!<Ew16<?%ck^G|cX~C2Mv%{OALOWNO%(qoZ3J?=L>O^+)7U9;#oa_!PmZ~M zj1Rh__$jH_KvtwYOZ42*{`Tu_`7(MdU1XarM-A_X`p}mtcn?xegnt4OPUsZ)2!Gy> zntqpJRzI}LW};rV7kEp%e%x{J_|5wn67E~LQEK7^K{@R?uxFwS$~hq2(Lp?Q^5JQK z-kPCw7Q^DeE?%pkB*5~x?3raMcyf*!sX<_@_<?*^62yP5`z9SuKylvHIr_%Ky!Tsp z^)st=^N%KBn%)fGa;y6ujV&e_+X5i%H3&zS8JjLcq;8Jy=f8*FTVDMbRyZB4Z)KCW zrF1a*LQV1<PX0v)f$tb=aVp*2&M4mP95n4GCicfwC0_qPU*Fc^VB`CFZq{MW4s5G6 z=-|$pbf`%-wdBo?Q*t*%!EVSC51~kT+NvY;nJToSB+YwV*no!?Oq4f|<{wYy1rfp6 zsLAM1q{G<Nq<(&S*+>DEFUXNt(hPaj$$nKBSP{)AM#rXyjraDM);zTCGBiK?E$>9r zv3=xJp+*!Zk?xE0t&QuM8EA}9L5do$wk@9yQy)00P%K$*`Q@T8?Yvm`)8jN5-0!1& z7mf#ng^r+(pi}>ui~ci}LNWP!b};EvOY~|l$kPu4&gPC?zrl6&@^alP2TLCtw+!lc zOAQyX=XKhHBthM+LYF%nb4QOI(I?p=-Am&g@UW1LA}5uEO|TH@qky20L<-=a61c_` zH7@7JC5z3O0TA%~t};>J7mf`rkJfk0@S5kh@h>%t$nfReh&AkgGVS7kN#AOyusDB` z=d%jE|A4cycl->qBM=>MNNAa`CjNpfQ>54J1)!*3BI%FjOhtPIMwdL8Xk|a`cJ?Sj zpi2@1o@=dsx;8P<-F47=qSFW~rC=>|Ug7s~dt(b-iuK_zn~#wg_?B<^8%1^W03Bkk zEV={>1B5im5d@NmCYqPCYTyWw&mD}=ekX7{ZF)xra09)SxGjJq$toO0wlp>sQ4}Ni zdEyz+8yBAauB3{>DMgAM`J1wcfL}*q3x$A7y{0E8y1liPtheo+bO9xS>yM=HGmZM4 zM%_h4<Yrd}M|XwR9Iai}nx{!q!K;QLA#E6V=25I=(28hH_s|aErhR!vC=MLtutbm| zhXYWEC~7YddETmTd@h16Glw>vgbf$jB!<)3Y578E5_OU1!Vzahqi%B7cQIq<g`KlA z|7QAvpM=AuKTF`Yz!rvHQ~3Q7CFkS!;aW!}HG=-Rthpnl>lCfs&m+H|DQKW3Hh*Sg z(18w!Qg=Z%CmV1}gav}VDh~WP?yksSPGDnS_tDR0&swuB_Z?=-WCCbrq?~`SZV~9B z%YrL4b1>B@;XV`7;nMwp?B%q;y34)3S%Tj&Eh&W<h@FSW`g_p$<;fyN2q(k!-OdX{ z_hG)C+oC+#z(KX|cgZ@^zj&-AF2p~;KhPZ_h}(x>a>V|zPjUA9Me<XLC{!H7VL$hk z+`h3Lm4Kc7;fY#F;x9qr8od*_T>|!m4pQ2)4|gddA)bvg!QWvMzL2!_lt4}6QtN(~ zH)GCh7CL+H%7Mw-`*FvTeDInno<iFFKkVFWJ6n6HQ6U;CoBev_Q(LB8v<xJG2k^F+ z;ab5=+Q*EIJ;b2jo2;qNZ$>CfQ!WycDOy+eCw`S>C7EC`ndtGrv8WYwyS4oFKDF~> zb%(&j*gazWx<SjWkxydiV_l#?^){XH%N5zb)m=1hBbK;K*g?O(9?qtk8++r8EafFM zjhu@~wfB4Y3`~+mJGUSze|-?(YZT7s_pB-hys;cO>4$NQ(Wphe+{;^p{C+c{|8RoW zDo)R`6GNOv!W$xoP{Xv8<%0Hn{Cy4QUVY6a5#$n|LQ1-dh6j8Iu@ySG{K42{JwVqx z&g{EL98J?`rYE<QaSrtaC7hJMDL5XMiKM-Vno;EA*@^Hk4W09Ux4Wa~1@)%SnRcT` zZt=(ghH8ANw0F1Ex&-AUMawz&6JGIx`iM4`Xy9W+<BR5=7}0&zmcBKuxkic0-mCsz zR?y29z@1qJG{igb{o#lNN<OA-;<8W$H$Ka6d?FHvb8o*+y5PmR7Sm4cWdH{X6>dBA z7`IqkPO7xQT$8zri`$I+Ky&XVP^q_|1VnrBJOa!>%1neYyr~`1czLu@SQvE=l4@6g zg=xTozSK5|$#=Q%0=O34w}rWGI}A<TCbntf0z5t?+%sYJ5D-D4EG(c-RVww3Klhi< zjGu=DA5XrHT8>kBY>W-_eUH<M!7G*pr%=>oLQponrN5#?)XZ#tWQqY{O!%GhJ6rl) zkl}^PgdiYOPBOCkYJ|7pI!aUpc*mjNinnN4<=Ei;znIt3x1~|@4J#HrTPJ*qqz!z5 z)A=|66Lv~*AO?JBhUH(OP+e}HW?-fK&8Si|f6K|jYC}Q53yEEPSIYzYNVVwtpT|kX zg>qAx;|AJBOemwx<LlTYEVJz-3g%}9jGJY`E}H|}T^w;EX>VXo2^Qk@uqZvN-5K9# z-^WNlbwgw}D@&IWEKC8`iIdXczS2B*+qGP7WP0|ge0aDe6Q?y4j6vk|DP_q-F3x$J zklae86hkINQI2&>gJpq$LPB5w7UcBe9IB$rUka|7zwx;dg^$?0S<c)(<+eB|5?(H9 zSXwx5!5FqDjWMDehnhEjrb|va#7g8f%dPY7wP~h_*=0$xgkJt@+HWG9liVfDG=tZp z*nhGDJOUs8i6gXUQ&7vB8*+QIoLVv9bGxun^7lgc=WJN=`}gp$PY^t-=NEPy?b@uD z7s6i)!)EHdcMJ@e>*QttZYIH~8)>m9t8Qa|dI{8Gq#9#WTGFV0QPOkQ>>-N_ttkuZ zRqF5osK>6OmJ_PDni7{<96wDb(SB@OJrVOXt2NqtMco@(clyN)7E#4QX(hYAMV$Ep zb@SFw#-cVWDbNp-YiCd$-z9k8I-8vdG&T4e<>)wtE2%g_0kMxflGZspzS~q4VqZM) zKHbqH^NzL1fpbODW<@Pyu<f8ANmD(c-gxml-bStkL_(lqt|E@-pHhTN41BJR#`!;W zTtQ}(0V0v;>`d2cgXz&U(G~OIf)z#lSy2|tb!u9~x+mW!3MaMNXUi4n9lk&?CT!s` zK7dP#&x~+1zr}?yrIlvJ+H<jy38DA!9#*(Mi_?nf<tr^<>8<uLt|DQNT4rIKd%;1= zN~Z7n{h?WMLx7hL#ucxbWs})XnfC)86Lx5;-)(l`>%BdbfO;GcW!Rfn{*VYXi-VZy zh6<g>SAqbvw!g#!c#!5nBvQgvCczf9+JRbcBFXkM-^V3lEYtu#_o+pu+iy?ONfy{c z<={$GU^}I>BOqd~XL>L*?4DKTlP>UeTANah=#cPlSeV2D??-X%BanJ`>;yx86CWd- zQ9Qhs1$$N$DU%C-r2#~xLQ#s=41H|nv8IkmK>%wz`eX&DW9N7uWsThzKmbSFe{!}b zzv{Vsl?ufhnj*$Rdk+saZ+!Wqo@RI=)Ek+d%P2v5cJKil5(dWjk_`?>Q)2IEija{D zDbe3{5Jc%nsz^@)(i&oUTv9hvOQa1QiCX3!>ZowTEi}B1-f>8~*Tn@=l!9pUnqey~ z<~xS%5zchpaI~WP+7?#aZPVl_;(tT|zAbs8_>neL9;Eb*suczF+mHO;Q`0f0KuOcO zr7Hdm-}dx{v<bVWCXP3a=vwbw9X0zD5qVpADHwSv$#pLPeC-=r<_DG0kd=6widtBh z7$LwN?qDc{eAqz>CI{kp`Sh{>@$zZ+)pTWf3N~wec0vw6p=~qn?p80z`QZxTuZ4Ng z!gpZum6sQ@Y6G*9r}PS-C;5blW>#y`a9TA5HyekbbCE>p+W~}dHv^o(q^Lf5g)ws@ zJP>>t0#uca+9C&L31C%;v&glI%9xF;<;uDc=r9f1^k8!%>H`P-bP;<hN>teb(a810 z4rKWyBF8*%QIe(m85S|TFGW43FzQXbLYHkX)%`|%2T~bO$&dqg5bm6XhN8Pbl2za& z@K(_M4r<PB9V*4sbOIY){RW<pu0wk}=LcM>p7=l!$$rDZEH_@W1#^ZR!&=yz{-w$3 z7NNlj3chwrbd0N=6jJy@N(bx23`(iF5w~S?hHR)+N{h>jt%78jE51(aGpz4TvR}!z zhEgL}tPb{t^mYsXJV$bM=JE}_84@0cp@#?l2^VSg^)a6%w)S_<$8EIXeH4H#@xv@7 zz#T&n?-Lxr`+--;53J^jjoLL>61fLki2d*PJp8dV9x4S(Il(@d_>8a^=90`6#m2gg z`X*hR#i9<VbxNg)(uCB(xFUFl7z=BX*k0hJbt_Y1MvAooorH!gk2M3lQq}bM!ZyHl z+*q<b1@3qfVRaCZf<o=!(h=10at@;0fj^ktn}l~jet_;>%J1<75*Sa?M-ksxtd%B( z5w>5`u0LNvBRYW4%O69xrT3!?oN^eW@d|u@Qm(nMTj9)zz14*zP6oZK&T3f}cTeZe zd+S^vynu0V$wp<BH>J|*AWbw9=#)WRKe8GIj;-+X1|N_Bh4~oLgp+A+<`^pl?#8;i z%S>chl0{%)os44Ot-5b=!p6Z^St<#$ZZZQYF>Kp@%3xbL*vi7n_L(ijk*%E%=K8e| z-QGhLHN%B_oZ{CB7!KeN3kd&F!PF&l(QBFLA<S!r-XP9$@^utwYe_WZ=^z$P`^EuI z{VnO|y%#F{HK&||L?ngTc%1Atf5+33a|7sdrvdk-{(uF7^~At0sX-tXB4<VL|7iNk zs5YOc?cx-7cPZ{J1%f-pAy_HJt$1-QZow%oh2j)<m*Azi7ZRX&2}OcF`TgJXe#)2o z>`q2@=j_Z}7lZ-K<Ky5nOPPm|Xq3{w-?RDpqq>b|P5Uz6pBSB#{&k@HD*hXPbKf#X zoB>Ms_m5en$vwW#Z=a9s)xq6FEYF4~5j{^d3#BUoLH5dHImrJLo5QQeQz@i#-mO>T z>I^0cF4F6<O>{;BBFrNePzS*!g!U3?!Puj{3>&Vo1-9!<(;wf{b$&tX%qk+ag(j2L z4b(6cy@v4~Eq6tItiyzDNSBzEgeX~xsy`W>&(YP{tJsVECJ(fq-cZCrdmnL!kJnQ{ zz{Lizu5SABrA)ovkR&r)J@Y#-nmg9&mHZ5NVCY?!lA)CE(d5`7M`*;47vz5NSqm_H zZ|Ym?R-l#HUPbo7^uTyvNJxbU42B%b?Q4V16so*?_hjdx=+^JjEBG{|<20{Mu)i6C z?!1rwAueH8pMahsg$tBEuA!N1qj^@BW=xa-B~q^=Mpc4-LreAekq2nF9?vlDfBC2a z&7?R<+8S#wj^A>4pai6XHR8<~jeD2LU1S3vqX=({reilL(`%ynu~hU<s6`?ghn0`? zP85NPvr7o-H4{FO_dO|_U0?`aonLnfjgmHkgWM*vttgWuOoS99i<n{6`|m3;XH%wj z_e-ph@4F+A`hUO%!l<`d+I9L`xhq!~kMikkz`BGFVp!m*nJ&`=qi(k1QC!D&(0WCv zNCf|w2q=>F2{1nuzmsusr9=01=q}=e7?6<<J9lHwT;fS{JIto)nhHPx`3iPLxn)!C zTYwKIg4tp!91ydXD9n>c;)OsRLBdYvQMdn=V+9TGZJv1=A+PWxwnH8s0d~ub+aX2} zAV}Y?mzyHi+-~_y)GWoXNJ78Wk{Q#+oT!uTRVCS1>uu}Ni;)-jc=z00gn~YuP$^5T zee7oDS05y&{P-=*p`%5~at$0$;IECnR;k>6&05F`OS2_}1@^1ijS93;S{lDX`q_q; z#s<iY8Mt{P<C#MbC?t>2P_mmi2`Z9(RXeD^c-OJc)6Ix8g={q~E|aJdHJ76VC8KJo zXmuQw@;LaJK?N`wFn|`5`iC5b=OG~~uQH*#9+YVfLeq6A3b0K=_{Q$i+S-i6<jmT{ z&aMpe<LEmmzKfq@5<ZJxxe}L16yxcS-H%RhW7dmVzMR(-$ubBsjR!+DYC#u8iRc`O z^{V^NdjU=s@6>L9es7rA(utQ>P3l+fg*ZI_PJO8vy?{rOz(2;(%n8iUg06OF<c4Qb z1yB1*N#SK{!BC^A<^4R3lx`vraa41TBJ?26mW>ue!xH-Ni1e30A2l1iBEZmaNCYpM zmz$#(?5uR49_q*d>ewwK$lM7f03DN)0d)%DQ&{^T+PDnb{C;!hqH|dYZXp*FeKI;_ zBKsRZ65a%&s|4vI4~-|&rS4g>I^)ehr^*DgA80`2?Iaz&95@vysXL!#LrvR~>BbfG zQ>6*v&od0^dBK96kzmUn*x=lU_V~vUzVT)7>mfrU0?;s4^W;18@pp^+PQRZXt*KIl z*4FC=XOw0e(6PlG`G=T>Pj2((^kbPWDP1is@%_U;h_M=CgOlu!!xgm&l$brkm<qK2 ziT4k2Z*SegQJ7Z1X#UKwr}_6tWpgBH8<2l6e=6OG!wVgF8dLVZUE8}VpLp<V`Q53T zX3|$LvXXjkmHS4A_yo7W@z9@MaryWd*d>OZf%$zajzKz%V^webx|L3*LmA4))u5=l z?5&nTODm7xUY*zFJxGVXdov!Je--oq_J>>;tY8=p0^(O2?6~J$v>cj@Di=mB)}-%h zsT@Mmke*?veElv~=8qv)@tODq<6`~6(%+LMp4uptvNaMm&!3ysLU!sF<}im$^_V?B zQh_3Mzhl3t5C5<=&+v3A0QPgi%9&ieg+r_WJ*u;4B5u5}^l)gP&(N&|s7S;lf_^ZH z_XHgPUI+ZNi-#IIHIAlzKM@+VqFa!{8mGB7S)*`*9p_ap<>*_(7_Hor9>bp^H8Up) zB%Tr(@<-WQ@n9%&5D^8j@B_V^exif^7_)>QjJ*$?7gxqS*3g^gAY5xIAH(L5cZNX) zHD(Q01|S>7?Jgfs|0#B4!u!Y3ypYw<iOEr)F7R!iVR}$Psq<Jiw{NrEReajrKZ=Ez z7Q{YSaht+FQB#>kRC|?)JC1D*_e!IsRpJMye_p_csls65L$Ghll}ruKbAz{0V0eBh zX*(}0q{AY+>^`P(ZgSK%K(5aZs0H)j3z*9$>eRd2s_79t`&n(S&BTUTes^TgFZMIr zKd%otJ|7P~wPNH{(|cPA7W{m9BZQi;<y0~1mcOEM#H12k?b17IS`7}2iCKv4>Gax` zz!zb1r>ARr_E#~V`Bm@!a_o)wZOd#+n@uymhy0l=G{n)WhY)|mdZOth?}!T;xI~G! zt(2F4Y0l)w*v%`KZdMHpm1kn>Vb+Hh<KB8dWLy6zdG)W#UjIGX!{Ga-*jkH&n~-Nj zcGmd=3{uVl<7a?H2s^!-NW7f6<U&OCmFUn1wHa2=eyp9ezdN&_QS)o}^=KhZcwEx$ zPZlK)vaSvBHmHYoy=i`~mz?TmpJen5KP&Zt_i;AsFtNq%8J;wASpPg`vQmAm;f{-P zRbWghX>4QijtZl1j((Zw0W6{C3{3#1=t4Pg{@Sy{##|J)sf3teSMU8Q$<NXIy_t5- zZo1_+XC|)A_Tt(Id{w|wn0SG`R}6PiIvAfVxM5<9%6n(eHO49`6h+tt*>MIbm9as5 zPJbVJm*>lFrndH$-Tr4{MW{x3q}I@GJ|V{+806mLM$1;5gh=}~<e9UTH${ecF)?B5 zUzHD3{B0}mntCkF%O6O9Z{x;dY!8>h#ixKLJehEa5p@g?T*#+@2p;nnE!{kdqBv%w zRx>AFIv!RB>bCYo+D104BOW<c!~;?uyO#Q;1(i@aYkkBUsKo~O?eHHefi=HA$b@ou zDlT>9RxZP*<~@`ZLxK`zM;GsrL1m?AQcShW2xfM7^udOsYpo#pd-D!yX+_Y5X2Z#w ze@Q*tSzp|C(YT05nLUG@EF>2LVwOWs3uLE=0R&@lceL6;L77ra-y4c!S4}7%Q)0=m zB1*{|A2B0Fe(7P8<}m<)z%^4-w9`|bC$jC2?oEMyQrW#%b7#lWojFssSC(W6^mC`D ziISd~$M}Z6C~vzwyBOcSP83rOeZ6Hz`lL3VK?BSYfy2{tARpq4)<Ar!)Tu>54>v4D z3)e8hM&;*Ye&;t~(#%`pL7{K^dIE;aE3?U)YIg2wR;oQ*Q|IijAXuJdRv4X-ah1)$ zu_iR@7Wz*0YiwuepLrWpt&pK7mMEY@*>{KyCZnS&FLgNa-ooOc4n^fSqc)Jw_dYDh zx@Grn?<g8Na;ev&y!{$REmYQ=r~3vRQiTk^mz3~C4>htV#^<vruxgMC>B56?HA4=J z?C{s;1!JB<^*Wg8vs&GxFU7z96sY=E#|1X59xU-0#Kx)&zd)Pf{3)bpoij$ZvvuHd zd=;}5Y9u0iqDwFqkuPBxucm#74&9)E*E0QeeE!3UF~d=mBvY7oX*_dRvoCuv#NDmP zEQs7Glni+8SpVd^JM`xEEc90qUR}zv=x8sSjr3Qdx^Z8FYLHK@p98H{Q}K)>YB;gh zG{b2^sRCNWU$zvvSDyMsFX&L{xYpa8!Q`OM&)w`P-_ZPXm}Rv9SKQrW6K>wSf0tD3 z`3l)&h>PcnEZilex+!1wTzv1PEkcYVHd%%;v;Aoz^TqOK4l5=%B428L-xC(O1=9NS zgPB)@jpCdK72A~SX^fSMZGr*YEM(FKNJWoiC36h_e5wfuv?F3>C+6tO(;zX^yfDWf zLbRvgY<lv9^r;GFzP9ju?wcfy9d<oS$F?e{({>OS{l78Fmx%ZM%6IUG?ASZ+T;;+B z(x}c4v~UX^OdA?_?;9`%c@$;v3+0NB*-JIMTwj@<QZXY#wm<~nXxYJr2;dMIyE+y- zTPy|)HArq}hQqI9Jk@<pdY?|mha4i&KXlFaewkl*m1^I7W$<^udSUSNSC{;BZR!1} z-~M=%z29R(>s*ME#9tC1n~kMqpLd&O>GeXr#6~Y{C)0uSYtdFv$K29MUc0Pj0uqB? zs$}w;M~1Vwa>bKmb<*$<S9*y*NG*arKO1^;2sqCL7s6|)`y6=q1>taNh4Xq4Mz%vM zgH;>g*~R)FbCDgAWblu*#((!dUZX7C1qa*ZngLWh&vwmIjxt3vbF?!}5L@CF|H3D$ z`@Q|oHI9>KQ&#BF%PJnw(^2?{xM#p=Qc2Use;c!;DxgaIE{U9D9SX*XH6jf;e}#-J zz)ykuT-DkhPGbK}CNv!ZsHWoPn-(JlYfn(0J6}Sy;7=6wu&BtG<G=>HWEMm#aMMET zS_Pg09$-y6O&cr`N}gW!-STcGea5t%>bAn=id=_|NYnWP!6u*h*&yk0kRQc@aXjBP z+A~M(Bzye*VOL_&G%?GaZl=rb4{NuhM#1!y(6vjiqV4{E*j;Ed#PgwfqrG3I>Rrgi zZh9J|y<+$tM65QBS$jnb$I$$69MblmIk!zu-UA1$zf8-^LCF*=+NQaNIBV7dFC{)3 zTp1krRVBase0+sL8?($LyX}<})CqK%cgnTzM}bx&1@P3SW#^tyXVQdf*$g|^jsJY8 zU4J-$){g%YwpIBSFNd-M=E?`0SDj(~*?#_VcD(@Ia~#OxWo5dRU#}1b6x=_03{;(x zb*1EI_OIc=q+ZHMla&-bF9iK_yF<FA)h(X?cCiP9ZN}9SYuKzt+R4?Mo^USx{@Im- z05(;9T|&T%x~xY$_{QEH1xeSJ?D2X>uShl#6Z%EX3_<$w;dXx+e19&ipH#V@jbHi5 zU3pk#W|ftA3CP@1Rs%M;xomc50gY2@44&jqYPaNZ&P$zNNLNShvCD^c*@6EQ9YSY; zs%CrDQdD>Yj6v<Y+Y5!ViJQC?3)1)){vr0?qNOEtS8cyG;BWhh;z0jV{Ai-?7n~?l z^<9YIug3H~^*dw6Z!n0MZDVAi8*w4x{Lxav;r1l|Q1Fmq6;_#Tg3xPaT^?AnF75Uc zbb+S^TC-mtAuU77&5OF=oFpB=>e(egpWjS3LDiXNF4C8b>+qFHrD}i4G$b59F6^W5 z7fk`VRVnn4JGVJlr(wusxX-hf<6KeS#0HovQD<0gHtTWZFcbTH>=LeM`LUWp>1EBk z@xB3+axlIYE4E%S0&1<-Q>uBVl3Z8QZA6gehgOM&-!Wh#Z<Z8+Cwm=MuVqiLu)I(h ziVJN~EktV*u+_?i&XL!^9A~HFc01}*E359hi#!yIOFwgO%o$WWw2p$VkUA@>zyM)* zR7Kf8Jp#t}E<bhXcte?*3i#g0gc|(tsRi^IIoOK5fu9##aQW`f(R%gWdsad_s9?gZ z5kVIpiFDTQsSZ3uv~;UV4a1mK#ISQ&h)VCX$-h8t(5xRsgrC3s>Eh8snBtF`VCEL) z{=(l1j?;;h9r)wZeoAH;y?cLXpO^X5=Pn|^x$^S3H}tWbUY_JXGY`}HbB%6TjZG(~ zV#oQt$?D!V+WvhO_Z7P*62J8ZUGRX~{TE_chC~R16zum;$r|w0mXLk2n9qS?J&ler z5%_g3b<(2X=yp^5MSAIxO1<7_^(z(2Lo5oy2rm-j&(`yAQdENZkpoh}+e<?o#Mch? z9g&s@mz*4Dv}6&}fDSUWcb>3L<xN(8iC$VTJf!kRt${ApvH4!*BCc#Fez4hCst)jd zi;fI&U}*7?w1q5}J8ilI`fZX+6Uur;@jRaJ8N5vTtE=YK-~Ys`Sm+6&*!TXk_jx@H zV2NL!!jQ-9KJ=jc!@yS`p*;*RrBq)V;~&lCXx2jZPIPK$;V$p;eXAB=d`Rqf9ZUNC zBW>!{O|vC~J?TH&0A2cL9rjhwf<Sc6{^q!FRtS{Su;mz4!W<~)HZk!r9A6etwf6Vf z@P|cv<7+b-Mxf0vBu3J=mvCyG*)4E;mV@CF-|;JdoC&v{t7#z2M7^cjV7{7pP3zAo z+KNZOClqh$4<_&K@0_CV`R!+ZqyV*|e7u>E=(EDvmp0i8A0Iu!#4Tky8K$-C8H^_~ zx0u*5hxx_$l#da&{BE-ODdU^>N~cW7==A-VCo^I1`jz7C6)c&^tW|aXj*IxBeBXKl zhkH3}Ek^39)MHsPw{PF^O)W=o;4^C>v=QQww3!_<V^8))q)~utre;;NoL1>T=g!<S zubw>GxxePB&DPBo7BSqtY$$r<IM<I3n?7YOs%AExNS2QH*nSV|SW~Cdx)sXg1p0(+ z=GCL6SSv0BEhADY;+5K5t>+fkunQnFTadRB?u#TlRrTel_11CfX5I~UNvTi8jU z)#oBG)%A)-p`z49P>n%9GE5Tsy9vv|KDqS{wZy!-4(<Fmp6}p#JM`3J$)VoMtVJZu z9=8D_w=uEKLL=~*##~mFq4J{`Q)l$DVK@W5-^*G#=#)(5KcS4!qLy{>#fSCBGpr+g z_e8k4p30*dxczAp&#N?K5_p}nw_4o~$!3anCxRorl+}ZuPsFs}QpEq4LzR?Vdq7S| z$2;je5pGyb4PE66-z35eJGmJcG}B-;v0Sz~rRczEQiV>Pi%YO=d}z)sKkIBIF!Y;G z7=yL$e>%PrI|J)Vcrta?gKC&ALPR}oiv=bS4Y-CnDzoc6QBTua=7T33@KT9P=Omy* zCxqufTI?UGrq6o}Y%z}gO-XBnY1%j@=3dwW51S!vxKSQ1^M3DM`KH_b*e@Y$Brs42 z^Gu~7;V>sx`kj!{yYBw`@CfBpD68l@qDAdnYi~kq_2CroMHN`i*N-ESzYE%G!a(Z$ zlU8+oM3lB85onG)6szbi&{|K?_sC<8V;zrW8Sg2dkEPK;N!jU|<lc;x_q~|fdOZVa zN0jqp%7IKsJm%H2LKdUyNm-b=x7$s#T6)pEA>V`wFOdblr!u9FWGC5p0fuVdHjP=e zN3=ju4nSkn>8jG3bnc7S03NDqT*Z!sAxt6f>28AMqGEZJiM$un(=AOW9rQT6&vf|4 zpK8{ve>(yF`b28pfC{7244rPHPANrO2Qde}IxJP#=zEHjSDpPUcJ$N!+}%|NN5fI? z$8!k21h3^usn9}>wo|IUG==%Kn*Ogw@E3?Y>?2w#zC<_3L;bXrdEWJNy2xO%zVHo_ zy$W9EPb3~~Y9c-jAu}nLUCYC5lH9@kLGQu`1cGKJGrUaEmpG{bR7qS$%BM5U)K8vt zT;PCQkey<Vt3*;cL;(25aI<R1M2DX6(*P=)^qPj{)VBrKdwnMHJ57a_?rsi3TM8bY zzC!HTXZEG!ZAIUHx1L9|?By&|!FyHZ3aiJ`Dn=X?KIdeLn>eCM?b9o~xo<5sw5eES zd7Jw?Z{<T!^drzi(U9EnDfVzJ#cKB-9Sg=-a~_a66fA33deU5^<&dh-h9TTssQR%z z5ELeDhzo@3;48+8>w@Lh3HF~O0yYV`9BfA5#9sWWsC1S1xV+lkkp;rBkl@3hHz5a* z7y#Zip>^?8Q&AmuUHb#K8Hw}eUJH9-+col+j`cEz2CBNLFP%Ui{2FQJ1j{L$rWKLC z(g*K=Hl6w8B`flW+J}lsBlg?zn{S<^#=YND;1Ib9B=@kkHou3x_ucPyTe#M7I8Pu| zr<U8Llbp@KtR%O;Lf*LT60;b`yieXW+*$~Uf8Rj|mytXYKFKscmzhA1P6`~Dk}#s; zaMpk3CNK!+h@y7AagB|)&w>1edNZ-BY(a6W(45ujkL^)UJ5zS_HXm(&-;Jv2b6U9J zq^`S^gp21-SJqYo$vZiM>#OUwk^bJlTT-%7ZJ+lsr1j3_sjhay@@lMI*qC%kY4{^k z;A8;^dvDzD@J^PGN*d{RH`W(R{XnlD3#~``Ug#6D`wFbzj_6x{b+z7li<-OpxH^;W zUq&UL{Z(iQSn%p`^u4hk5Klhqb`p6xN?Xi@gDd0bC+${=H$r^*h*B%7o0q|vDz9Ui zc{>hLceSlT-VmU(cipa4FaXDrJ;MNzjtVY}cx))OuxAhKx8?sf$6wM*#BH^X?3ejW znRnc*UBxiyp&jOw9Yz62pDB-*<#=4KH^X|)z-=Gdqhgbhz$gP`l#8W74Yvj*j^+<N z-6nfq_>PVo37|3q<o7>Q8jxBNlyG3BTyF`$Rm<DHHQ(n6c4BP4%<ckK)>uTkp15;c zIQ(wX_2hE?=R>_MPuv3p^NHOF0ug8+<HSc{I)F4Oo|dFX<@rMW@6<VQPD-`Bp{`kL zstZCdW<<1@!kS}nXhJ(29!!6<9uh!1s(HX3sIA4VZiwF=DyX<vf|Bk#G@7@mMOBXr z2q?1|FZ{o4!<S7i_k^`vy>r?TG{l!GsqMjaMClk@z3aO!0K8bgq9~uNm3!1~@NkvS z`+TyAP?Co0f7jZ=nPUZ8$sa&Nd%sI2brV(hYzX5EMq-t2XlhBg#w!RA9TA>gWyiIP z%f-ecy1yRVHZ$6ch3NYwBpa?{+&rI{5`yXyo?t9sYhkn070H-j&Cy6QxV3dg41<*% zBiNd9<tf_?NVkEK74tT}-hwG+vI+UKbFYef_))7{ApZ#y^(%?rnhXuouS!H_W5%Sd zq*BXPq<TfRG!4rbiX@#U3*13$nPdMfSr~K-%k)n;)v1Y0IwtcP4rn0XAqJk=mvl9& zN}IiLoSv(N$)F)im4AuGIi{_BImhyCmyhG_iq6o2bH4SEwjHNo*ej^dh8x!KntH=} z+ppF<chMCS<{ipaJ4UdSt9+`05~k-Ty_Gikje6hv+;wAisfC17{bzn080&!9BF|mY ziMi~R;S~k6f*zySo}oQs`wv+^Cc{o-KGv<$?ZUSzLPWPF{((WuwL#A^E5mdw3&V5< zRS}SF`cuBdXLyMm#;@qViC=Yvy#j_tvKws<1tm>AEQzU07%P3WP4^=g3MlaHWuNh} zif-w__D@Wy3fL&+t@xhb9R|6+PdkpT=UaowmC8<}k^R@Gl*lCLcx_S-wVFSbht5_# z4fSDIeq7-Lp+N68PRJNythd`fH7dkW{^Uq?F0(731@xT*@H9diR$K#r!U>^LGa+3p zBFHd<y}{Lq>qTx)#?DXDrb&vvHgsE;gM^9f2Zj6@g2KA5`(GcGFRGcPQ})q;zX#{n zZ`gc3ZBSl%Gz!0#xxM7_G#g(Gs7%SeVBR4^@10XT{<3}DyqoDJu!egIgq~evz2V%l z>Q_$Y61y$Dx)Huj-tgEjW3W1E+q8Qn!H&DO1aqo1?u!ZY32U~obB3PuMN0g}H+<FU zjJaP`pMmcttHCJGHK!c1sZyvKYXo99O#(tkurPXm;wOGr6=iRz?f9ZbuPrHG+22#s z1N~4hjA!FUa!8zT*k6^TGrjwEb>uKNg&yBADL<mF=;9PTh&cNz)5XtTCaeV<LDS`B z=dD?hvTd_)X_x+a>XVAB-s15`2qt*Yz83>L_)+1AH79{^b;kWC5~P{<kb;sVppMTc z2@9LKg{|Sbm*aaEPzXf=$13zokl@<2zaFRM36pLU)ekU_DT6XWvQ$b~$?nOgNnQ2I zLerkyE7CG$Ma^+bqXQm4l?$AMDhrf1q`WR%vbsk-<L=KiVAt>0Q^-RZU2ev#IW5bh z0s1FQQm<h>e?<LG4Dn$-9AkixRSF*5O0oZ7tu+?S!<$cho0lH4gSY6E0hUKh7jk&* zlIzO$x1bA`I@U3B>$IZC9%WfF(}W=leQvN$y&&5ub3<*UTuIS}Ru!=Yi;iRxM_qCx z6xkE>$H($S7SYh3TX18e7*oQ}={=RCF-FT-;(22$K;Yp$s(Va?z7iHH(+EEipCV0~ z%~HB~JRQeROkWA`^^nU^+Ty|0FBS|2E2Lh<v${$v=!#%@g3T9iO5b8Yq2%rCRXUJ> z$!6Wu!#{*_+Zn>9+ZR}TRSK@*x;#So&;ro|rv&*3Y4t)a4QaFPBHnpc7~-Vo(Pksr zp0isH)%=iT&Z2HOyfH@yx8&9)PfqEJMfnl>n-85nq3nxA10$(`T$8i?bd%Rk&i6yZ z@=A{pvSg1~a$<o)nGmm+!8fvzN_c5IR#{KnetE-<CU2QCLNIiTc+HslpAF%eU)T$u zZkpqoi+*Hq99SV9o0UpGiWH6+;Icg7DCB!%u?uC0M#+IS_BfpSu~axNg{KwCf^^tY zf-aw%+2s@Vy1_3PkQf|r-NyYHixw!6!x+JDb86p`M8lQ~B#+x>Y05*1vN2J`+dm8U z{0Ye^S7wKOIzU=U$s9^rcSsSnH!&wTWxuMm2sP_4{zEzJMK8;M*BJzDNA`@0B<!7K zDw3w}T)-D>MWlteFb8tq3{gb@O+m8kW~C%2>z;qIBTZP;tT+R84L?HAj>$Ofm%Vy| zUdZ*ie~OhrgU@vB4iQ*(Ki6T5taD2#nVBOg7|NtuO@-v2Av%I|fcq=@cgm4Bj<=Je zPAx9mH}`tazzyba@ws(-G_1AmSM;*jZEp6<?x@f=G>Ly;!BBK4hl^~t*BgHz{C}## zfvG4-zt3Rs{nS{+?<=wOtC@kk-I><vokR?$NSV|Pkm*~q$M8tew7+zK4oz$(c};GL z6$i3Ez2noR-7@$}C-+ZvFtiHQ_vD!#1pNPT{-aW?vgpIdT}o;3q=**AT|3uOe7_63 z$ClPk3#!klF@#H`y^HOG!B-;3O~Y5Z9R&|}DH8gLbWOZX8&6tc=2_r|ZIwcK7crDe zy8ZuLe1@r;W3Dp6CaokMb3_+IAhk+7OM*lT*NcX5Wv_*?M9mr6yAVSowji++w;hxs z8ocy49-0sAuM_e7s7Yuc+p5h{B<(e60d&;-&q0tq`+yoNB_b3#ZJWe-oWFQ1E=Ldg zP+{LE<7wOFg9y!XMX=C>%bWwlf=I@AJ^p#0LoOEGSwiuXcP6Pixj|M^t%X=)08gy* zXze&9glY3q^4qLDba?PUgDs3W#f!;XpwG&Uzp*K_NH3Ina%hBi7619qT*M~N#_wl! zFzw9+Kcaee)ZOZzq=+HG%;lb)5;jY{nXcW(V{SkR|E>7ilQ~AZEta|hcQ@ph0iJ*K zHyeC=A|dBoG}`sfpo&d4uMQ_1xDlrZf6kS!YgwzU{Q2g1%9Vg(jWxV%9*yDU%*(g+ z=lY*^7i8VBj32YXPhYp{$GBni0f{<x=~twl@fghiMaznKH{nx9>mgx$Ar4iv!MJX+ z;jq$gA#GMvO{alIP0X@@&GLiAa^^X`F%NPmjn|Im*W0_Tk$a5z)0@w_zcTpxd!nIM zq2YZ`R}v5B@?#kS!Oz40PH$zK&6Y61!@1XLCfdS?yq{^FIxPP^aV72#dwEQ&^8L8B zNLC2Hcmmh%BShRQ>ytQ|Hlj5s2}LCC)LHWH_+tLpA+EzSMC|w$r1J{a-xmaj&0Xv~ z&-S$!!Y*Mu{ZDZCMQCWJX;~2Jf9{7eY7u3Gh}fs`?M`UdYgAp~**B>~te{f<*%2YT z@7JjWO#v8*IiGoQKMx_BWULU!-vs-VxE{ipF+I0f&MHEGmZcx-WFF0**vnabq~I)% z%?vY(;#J$j-SNP+=p{SiDm`<>{X5~k#1tZ+uA4{|Fn`BF&Cm;j7tz!usPO{yktYsO z{9oA~Jm#OAtRfC4TmK@r;DVm-^<j_wyPspru+lfVJ=2en5`w5iQFX|NqN8Y>GR+g2 zCX&%V3>-JX)*P7QCGFT8d<9&vC?|i{;!URKbr@MaJceR|F(&BXpIn{}>lpaf5B?;$ zY|sVwl0F-%ggRh|ihYsIm=PcrC3`lp*H0Z5#NYa*P#D|PMc)WAU&CjJl)qBc9Ng~b zN+U;rS-p_2fOqlVuv|R=Up|m^ItF+3wP>T}pNmHF416RJRa8^_gCz^n(L0;V9>|?o zj18_k#%!UI31NON;VV{$>eqX&W-QIobDi|2y-(e70d)^$X8P67p0toX!rSIvqtvvp zbNQtz@2C2hqI%Akq>i*#A_*Q&!cs*A<qEPbJtP~Xa=2&G$(IZhg8Ym4E8Bnl>Qa&w z%B6cH@eV0A)mUGinU9@|Z$3LO;UA@i&JY2pOqV55&MB(oZy1}5Zv|PCXyvGLsnEtB zt|D2vZERi5(5Eg+XvCqN+^56zk7i;h!|iHhji(RFx!7yx+~Akbj8EF!pEx-0kyy`m zx7C`nG+}E@6{oP}{#rl?DKx<hnwJ^@Vd_?K6Wqdu?I3$H;n}26#?Y_Z+UbS6x%lc4 zvy$*h6MMjM^=-&6hHf?AN6%B7%CQlr-nOoJ!H*C5YEF9JKHID^>ktU<i>CTDS_TG{ zRh&A1_2ygi1=}es7h(8In(Q-K-6~|7Z2QI}N=+Z(RjBK~G@-*)<enWpV)#+Ot|^-z z@5RCW=H|en?F6IMa6irpHp=KIaH`@;-JaZbaRc6Pv|tLle1s>e)LAnAfZTT*^aaE@ zbo;o&1G^~I|JS_10}H@`xo-Q83(tgI2Z70$vfXS_F%)F#<d;jty{|1MxQm27s2f$d z!b<N=C>Fk`;>8M$KghPVApZH8^IOSu(!8*+xsgzbA4$ta*Kzz<KTFAT3n>a?tRJXS z4V1?$HRmy|^T(|9@4$Cmhq5FIO7+QGAx{A$(A+B}vo`(I6@We9Je~twQp=-P6@IYE zg#UojP?b=)^&Iof$HJN|hM&4S#15fm&rit0Ncfqg@rt6v;cO%x{;K@12-7CwzNSRs z4nnRQIqu2q?v@%ktc+ztH)V;fPLQBGbf}#S(u>e=uul;WX`BF<`sl<tKQO(-q%I=3 zK9*x`!!h6iDspXYb)qp4boK0Pt*KRE-{J6W3rOf0h5d;=Vz+~^QScmzUCTEO<cV}9 zEo7uX6eSsLO(Kf+9p!B&(MLnM`rv2A#G?ro*}6Je1cwIRzwLW%C-b722vds#d$~TZ zUuD;n(H^4%7ffqy-6f`xbV9Bm$O~SpDO3QAD8$)2fi|qg(vRE{%qIYU2*ZQIm_5D! zQWazrsK1l`jUmEF9D}<{G*d?B+JUXPr^_)ffR#6tb@#C9T=at96?$_;N!FQR_)vSj zJDXbr+)-=O+IZ^Ifr<yf@nE8JQ%pW6L%o4hu<#?T^<LY$;+<<-cZ{kSySN-C`t*Jg zpO@Es)m#i#bP)N!2&%A|vHGH1&09KONWu&Ou_l0=WR$q%S+gDt;qWrR$c`FE3%Mj8 zCNAjA#dMXEdFmpJV9VlB?YM_)5JeQRA|UMn3FbKk6-uOJtKACoP=z*_<1t!dw*g># zioV)4>=1BoJKT7_DC(uxreWZvs2Sei<KDN7z<>GTP_L`c?GQilk0gd)lXbQ9hXhs` z(cN#KLx;*79$QWW@luQ^?hB6^N?c$mU6PMnk5IfdS)c)Rr?|z#BL>>I+fKTfT*%u` zCS>!Ln0*`QK^J`2*tkDMshkmZ#+=FOsjm+U^2e{EK265&KOh+U7(fAa5zwX$bY@iC z@A*KpbBvCrBBI~VX+GIKTE?fRtwO6i#}`LFs4M&x_n_k$-oGQOk@maf8j#w&e(X(9 zVA%Chg7HKAk#_1WaQjCd94MAshy`m#XV>dO)B09SNNR;eU8-a-97~ckqvIqHLJPn* z>^Toc9Md{saWv}7Z$o|OzrIg-jALk6sIQKn(DrKo%#s$8u=(%qT1XMiN|Aqhra5oo zU;bN9`2<x*3<E*PPfQ)qpvL=AdcsEV-F~2jG|PkUAS8A*d#EDyfuw%q-M=5NF1il+ zY%s^K8#fxpvzJZ%J*0izAx&F*Y=eR1z7;W%6+u8ZpJ3vW$7WOLn}sJbxc^}}s00(F zRYj74Ltf?$X4D;VJc)DHD<%0oxiR)<^g8H$zIBboUkssKb5gV0$CoBQ<xbaOIfBf{ zZ9o_)dlINW<ll39jicj$irY7eHr=?T#B|9DR-?xN6Hh-CTj;{<eUS3AGbMCcx8+3A zbFmOHcsDWOmUXSEK=E5`@Ee0EM3)b@DTFh}EAmT^<|AR+v6drp3r&Kp<$K}S8USNT zxL@zq*5iG%qk5>VzticBW2)KhMvhygXB5;8)5f$xin$*Ps*opCnj}Nt@rGkH`jr7@ zf=9uas#-Amh6A;p5=7G!1s>rp-rbzl#^Kr!x_l>K&M31T&_V?@+DY+a?e?j}HLK&= zn!&Z^K2aj<G+|Ol^4)YuZeuLRi*NjgeEm<0y%*huu+vE{G_CDRk~qDB*Q>Abt^!u` z-+C{vhef{iPdlDip~H7Ywp&~Kg6s3%Js;HiOa+uGaZ!%ql@F$3&qE?yG1<{Yk%OZQ z{eMqOx27I{VW5WO6hsjl*k>+%WP#K!ugFFQ<x>rbGqs<;f-f_|t5%IK+*odxyKLVs z5FETcr8RD2#ALE@7E&CdsBAZ`AQ9^OhxSJ$hs<&R70dGhYQSnl-iM%1RIE7ERxiRU zpBHW!=mSqEsFvmWBJEDRxC;w37xbSRA98KqI(#J>WF>IS=f-JcgtDO61oQ0XeQq&- z^98~$Nv4ldl4H!iqAG%dS1Xdh>mKwZv2s=@1S@GzF1ck*E!u9Y{9G?H<$qG8aMFKz zYL{wu=GgmKd+z_HDJ<e%MPYz`Sk+sh?n&{wETvSh1$Sb>=2f|(OxN~%eX7Yp3VR4} zYy0k=cnkv$!dS>C-j<A>t(kCpaQG$JzcIGhREP#A|J6qBqVOlG*M(Y;dm|cWP&De& zz6F;s=tx_g=~(7R>c+}vUuh)Fyb+nYvxb*382%E7d5!1T-knw+f(7<lTCY3VBp7S5 z^ibxdhzDx4F{)AFw=q%;3V$B=;N#%97tkX+B~U9H$D$b1i2EBKh*D<r#B}Et{G{&N z{cO%F;k*@i60_Wh4qLccb3-^@fB@4iWvA_1WY`Wl;Cr>3c6IJ30^9Pd^@M2o$kNdF zv3MId%{m8h%&3u5b|^A5opU4OV5Mklj#tyyYx^GLV~GLByIJo33Ux>Cv<)sgZ9@RQ zV2aXCwJ{nVlg1?U{Qbj8)*rt5Gb3-gD?uz{S0LPkCjZL0#q>4XL0yBawX{zZ0z)QU zrr${JdE4xzKiV+$g2C~vUnC)T!G;o=b^Up{s}UeI^PV~)hgg8g@Pig}hX&35yoV2( z9lQSQw@I`_zotqFjqw~ba#wvSE7`5Ndikb2uAg`{DOZAEVu9QDd1?AvE;df4I^9K2 zOQKQFX5lOmYK^#r_`{ve+h~IKQH&;}BX;4ja*ZJZhM7jnzm%|>?&FtN_>#GtEzC}~ z&1LIn-!%&07HqX~1EdftY_ddDktWmBxY47D94V0@O_kqeKnYB&?E{bs@6QARZSO6T z4hGDu@uzDohVraJ*Mao5HtWnxey`U7KGDl<%iU+C9%M!PZ|eRFbNqG(1n`n0cbX}f z3lU2ib(GZ+mig}>NNS({;!J!fc5<Xt*NkkS{Q4F5h4gOY=Dt!0#^K!Cui3Sh^A#Gi zM1M1DwG_vI1>x*dc<$mFROZQ0Vu>i|P0B3(LPqw%rs@Nu=pObe9GS_SK%-$b)>kIH zHN|>t<`8}mGW(`8TJw#>PVc#vudlsd<K5*<zJz@T0kk|QIbS^|Al@kZMD`YxXS>Mr zOFGoGBGZ9=Onl5}dZ@VL%TEeQ$A8?W<D)#0E2s*>?@`|~dKJ=H-QSJ3C~u$3rdRoZ z8qzQ7k9Rp4=9E3E)y^Nl7WFTd%or4_brn<56hBsJngr}tV>_^gntxZ-nvC0-+Vm~X z%OhTlnm7PBkYD5YDs+>eIs0WaDASI1UrpL#?NJmz+rfCxJ~%jOb03He4wo7jZDh1n zm_AQ)7g<yEH5ZL~fRF|7(+%{Ix@rpfR(gk)x~S6t=zK6U-#*{ySm=Lf?_~DNxG3U$ z9|V8jE?r1db9E-w!HfV8cTal!#lnd{^j%Ugn5S_0IF-gW=M%OuC9vwtD=uS-+B+=o zT+Y0Ri^Kq$$h(V<znAT7)xW`9sCCS%b!HG<k@UHyi?Hfq&^zgUux+q3$`smRrF3)N zl+WX|8-FA8b{g5q?UJ1-&l+=Vl@zcTCjs0XXlzlQuu7JSa-ylqvIHm-2U{PI$%e2v zpn*5e?0Joepq<0Z!$Oyzyr67b2+->B?GUmIcIpUG0A{zc$XIc%!BGZT!bnAoI&GsY zhIur;Lp*t&&vP!uK#%f^ZAxf}jfH7rUgYKy8f@V5l-+$vW~Xc!VT8F;^x9X<IJ`lI zHnGHlQ`jBx7+G-ZVXCjTdk^fEYxD9z?tI9v4!1Z1rq`Syk7Zp+zzZ}DIw*smPd%ua zb?&RvTbj~fC>{cc`g1Z(2B8i6v)7yZDeiOz!R~^2wL_e&ApHaz8KmYw7C{S#YFmA7 z2$hY&+2<oj1L3LiHJBD!Z;QZ=*TBnvSnQf=MNjq1fLi`=!3+?@(T&&VVE@3);vAUR z#CVzI;yvIq;xU=3#my7?Xu@0+)#+0N^aE6xpTOHe7^aH>$>t{t7@alJJ}$Bk#%lx| zBd@s~DbrM;j;$`3sg687rJ9ckn+~4XA`TTtrl*<Tth`k&5H)p#|FlwpDIwvdxwsP0 z<jsA_o112@0W?LKcYeaeL$L;FQzUO+MI9)#7Gv%ZGv->V5!7DV)1FKNMZcH=pYI}> zU()d_+VvLi2U?}5qK9F+C+{kr?EgX%VfyC?KR2vgE=fpdos8zsWcZPyCyE+8NHcCn zzOt5^(+I54oGkv0c+mik0?Kj^do<`nwW51goYfFz{CNEFzAr(Q21!FN$3zS}X~jO8 zbwz&#D|lC^N|!04n}p2rYh63kwKz~T2rA#8Xv00d8ARj(?^^b#d(mnCFgAs9G5Kqb z!^Y|5=t3G5Ll6}K4EwiRh|E36w~+v9*7AarC9PrCZnki=)i-6BdM-NCnoLrs+ajWM zgT=$DKo!KToA#A;Nut$ZjlcqpjB~?qNS%pGhTBlo*5Ll`MDnrJLH(z^ip;0Pi`ucs z%!=hJZjjKh{kSy4i*P~6pKf!sBg=&z4I|lvSVeYF6C=997@Kum9jh4sLyHUMPW8bu z16NCerTkRIhy!cl*zW$flzzOIh=5T27G4u(S*i0*U!x@~28=PW8PAaS6;;<Ik(-A3 zuV9NZp0AXW7%Qc%XDP)qtD92RX;_MywE;jWje627)50-6*1WmJZkUunA~t>K&&^bw z1K=xIv)j0z85fBb0+8F@z&!c!Uo_yk?81|@JX`CEX&*c>?=;X_PcLLYW&wbD^IhZb z)_yeop`5DoV@mqjevRb0-bnns^7JxgtmUCrQ01Iv$A;$ud{vv`EJ^V(YK;ZluTxp{ zz-tWn8vc0lW${KxG><BElmn1!k$V0aJ$f$#>cp1RG~WuX-Otd|68dIR_V@!GD{v$H za;1#ZfvAPuDfsu*ad!h6!%nm}znARn!<?x3lM6a5B{;i=q1W}R{lu|7QHIv9q5L~; zv*z+xwkJ>gw16)hq&})X1E(aqxR^=5CulG6-0}(6vt^$DmedoTwy`&FykGS?>oYQC zo>TTRfoU?lh!@b^Sky;&{}gtQsd_I4&>|V0vD3$P@oXWZ&GCPg)?w;1D;dsh0YOEg z=sn@+iisSzG0&2DF7Co&alZu>JwW~g>u(S_wq)LkFXa%j2Fbh+f-t;D7la)DXL9F- zAhmF5Ls8UMA5t7mcD<%0gPP7}C6Q(iaemx!rf>g=J!hMK9ZEUywLq!&QaiD~y5={y z&LLi>_M&~v;<Yt6?a&VzzGq4U->-6K@gw~fsI{<3;j2=YUSJz*qL|w{qT<sGfs(nn z##N2XJH2x$-`DNP+@WGosU*3pxM;zK6p;&jBdK!(-<lbUf!oVmu&kvWh8g-l?T}Bb zRNNm8mlrMvuK@q$M=X;<!_l$uQ(eL@lB~-e^~$0Su$Tt0Q%a5UliWaaUpZ*O$$m~X zq|vT?L61COdqIVe^AAMOKKVXAAfgQ(WM{Sq)^VkRTDv`EnZd3d#xA8MiYkLwB)u;z z7JAgfAM<l{$eQ0ZeJ!4Fc>VEpvRw73t->oKWbdxDIG-=G#=LnE+LQDzJ5|?TUR$G= z6*|ib138`EQjZV*{j}N0920%bhVN&V?Iv@ox6_J88|BSEoWXopb;y3yes2;@l1)o! zkE8tBl-O1wQT>DSYp<gw4u?|eGgC=_TBSI0+2?=*uo<Ef;+Xm{ec#893(IY@`Or(+ zJ5?c<T#>C`WNwvCmxr`cG>*{5O(BTUI5oX{L;$3Z_73Dk-vMwNv+itS^o?*c2y~*$ zF1OYHgj_C6H9p4~`skH*Tir$jXQ4e6{nL4)XejAaaQeBBsNyrPXqtPF6K&Sxr(-qi z<?@=tbjbz3IzWRRjqLXY1~D4PNq$D68J6@gN^=!GI$v&q%BkpAL*D&8k@aljB&-cH zgdU?Q{acE&58yco@U5lc3YGtJ=k-m=?vX_4^1Lr3J<!vb5-a3!>tvqc46LOmKwO+2 z#;v6qZ8Y(n>F^b6@b?iHu7>?Q7gC$?Y3*FALQ{+Xjw*3jb)8BdyOJ|s)kKj(H)-!7 zr{z+bGqiIu2l>Fix@a&>7K=sp-#SM<&&pQhz~x4hd_BYA2z!-F#i=`*BRZY)@L6gG zZrt!BLfLY<!2&+(4AzfSlk&{=mk{^LWnGbdljI=J{f#+{{*bru8moS~$46hpF2))d z-TTAhcFO|oeIBWEYR^YyWt**|T@R1I-*<UmCF&WnkLf)ob-xvJYR8m@2+{m=d%c~; zQfZ+>do|_6A*94byak-1f6+8FTzZ=Tv?7GA&{GVV%F^!dJ9V0$Y`haiTmN`1l=?W7 zH0=2EX*fkTB<SvU_q@4TdH3ykum8)<ZzW>yzxPA@xG)Xk4h7TqGEO+7;lNUo16Hrt z%GPXdYGfs^=^OEVDjhfM>V2oT2z?>=$;ayFNvtWve!nzcYV=$sOT8l|7!vgqtv|Hz zjDm1`W;W@XVE@o<iB$#wxCl|w43xnbKvWGvY{ESJx>N4D1*~VJ*+4HHm|Nj=NH_V+ zdEwQaZU0*CS}snkY*DVC-SXE1dTvlcJYpD;t5*DI&scWG(pUn}r&j=ZZ}hA1Q5%qK zWBqj}frC8wuHnzsP{1u&z#-ZF9ofBPW#7!AvBb5Kb+D<q`;L4OZ+%^m<jXg$ko<Z9 zL;gLqO&oSkOpqFS;x9P+;#<K7IomHh@~e`^3@NgU(JQn-qnAq?ySL*v&0$N=4-5*S zfoUrS60<<Qvq_SzGj$1P=+E9(yN8DrY4BUH#_!K=siFTYx;xR6?F&!QWB(FDXy^(< zmV_ox%|J@hHj<uLuhH2UlwJR}a!^D*MF^PRUgnvI4T=}Ep1+cKxQx{F*Rj-UU3hI| zv=}haUQt^fhnJj<<ar6z5!>K<e0*|m=)GCck^P+dVg-2iMFTva!r^eSi=vQQyKcDf z-e!JseloT`|NK9czushbtV}j>Vzen^{?g$=TXxhE0M(3{z}{6-oRha937#ila#Ln^ zSwD}|I&zeT>Z&cbDHLE(QqM@3Plrc3H`}V#cn@W(Qh{$JvyR$oe~Zg5x6aa^VpRC& zJ&R0TWOs)R(F9G49kQ|t|8l9J72_qwi813pYA<$wrc(M#A?{T13o!A>{IHn*-492N zq;|U^7$?Fd4oTe#0<MF4az3tvR^)1Fl1s(`8zfeFdRLc_Ul|oH5?@~e^--arbkd3q zff|<8+VrQcZ~YPDkej0GlA)il(#X-_%&dxaS4432*S8?ApLyTm-o$zwnFmB4f4oz2 z@<2;ZK_%C%#M50kMl17BdpTFVyEJxx)RFCdL&BEm)tGk^sOmY86`iTgG}yAYZ&Apq zEa5kpQJ(94uXMCXGUF-F<g^t0sP)=6uK;s_m+o}=oK{*hMhDIE+Y!{fc!q>rt8&40 zep{{k6_~405l;p0Yc_G~tgu+9Tf_KY)pq;5ar}%Lo#)sD2`-)PE+5(F_~aJ>c4{cC zBnQsp?**MZL*`WGDZQ46jm4l*UZ)5F9g_r1?_A;~8uJjFQ~$GZ_Y`0K4X_z?Cty3b zF7?3>R(<?&ZsPLDTquoi4?GBK+S`I!vs<F6obMaDuQ3A+zYEi84h!2+I7u@nV)x}g zuW6~}*kf@jR74jPHjiOTd=MP`T=Q^uSkXiHKB))17;repWhrKqNo5@M(oAfwpQEV8 zcb83a6TtZEZJwQOpV_!dWDu#?_C{yu%lM&KB-YgEWgWg{fxEv9{JnGFgR}!5swcpK zlESJp-fMxz>XP9W#>ra?8m2&gyOPhDx6sm{SQv14rQ@(BdBUKdB<TOCwu4EqBoBEN zq~@10VM96QPSe?hU^QgxZnf-(-W`irq&;3Qi+soHE@gaY8QWt{<I_#t^RIhrD~uJ* zqws|}HLH88nIUEDVP5kAQrslz<MH_MTAeK#S~>WEfjsl`vZT4hhb_8mge1UC5DFfz zjq0tJP&`R7$<Gco>Cf#xU8p>zVo$-!=D84QpT>8F0Hc|4#8Iq|F(h5M0rCTq542uG z)NwP+Th=+yZ*fOo_+`_%k@32R85FQqb;<cuc`;#gT~E2pFU%7*<HQP|Y{rTLWa82g zoQwg#U%@eIfb^Q}^iV(OR|sp-nW)t_L`~AtvfU4=&R@}@PtB3xd^KSkZ$Hfl_2>{? z#p)^jxohJ8OQImgoKqE}e<|cq-cw?o#{okLu<b@GS5uDieMwEIHIN2<_xr}#i!+1l zkV-q6zZ>hk_EZIsPetvWZo$s<<<Ug-a?Qe7uXf<zcOQ7A^xE3B6Kc1=|B}%w2`vrh z{_pu*x#|JoF+NP$AWnQ&IZ`f*?#X|iqA$pID*GK`ek*~9+gXg@Y#GpKrkzSJLj#TB z>Fwu0cJ}MGFiphsn~SyweZ<)lSDlUa;KLmA=$DF1`Sv+#kDU&!;`|4P_J`qf@h;@f z7MA9{S8xWpS<cywlvl99OKI6eNcfRPtaJla>6EzkFRh&Fw^u}H>X1JwS3&NdUi`0C zv<;TluJdjSv?^D$KNf1YFS>amOYErNW$uo_*GV2lw?TpaJUE_7Xz2LOsWm^uyQVBa zY*leJ+8kUsLCDb@8OK8>)I(YCALU`uF3jytK5nmJ2?@gB)-9<M?Sm-N50i@B-|2xP zerFjE19p~V_zD8k!=EjEjAn`{8D56hZ#y=~Q#B0dS+IV}xd8eSf~@;i{harb(u!kv z^|cb~9*V$I>>Y~-A-{;eQuo?R!=FQx*j8wxAHOZNSblZ$dj*TY7|QTftx2}{f2Ouz z?k{JA8y5Qc{!)6FSoHa=tV$Hlvf*(@8DB+jnEM&r+CdbP%`<p+=nOp@(mg4l1mojR z3!ROgEs)VxEQ3?Hy%}vHRZvh?OOk*aNgvc=BFoO_-*b;XInZd~n4#4@=`NBN-{Aa7 z(&|I)gcHxMH~H=e`{lD#*y=N9wFHsQInm*x+Y?c<t<s&JqcdLt+}{Vhmgh+2<;$Z` z46dS5U2+fx3I7XX(GE&=aXY_AkQEbeD2GM%6a+f;GPUPe3T(Q|UctKFf?sRWq<tIt zRHEmZ(GsmCyttiv|4U~ZG@4sGU5~gsC_GOl4pr*N^MLIY`2b#4=~lM_;S35avzkX` zg4boE%sP$Ayt6%Qqsa4fc1NFnB{?Sb*sJozg@{jGOtlXk+xU;P6_~7Nc(Z2)Uin;G zGHs=368k36XzBdTRokd$&h3w}O#U=E6ATX#T7S)1h0MT5)QXn@xk)2p?GG;kB4S)I z=)n{?B2XP^jCDB4LYMuCvQkJi>suB2ZQiKwdG|TQeNURA48GP!jV%dFz<%&@0EB>( zX=0<2ySE19|Bs@p3}~ZUqPP_+?xaX5P^7rKyOiSY4#C}_K!F7P@B&3kaCav-#htbU zC=F7A`^)>kd+*L>GP8H)%sBxp3gN?Y^Z?<}45*WxT5Pk|B?eGFm_5<)&i1Yt-FXN_ z<io9EeMw1Yi_me=I$_HDskFK%Gn}He+1dG36aaRg;@ruaO#7d39aXM}C9&uewE&nl zmE^&`fvlu8k^r$~E?0vm-B+4Q+^DZlUpR}ydo<N2?dQ8Gg1-W0>zg)SevB`V*Ub)P zYf-#ju!I$VPSC5N{S%!@nD!+2rdyee-NTw)K`Y8EsRXq~4K+$afPC!0QztO8P4gG+ zXOlC(k`h(ZwFLh=T7Y5y<beOm90pQvCtn>6A@=}nW#uur2<%><6MfbX^6Y&b7-XQA z(i-vwh}D^#NXMz!X!S8pZA*U<Upw{p$}d+faZLe5f0`o&Ul=kRy#4M>Ik8L<WC3c& zgkkgRd(0CIg6F7s1a@@*ltKv?KGyNzpnMfE-{?>h<10Q{?#@OsBV~`1OX?VjwiMPJ zfHZ$l8LB3PtpfMIV64uOYT9u1itU)|%tY(@Z*+j-9Sp>yE<6j@wAe58!fFyll=qbV z)W99WKe-O>wt?Jfe0WRrO2o!1TG!5S+c3S;XMKz>?5fj!*1|>l`K?y$pcLZMYh}W6 z8A4?b$xeS5+Q{Db6GyBP+gE$Ax1hB5SNm+FFrjJ5rn_G~34OVgjGIaR)uBvxZGw?o z6r|7)#DLfU0U*M&@7M7tC6Dbc2Ro|pk);=GAkg?7_K^E;X$$5Xsv8qD$RYM!N_)iX z&rUIvh`=3D0@KvH14RcVinG_1^@9F|VIsK359gcPj$`Szj6u&Q$Py1UZl&i*Bk3Sj zLWgFSX%-t<I9u{+YprFo-dmNG!qseSpd9pY2949en)2L}xP13F8$(%Yi&Tz--;Hg; zR7}J+F`@2WW^3(8zpP1QXzL<{)(aJ|CQ9zR_m^VVA-~p;X&0*Hk;A%WhxcWd9Xfb^ zH8AxZ%VjHsi4?XbFnakDUC-#)Ml=<l{Tmlnr+1GirW#XJ#TqChNGbY_$;J89E*heu zOJM(8kxq2tz>>(H)Xn57WCiI6Z*8FD(33@C)1-&t#IFJbh&R`Md;I#+SaJ4e9WCtC zi3Ql=N3^c)Aq)(v<0zdiJ`~#Tp~^0dL7q1GB7{`1QtuX@eW+#KauhEb!tj%Ro>sfq zAljfu_P25{U0V+sC}wXbHDnn%bJi!o%DI%kH}=n}auP-Htw~AxBklMXXc3cQ?rnSz z?+(}``doOGraA?tnCdix)k(I=Y?9@Vxu3B;4>YofkNHUh9bWq=dv2FmWYS(Mr4OJy zBNXSFI%_86-aJb?iQ?_0YHyvENzEG`xej$(cq2Fnpk)1#Ml00XsK3o@a^ukk<LT|H z@k1<J-!bXKS@}X0p9a!j43%4gQ$x5C`A*-q16F-~#-oq;3<`<fI3}yZexsGX7tHm( zr0Lh!TwOWdNb6@;hR`OmaniMhqk=BV+20M8v#a%bYj>IkS;zIxuh5Gm#o)*NEwj)* zOp~usHP=J^o~1Bx;lO`)5Gbu?BCB{c(5Nz-Qvvu=;?!W;35Ksle9C6Nx%g|*s&{?j z$RZRT*wGL(RFIH#u<qZh^(k}aT;5EO->cAZ3oi9sVa{wA-vfOOsYhQ8O<`BF$gyhQ zUlgf160C6Wc)D2<tSHuK*M1e*!{iDxBz?d!?e_smd-ME5)MNm6!^ia614#V0GDc`5 zi9cjQ54y%_x4XmY9_63l2VkW9UD%@%iYWe_64Iq3807ke^uo<VJgyFb(GqK+&*Kj_ z0XyGo=_w1lRh|dw_Un7@2hR==&HjxU+cmaO{fD{JV3%#}+K^=pR}WBzB&OIuEufaA zJ_qI7JM~iPO*mPxb=&!y9rA!}Fzkxq<rrJJ+gQHH(S_b6YL)uFb)m}CqwrYtR668H zZSiOaS8h8=6oDY_1LoeIr8!-Z!Y!uCLWsJb@Qp@bT!oLwX{~gnstGNFgdkCg4{B6q zaUYWUj5O3GvTYs-US~s-Yr*|jUZ9s{+#WShK5SD-AFLA^^6-ceFX7o>iaG1l`^AUz z?7G>&6WaT?BAygxhfmp~oiTw&ftJ1s|BFu`t3+ookyk&v!=W^)&KtfD^<lt4_Y-PR zIbABIRTpivpe>XV*#&;xl4!eTD6k<yhRw>yz+82hN+t~Ygx6{Kl!*#d0PeTOD0;A# zq%-~ghlr;C2fBT{Ksu3gHZ<Red5-=VOZ|COR%o2)*(C^MsAZ(^A)TcuSrZa-5O6wS z_;HefC&8(`8{>}DH7dt&+joutC=3i7%pH9;2>WkaC;-;uoC&PrEe>S;f7+WY9y3@A zzBY!tO+<u2@$TY_jq8i>yB!~~Mv)#t(&(`!?;%R~<wY29Q{rKv{_W}!aHu|_GW}jk zGA_*Xbku`w!Yl5-*(pqi(9sm0!COatxGcJI%R!<^!bYLv^X%{2-MK({3(Xl3hX2Nq ziCKDM#)dATH~EwS7L~IqeOxH%@mq#0GOi`y>sq@JAWe^IB1KW2BbJ0+j*}6Eot(XG zlP}~|9-Wo;Fs@#ORzB_VmvNpC5<9#xF+F=dX&AI=Y<4Uom3JXLVtw5TgyAmeDB309 zho0wPqfvbtZ0`J<J{Mcheofn?sBOL7Q4bZd*?_d;j(cSL+~>^r<(#xL$XB`Co6fi& zIk;#44(G>U65W-op}wrGHf4t*xxg^~I7x69+0pybI;;d+=R&ELT_>}b*oqH|8U4L< zH@Cy4MdiQGMa~I+Y$&#eMoOoAW8c_g0?LXEekQ%^Gmq}hT=E_%lXC8k;<Q5~=tgp4 zwo^UKhj%-fCrj`uaOQ>Hw}k`+hPnBUT3TBAuP%nZ4}sc_HoDL^3Z1y6_k{ZhbbdA? zo+S?|O5b1gT8jH9FwjB#2jNBHz%>uT3DizT_ld*MOIX_^@^_MKWYR`&D}K|ZR5Vwy zSlYo+S9e+OAXd14XLK;WH`?n$uecL*%75{ZSsoreU!zQTDr2va{viYh(1C|i#OpmL z(R<oejeWApB)mp=m*xc~^2>TZ1=P$oZE}-1b#_|ei4Jk<ExYpYt={}8zqi0l8Jp3- zgx!8Tz^0bB861ksSU{$-jZ*b^D@`8qkb!KO?B$PT>MipTY5J+?=hCIo5+QMA;^>RT z6Z2hw*rZT|W7syG2^&fV5}7CA`tJrU_sU+_y_5C05kz1u|4nK4SwUJUQ7CA@MtBnA zhQ$yY9C&&AxyLkr)sssS`Htmb(yQ>R<FCquTDxz)mQ=V9Y0{H0oMA@l@@Giko1*<_ zmmWNJtVADz2CS||QQkc_1XtR^uW<#Xh{3O->!GW8yE~FVs}|_=A;}xmlljts#-A!` z+7vXAbZ?I4Byvi|cb-|C$4s=ZCXv(~Ka0m&ICXx{=)iXsV9{Qw(B{ln0+Zig6?CC~ z6}BD3l|MIJ&y#VZSKB&ir^<+k{mJlx+(s&S`-_tJR(O2(guRnFv6M3GCzu64)CMBp z8hyba>?Y~eE83Ml67b8gesueJV-LCfkwP#m+Q+H)!5*GBC@Tbf-3e%U9TfQN+Rwri zx<UMppVFYkQqt<#8R7Q1_sPMjcQ%*F2Npdpg_tD|2cdGMhrvceEsl$44llagEOf1^ zMdyK`al(1}BP%_|Zs7!R47SpA1jnutJR6BUlJi|}|C#m&`YiCRx{n8Z8{K_&X*A`_ z>(NekWC9M>EAP0={3pv?yBQ(f5?;16S;UoT@@H6yy|vLW)4sEzTv&eCtasIDWuG%- zoi6XnEv37u%aNZfcuF!{gt%NvBm6rBmm<T0Uu>HT`hlYQ&*=~w&xmMwcuFV?xx8y? z58MwP^PdeQ$0gCS!^NXNbNM6+bVkDz!MFbofw(hv{?r3CRLk0Q_v0Q()f*Rw-GVzJ zp+woqcZ$s8WHtk}qI(vg%_`9&`wpjFk?U)=gAZz7##1KrsZA(tCc`PT?b_MkMz+8E zuhlz0+Ut@V3wut(O<-#T<BK8s-qlk?3aOO`h_?9zy=}s{HEV@F9a95}oY$hw&{uNz z{}rDYIW49sE(h;0L_EAS1_+63qv=xZ1QIn93)1AKusF!!;+o6Q>Maxtj1WxKX(X8n zo5j)!TSQX++z*tT73asUmf=#w<fu2P;GfRq7uvlj<WG>@jlfEubA>f~pxjZR!N~{) ziW382pCS5o=8XObPfVy+jWjXT`<`1d3>Wxz&ay4)vG=G=-2tR+=?5aMAq}<vx}U>h zObg;6w9MH4?HRWsF4?$QQ&Lf#VbHeKo%!Ct^>6vaX4?FH!LbmW0Yo&3SYTybrGR`d zP`j)7&{nioEj2<iuSyQJ>InY<zKIjfk_k`uG?gJdjj(QJP?!N&sv$Lc4G;d?(8I<= z*na^okisI8lUFdY;VNAhjc-;Mm9AkY5g%egSHftAP|Ak4RkY|T6%pQc5b-y21mi(} z8fysgeyG!a9Q*akg@PPVT*DCL76Hk&ceyXIPI-K_-_2vQnHu1;aBo{h4RgKAGWvEs z^ytxUm2VXFXg5x)deOoIg_s69Y!@lGZ|7P%YzsL!dS1JXS8sYU<k_r1E&GFo*t%!B z2ALUwp2ByHt)>&+=4ET^GlvqZbcf;cZiPR4uv*gIws9NItioGiff^?wK`F%>mK?_L zqb^ogNo!d4XeDdDV31(UBfm=FpHMt;tU2M}MofY65+bO$NPJ-%igIQD?<*7Y^?;}2 z>P?<A=7{G@QGpOxbC;w*oCM;Rz?hvdsAtwYsbVi~GElQdCN&2G82f`Ap9oZ`nm!^E z_zGHbQ%Pk@w_bZR*+=~SZ`E&MS8?4Rg&C^0mTFZIZ)b1TTziF0@0Dvd`KQG?t5#Y+ z)Cv{*|Gn=2st9xtk=j+3f{Q_wn-%J8;bohy^epw>bVEr8bI|+4;a~rZ#q~-0Rnvzi zIApnZC$8%Q<&k7BFMUBN1uY*fo@$T&;z70la+Y|8-+ru+<tE=K`Njj?+@6L97#IY| zwEo-paJW%3+$K&3H(b-yZ@1i5o}K2`f8N}jvk>K3uQgqTjyJuTE?4G$`GO7u1f}ea zMTk*pow+SUMdEAFg7&g}nLwOf#Tzou*3H&f*FIih2p4?Fcvk&1WyXdRCn(}s9&pAu zR;LFstzECl3ZD84oMc|pp702W>><|k7%_^KqX?{;=AUgYXv|vU|MUKnMyT!aA$w7z zU7@ny@Za)_yd*#LH^$H<#c<LwmSR~nJc+gb-akKct0!{7#IFe(sL<WbXEABu%_L^C zYTS5&?*%>ltfyL-@L?}{zWfO#8B<KwEjD%BI-DBklPgFrT1fm#$*-nur^Iky)0TTp zx>c|*sd3sbbM_pGw*VeJ<F}xQR{g~yZZhZ*;iV8LVkl9sn;J&+^)1Nr*cTnrxMh>R zns&P@mG^QVKH(AO<+!a1fLpQ@n)-HVEnzn>g8h&mQih=JlCxsWG@}voU7`-Jf41*0 z!lD@Mt)YN{80;@4eZ)qxm#}p`Q?jZ}Q1IgQ9WQY@=IQUSfmT%s1xkB8Vm#%Im($W1 zd3_%T6FUB{8DAx)!6Fa2HNWKu-`w^UWYJ+t);_=EPU|cXWB7VrD51iBnHOcoprdP9 zac5*$YEs1ErOH4$lrT?2rC-qGr#9iCbdZw>-VU#T340YhdUfb2)4j_mjO^je`1P*U zyw_BJ<^JtpzCEi!VG_yq87oY>Vf4Y55F#C!Clk(RnW*UENxX&H+K&c%|H-mqm{H3g z-p8!go4m|c)-CyOYd5IQC-naMdu2s~xTmxaro=>p6&N8Kn%GRvGY`!6z1f$3o8Lzb z!WI$Dz`2Cl{)m(075cW*=Z@L=747hW1ZGNj@!yA|!j?Q4E&3|21JNi67VZ#$;7*k+ zSx_N<YfdxCFZ6w1tcrX3G!ASr{<0_uZk@{?>Rx^2>hFk#>~+>@yj)JGOc)=l*^Ov~ zmAyhW+KbJXhq6r;QXGgI%z{@woE*pJ++6C5%f{&T$Phtbz~q(K$qNVgq9G}C&=ben zFYct?GF_zgipP6`J#o*X<ceW#v87HS6S6sW*USxB{uJ>;i^pWK-Le8=o4j&Zu8c%K zL5<(yL(gfvi2PE&bz{etm7)O)e4^e5)9cOV@5Y#sl_+0w#*%iiLYe<>swh#95I=@p zv2&^!0r20wY1k(;$&k8DJOsaGbyRf0iKgTjSsiWg2|yX%3t$}8*T)}YYgPPC=Jc?x zurig`f^mnX9BH<ymxdYj_+UL~B0EdiSX0<;5`iKZ8EPJGFT{}<uCgECOuebzGTK(i z@ZgTK7{#Gb*LNSlX!W$iR^0Wp+`EzmYTY4+mAK0E<)}>YZD-<+<Pyl>z(7oo>lsXT z`x1`mHDQT#SiyRPc&Shs>6o=<U_;PrMN?xU<e)0=I~)Qiy1{E4OSvt<EJYj;ZP!Ar z$bRjyU#}&r$YX?H05O4rtt_fC8;`FmU~cKpQZOU5SjB?yg%>du+kPImlJEoQW7c3y z1VFnpaL=w?0zV&yL_Y=#taWiQPq{FDWej=X(QCIHft?`f5%FO0d*-s-vY-B$)q^R` zP)L_B8kCz@>mv(5<z!i|Fa}yZ&jLdT;7|v}N25pfjSydyCt=w1cfcXBZl)LR9<#kC zAxQmFpE+uaT!8azQV>YAckuHb6Pm^S_~N3Qa%R){8`+X(?`p+{D$4-X{9{a|QhHY$ zXK1242q2~_<lnZEhZr*ZcIGXKtfbSoEk2$}!_k1;<fo_wIykkDXnL#wy62hLjqePi zG7JiO|0I8K(Pr<RsKdO1nAu4yq%Pk5{8)`L{c6tiPJ#`jpJ0FsEyd^*pv%N`;@7=^ zHXj({1~Moz^`P7_IA)=Ps*K*H(NX?>`U~dNpHFJ;?Us>ZNac*z{!_x<?2sa3DC2Pz zY0uMkW%x1`g!8aG=23eQ&r7CKk>&YT4*QSye-n}Dn*R+nq5<pMXpT!aLBP65vyXVG z!~@^PTj}`N-<zyLWi`<{=jfvhYr*37%mJGYqr>xL-5q^Or=G7Pg?m=^#7Z{1lnC{= zChEYP;qnJ0N&ye+wZ^svrcS+-`L*4_SBH6m>6Tby*8P{z?}T^Fv&L{%X#1A(Q7v;% zXDMMSD>VP2`A2|CufN3(8ql8gkb`vKLV`*i5MU}xc!3KeoD2LW!*D(%ptlnIgO@YP zge`}WmH(HC41;$L7Gkp0`Z_z|1dzaf6Zwc8a+nSmz>l+*IesI77gvRq_(|?F3W*Y$ z;wPrKcTNBCPFImMppDS{=evOEi~2s{>ZkOqYQ{eolBDhH$D192M8-zukyW2iH_MZ0 z<^a14(n-_ixp@vO(PY2as;eJDaP1KP&iP}2@;&us|IX7FmGB4&sI}>^8Zwk^>o-(x z;7<mJIy2lQtiCOanmr6qqT;VhqD~TBdNR1hUcDE0TAqFzv$x^D5ns?Ba&zsxZxWFh zI#(50sBAI!uYxj?3N4Z@;U-YI82k_8VkYA5)6Rb+-y?Ti(Gi}|)?(%7>+PweU!EsN z4>Ze8Zj><X9odH^XNpeNYTAqf!dqKVvrz^Y0yVinvn9T=89`+v5%Ww7!d6Q03=^e* z*`@Rc+KkOu>WHjPNkUUBY^g<nTG9|OCi-#-1A2Bpk$+5)uJ*3<!1QUP!zA;}KT`9m z%Q}Ove^180VgeQFj6v9pNAyqEkb#kK2TS~DtcO7lgY}A1gNIC=-rxn~?bp?ne@#3q ziq_{y^TNk$MCZYu{KcQYUb*?k#RN!+CqK`*#)P8AJX+SadW_9zt2lh#iu#xO?5Fr$ z*N-sC<i^Ur{cmn%2LL~L-$Yo|5+BOgCKE0(lWIklHtU7Lr``18a82F0!sE9{w)4Th zMe%gLeP`{rp@>W2C=EWM;r0@*Sf2~X$YnOS8B*{(mvTA_aSZcL1dIcDYhz-z>(ZV6 z+sKUs<|)nU!r!kDgEHQ&%{VT@#B+n`TQf>mN?u{y0m&Pbj9?UHgh*}6)K}t4vx6S* zS8zZXic;d(2Pw-FHxU-fkTcP~9$rxXzLgQPkS3~vIW<fGTtFFX-S`}*7(SxYklQZn zz*QLfa!5Xo{vT}6J{4S_jp{mm$!{0~iv`}liFp)@DHx@31T$I-W`N=GA+FdVJ1=)V z-6==q#xMy5DSX&K#a=bc@Ti%*W!4t<ekCyZQ5xWLFu=eTvW5+Rfj$-6GU{V=V<x*i zum2vBNu}2}8h#JFnS$t7neUk#2EpEE7Y}+U`*Y5X8Fe*FfAWrgDmG0n7=!W<{eOKY zhP&mR3U)2F^q4&frCA%z00`;pF{*~~nA773E`&egshxDfl(WTRgX%6xR%)d+d~|=o z<NC978`QYA8o>DWkmCEpfJpy+#HO3Fg<^MHS!MAAOJZ~kE4&BncKWk6K&`YE``sk0 zfBQpRQHp%`ImwU#k8FBr*pYTI8p*cmv(YCeRKLf^w$f|#3fKEdj~TUU54++y^_C{1 z@a~m4+^)Xs2r29-*K};=(v{?oR9Ojf0<Wtj?>PQ^;^33ZBkr$Zqf7`Dg(}>o1!zRs zy!o**Vo}}VVz;<gpF~rH9R(=YwC0LUKZ!rB@l_QR&Z>xxJ(c6A3@+*EBpMyW&@2u= z7*vDbmdB8HuNc=Zwm>6Ra6ya0Gbzz(KX0u-Y;yLhdeMg1)nrU}xG?r8PZlWWmSQJe zr|l#vz)<%UtXm|Nzr2(IYRg=hH!SwGo7VU%jw(lCeTK$SDG_3XOrJ*ZYxnK@(Kc*E zX;*&!USui*DoiSH<qe=G#k&ak=lB5S0sn5H4dPdlB7^A}M^lOs5bAyl5PQLer3{MG zz{Y8q*g$al4>><gKKEb)Ra$$|TrXWYH+F53?#mS=LGsmqecQ=&DPcNaIL2MYpyG4^ z%}Sh-IoyGZWE9D=;p^}ET`6O8)3(wiD2hJ|EPQ>(sn<K<lJgMIi(b=owos6rj)+(e z19@JywVejYttc)sMe^zIZs@&N6?7St%pK~ctGs{E`i&|Vv5SRx=mJ{gH(~jAOzX^i zqu0lQagZ8g!$fwU2w=E)?D=s(-JxCCJ_=VNBtQ#Vhz)5U-kJuFBb`N`hWQ4qduJgm zbhyDWY5&&d9duC>y&B)`p)W;U7i|pdPc8{ARc7{qgW4S__)@0mKx|008bz3c2HRjg z@VlO_H`h$9zSycu4y6GSmpU<0u#Xk|?oI1t6Tt?PVxB|i0&oGyi-7<vH(?_*?<qm( zGZSM!|I5U6`Lgju4@=Ae)Qg;kDgz~&<q@tuD`Lrh6adGRA9PBh5^y^Zk?A^tLeoNd zXAN)jsBU#tyt#)}>>k@tFZTl=4TQ-e<W*K${dTU2EV_t{{i73PZ=vE>K~lh!2lTqI z$rdll>~G5}AbVQ`X6KSz>%fD-;<^_7Z<8F0=pK3C&!yK>-Gd$$C*c&IB3NjZOtuH3 zQZtFzGdH>j|45OK{&-8JD^#UgfxXFWptS6(=$CL}>bDGWg}IujOGE5}IqVOfLl$0` zJ60Satsg@hWnT)l`d@JT%VZIXB3_GRk;$_-s^FcW<G1(+C=?#V6zyVvqk8y`!LN@J zKfA_cYOECw?6bKpDHXoCP=UFFC_f5e{jN49&5n5k8fFH)hEB1l+LZ5G%Jz|emBj5l zI-Ub)e`zbl@4*Nv{#_S)MkI1e(dyBMOS^5|Sm5OB8!<?6SMF@#89@<`irJll*15Jo ze*Dkq+q@Esl@2<v6}&Jn29Keuen-$@y|&Gi2Th>iGc6%$iZW^967G715d7OH>=lFp zHJlojA>^PuIdXJ<{YVXa2ObX5`G#Oi4!uwY$p_Qk;Uel3Pl2-k{k;oUge3ez%$9`+ z8@*5Hy8AN={6Gvlv=$4X4Rl%7_Jh!ZHeX`n>s$MnnMvDtt>0rp1MJI72@rBd<zXOf z8by);2&x$^?3NSal1xYLHYsrwNoS88MJEqSh?daHck%@1cSoQHF{uqmOehF=ec4*F z{Esg@<`FNPJ|Ct4geHGLJOp@bTQwHIcYqVRa5m&L9)&1mp5_aV{}j&qau7lK<t%Ws z233>~0$COL8zVvaTExK|?z+V_t(^6G)J?5jZmOf$3{Dob8X3Bf%8mhi7~x6*XUxmw zXTF9$yndpE2yIvSeH#&}MGrQA`T*2ZsJknS00h{BGDNj_Z{E2`n#CiH=dpYKP?X~u z=HG^2v=)JO7oNCcg(MIy|AvW=QxRMHf&8ectI$uT&L5+N0Sew7(#%`T?4vd^QfCE~ z$eB>+$7SCrQo>LtnG)QhLMMquqYC1Cx&hdmuCtR;(8N={vNy4Nev)YtGHF6!ceh7V z(56+8Z}TMvvQhg07GGGVnCo4C`XV}uP&p`OHic1^i9WxFmJDwGM`4l$?;s=3Tnfm7 zYH)U2xiI<kB2)Y}z;zK_l&Z3P^legjx+$1h)vh=_g+w#1w3ZVCo3wN1<9cS&D^T}r zToZP5s2~PxFkWV-ifmsjQNL?B%&cZlTa{hGhez*iNP(;Rp+=R6ab?v-J0QozJ;Sdq z3;A4<$#l|$%U89Qe)xz{1Xl8X%IOv(3S#O)u{eikCt3mkBC>Qf&;C3;$(-ESW2`2j zf6($}1Hj`q^=21UbU}T{!Qi7K`JGOXhbz=Oz?Cz0r6ZLymI4bT*lD{p6Epn(gc={& zGam*jGgvYTHalCkb7BUEem}xoZ(B)uqK2{L;+YO9gDky=fx%zH{AavxIJ>#B>GsDE zD(wsjZeYu#gM;>5WvNhz-@9~RTH`ygZ~wbetA=~Uve?=1I^K25DXltL@d^!OBma5t zyEBXZ61OQvgnlO7!W&^g06SV2&jUE&=4{KVQDUL+;TLrZxcRwC6mm=voBWzWG*Kqp zB)A99NM807xkG7(yMisayC}RZ)Hh}np^}!3kC^)L$Q|y4pr(lJqyy!@0j_-e0Cd!a z&*ZWp*G(Q5_G~a>INI6cwOhTnhhjhs0sXWlnoZDlZ!Z(P;YdMyTK$|sk3fN<v++rf zUr&cfC#=5=_5Me7*NGkTWOeo!M%!K@vP1U7SUN>?!QFt<O^s(a&w&HAA&AcLzy-_r zymxZ<lJ}O!3+y_=!}z0D5~)Kbf>HFidKES*Vcf)J+S$xJdT?VCpI&r3Of7W-RR+p- zQ{c1xS$y+jf&a5exCtiEM{DF6IcZ`#;Jq~U9H^dMTo}gt0j|Wgc$ZLk0o@#!e(Tp{ zV^x?_?A?-&+NsM5C8C1S>}3kDT1*s)!?3YnN=o*id{M*`h&WQT+Uq_S^={{T^ANLR zx-gzMOV9wlb<Z7_iROHl?xvkgpY-Gb^xOwZ*m(|35o<kwqAtac__ZHiHe-TzcPQ%n zwoH_i>c1}%ZJX1Y2-l<&)9<+Ux=H}c@)$%J^B4Y{JF0Aw9Q#{f-Cdpa?&PfRS6ZAs zZ}9O2YZlU^g<7%@x7Dc<`e_>m!3yQep61W-K<&;6pIj8wwWRZRi4OV#&L7;P;4dT- zkTd=E-Bux<U$Cb4p>5xs#QY|&@LXw=GBhtsE)DQWtldph54o!Ch(qg@J!JaWNQ`?- z*`&uVhw(s+j5H?+T7L;4!X1qGu}UzymugMG*_Fqk(nd({neT+>F}O7-D82mstKt)A zB_5rU$U@W?3x&n57u^58ZV{-c)fG3PyLJQRR1tB{{=iZAGlQ&=UJnj}pTDJ#a)?Y+ zWapPr`=q@7*Z-UFg99WSk?L$+f7MpYe1-;Nb<-D1yB3PxIuDEBFjvdqiZ)YO&Hb?b z9ho9IpD$j2YMu!Y!UnSH8sQCj=%?zTvuQP1C^oez6Ye#9jq|+py~!@7=AuN~j=diL zE(u(DkT2`iam0kGlX;Tu1!J11Uz=DGBKoDCQG+Ay1I4is-_M;cmnx_Cs6N8e#xee$ z8$?J1cjPwz8`It%|B-Sf(v+~L{2dT{bYLxTdU&1Y79m_p*%d&PDaR|{X#k}9X^P&7 zuHsG$t0jmDeMr(F2p?6kxU{LB0G~r|K5ei%X8J63QJe0%(lbIt(s~F8gFd;hM7I@$ zBf~K4<tn(>k}LW5&gm4OzxkxZ-I8Sfxs4~v?txo9Ug)UK>Ia+LW|{idw~_dB4PVNe z_?>3SUaze6h_RFWV@y!L`sz1bdXRVt+@*M>Y|G6={3Da@oc6-J!FmSqK?amYhsNo~ zqVv~)O`=LCX-~#Gc7rOoUY)N2KB)527qnU4d;k*7a={E#*A*-wRpXE@4Zc_i4cxuQ zvcRqOmWvCdvP-Fq52P3g!`;(+MZXUpgX8H+Tg2<uEa1Z|KK0vbX35_P;B<E0zO7Pn z)kka}roK||G|p0`LTXA4jg-FM$aNy3*Tl)RmGNkCODf3ZVV0he@%X)RW2`JF0aUt$ zFFsm%r>!vN@4ALjL+kr@EH9<PPRzF=*rVw#`_Mw7_Q6kf+fI3;{@t0_DV}R+Ru!TB z{dP{<@!$aGw9XOb2Oo!*`4g#);W_i4PhapVXg|F)hZ&;7Tu8e3FlN5NwabyT9@I4; zl6mfs-(nr2xv_fp+>+jyS@QK-S<_&NH|nfe01S2EOFwfvaa>g3{%?Dp=2u}|QxM&C zdmGG4k#96vOt)Cg!OR?#pOgP6eWnex=QEJ%`eiF8K9EfEZ}o9c-NQQb%DCkDT|Mvb z!RXITC_!{xOCPP{(q*_SGjraV={Q!p{8n?-SM$Nx%THpGbutVmGo7pys#Z<E=lj8Y z<or#}7%k`>e;i7uad=xl$?v;Met)Q8)FW)(>BcX#Wr5jK%Iyj8^0SiFv?W{SIq?wM ze;q!vQi2LAzCD8WO@yPaKmGc5OhWC7j~}yxB%2>VsutryCq9P-6A77bwzWt$S&^un zZswRzUZ4Cj0mZmR7Ruv3_8G;CLZ6ORHCT#p04#$uIArOB#Q*)?m@@Mi49#=cO3NmK zaAFfxPB+HNPojOak6R3NGB2s?*~v^;DXfh}31VdZj2ly+Lz_W<Ga1xZ@U=>y`}&W& zd3y4FSWn?}OhLkmAXFEtqVWe;)bW^1YOn!pX05hgD;?2HSVB<u_3gu-6me`IIdYm8 zu<Pm<`!!Y|f}ztms;!+wS*OreBR`*2`ki*Vyn7xqvhW@@leqJcO!>|H5Th@8>{=h| zbncoez<XkV%g79Mi5ze?{CpR*+8x9KYL>JYgeG2=aXR7nK%R@A@Id^|*m*3SH`o-j zR<F?R*EM@2f{GBSiId+lQ{DzrdwWdD7X8VyW&<sI?x{k**?^LxFaGjFnU~6TSKN^F zaj4YbXjDpQ&WDX8Ig*;$Wqa|w>3KC!nV+1nuo49p?IIv^1c3%M=R^+ZJ^Y+!Qxam2 zkw}H`ej@`2!=X2Z!B^{#7H|izun0d4gJ2{~O|Y-gbOnRZ-*pku3{Tz(BSfSf=UZ+` z*)BP3qYlW2tgQn28(U1xTdHsoY}22Ka-tt69QH2>J;J|JnK%}(0!h-%Cgo&kn)UG? zbyNv}3Dg82Y`tIfqcULbeiQQJ_&jS$xh)*oxCF2vhNxbhF!o(${vVONxoBC!_QFvJ zx5$GN!3{NtBFThU)K%v6f)b{dY}zWDIH1f!1#`gyjshx`3*vybk#u~z@Q_+Utd)y~ zt04q`Glsi1(uNQi<jozj0LXO?<&0nPjIdAm|8HGW-*W$x|MhjEY~2UTmMV0h1g+Fg z;I=(rJjBq1-(^JkyR266{2bX_%+?^8HwjmCffVVJ7AOZxb0x;CKikU(OTjUBI?8M{ zpG;P2`3yHx4^1=-Pwh56?4kn$SjX!^2;1tiVufblAvH$Jv0x9}Xr07H%7o_#etAUi zvaUHuJ|(6gUE>7bAAOuB_~m^qbN|TW)$#9Hh9Y|aqhrt5$2&Kw9ztl4R+uQXUdJkq zL$>HZ>qG*&i0`~Z0vhiy1aZba+e5HA;U=#TX4E;d4E9cp(=tU~ytHb>qa{~l6?gu8 z&FV!LNXR4(ux`F2C*}%Z=p=oxhOGRPeP$}l0%+S8NakaAraNWlGVeP2A=C9Cl&IS^ zdfUjMC^UdIbtSqdD2eeWqoZk4YA7<|z1+6nz$<q~86(VcWWyb$QMz-A>p_frCd!bI z4%f6~3Pn(a1uCLn_mmIBjJn_ZOFj(5ET93%{~QF`L(j(q#Z=~k&l=bY{?+<Z!(?B> z8q~psh|KGysXs?qvPIK>M?VVhnQ4$xv6Wj1(@&oMwKy-ouGp(RMqU~e*EO1ILV)-a zB!Pk@`-Mfu6%<-VJfWo4s?1#@!@X6_kXzOJc-#|mo#zAl&5C8Cf93vdT6iY{*6`+w z)PtLO1MSp%wq1ilx?U8Rv_J^jhMRmIg%ZRO@S^e^>e-mobJK_c9JoiEf=R5_PWSFP zl1<tf$K>BL@R;yIe|e^jkpudfFDetJ_5tJ3E#2cKVTO#bpA~A@B?a7pFb0NOAT?CK znko33RSkHLh~%hASBr5!84cQM4r_{$oG1Uv{xM<*z_Y|@CQASFh((ia?%1FN&JWd9 z%&ehvQw`5$Qa&?g1^L8%)+7oOo|e@Te!>JL*ES`lJ8`@b0nsf#L-4-Q1j;JR$n7w` z$L{n9`+dI*@LaWk+YHCsbf*L_K2gfmGxMa=0fgV}O8c!?7337R?qBk6N4DWZig}_R zub=k>%Pr5&JYNA4?rrl0P94zU!MN+x2hhgBsj6aAd~0wF9jg0qja9ocU;kxx6y2z0 zX#*Ra70~{<c0qGQ0tzNR#YzS!*ZiAicYnh$_6bRA<RtN5RKdv>U|ioKNnW%>)}o5? z3MH6n&{g+ShO{pD3LoeZI*Ey3ZJ(!P1s#$zDf`FJ!DcZ+xns->vvFD`hy9K@WPJnZ z;rVf&&T|UCPTB*MX=-?7+D<7T+q0>JkmS9mY$LPq_(8v&wG`hZtM)4~QLN{gcMpVB z==9S1kM8)8oI1W%H^+9@G5_UL_%>&~sSpbE$iIIQ?QcN6TUC!XZNBNUTqn;bGjE~9 ze>J)LBc*mUJpAOdc}#mfWXkUae?NF1bryUSWXQR&um29pH+f_DyYU^%ZrNJ$XdZ|0 z5kAb@NUy;>&FomzXLBpUdzvulh)SQitQ8JDclK|-TL0VJrU+TAIp67D#r*P;is`&; z1FFvw4qhp<&vXTy6eg+M8|n}%QERcSxN;_fv_6&(`bTdobQd@^dU5sjvwHTwP(vNR z&*4K;KE?EKeSnKCLAVksrehxO8K!1{VMkZt{dK6oGEcqZ$@yX{;4^vblU1W&tz&On zsAx*5PDK_LB*lcX`>bAg>*e^8f59zzr4D&KFi-1Yr}z3N_KLvu2c4+SbGbm17L_ny zH;>m{GSMPx&n#EX27V=ola&{|JSQyJ(ie36*^u5LymQ<1Ou7OpIOYQ?rUlV1=QDdI z!S>xvexx77Y(tra`CPJaU=GPEPsAdrM(wFmsaug-RZ>vu@|4f2vkXCdrY%LLN=lH0 zJBG+m>G*@yo0lM~UU`Pj9pbTRFl}puQ{gIDe<OY05qVy5*VhE~SBe7VXM}fNj)@l~ zHV6RH5KKgXQg<0M%asfgXiXnfW)1HG&YT}e0>}A~n->rihQD>$A|p_6s~040RS$wc zQU1Qw;lYlWm=}9G(w-(k6zUyPMJ!*@4z)Nt^@=p5Mi9h2_S)MmG4(#|4_j|nUA4xN z@R*&kUOJZfl9v7*48Shxy?eGz4Q)&9S((4@MoxWQ6)sJLC<Q@mH3U^@iC0bVO+3Tp zsSX{dpjC?Z)PUVtI?;@pyz~?$|75>35puad$-=u4z6vpP2^BJM2}A(ap7{5S08f^+ z6PcHmqswMXjkPY_@3H*)LM^FgnS3_<F!Ehz9O8Nhzb9_w-mgfs!5LDuSJ2&JI+~MO zF&;dB+bSVI@4qh*tthZ<pF=3$eR1!_QA!!sa7WTDA;0Qc82^e}-U#@UoHfr;9OzqV zO`e*l0a|u+2Ou_+pKSz{{r3>&X}NG}c~Wd9aJKz-;ki`zb)dxFx(6SBV)6FX8p8{< z{88HK#RlQuFG6g30>R2!OQ3fxe4oMez1wkzVT=)dsS*qR{^~C85i?e)yY4|Tbf*p{ z?C61pgqjl?h@b5YOK((fyMl~iFgb$Wvx(A{$!4+bIpw7RMBC(b*yFH<$fE|hK$bxy zJZ(9K%jD`M%Id#>UsU>7om-^dIy%Y<A$%zS>EtbE9wvaxL7S$Q+X5H&EmMtW<ISF7 zoyQkP5s0A{q&_a_s+%VQ)ZYE<Ce**1vN#9K2qjTrSbF_qN9461Ab||ptEp!)D-<TJ zqi?|cQFr21MHr*BHwp-S-vd++QI-v`3<o&Iwnu>2Rd()=9Ft%ne6_N#{zk6s+ZB8R z_bYnnfd!_iSN9b?gmmA8m0_pqcD8QaoF8h}LYNH!M5OQ=6WX0w56F*4RDe{z@uBAf zKsy%}60_YZ@~%qJ{gm)+h;2u0{q-gPG%s`fXY-1qzb6J=UtSBkSDfutntA!7Lx)H1 zpH`GD0N6vGwEF`hpNj4Kxsf_Wom;k=-{>$fTi>wn+YLovjN^**{q=*XL;6ea(VqDa zKdzz*9@_4X_kSpG|G|-o)!A&y3q5O(7X+LQ9gA@?2RZhv_>`;iG4M|^O2Itea<z3h zFyb_p>TGb^?5`D;pnvm5pR-!tN6|KCGUS4K2!H9%I=2Pvd84I1n7~*Y09-EM(SQp+ zU~WYVFoZhoZ#Xe9B=RQwQ6aaR_5&22_JP0?dX~HeaBMwkDY{7})$eM0gU@m+4G?vh zXv}<+XL?|Iv#gnjGx^JbV#enOMva}NK<2CUs?zX|>a1*&!y1~J8rW|s8vVI1<MPJc zS&EfZDpV2qdycFFfuzZFJxo`A7xQlhW+LLQ5x1pyEF^s@COzeR0yklg@<J2rL*fVl z`j3H-dUplc8+lrW5D35gW<bCc+iEvot5mU-Hl><E9v&gzFD(kDXpHn|^-9$t>C}>e z$D&Dj*C0Y{j+xg61@iJkRdF~bN()Zp#yGc$2$j;(c!lR$q*~)9LqEzGZ8RMd<9+7v zyhr)U)5hPtS`EXky^?8Nk&}NrX~nl%7^%%QG7JtYXURe}6)WAcz)#mW^avA6m7jcR zxKa49Dty0$;ZcH2xov0%8wQ_9QgXOq*gUIPbKdBpld)4sI1w{+Po)H9ijJd5FZR4$ zGTaH*Q5ZNdugHLIVK;J{ob=h$kA88B+)N1HsdVA6O}tDG#ijK@>N(}jD+{;_eW!1< z1YQ>#O|S;idehyK)?|tx9i0G!lVhdq!M|3t9+`XzI$6irMzeW#`9q(VasBd_SbE!$ z4<El_0cYoolz2yT&n4~Zc|!fo6X(L(QHGldb<jyqX!U)f6U8`YoR!ZTyayuoGG_{p zuN@BH(${M)AdcvfQp~b!QJj{pKbTyHs2l&?kd5tb+~#13a)r2k)|6P-?tx+fn8F|G zUw1WlbhvvVB#QCp7H-Z-Uth;m2lyv%Ej&N&^(TCNp2UW^JQ=D_iXEn%w(YzIB`ZuK zg>0+1R6jB0#cbKXA}KYgi=bJC_bxnQ;)zuy477Duf5Txy2B5Zj+A=zp`fz0i(aZJC zfL$|l^I1PXzp$rkMVX+qeg4*+jYjt1Vsp{7(29?Q{=)|zvJe;d0Kj5ApqM|d0Lft* zZ~U|6gS<LDoz^MAZ1s;%6|ktSzO-U->L$13Ek>BMnPpMdAB4F~P{cl35ca3yBm6_l z${p~OtjMH575YZ3!H$~?l88S@f0SVQAOxHdr~kcSn^`ohZ({wmoLR8+^P6+!nfUKl z<S`Buoq-{K2lLCDGKjt!8ki0oKG#rh`uq_RV+QqdQqxgp`Q~)mN~pVzTSAWGqs?Gg zaiXM2(Jfwkt<M=&sbMhHU464R_a6A3*%Nk*m1<ce>PM}zV;B@^ChsCX^y#c{o%k&- z9ns$}3QT#PKh$WjRWEwq!YCAX5@KJ2PrB{(2~c5wXRj~bM(AhPz73WRAG&Wo(1-sF z1O!!L)~{qm^_aK&t^NM|F1ZICNhh6!jKGcpD)~mRpZK?tpC{P)Am$=qV*}mw>j^n! zlLR|Wuy{T*Tb4JGs@GZ`fX6ky>THj#^xcg~njUyoX9oqwQ#Z@ucg2L~qA%Yn@^<EV zyABIRB=#@e?8;39a$(y_fbfcS*2!t%j+2H)@e^ZBdjp3X7zf|otd~R<sVX&@PkgcY zDCc|<KWYTQJ**Y|K7w}kbi0gb{-x8fP@xb1y=|OQH!Rjd!P>;!bVIqZxy$KP@ZKGK z$l`8mW1hcswh+&I1R%uw3&KkLS7eg#g!ic<C%}4V9qXNy6K!`eUX#B#r>naKuH}dz z%Esf{rACyx8#|VJspmJpSc5WWx3+1FU_9J#neaPfl%NnbS?|w3W_bJ8l>bu=jHU~L z1pGQ~Uf&R&aqPVcfHAG7#6*jIGiT51XJ#WM{}{xgGO8hrw&dHDU>vB3|Fh{kS+EyF z<d7Wg^<#VD64J+n8oq=k`oVsm7(<3k5!o22XEOZxk2Yz3gOr2@dIG4OLd`{uEw5bX zf41##L-ji;urd8q^7oc@nd+rT$VR?yjIO<XstV-<4$Q>KxU`VtzYbz#NzzIRy9#@J zT-;ir73)rf^Op-Z)(O*$Ywwl^r#!{vUcc(3bI6tD%!G<?uL$j#!3*q8BztuDkAnii z$~hLwv%3^Vbz<?|_gl`r?jY^oU&X7pqs&UM+C{wiRTTuGZ;W7yKI9*o96|;Ez~p4n zg)wfa$5@^F)7{s;JSPEIfTlYffQ+t>K5lq@VT}D7&V{VmC_(o#xq5DYH5P@jpb@k) zmmlXOsZ+E{V}AVM#WN{k@d+^x2p>GY$FzN9dL;@r&tR1;3ftIRColx{*w<hEYz`Mz zOiMMaRdx<lPoE$OfpnV<YJd$C9I2^gFisG)$2R=`U9Q7y9_+d!%V;M5kVi=X3;mh~ zE*|BOdH#DtbAJD7aGu$6%p=EZR2bwl*FXA;`Y&XJo?pBPm*VR8l+K{y|B@u&RJ-d- z!SGoRRg^pPOo^S>`J9Dk3=(45=O-#}hZtdY{hk#z3>q3ulp&&8sHoAPGX4o9Iw%v9 z_I!}^PY?e?^Qud}qS<)GWymAmKJUb$1Ax+o9W-Zy3KM3J43%7I^{>-FJbu>z?w_|U zi6d5yy{UeS2$ho_f|FT9AiJ`vG6AhAI}63+x!;}v!nhbD8=qXj5o7eRLPa_weZ#Ud ziEja4@4S@iTH$I(wq<pMA>})1(&#|~OEN_&5g<!3neeBBnFudaZ9Ph8aZm8$?Z2-$ zh+*T?LErl?8H>&iJrTl%F7->5i==%L`C3GXpRi?HZkmrEE9v&=4_{@ZYy+S7F%tau zPm9Ba@?ZZ+RkV1Vy4zQmygHl`sR}TW4yW3Ud^-+5cX#^f3Z5e4{jsW$ReL5^dc8)x zBm_pvAuffb=emDfE#`JGTwq|x(g?o}e;lTR4LkLHk;vN7hiifQ_fP-<#xU&uG(LKI zCx9@pIPLj!)7GKc?fD;XjOz57PZV?qf<+3l6$?*=7i&v*gxOz_!q=UO&w~j>48G&; zk_kb=E8xlnjJq6ZPtTW5mFK43r^Os^pOfR-7M9D=`iN24tKdNXk!^`S`Z=hqPjbQK zjBZunPa$1vEK_+h0M1e8?b;W)skV?nRVfdu&#ecox@!5pZ74Ol!yGFQ=Zj+?%;cUQ z2>wPgC=sx+dWL6Go3J=7RRBcWS+CUJ940k+s)+Bx231}>BTVbqey5W24)u;r6iU70 z@++5Q{7Kg1wyV_{yf^;)XUqy0P#5J+dlNZ!s<(H)tAXg~45thGH4ZQQQKiG3vVHG& z*<E}jQnC=52U0c<;4VF#tbYlk=P8-9)bEiiJR1=%EmU5Klzz%oi@!L2lHrcyffBe? z#}2Z|X%w%-fm+&)W$|X<&e`@JdDq`huI+RC><qY$+Z@^wzKS?%J~2ou$J1h13U@$+ z|1*)66o;VQRTBWq%f5_hm(eY;(LhCS<v-ka|Cw-VnG=YZ#h=3yk$vV!cD#yC0=#@9 zgYnOJ_3c8L=0Ku`;>s0Y)#J`bw}RW>BTi0o;&QJ~PIz{)VLz{Q>7lyk@HL2b#M4Id zo~fz!B%HZlZr39#Dj5D<(RXV5+|bnYrNbkAyKd#+@Ep%i-@_Tv!Mo$xZlqns+vW4P z2s~PEkDuiNRi;#|xZivj#p{a%Q-DF%fsQ3K3muk#+CkYXX1k1Sl4)(tDr@4cf?sW& zNx!Kqv$t=~n`JG`A`T>5i((`eo!$NlVBa~1C(CkA%FO=vT*QB!J3s>^GT_$!t}Pnl z94>&A0{E-liB{=T_#a>nuQBz%L)n++04bhSGF`gyej8K8P3rUwT)ZK^YsC_0YV!q^ zw*ZFNT;R&sp2nhKjwF=f)0dpi+n7jfVI0|5d*LZLtIOk=496F;egmG}^_q{41$GXa zXm?%J;pR_&{o138!wi-Uaxgkk9%*9`cl^M}P)wzX{gnd%l_e79lMe1)t2p`^W-k-2 z+M1=dXCK+)qx)!P-&`!By+RC2TsiqhQ-$VVeE@~38;I!bKT?azGT622{1<XBa&gYC zd?tf4k@%{)t6@6395&}nBmWCUa2T7>L*8%K4STKa5dQSsX1T59zb91j^L9l7u)F(0 z)!+3c)Us}dhWQ02oA{O=8&<W=nxh-K>U?@4)ZN|w>m#y1^>tI`Nht?zlHk_frFhq4 z3!CQ?W@Z~1^%{eofBc>a)|Po*?5#&0>UO*Lq8_Up6RI90FSo9PfBc9cwN=FKE&Fta zkwY_HHGu;ZZ5O>fk8x;U-E8Y)V^iiTabc_=Le#deN_-Fo>tMgWY`AH#mlz$BjlMLc zZ0yh(M!o~cB&Lj(xiplYAVp(LV*V33M?%HsS9j6(!zd!qIi~^@ekbU)Dhd!G0+v?< zS?cvQbJS;o<?T`jV*O5Kcv%^0$=LW>95h>e(q3KvbU^B?N8x@z;+)*0jegx9#+K)E zUUZzEc^-7h9#Y@AUZjA}lAi++Fy3gwVydUsmo!XKJ3hpiKRq<@xDFdZXS=QU3KX#_ z5yoifDJ)F}^wI3#WzJdmqBZybLPt#b1^viy3VQD7EGjycW#ro1Xn>B`_4oIeN-VAC zl{$^;S(Ok<kd!}ixah$3GyNHIVOO81(G}N}92_kH7wW#It5oumY-0%FLbo?vy^#sG zf~RWgn>e9$$rFvVmH)61>UK1DgpyRJGB_yW`M!o3mn@cYDf~E!)jt_BLIW;QwDC<q z*kl=qeDm1Uf}U+t{zNks)+`Z!h+;g&J}Tw-XfMB>%)6)e{ReL}9)Wlv#s~XKl~&1= zJ2OMfPMVzkwa0F#fpg}XTgUs>D92JDJTB%@$v%-%%Z>k?ZAjr#jD+_7e<KIWf?HSz zVa-)k3cRF`oYAPQ)~(|Bq|uLfwlEfo<c-`l1&t1OoL5AmviGXRKk+<0xGV_zDQsT_ zW54&U`&^tX#mqw#aN2xu#@K)A9ojeHLGTLLv{gHE-?`?fjf2Rg7S%^mi#Lh_*qU@* z%{|Z;|Cmzt=y&r0ie5pj^Re>luB;CE{UNI}CWlGzYd0xS{g9oo<04t69D;lrO2oL` z+v@Z3V;0iAYl(vBjd{1}dQAY$XT$#QTYQGnWkd3J3YdtrhXTZd-*#0@;zyO=mV|7| zmDJxAe@HvkU#LyD<B2V*XtXaQldbXyH4PKJw!x!>Ce|cg`6Mn>oMUF3Mhfs+10rCi zZWPD*sbtK##C<n3y#}pl9|MN#GEM{j9{|fhG`}L>zep{ZVUCn8hVZk^a@$O&MJB_^ z;CE4(i=#1qhVr-*ObLRbMEF9bm5qt$qiX<p8)XT!=0s;lS+<T<7J@vtO$Mf!+dfH0 z^&lTUM{rrFvW$UtotIUl5h>TB!7x_?=}8}!x=<d-3uRR-mXQ<WM1qefS`OrbEjMY^ z&k1*&YaGS3ex^6?Ov|O}OiX%crY}ReUDUiY-PZp7(YtOm|99kQF$MC!&h~$QY6On| zC&+iZ<{PtJ!)SNb`kt-*8MW30X}h^Pm2M+J`C|9O?gZrB&W+t~H>=46nw60Y#tp-T z;xOh}*=+?Dgdxo3AX<7x?t}b3$H*V;d?MeW0p$1VL4F`)wnf9*y$E`YgMhqoKr|EN zr_D^NGHD4k*Mj`~;t2||fp6Fn`?2*r*^cU^RRUC$&WL&2LOB+Y4|FB-v2bM+;~cID zXl~963v!sYZ+?WrkT(;MmuhSgs3OlFLHw@u+?4T1b<hl^)3wfvXoONvZa)x^BW5Bo zE6eb~IJq8>cTk>#d@MMP)u0ySD90Yig}YfT$PrbS8QClqLzDt?+qOvK$$gS^3go)f z_;W>&lQt9q7?>VJLJC1d6b~%KaBmQ1uVIQ!IgtWt*20jkB8Qr+_HMK8?~fsJ=j$`> zezp+E|2R7X&8dq)4t)VWpLWgMbqC}ySqt43g7cI@j&5{YK#t?zT{OC}Q8?M{jmT4r z8M!Tp^F_zVg`>;ZkenGg4y&?_sXy86&aItC=S1K6i65jL)`Hv)c?-x-<lC_01IR*{ zligYmAMZT}d864qFaoWO_w31T4}{eX+{D6L?3UQZm{RKprz$fTbo$oYVh+^M86%IC zO$sw(wliD=bq%>=Qz=O1<m;h@oHkc010>Uu{waevAdjV4X0Q+6DUbtad`2y|SE+!! z6bQCExJ63lT?fbqHX~1raMMCA=}|q%6Pu9_6Nv3mHw-{7Y8MJDcR-#>@SJ8_CHPgw z9QYuws;DSXUJc|f9o(s39`|@ggLop}{JfL-uRpDOY8;!Gq!`PgDKYFlmmiwfc?jx^ z*p>l3V6Xf8zaB#}*$tXEBmdX|`P2QgzuYa*CiNeOAScPqh+Q}LR(6AZ%39lbp4&#a z?CCqWe0M(C4QI`tH#?_IX&XzlzVoubPF2M*a+$M^!VZ$pv)1|wOm_2!$MHk4^xe<= zjQsExM#Ty8d(6#m-Khn6<bxaxo`@jNPP#bj66B_&jyOHN5rUj0)V1(Fw)UQYoapz| zIr`ECW(f)zN|LSvIpiE8AB;z-QU<Ed^f)6>7G@$y<{b3IcK>Qp8La|;59FEg7oLY8 zPe5=6(bD~|Cqc&MI$hOh(21^RjJ&`t5fQRaGy!>`>&M7bJ4S8=gCH*hkW+CdH}MH_ zO_0MR$Z?6Lh&2E?bS01nDI=*upin;UXwiomtjAQkF_aHj(u)S~%2q~oJ>?Wh%DeFo z{|O)4MJl7N_xryZbF$m(<alGAmEF$vL;Zua<B#X3XIxyUM!O%rd%4=shg+Unn(uBl zK&{`6ytNg%+VValHwih)n{UmtX^Q3eifo(0%zTx**6)16gnV|_dK6^j{R68^K#tMz zlcR@?o(uBsfvCZxdsap+AeSt>@7O&_)29?yued$yqS6O>haexQw8)3kARp&eu><n< zG{{pj*z*rTKDH;90C^OEoPowESRP*;<f%?o9^0EkmCeMhMqx${XRXr8j+19lM37gr zK+d=BTnO^P43H1C9@c|=>(aB<EeONSItV(49?qv-bn*s~y&RQ4Q^kT_E|VrUpMZ@Z z#&udct<Sw!?>dsr{=-Wv*EXK({r+ZvJjOrU%*eOrTWkIE{TiJ;aY6n$GV&KCf_$Ue zjQmY3w(f0XDn095*X<?_vgZ2Mq99-H_h&Dy)MU4}gUN2f@mo8;1mBVOgsIJXkoSRk zk%0Vh^TG5Od6x`^w_H7{1$kd?bYREDC3*%&3vvXJ&(e;zXMD@8O9;63yVgrp8j#EI zwjg$-lF4#!IanleKwg=K>?7CApcAD8%AyeDxPj2G2th6#>Bfg$>*7;b-VNP_<EjzP zuc2!_PVqR-7<n2;Rhbxw#{zO32y=PJV2r#yV~o6wY9{O#fPAPbdu<xzS}A?iS?jR} zH<AKnFsq9gqQ65UD~4c||6NyoCQAOfw{jnYLC7~g8f{*75bMI15eP}Ph6wvLe}Cy( zcQ#FVtufCS`JemsBzHjm=LY0U5c}4v*46~&Z@m0wRqaAtY26-f+KtI?EZ()g-2QcW zf|b~hylz35!>@nc`Q-l2t*^g6^g;gEer?vT2RUq91#I{F4#<IU0XY!PzX>$<PBVBn zGh_N7w~0DK;iQLnCID?IPPZ-CQ3m29D`)JwtyCg&)-1>?HMY1{h9?7<LzL1T9*+ku z$fMMT7^}8`d@z}Utpx7$_dzaq=5zQU@7Rk&8zeU%%dJ^RkPIof<o{VNJ_y#SA{3@! z)>#bXGWHITv&ua4$fo~k8r%1W6G5J&MF8?d>-t&i1=>SH$;jhbAdl0rjiP3Mezy2p z>wbpnbQe2-bh6xVY?&}3(WEtPH<$F8=nfqR=`X|jBg6HJ!SI2@h2D5?h?jY9HeUDl zmyFzioC*0nW8_cwYxVKjx%uqrRJykT`TwV_UCeiTkHVC7j*#1)b(y;kbNj}c?S97j z>ee91R}kd)@D=$Td_|67av$Uke0Oou-K+0fxAV(;#~3MZ3CPh0-h15db}fhTSqEmB zw{SS_cddU9pN99l4}6d#2KwX8q1)@9;)8R`Z8)A9v<t`^2-5GF&(Z1>E8&HqH0e4* zj&7-$p@>s8XqRcK;ET#3QuoBpJs%E7$_2S3_d{Ia=Vz(P%Uq+S>mPzVQ)%8V(1IW* zy>yOj7(v>((utk5j(GNY3n}!lOjR2<O3fppuA}T+dsPAODq9TXu?BB*)i$!7?D?=% z@>dw#usu*Zb|$-(^7kF%Jo%1%kfv1ta&~^Svref-#zvcZklXtpN)Gdy7KEWpM(&V< z$J&jzr#qRYZpIEK#2zW=@QD6&@X_QT%Y7UdtMsKO#Twp0&clt;ymWZ&-~V;=t~(j| z);vqJHhz4z{~vnx>DG;nmLrUP+yu(2>YaDqX;ti3hqz;kpd1`uxNCiB8<NYP6`Hjk zen*bt?!7~lkM7>R<ANM|xChR*W`P{ZcoWwTq-$NgyN`Po<QZ&$sP&+Ux_(1C*G(`F z<Wk!^57n}0KR$+yBwj#{AibsuJZo{af<#Ya(iPxR<5)l*Ra&XEZ3n26F)oZM<DJ7w zORsAkrRGxNz_PT|C>;L~<WR>nD-s{%Xd>Ui@ghKO?6kum@xa6!GQh}oa%<G5Ix#p- z76Q3ERj#ZuLs4_n$qacu3qfvfHsWNrTns&^U)hcAQ`ztZ4`0=T9A%-44$S%`TCZWU zTYxqgKCNK6TnVOyIWFPKr~Zs`KOLn*xRe^@!w_N;J~f!^m>$My#k|NWl<WTf2IL?) z)G#Ued>MJ;O%9UJ)Snoo*=R}H#($x=fN#Ta5%CSdhTh(y^8&k{Ep_uVTC2H@>0#Zb zDRb;PnjN&f)2uPwvT?vVm@N*Bi)3BbR>NxxkkgZr^UH{IjjPzHsh*$3SwgEySR1-h z6}{;{LkXMJZJWY}(TV|`m<%wn;@BzX2Knp_-paI^nDIhuty5K2#opV^)({|PtHM*~ z3QM$-A1*}Xj2sKM4e@7fyIkTasp=w({w|5aRF#;c>9X4K^-vqE(kcg5vdZ~E(sJ$J zAA{sJCFja+bATLu>z_XR&xCvf@?~lp+S)Q7BWxShc+3rQHzi-fj^w-}N9b2`K^S~B zzVqv$gYmEULE4K{|74;p@<os@EP{L`1(3fWz4xNFF|8JAHYiOw($~BnIoDcu$x*ZP zn8Ok>k0o(J64IY8WS)y%w)EiUX0*<2-1hElFaLSSQ?Hf3I83l@3R|!H`+Gy=0`k`` z19JY~>*)-VbA<fu#*K}Zr)~2O1#5=eLfe=wH6iDEFvePmZA>{vP95I0pPNzN@9cba z82x|Rfc#pNeDFr}0`$rUHy3J`%jfLF*&d6p>_!PRXo=kI#VDzFb62UO!AkOzB9a`W z(uEMD+)&{PsC65fcs=KA=1x)%AkJp%{{9Bz=L^Ej4f5@+H-CS20mpxTdy|kaStR)d z9`lZoug)5+FRknnt<d53UeEes7+)ojXL%=DNe%Mo+C}32%ih_nwhaVvoIZus6j_!L zgn9+OEj{GYLmncR9{P?YP{;%1t-8wQr_N}xks<Exy7PBzX|-Qk2>h7YkMYeFbpLqQ zT&_4r{^R%e<_aKRthyE?N&L71a|;7in~G{;m$IsT9NMW%JW5-i(&PqU)KG47L>T}c zr4M$c{o2RR8Lgb`)(2ex@}WNpn>@A0`@uk7rA}@?D`C|-N5RBvA#>z?+n8=n?KL8j zI~u*V+J1dJa(E=L0UgOoH*JaH!aC(Sj}ck2S&)Pj>pFgw2b{{v+bnPjnk61dlbG2~ zo$ANmO-A|q%BTzG$Wb8q)9Z7}@^8=2Kc9}hIo2!Hs_18V4RWHdMT}<zInJrZbbE4- z55tGL*LVA`aQy0WYv;)QppH0Q&g_z*e8=-6?X3=y8^EBY$^?frguP6P{wap$cavXA zlS<d3MF}feyfgKyAOALpN%G4;&K9SmfBN<M^W|CS<>mF)(`fd1y*h1?2Wn<NY@PLP zpZ?n8*$;#<kl&`-hsO`rL)V;8Hjq19>tF#8K`d|x-WI_;1ijMb-n2yyzhuUg?1;wT zCukK+7O;eA6yrlTRHQI3p{(NC$B%1$=J;xmqkX91$MOFDK77MZ{2Tqz+5C9DS{aW# z*BPzC!(PbtvwiOy(@pBox(`%)X#SaezrQ5<*(`Cu8NaYD2^#{b$mC}+Lk*Lt6h&jC z=p2aYOtM5ha;dji*~W)=k>k>i?ApiwcG&txy4Kz5IdT;0OgaXIUl-MzIbO5QZa*s~ zY|5wjE#W|z0P<a9G8LrH7l2%c4dF6<fRR4UGz}XftY5N0t8!$kL(Jh5Jpow7S6U{? zyV5hj;{|A%G+DeWH-ej8?c)y^XB&CYFtis$KSNXH{_Rva6z*(xylS1d$Wf+~-RPF7 z`Z!6R+qHf?G$vC)Ivj@!EOJ2*$S0iC5;IUlOfgdwG?KsE*F_=;K+2uyK%$mg8m2Ki z5#XjT9rjF_z-ic&uKw}IDRTCo^=pHsq%faan674s-+<17JY&=pD2_#5%=WX*;B48t zsVKFa;;|a!!fX`Vt@Nxegh|7OkiB3X0(qLRa~<7NkbEC_N?J!6g@t^T=UmTBlfj$8 z%=*V4E%NPrAj~<CoBkJ_0eSxOVBRTS)ExQbTfb{ered`7Zav65wQ-7H>8vIT@W>Qs zNp?*O0&+LQhYwr?d|bGrNsue-Zf)6e52u&C!F3)=|917`-);$-5;<-lH=PH0Dd)jN z=Xx;~dGM{<x^+`Qas*OXwQ3z0&7ccPH%uiI)BC?5Di?kgV+G+TMmALAUcG=mT}7Fr zz)%~kG?hjVouqe{)js|%V7%K*ljH-t&zynWbaMMy2`9A5Xyo%g@@z-6qQUunV=@(@ z4ugEPMJ}yBX_LZA9t+w~4oegK=@r#vV*#s;SESQ*WIW<2Xy!RJh5uWDmQvK@k+j!A z`VEXfpnTH6{xbu)>9j>2q-V&pDbCNA5;Wz_w>}!lO@*lQoR7T@<S+p!N}~^aq;a@a zGO;qj7k?y06^TTRW!lEr6&5XbC&Q*B%it6|wJ$!_seAn4GJDqddvmRust98`nc<~H zKYJ&+vps000(9qmJXdoK$aitEn_d<j6G(7UdY028M+MPHlaIh8z*I$`W4c5w@r5I> zDfXbHk-LRd402w#`tip(@(A*P^4=_R)5<yWh|_$E{o`5Bd$JqT<m1>LJ~t*)M(qx* zAK|#x_VgS%T!SdWPK=7rgqK;CRa7B6wn%0&^-P+=)ZmT+P)m8DMV4B3rt9i`<QkNU z+O?1WOBXOcaeQN|)=l;7BcBa(4D#^F4)V<qNFL;!YfYvca?W`_{R_hJH6X_#2ORMO z0_Q9ZLtU6sv0QShDbF>N7RQ%DRRn<%OazMbCqT(lhzIoM(ma8_Ty9|e+aRKt2AM@} zIs@`DqMxyie7Y3lT8}5LAN^=DWtDeue5vm2$!^QZSXcqCfF8O0shA@$hf1UoU8qUn z)V>9i@e-vLpOLH9vQdi`sYEGp(Zi{I{D0UxmmIf^APmR3gy2cQIDyfd5C{l@A;1mE zCBdCGyn=KCooddQ>aKj6>ggF}G-H{f)4wCK-wz_rm+B|S!6?b|(0bN27WwM;ks|^5 z9Sp6D{_s~1JV`Dbz;Ri!Rp_t3LMnNQ<P~yzj|OX5h;&3F{Hd2>rJkocL$Ua&2oKe1 z62hewHV0w2rNz1bEA=1Af5bVK>nf0A0LDDRUc_&>gN&6)Y8b;0PT`1nYfWi=z{MDz zwoyS5Gu2PYgd`R>k>t@@Hs614KNF0HIr40gXKlhF7ismM(08@SzwBPqSN}Ij|2i4r z;r&vKWFkNw`ol?-x=Boo9<Yo|A(X7CNUbi4Oe^GR!ctK^*}cm<bN^TG|LezV{_-lw z6E;B!%d-fP|9x$UhLRa+Nr)Io7E_lfi%a85uT3G|LeH|0DkuQ%ZoL2gVJvb{-bbEw zX&<?O{2sQSDZ+vH3ipwJDRx;|Thp%>KyFVUv)IC8Y{7Wl7%qrLq@|ubljUB-JSD{w z6q}@^p<&j%C4*@IP`99ds@HZxL$}`l-^@|#U-Qs<)*JSb-^;;npX^!d-yP(??6R`9 zriWKSo|=rH%&<e>D1?v#&LwQb3#i~B<g@&wnz$g~Nf|T_52TEs2d@Dr5qR+znsf90 z_Z$c0@47Ul8HRFqLBnx(Z)#dve0!C1^9@ToUhy$+wvYTC&UO=sW0J3Q*80OPD{E`| z{3^&T@DR)ZE(r568f+%ikP0|zGK)X5M>u-UDcS>PElHEpSNR8*ZCE^uO+G?HlFj!& zfSft<>rZxTYA5Q-XQ9Dg281nc+}%J_a*b$G=jPq5MFaQl^bL!2?ux`W9a@LvtKXdR zX{BpSzwENIHm2V`U))CykYEI0f`yPJNq`|~{dQfLjj-_LNi<9&7v&m);*OY{UYn9o zmbb|AkZx?c{~_?a*bR<f1M;S-_RV;3^)ueI{@DiVOgDmN<M!8Q8r%>p@@98y@fFH; z{IM+ZpYH|Z+?n!I!1&G1TF+zaSwD;(E?MLjjG`AuhVfd4;UPcR0-AUsr6sV6l<^XD z3%a<dh_&#J+WBKFUrmD_U)1HT_rDO5>lv+({LgEK)?3%;YkU>tR(AsO+l#NTS-r_3 zSCp<KYM0*%`^ZIk$w=1L^!Zhb+^nWb&Lc^$4IxEp);_<F6Nj}#Ne9e`Fd+m0HE78L zo7=FKlJUl*gT7>;O$@Scy#K!xp5$hZ{K~V|yWWf<4|TtE0`|Fbef7AjdRJA=?y(lD zyc*l8uLJbQy6?NPns%yF=bw+2WUm^ZXgovLWNHrL5^J=qPu{!Kl0zz)Njoq7GR>io zkUzwbNnD+{CaKJ4nxr|6Hn*4N(z>qEg51)TPZI}{&!b<uLtD$xs27}W@pa+iD>T() z8sNQiC=-!f(};`qoSL0&hJ3O)w4l*mkJY4ED2u-P3iX2=LO)t5wbgGTP5Sq%Odqkx zf5seN%O<xo<eUfd{q~WgFTd`xvbH1)@>f@_+Xu#9N)^B(!cRi-Ae1BlU(nCS5D5Z_ zv!mvzxy&D$VCij}MWujSwe9{3#JxSP2D#|!RqL~Bjk}&(kM5y$bvy0a+O=)D>ncA{ zT-W=quS(%aFF;wkvpHSYI&1B%<!<q;8Q_vz>iOSHRo~7hH~YY&jsr{wcWOy0748pJ z9SRvRhMTHt=i1G|HSbRnbL?E#j?x@~<WZU{OdV;R^A)wO+s{1{1tDMUB#G<JZLRvl zzN?mJ&c!?3A-Gy`&3pwvaG;&mrnov(d#3c_e8w)M(Tw(MiRg%YO>IHF=of23`{u<R z<9P$OxBWPT^1aJRbK8(d0)~$dtwZruSPsp<$M&<l11;-^5Sz#^-+uOr3!GSlz!zXd zG;#5WcO-C_tOHM{sO_~OL?r->$FPZicE1RbM48lE?|&Fs$0C2nHKxKp#i@Ykk*6J6 zSC9t~P98CJu!ifGKps$9E)`q~nFgP-3z-hR#Gm@I>05xsD7yw&kdvvCOp_aZ_K9c@ z^0E@!UY<3rYkgD*oDL=bYvM~dO%~)wH-s4P)M9Z;sKkwK_AdX>R?+Fubn#Xp@R3Px z!LUwEOsDW+%-5Ru#+n<D`&zW6bzptnry%b;U-qGt@@HaPD28wGevseG!ET=7=7iSo z4e~s=p0zQ3z5sG_ZAg(`^9>MVlvxfD!n?3Rq@a$%9)E%;x*(4}cmXqno5aSK>?03d zDs)AdnS!?3djAXdpS}0elw<9L<=!FG3$%R^<b$WCo5K%0Cm;`|<(~O=!(`3Wc(j#$ zD<uM~Xr?~4$f-#J_UhbOkWX%a)%zy^R!b9&H(=}na{Y;Vc`d<N2Iongk5bG*vlx&! zG-bwFb*B4v1^y}eT0x~!e*on21-x&Ph~o}4Yl^fVr+P<yuA>p?eIUOZj_W<D-{Bh5 zyag@m2hitBAWt?#73xvHa7n{8(xgo7QyZXJ8N!w_qZ7{!dZ~w)#0*AMVXqAVe}#rg zjg(=EAvN{eLL|qg`!DZZ!D6?s*Upina_ZdT30`|u?p2UWFraNxkVjE5$Va!-qD75e z7p0>Lt<Pi{$g~%`+bxGF2Dvs)ir#xK<;|`?&9Iz&7UXK{D#SftaaOgLPj+xscWfe% zv&1fNeh*j)Lgn1a*9%{Z>@+dF0l8TA+GToZK3LL^MH|-F^kKJ1`=$?o{4TbUa~_O7 zZhF>wCVAEmq0g5<{=27)LIWe#LIaj)FcG2vxR^v3uAxMO&hz_R5vDIM9{xqaM5>pP zpd~)o3JUF}a&GG;hFtM`>-`TL=ZMy;ht|<i?8C0_RR00;>2;8ga4P|Mtwm3vF4w#b z<R{HE_)I53Wb>aOm*=5&5Y*%Y<RDm_0m3-lqIDg8ySv5p$2Wr9ok2eJeRtTOQjj+> z$h8wvK-@zOPx?_+nxyr8Fnt<7Vv(<ZCd?;ZYYnZVhdfW7wFNOh{<=jD64Gl!EIBM% zcz_ua#Mg!taSSw4fmaH~4pj!G*M>khrQ!2MYFMdSasghSZPLaST}Qg@{tL!2$afy& zS6k%!;XFw_yOPigATNDXI<$UrgfZrwj*?>~i;?*Z<Og3hg$V3JEySa-uPw-D*HD`U zxu`t2G0JyRJ3JX$uW%}ujhdymARpxyobz*#Q%10zOTHE$kA~JqKrS^t4sN8yh|Y~s zKQsf=1E}fi4}g4ii<~uf%5k&?$VGWOdDi{w;qw2E{{8jkYeSwJvG_n_bek6<Ia$;t zB95p+S?0M#abzZm#;Api32Z<J?GTnVFKbO3TU|*Xov^a`{)cJu-5+6S{d$YM?n|9a zo^%dZoJZ_T0eP8#Tyn&V-8x@FQw0XsfIkK~3$@3#4D;cGn<J2G)mlgsoGs9kxVhX- z;?qKe^DK6A2Woo)d3hLjBoZA%k{V_=uGTei{uw(DeJJA4?8ZY$*WIHQ3$CT<5y%OX zimLJ7peg}5pX~J1r?&Uarr1e(7&L0%O+N;f4;%(SuHWLcd>rIIt$rX3AiwP#c}98G zw)GnrzhIHa7{X;Z$OGaavo1WfQ}s`g97q=NF|J8}s)E#J-Wm{+n|DO?z`am_QqsF) zB4fS-`K|ZAD1t?<o6r6bj9+&k%;c)$Ftu(8c5yq7@(9-Dehfpu`|>%+$G$oobo&`4 z?B{CHRqGuEL?90(4b4<l3Tnk>*)RJB)VX;amdXWZx9^s7roGQJOUs&2aOotIC#5!b zIJjd3@~Rq|p{g1v8}iNKlCHFs2WPpsuC1%(><pnzRZY#X^o_4|Z07#NR|w>uTsJhW zfIR`Z)OgfJ*8Q;=>OKK^D7-t=kAU3wjAd?8?Ci6sD)+eWYTJ)c{y3N|bVuovHsu>! zW4aQ_fw<+k{8<C!s)q;vS1FIOXWf;;#P9<Ye+$T=q2vQ_>gH#TB(tN?JiHf@YT|;F z5n~}@Jl`9+3(qauKwShrH(oJl5zUMbZMBW2T+H09_h0v){h=s-$Ex*X<(%suOXZ$8 zTRpABodVk3@Eqj3rdyUaT5|6Cxzkbc#k+|ZOs2_KQ#Wd{3d3s+14m^i(QWGj^?brO z6D`yB&PqzLYqd5zwBCd)BTYDv&sWfoiqW~Qx+XYFaUPng=FItJ<crh|UqOo1KrP6C zoKbkE$(xfn9@C+9{bW_k9JyERQ`ovh^nHl?(R98K(@sH7w;$hqvfDijt*boA&4Dnt z8d}fF`q3qe-4r8`CBD`ZtdXX8ewcUxs7yF>!_nd9sK6Uy4Vq%ELAzj^7BsJjDQZi` z1rv>j3^ZOLdxqr3`(G4T5}eR_^<uYi7|XL8r@b~M6+FXp1~&zyA_h?jDkZvg>MU)h zv}LAD+(zY~ffP#}QCA=;)7)fC>PnlEswAelc#T}?+RLAX3Ms5fdX(n*_*v^~z??ec zBVjVgv$C!g7P$o<Zwtv3mQaU8P|1pDjA9$kGvTM9lm;h}W`;Snkf|)9EoGTJq}SN3 z_y3oIb?a)6UultFuc^~X_2HYJgAT}VtLCKU`=fQ<Rzt@+gd6C3kl)qiXW1gp%K8Q% zXP0wyyf}g<(dH|=^cw0A${T<|B2q*QD-7_8uvN?lrdz>PWG6H#DqTNLgb6BOpgq@R z>-{f80pyIV-x}nztJ>CYxZWzrtEy`cebof#L7lhN(SNd&Tdv4*OOUUR@lST)I&<V1 z<XKto2Dt|u79eoJhwxYo6<~?{Po%?JP$WT&YZF7DC#()rlafr3RGoI)Hwj|A`dE#E z&k+!df)*(oMceOx;bo3!y?l-7$2Fdos-9m$WH)};*uSxuuwL5II&UfJsozk~8X#Yb z=I2{e%%v$A<XKton<Ezxu&cSyS3qH5aTa`L@07}1t_g-npbwJS7$&R>h!nU+az!vz zQ7~v_@>sE#9I$H6QZeDc+9DRN`{K9W|H4m`?{??KZkJZA=cA?nKe_<&^-pO1#O%1b z6y$l1JS*$nAde3WEwEV$#Q<dacC>3dzON*T<Ir)iBt8VEP`dj|QB|m?pk#Y08jVvQ z&47tuwO~OQ*^NDpd(-_7YvCAK2jpM>%plKt738Az4|cnkv(~e+egw(TI)-6j1h9~& z@(va<C`|(FLkY#!HP?oaA2u1IxzNIxBSt`yG5{m3(=bFNL(cflp6J>XsSd7+Krfiy zcK;=+kow}=&$30H^``A-+zP&mFw9p!*)1z;>k^O~^RP%4SjjJ-M+32VB@_zA*$V#y zFm~FPM9-Fc16^y9A}Y0h_)0k<Z4o6gM6Eu|c8U_WA+i41djE@GiXHpU0>?ARv)*=T z%1>*Iu7mJ<Icq&DYx~mM&!7xEQDL7FpciJwBh&?_sK6w$oIz=5>C>yd3TX?XsGdaf zqYk^VnpROCU}M?0F|*;Z($rv-2j=;<`(N0lZjd|=t!Lf$K5{SS$N~AMyx1)(>zyF~ z^Q)P6jfjFfwkcoQO@(0$bo7@P#>&hTl<7P$OU%`9CJ>NGxG9!G0G+}XgvMni*z{?( z-hVxz)k|l|f6pM#y6PI!)liN}o)3h{%KE59jtL1!lKZd?bJU~3=DKb2q}PTJD0xW4 z?V?npQH33erlR1GP$r#2UBu$TXjNws+26F&HthNSv(5Kk&x0w{Cja_DkeAKw1EPqm z_4PW)qrvqRk6LHBTRspbE9=9n*2B7IfW?+*2?J;8A>q&iv$xPB;Ew%Q!J*|5V<}lE z3@H*7%uI)Jb%V90^dZcMYgEL>A_Rc#LL6M15*)r9ELw)A0~)v9e|ZbY8C(C@Vz=~6 zm-M{W>rZu|gsdxd`=Ryq*Sgt}_4PphMf5o<>kh@gn{V1ju8_i@#UiwGxDqOUEMII~ zmXUEP**U4*^+mxx##Y8Gu`y<$R3IhCx-ei)V&!k4oTPHFuAxxZ|FF|3SzoZQ*n0nU zj=cE8EOz_WAm?E9*1aF(uH9u_uiMX&uejEYarK`d`AQ)F^5x;zeDPV<KkS{$Zrer_ zhLgSo3o~GwAYvEQhM-vibOB06P{UDB1m0+wRRF0^poi!tn>;`sAkWyDIsE7|VWn6$ z6pHrw+lu7e$U!e(|GAwLRhFKC^1UF>z#Sk`-ZbqpF@}uwf}IR1LZ<NJ%K9IgQ3sb| zm%$khlWa+9OXH!n*NxYuhZh02_Iq*3KorNV4r5bpcI5pJjE}aT8OTlF0r?3WwvHF? zPIvQP^`jTNfpMd_>9q9%l<!%!4tYed1qz~!6eU>JuL(XepZH;LNdep_4pbd|7Vp2( zhMNXB*M-z*-keqG5L^%|);v%ayFK#$`<h7y@_P)e&IHwxrS_bkypHf6J_t0eha z<V~?miY6}#kM(t1V_q!Eri;rxEArJQfV^@|x_Z(=v2}M#X~A@Wjs)`OKMhZDUMqH7 zi0)5lJ&GeYjGG>TUVLZO`b(BvXL76==ztyAKAys#<YNqh5Jd>I8O<_Ni6WtnJc2H5 zO(~9fg@HQ|8@cel@Ui_`Bk#W-R#)4|4+i;lzFID~`Md-9wpcps3X#j3bx}-{>vg`J z&68P~&t@Ug$ZT2WOJBGwXGHW`HS3!?Ux#Y7yDQojmPIp7=I+k5U^+m@T<mrlhqSiW zVZxZg@fV57Gy-L3zwQOO;tbQecvvO%$elKZI&27d;|7b&0i$|uT1WnfD5${5N-xB+ zHYq3fsZ@l3z>nHA3hkwm6c~U11Isz0^<a>fQ}^3!JCKJ^V5Ng^6-L9WX7<g{dL2q^ zJ)ZMg1^DuuUguRZ3-xCHxehJlOB-50Kt~7pNgeIxG{}K4aNO*;X)J=|JBHS?7#g5S z#&E$5#9}pB1}h`~N(&?)a$=twaV=ho&FchW8P8o^PD0U?%z$(X$tf&^M^Li;_ObV$ z17VURdHwp;J>!v=We4&lQ{}TJq|~bz<kNgZ3I7*bl`Kx5<<q3A5-Q9L<cH|^bL7LX zb`wX=Ci0^?a^tw^k?3qU$p3hq#pBc*F&Yzv-%M?YR&&5@CFO^8*bsqM3^6I%_q@Cw zql;_x=}1A3?2MJ`g7H*Htv*lJhLQs7(f2>oL+gj{BVR1*Rgsr^v75N)ZBu$RO$_pR zzVgYd{6>KsP*aL3^L4#y4CDi7KgdsDZ2g%c`A|VqY+T(mD(&4z4$ClxSXyA1DPxE- z!iI$8UWm|;1U^Y5CzD^cW4Esbij0SA@5uuc^R?NZO|!9O*6Ylnyr5n+B$u)GUq;qF z#}C|o26mfzcC)$#`86(j+ti|OLB5sb`S(Fy=c{@)H;@mYeIP%9Me8E@0FnQ!9}Mze z&k~bqOxhd9G$YstG>pS}u$!vGBul@0#+W&4jB!RSMx^!5YbJYzSD;v7FH`ZrMDUTP zP%&O=MjgHfT1$iO54hWnn~%Kz83)2}LhFH!Jm2<*)`jQmroa7+dyxitQTIVE2u}>; z18676Juy!qY)TLqAI6c}z`AK<O7}-UOFLt@Gi*o}5a^ZSDaBlhEtMbtOqJ}`E~^94 z+5p<2aZGZ@VO|p-rYeG=@}AHtICd!kdvLK$U=ua~b>b#)S<0tl?>`t%ShRi+$fp6^ zRdWmSa98IQ=6rb_M%qC%(7#?zBap9~%KdJNg#!6?XaPrV$G0A&<A*WjWVa!=pglkS zs&yM!H$5Jm?FpI^{H8DsZwU@DhfstJ$}xJ3F;<oJvTXp@-czC_88prqvvyB39s6V$ zE&Sz?kL=2*n*Am+J+tmK?*0ee?jt`u`dL}btNBXJk*~J%Y8|j!Hk-v_9oDur#f{$$ zo`1dZMO=xSqKF-NRTS6NvMID9pEfI3vdm}F!Xl}f!cJ;EKt~>0e>R*O*PG9}Lt1}u z^s}GMkekM)Y_}ta82x?L3XZA>%)=OBUc)^O6IZLTsJKWu{3}*eWrx-^IUy>e-qJW; z85;XX8fiZcmyCp%jCqg0{|V90;P@dRuZlcxmZh2_uU&%J=Q{U!!G9O|*RZ=Rufju~ zmlYtVp;bs#AeWNOCV+fV<aIK2_&4p<0E^v*+)2)73~@xO&5)bMr=1{|IpPebighHk z2q4q^fM=aCq&B%KYzXvYmlrwI;?0m#7IN`6p9dOU7Oohca!=S4DV=gUDt4R6WayV> z${&xu|6yz$NB-*Yc;t)4G)}0xgz3EMhfV2Mp){#Vb4jCxsTuO!8U*Bn9_<Fo2iZsd zYnqr$W7FBL#cudRWeip54#I|LW2g|Q)>JEFEO#v1rY*@Ppa?<3B}J_|7xhNUmFZUM z>d6~P^)Pf#ao7|m%|ce3kG=mcTOZMC@yJbgJP_vDpc}~{`O)XdZK<2-5$VM)M^5<9 zRH&9}$4A%@ILJ{dxJ#_8NT8>dnh`bx1jadHKD)7Ly_}nHWz>Ri^0w&QbT~-Z6bv|J zISN(2)fEP;@O$+AcWJj6H;|hSTI@EACueq^Zy3apCnnSAl<qnZhA5oM7z*!z9ce`3 z^dhYn8(VRWa)GZIx$uY_c2NiOi)9XwqGg7&Nn$FQWoCdG7^0L{z~IOjXMDuS`!DO= zUa2{9Cj+_ZE{ol8;{$nea6Zf&x&6yv8lm=qoUkDnLp)+HY)A_Bq%7;TzA?rW<9Jko z4x$1$>LABjZER=DUhv09xC^t#8n#S*gJv=ig}O~?<d44pYKlC_9J%Q`ARl(wy1bK@ z-#YT=26B_>JIZzqtwXQ?u3!vtf*^)4Uw}n^03F5{6HBc)vIvMGp=%f?O17&mU{oW@ zfDS=YsLVQYcgu@_GEGuXl6^ir9e4lTA2LbKVmAZ1X)nkF#|KBbsC~aVa+B$yAZJus z1qK0+0+SSGl8rG8)FR@ya<m~`2m|~49Sp=`QjMB?0@K-)Wr149Y<R7S4HV@LznyaY zng3B6!FAY_(f8kR97}GF+|(-DGe@p1`G7~Q%TKhA+(2$J-3#O|Tbe+t%nMe)FI7ND zr51pL!jM2*O{}I=PcgfIR(vN=l{(B;12-Y9xYB6p7ukFR?a2!`Dm`AW2IQ4p=lzeM z|Nd{UpCY%RbrZ_&>c|JP<lx+f)=j3nYv<59XN?k{6JE5alCU8>wLX%8=#-KeW6eTB zcBzmg7+rnlxm1T^gd#~9701uAYpZkJzBD)!R`M?1+a91w*cACf%sP-Bd;hyR@<ayK zZPmJIAIKdphu=otO_Y1#$ZcrdWV$cNU*b69z1aODz}XW8#;~#^gbRK&W3*VH6o3Q= zam(@6XrPyYHWDZx$+U^*Wic6ryeLh>80mH!x2Sv7*!!P(-F0Z)w$45krMp3{G43fk zupvk0$W5mEg8UB;@>K7;)*=Bwr2?%Kf?;KmFM#EgN5qgfNQ%~#(-h1Mb`xB|v5t*U z8w&QqrbLs@%Coa*ER>~wHv0azljLk8-|NWjFsrAc7k4_@ZMgks&v|QS$jy<POoxIT z1xKE0W7ua0))Z!elE5?qdb20G4@2dV`;^3q#%7is)w~``VvhL+&1fB|#EF(eeeyBJ zJ`tZh_Wmczkb`nS-jf|K{Zw?e8{{XlX#IH?klcpWO{Ry=k?WOQ@BtV)#VFIP(xBrU z)NYI#bqrLa&mAlkV|!skG++5HC<anV&|y=+p`Hw<!HA)l<k9!v2}|z6k?R9t`m)ok zo`|yDAU~n~XRReSM{Y7b6y(GiVd7W)aL5VpLvh#;p&<pM?O#G7mThZL!YH-9N<F2a zEGyANeZWak8l#>Lo5IIoc17?Nx87>({SO$=7+ZHF7m(Z7`jb|AH;_LYXo_5KKC_{9 zlj-4$-56?SWZ5eY^??*R`!l_mSeBEyM?5lrh<pKNn+XT1@TA|w;ie&%qgACTn5Wo@ z#f9uFW>3Mgnmkv19eMx7kb8ymU|x1%Ol{rzQ`Xs?Kn})#G|Tl1$1}8kesRI|oCi|9 z{<*yT>$ZRw*RBFpL_U`r^_q{DAEl_zB!BFhFPGJhtSV@l9Hy$@+~VeXp6u6Vd!0N` zzx{dNn*7tE#WVky+!y4(zig*sArOQR4&ga{mKu{5_K@UnfhES6ebiz_Llys{!-lB1 zqY94<g$w2=PT-OZ8!WaJ%mzLZlN19EpoQcrYzkbJ%h>x5$vJA>YY)g@B&NqN4Egth zrpP|-;S{e~Kk)-${+&$x<>Jj`@^^AMnY<0De@!NTh3nPC>HRx*dp?<bX|q1G*SFO6 zdN*lxl_Xbk_vYQX<eh(zoD2W(hJu&L$TiEIW<15pMP+pm$MgJKMmM=r0m{*|nkw+G z@^Vm+fAIgbXiX-!B)^(mKERQ)MGG3;nn)5kpA2lmBftisyg*BvOF9gq4LmDL#3Yd% z$xN})Vq*CMJ`)e^)X|icXG}~p(F}a~D)}zCj=le2+&S_%`kC!Od$RiF>~4-6Z#<MZ z4u%t9PTP^UD832^zjV;P0OY{=z5DCaxi9iwfGyY0lgU5(KrSf1;QtarGw=U?OdxmI zt?N9W?*RF>uD3<rEFJ>#O`eytS<!pRO<t<<*W3A#K@Ok)-;m4S^do@$kCz-)3W1=N zit823AqT5~sCaf49)(m1vn>gNAX=5*$lfvv9)}H~4g~Fm4WSi2nwOCTI)Ncqe!3%K z9zp+;?A5EDBe%izr>nF5AU}oUV1mL2jOIWXhhm|!ciorrpJYIO;YjQ+UnY~!N%Gc{ zTOfTAu5XeE<lK^X{<m{#pIQ(8*$u<Lb<Lgor>o>qXqneZQs>Ly%rWPvW$!jG9|H2i zweGae%bg%c!-4#A@@ew^{5Xz0#ZKz5As9&5#6ct^OF<kggTHuANTgPhQAZM>WXgK( zZ+Im+FiV9fL10sbO`#$rr&Bb^4cWvi8GHZTA3F|&u`Os%RA=Z;bL4~397{ebkiYY! z7La>q4#+?7A7lsba~Vtb_KWL>eIS>#V7ov1)_HtlAfM+=xYT92soc$?URLXJlO)sG zw%l%f-mI=%_I3f7eaccAndW&FuCtIZUzg?DCwwjQrd}tTtsfJZCY$=2W?Yj}p>!|# zT34#pF+dKguO@Hh{^Il1)nyCv^LJma-kv`Q<gcL}q!2)8dkV^6A&=r~Q&kPj;enl~ z4y^Q#Do!?5HA<A6=%iC%##iqMo5F{~)yNpj!`S<;7rVW>b>v3!C#(P1JDVIOf+&uw zmmrE7HFmFh(}7MWu%MZcCOTw7+^}Rt!gvA>;fBo|fCG3O&ttuM{PdOW0Ez?}`!CWT z^+h`qf4q;XdVwB|kzd57DNY3G1>+Y3^5H#a_rnUv7v6GKkZ;7ft{_)di<IHhXyZ@6 zY>$h5AeSa%^L?Oub8~k^ATQLlZWvhw`B2a-q#wj_nn{~ZD#Xv+yL+u%VJBY3qFX@T zi)SRs4dQ$I#X%&#`czI*S5cI?V=mp~bR)exEz`L0W2XaYbs~_9-=_a@`!l_pMotrV z#|KoL#>ZLYaKQk~q>#Zv>*=MGbIUsR8Ud`V*g|bUixrK53ZB~V7sFNydC>`OaXi>` zAfn8gvDIx;ew5Vx`62lsF>=(z$*)($$9F6UV@&e%TjWokURKt6;)p=hbpUw)d4K9+ z*?|0R6s;BHif`3a&F`r=;l~Si6mEBa1$p1gg8Yk|tV43U0k#$EuHDIQh5mD={;hCE za@_IopA}i=Q2aG%Wdo_yaqvyDRXp$@mtNC^UL4|k9}@iT1JC6_@{4O7kkgHTewMU` zKD3_1O7qUiKz<W#THR^X)t~L$xo$=t<a3G3^heX9KyJ4U0dY8Uc?WsMDGg5G9IS+e zM2MYW4;y+0B`}e3bR#p{Em`TdE{S6FYpLDl3g5I@f{oi|-?aKazvs9MlE2>%a@0&G zzgE3`aR|sSW7`zPIJ%Vm$n#i9eh+yJ$VcM(2IPH*?+GAxZ@_n~rH;xUyK;XlcYd4f zRswR3y-VYbH^)V#T&hN`+AF)gEgmUySS^YoAILxVOrhR!hXQALVF=vAi!NZ!#c~h7 zD|GI)vOlciPa(*w-4yy|tq_K1>f0YCCj<FfNImvB7K>=qRR>Pr8|rGWADgwVyf9p8 zTeA`~mN`)%t!*8_25Y#BDGY&06-qRVj0Iar4Koy@p0?(LFf8Qe6Tn=?;|{aI+Vn!} zx<9`MxuE>L3XnG_|NrzFjPC|H(iruHSme(x1>{O{IBr1>eF3?^w*=%13-WH{A^y1~ z5m9%3ILPPze{|9OszAO&@m4*7>!1(`f{Qq%M)u)Tss#Qdm#Kmrj-%{;<-PJ!;e+(D zjK5Yv9(HpZueOf)LVPi^`|Q|cw<u6hbmv_&H__Pt4$QY{?0pCIHJm>N<g82rCV<yZ zthD_fu%S0$lCqKda-b6Cr``r?G^Yeu0Xdk+KHN6+%qOs*)&fQo81iB)NGKx))fJxg ze|{%tk(*pMK)zcq{lhn2_A8LCG-N1#Xx94KI1a<*{lYAACAs0awaCk<SW<wzwT?y$ z;qjfoTBSDoIGQhnzb+zL3efk*$T!hi`dj<C<ny`n&|guE96dh$ERA~}w<!Ms@~ktE zcy|@#3hhw$sc<_+y?r3hT@{g!kq=YpbD5k7<l;e}OeXT}PktRH+wXmSMf=fN>vmSN z;s;nkITJC~GQ+CSl%=&H7rg;E$OWXV9~t&)fw|&U-8KZGhB<G*5Ubc)=j;&*6>I<e zxYpkVuJuNZeh+e|%W$ld@P;mD8&e{>6_DS_%(4w2_Zds;C@M8o4NLvTvwAug6yHVD z2SN2-koP^gA6&15+8?eJ<Sg=LW8~h)t-)<o2FMeK=GzZhuL|;Bhj2F1l)1#&*PrO+ zK#&i%ne%xkK3$A_1l}j|lYY>O9^`6~ADgvqsAM<U28OW2oWMLH%O)=y0s=*FL`6!% z#Bd!*1&!$qEYhA!`zZtbF(RF`D+%m|j_vwCe@jX3#60o_<c%KBTDLjt=UEblan&Di zX|8pryvlJ<yb<FYkPFv6$i126)E((MF{Lc)vhY9_Lhl1P9hClSg7&+(Qjq7rn|?;% zdJtm|1M&~?Ob)9m$R*=^`O_3%F~2<VA$GI_<QgMSd?_vDG&>E*%V=7PZlbAo)oi`( zefOqw%cn<zoGrN^OEn0q-~e}!1aSpTxvNcKn;!KNPdB*b7B8ISZH5P*92pC-x~UCT zTb7e3ZeU1Z?VsNT$Zgho1M)`uV&v!dt?QsN`lV&9t8z#af*e!>a$WSL^agb_`P^Tu z-9asCcfYHEjuzy+dzq~Dt_OKpmLJCw6W6Z^<FfzR)fj2k`n9aJzGIO$y(s))>Cv2| zvmyj}mR3Pd8!Yi#Y1xxjxz0*k%?bhe48T`G?naUUvzc`CA?;A{Bp??Tji@`-35!DQ zjsG<odGma7WU?Dlq5(r7!wP72&o6%fVBFKH0ePrs^1SuPwjmg+Ccz6)Xs2O=Nd$g@ zF=MObQ51+QmCg`B!dUH}Uo3Lwk-zmZ@&@FM4vmqYYa3HwUZdU51mtRLj{&(7ykuIi zXhLN*xfUMidP7zIeu>tNuhm_f6<e(@w&wb|5DaU>RHmPaqg=q6=F3#zi)(!l_imSi z--5iAdxtzD%vP&`?<|?c>2lfeG4v#kJ3Zeh?IabDyHRA8dN0*vw~mb6JCSQ$_$?B* zy2tkBVLX~feg8``o{vYPqd`tA8Q$=hT}K2`)M;BHS|gO3rYC6T57thGy)0c8Ox0Gz zDOPF5#w9^yd%HggIcG$_+XjZ#oThGI9k*-${C*cx401>E#v*TYILOZyCbyn-CHdvV z$R7ncUhoGGa-86$C;Hr@ndEggRp|<@_k#S}reu_lLhtEAzxBU?JoCq_Cz)+u6F|OA zLHn9lL9X<lnLIbAj_)h!u?>sAKS;EjVFlze;B1yBsULeLW9KKDes&X$@UeSW`eYh8 zhs!AHOW8<P*FQ4Z4XR*ShQZ`;b1##H#lhUNyN^)AW^L01utF{>G76O}fPV@DSb<k* z1o$jkc?M}gUr@2`&rjC6Oe1fS-5UK7$e&!owkhb+cR$;!ySsnl0`HdfUjXJW7I{NS z!Ax#6EV!{-L(?)D{yaDPpFJiIa>hOl$g3**mEWBsHci1Eg(sMm7>0H=bCwdLL@OzK zC=6C87b)T3m!TNs406%v9gLdrvu&ZxIZ#)xP>_#a$sXrW_vhD5Q(lW_{m(%DywUZ@ z|1=K+`P0i;4(4fSlh+;Ojs76n?Lw4yGIHI~evqF-`(5ko0?G@P03^#t_!p9hhFG-$ z%5037b`%=QhKz-uq0J5Mw3Iq}hAX-fVGch>rTlg6pZ_(<Ztve6?pk+0`j^cV@~hJ8 z_6t~k;9Bcv+cL!t`?NMO@<#t~k+)0HDo&UAQf8^w9^`-pK!ibMC<$eN2bX~*Op%S{ zQjfa`D$y|{<;{Ko+7lBujJAPq>H>E;z*qxh?(0R}pTFg^*59?vJn~ojK>qwqv)uYs z>gAi~hh(jvch?j~gy_og2IP&-q1-PwbK9zocErdrA0Z2>%+|JP+f;`s0imq#nsY9| z9JPWXJL}uabk32=LC=QTD*CVoibVvq>;3#rf@BSnE64Y{)}J>RzgoR~{wFc=vn8x^ z@Xr03B)c`bP7RB!RU_@0erCDEoi<m14uph^3IGG)R4|JR!!=H=Ny<v+@(Md40B!rC z0k)~FZwIHCO8O2zYySN1E!@R)|9<3eUbY%ttzI7v@+W7^S|>#Aj&<3Oyiud??43<+ z+b|G?lU_mySh!8#T~E}kv+PNFkDesQ2)t=7QYGV0c@L~?xhf#hnwMHX{Ij{~hv5u| zE6`Z58%8FW5q9V{Dhj}d0|`~b&>Tn!zWmsbh$%-(HcCmEDh=Gy2BNaAPC3VY61OIU zv_Ajt!$-cKln~}?n&a24(;#1gi@b-o()?<o)>Ek&nhA126#-R9EziOO2oj_eaX|xC zh$%VN)K+!(bf7kRJH&Y7hhZxVaSg|XE|sAR-}!-5H$Q*QJ+Y|u<oJd)(IO{oeW}!L zacD|f<f+vE@sR@@2U>^+N(C(rHBV7qJCoI9#b&0LLbpCPB(5?llKovE*I3BtibAoq zqoDcuM@E=P2y=hdM}C*<>esKSAir5?1KRBn=VlzgO^~Nj{{-@H_jYiXaE}|bq!8x$ z%5sT@)E4#q0zirkQxFPZnFrWIwD~@Hg`t*{4X#qiGZXc=^J|!Y_pbf^;Ye}^xyQM6 zsq5ENkoQ{3AV*|d|CCGXsni^c9HKaMpq3omVbNWH#Vk<T(A&zmFg$;5GfOW%U=}l% z*3Qb1l8}0On@^iLG(P{~5Yt{g$+5_DVSUpolYHbi3+Hw_dg*g%J(Zemk$-XE8CG}% zM(Swhk5+W8*!5Qg6{_i~E8Dst?!zG=pTm$2hF6*~4|AV4KYx;~@Aq<yX)dg9Tc0OK zt%LDJ6szkQ?3PN+-+m^rGFP*2bK=!aPF@f|GXgTEA&J+5&1r;$U~0aW!kC!KN;t$w zhIVr=yJ36<^Y1!2G$kzZG|0ED-O2OF(L&a^ADaTl*K{6vDz#RPf*g|(z9`C!h03-f z%_uj}sbHbX*0&W|MFAQATpClRCyVncO=wj30sy!`N53W@b83A4@d(J@bm|z>^pI~w z6BEKLmZVi~YdnuUm0GDzfE+j|=3t{R2S%0}RRxxop`wJb399t85$?qjj59tGue4Co zjcID#f|gd4>BJnst<Qh3$h)55XDsr&(xtYcG6wRMoMQUH@Z5fuO3ep36jRT!<AaI{ zp;jn%EuG92U7y6M?=`v{x5EJ3jKFT8YJvYg2GVbDeg1Fi9(ED!b`IpZvc46KgS;0Q zU)DoTMwnb$Po?HZt%o3lZrE~+P>)BKm@N{Ym?`YU(~H;Ccdw(1fwl;MrL|6j)_ipN z-M_B+`FG@liM91pAkY81Hltk&OX~#NrA3}f&0bnpUI@=Xj*(F}Fgr0lz^igb(@1Ng zj29$LJOz0Lypu2dSjZb6Z4z~@&p)!kM6&e+d1?yC)g)h3$9TK6$Wy7A+s^=l;{^%* zEQ6>MN6NVBizAL22y3X6JzXQ&QC%fE#Kj=!rmSu~a}&4u`S-<LFFE`SkY5(-#%A=l zOP6X~yYZ;?)r76Te>wSJ66C4W+^BVd2Ldr*3XFjk<Vf_9=;B9&K&4_<FxgQ}Udo+L zCSMtckcvykBLg-+|1L7Z^dx@(<riDzKc8QJ9S%>A=x})X{rsa#wW}%n$QMF62#<%{ zewIqj2e~CcsVM@v;$5<nTl5tH+9T(QdYV!Zbd5{J*_vz&?-x(ADxh`Cn-c5V{QQTo z^}!;)6y)Du9-olvHBsKKCi%!?aeFCol4)Q(edMXstjun}LD}X6q>&>L*cnZcyu(?m zu)%B6I&UTasj$>@y+~O!=h<h%kc{2_{Qt0b2CZ$wP#mY9!df9~Eo?^XgzVt$lCeX` zVi=+1y6j*E&Ijn%2)p!>(@ufHzC%wV-(iQfVX%FXJ?Z7SewCd@?KV59{)sJFlI3U& zetl2R5`tVlbdFpuS6PKtOXp<YRc!%sBx!9VC$rpv+{x+ju66#xHHop1qt3XY#7N|6 z4pTFj+<ctLv1;>_N{k3Kj&VE~o%4%57(Y1IB?Y_rwjh_wNmi-J(sSBP-4F5_8Gb+q z2E4f?S|21?U1+Zz{FD7@j{jMy*1MnG-G%dBwiv<I<krsX**(V0E=#!Y+c0*iOMYM( zQ-#UQ@XY}Z+WGN&`7WkXT3Y19aYyoI>$zvI?SkFvja;Yq&l+fvOC=9Js6r7Qc{yEB zE!{_7JXmF+bpRh()(3xBzzZ=6_)XNDb%q7>Bj}42UO?^X2NZs)8-I=Cf7l$k!70wO z!Yk60n&{-9tTrq8wjrf9E^o>G(!6QuqAy0JxwQ&^%&w2$g9HDw;BqjQ!EPT`*+#A0 zJbB%cq`w35hRl(ZV?TGTHzwFE@Vnh8YB@R8qA2P{ejsf@USMI>df<FRkuoEZYE2lL zU9y@2Pw_FV38SPLR?aQtBjfq(VWofv?fUpZ=opf;9eHG7k;`A%J-QA&r}`xQZaZG9 z4PQfD-_o@XYK}q9-al)EYh89*r^mv{sYX3JZAF14$j#TWD9^7sJ5gq(5yf?@O_*d) zHJ^fF^knGeOSST-a=b8!PEB`v{OaVPXoXfA*Sh>L$?nm|ndelOq$G-;#H4mRZqMkf zB_C*!*N5<fJkzWtTBR4Y4uz9b?K+Np`<2}Y3A87+vE&%Rk?_G_qW2c7m>R}n?3&$H zZr>JD(*`x!$W35#?z*Di;%N`YPr+^yIBo~>plXJEa&t{N7r9=WWYAU&C&gN`_6*=X zi}Bo6sk97sYrq<<d7N9Lc0ZGm6i!Z!kc^}i$hrNQ%UFf9TpJ^?h>HkG!?kRLj+=<1 zgtL&kr1q3Ae@X1_T^zT&KmNjg<RB~8da(Aa|N0`dI=?g2Qhd4uh-VY1EBbii-mSbx zsn_ohW6xeOJot$S?Q!|+SZEze^sl$u`h?$^I<>7p&g}6zr^qSO7>iu`j^j>^k@Rg{ z>+H3tGXF7WABQ0aC2Puy@WiNCouiBL*SBu3`NNpZxn{I+`48La@q^GFm!Lq)W<eO~ zUn^KovW{5m%W86c1NOMeUQRU1FMa9d8iu#(Z9&>zFD}P;5-QC-Ykdv}-cyke;4XT4 z57!`{p+yb}T&UEycdZl6YuEzqppe7m<#3X`c8~{=aB^ylTD~2~d5m@i08KVAF^iLN zapQa5oRmlWizm}urG!^*V?UQrbl1o4p=+H;ZWZh%eZ4GemUTK=CPX&**~zXuV!4_u zMdwl>9*&hI$oqwwUKsXEIX(`<?+Kh14&)mI26-Tg3c$Ti7P(Gln0B`Zc_U)o4%C4e zGRGU>T9=WFa&u~s4!hDG<Qz8^Ze>cCp=eOdC}1*;Sfc@7Q`LlNj>5{{R35Fq2jlmY z)*QESt;@h)DOBSj#6;<LN8GF?+0V-f3PH{^2orW~5Ark&hmg!6aUkC`Lw<6|qgfTm z(If|kW1^XE2lD!(-ST}*Roaj_av8LQlT(A#@}<Rl<OMWrKn%5G<s5ZowOeq|*rAN8 zI>fCKs^#<K1VhTAc76Pw0=a|_f?UbMwf=FEO9%w|_05FoV>QU*(IQC|iic?$Lo!N7 z-aG+2JMAIU7h#yBQ$_T7f-O-O*h8EoQ!h@_-dUO~pcd~*k~RE$)V+Q}lFWN+kVE<W zDa@3|@ws3+K0k>m#4RSn94;RWa`mZC8sp?yuidpCM5p{8TM5pX6~dY8PXAe_QD6b` z3J>m)md;i>ddr-|8$-m+;4brmzYoTnZL(b1Z#93HQG};`7{4dUwQd)+9^3(WsXj(Q z1<23Fq0$J5GY(U2i}#^Y3Gw@x>feWyBan}o)jp=$80XFhs&-1<=RFP1G|1;VAA9>Q z8K0aBu5)dWgA~f)^C*j)BFF!`4(O|0>rGh@Cg?sZQ2g7EtG8d7-d_Fq=3wshA9dXI z<+dQ_blGGBn&JUs#J}=8sfJgY;bZ0&;ihFxVx^QC^~MGJ$vZ!OB`=S5v$M#z0=ZuS z^4=i4n4XP*!<y7XC<mGkp@8Di&!%BGANGLN&~msSKf7)|NT)G@JX}os15N)l9FNW* zpXhn?i{TKx@6czenhZ432k-ld0{os!2Jy)&!Szb{))l>HNOOG#mRm)wlaQvhO_Jlo z70DYBwJw9#BG=2SuWw8A_3EW?da^ogMgLT-Q*lSH{Vgr>*M8AJ%uie<pSYVjcUfb? zu36`dXjM?!WXm2|5SDTVbNL=ByFUJ-d||hIj@*B=MZWxWdB1DDkA`!quaYpq$#HXz zT;sW?+gwn^C<MVR*hUo(f%(*asJfV=(Y**0^~4m5hYI99?E+YMdoBg?^AeCF!f}#Z zC91$SYMnq{``%~jM5@^$_oLhpdU^G>LRT-HQT{}A^yb|^*PB2vMHUu0+ZU{yh5XfM z9(`pU6-FmsZ(j2U^G8}Op2m58cZ_>5evb@t>!|e#kS~S!T?Dx_L5^JRgVHcW$d1EN zMX;NqF52O7UNcHU&|J59kM8yhZwmQ7NZpoqKUSSjd9WMQCf>fQ)FKCxznHCGAXkaC zMUEh^FW!xZy1~(q1!4ZMcRnvp15q4D@PEiCXtyB~301s=URGQpQQ0CTS2fg%dJ&qX ze}jjD@zRST^<;O!y)K^ClXw)b9{j<Ad-ad-&Ad#y)7fcvT5DQ2-*%hH%**Qr!Oy;V zFEjQLkORlHBridJI#s*r*$e)+U%PPaW^D}Q1}nQM6jAfC`tgdITb{nkxHfVg5p|r4 z8bqrUSK+C+k~&xY{w+cB5z1!*`2ishd1Ghi6Ja3VnFjJc70L?HBVE-x%@P098p+4$ z^mX_^G=~tV3pL<dgc#p%oj#E3B61(u%~RxXm_0|1L@iVd<x8?4j9tBu=f~gaLH@4H zlb=e}0I>@ee$9oMBJz4wLn$>Pt>|f@bjuu4N7Q<9ZNZnOSMJlU<D#4?f$_@UzXdNO zxl=Wb$ZI2zUm@fQJN_VChd;^pDLL{!OpT*3VGgv_M&u88L@q}BTbM-mDGYEM4Di{t z4RqPG!jbzYr!pd+kR!j$f^rUY&U1f8kQYny?5me2BF{no?fL|LD?xq=b^hih@=sL1 zd0zkgnI7b|s`99oJ_}s|X-GAvD&xO|O5o`p^k(t`EpncE<?r8uH`BaR>pMF?5$Fi= zdj|(oa^x>C<?UxrhKCSR`^SJB8I3kk-hBs;2=bS>M$B8xf`deI9Gk*^{lSCgDFV5r z0XgG0{`mZ58j;J>>V?j&<A=cbnSzVmGLWyG`!EUQAI{|@cRY^>dDxbOHV)A$=<N}` z@NzDqm)Gl%Qj69l<m=+KcC#*l+%aDe#v}yJyVbB&%^Rx$EpoS_uS?SluT%M^Y=0)2 zQ+%%a{aY5kF(R+d2y&DJ^20Y%rq*xalV?C_B=$Nc$#0D2!3Cu6fF-wokb8)3_*RqG zv4c(Y#PVN2n+^2WS?C@;W#$cVAJVrB+fmcvb#5id{VYB1izm<wBXTJuFL(nqdDE0) zw=s39Imoln`}5~7@cuGR@)5{8l;$7~DJ8Om&9R(CHm5Wsdg0|<p&r&LjYz3QtLu?} zB=6c>AXhgE(WiwK3)zKgEC!|!O5dwosoPiFT&sQmi1MR3@>xNC@N*30zX+qa7UY-~ z4{t{qfJ5LlFHZL<XgxRO!+o&)3P0=PE4}uyYMp+K^4j(2HdsD5;{FK_*SX1^Q#G}2 z1IX8iq%H$F5_}Yr&$=KC$7qp{pK**Y&B|^W$k*1+V~QLo&IKg@z?CJ*&mRSOpP<^* z4CItDG6c!qRFH>hnkJNLN$!D<Qj6B&GURHOTn4#qw)>fW+iR6(dZ5WyR`fRJ!SV4P zCp;7;Kk%jX`5)Xr$GF9}BZnWOVz<Z0YF4QJgE#KyApi03-u?T~_gKHO+ntcH_=(7V z`#8`DM=9-Q$YXN<B?aAHAKNq~y5nOo|B{XR9PxeZ&)wg?mD@*+)0ZPZCui#N1z|8E z7fJG~W>f3Mm#rhjrQOI22DzQ*$j3o`{rYDdcy<iPX^hQeCXlOAFHiCBgs9w@%}D<Z z$md#XUC$L6j3!xWnXl8yr6AgHI$ZswrB9)izkds4k9ILN1Nl!tHN*7*5k>0<d9m9e zjDT>hb&Z<MbxW1J|CzA#B^$qaYkibQ_t*V=0Qyz;(0v*fWtC)K_Pr`Os;Y-Onc|fC zC?LOT@*H{L2p`)4ZAqRZS3v&z8&}S8^6EH{Cm0sf2tghUk|gDDPgBxKIvL1=GzD-w zd%dJLgwtV4X%Bkhw9QUp53Yh1$m#Twj@?dU3FHWV9PObYyCe+=K_75{^8wi4w}7`& zivW4hYK{)|M;q=&qfTV)wz}-lY;`M--d9+2yHz1ACT1J3#(QW%cO8sDk2dunw~aw= zKIuEnz{Is$ZU)E7)G}}!(;{*-qC~S|Xw~nZ^=7qhS(3bVRR?l42-&%h+BqPw1`Kcg zIy}IsbvR*||E>r5{1PB9rOLKzzSli31>_#XxD=3cq*rH+$ctSNh9~KlW%siY$j>3j zg+3EK$a@jBF;U&&Am5`jiZF9d>44G{LGFdn1)neq-6HcHlQtMI3+Sa_$4x*<O4~BX zJ<7f(h-eg|;V=?k1U~SKLD3Lhz&jzO76Ed1Ge6WfHnz7KE>K$1mK(6cCL98Hi?_B3 zao=xkH8#LDaQC;^RfII$Iv8(nZ9j4W__~PvqWKc7DxUPah?uiaWv#li$s8;^S&Xb| z)$iY8Z`?G6Pp+FS(F(Li{d@>a7y1Dp7wr<{MF~UlZuPw2OSQ{DE}l9&vYY91YsMUT z(RJ%*mT0YYr#2RmfBwkzj7$J|n$4VtG^UjEw#}d#*$m`i>^U6dUdXNbbl|XdTSV9b z<k0VQII2^)h<N=-2DuaWxdU(m4k8-!CeR$d2z_|KboeejPaJSThosbELEdWBq1kjB zT9A`R8}-Z%teEX4zZ8uS<jlveyEXUJI)}&fm{zppEyOC?nltre`UBGFTz`RH+BHw7 z`&j+^xALdYY~y0LPdTq2V*oBl{yiV~RD!%9*>=^3H2F259OFld)_GiRTdTYK*%Gbn zHU{!n1T_)l0gVvI9*@Yq7_lBOR1eXnlW{zzA>oH)4CEL+M_}(^HylPF=Zg5b!@c*| zAQ}cv<|Abva7a984zMb|)M7!7O@Osq(Sp40?n49Y5afZ|#LM_+4sr(k%6!FcwW^9V z{4r&rKDn#3bmx;CR!*{*iwyOX1-q+%|Kfjr$2QH8Th8nI$LmOVez$6sDn_>D_<(Y+ z%fvB`B*%~(X$}qBG6VTCOstF90QOprh}_Pr*3TJ$oFp`6v3ATs4swDaz&A$Jq7CCX zwqhnq$3Tw53Gg|_DtPeMma5i!dDXf%+zVk4tiv{dLimU%Kf&`TjU7^IK_K6)gIH+2 z>vjneyE_K*O=hy|26)nXPeAT|5Hz8QAcu>aM?j9g=C4{;*`ddg!IZIjQAIa$;#Bf+ zKIhWP-+#73tKot$D7z+zt<|rZW0fjIJYQ0~3@C?}pL3kQ;e|lITD7d1L0$yQ)sTES zmS}ZmipY6@9ng><$m4{9WRQafm`4}Vg1nujwv`+?&Zh@S#G-RH=!LA6dgwzcf*(*& zS?#tckZ0ON28+-ew2O&u=tuGHO3Otv-qYG7m?PgG<;d&8$DC8^3*e&SX!cyQJb8`0 z{JZ)O?%%pNdWhUH19|oC<H;O<e79;_rHYab!pa9Y*Z_9DsriC19HT`(NRAvAN%Cc@ zT0a@cNknbnE`mIuG;Ie?D1#i{Z4THpMrlDl%p&qc2032LXr8o(PDc57uNTqK77@8e za(V3(Fdvgrivam{0NUjdc^v_sL3kgI2=ZNKlFzU=2u9@fdKZSk!$xbv-LDWSBG-c4 zG5~pHI?qhDFp&}V_Zey&%}%^<)$iYe7v{*>t6DYK#uVh#K1~Msr)n9H7b+XYFs`Mz zc|>09+HUZ*%A@4$_d2_ZAcqg2GJ<@7*p)#(VAXFtbnX$97UWo*4#bv0jz{63hl6N0 zL>~z*F*j`61eJnqsRifAcY(kx)s2yOy{qQP(UJ*yzOm0cDy^0b@_l#iVmE`p&~OR# z>3fQr%cKzOWKr<S-+xB(EF?Er5C;GEx_UT?<A+zv40++QQPBFkAP11*yErXjvD=y< z$Q?@A0YQ$BhRIXw9md|iO&m;Q??ovuZHrZqvyZ+<oRp4(JPx4;LGH0ZFN|#bi$VAZ zJwD`-Uc@{PN|66y@9cFN2ZA_$@Dg?+<u<W=MA)2Coht;2loWJnkq|lwN<PF>P*72) zJtSxmT`EM$8*rlGNp9Ag0o%e$hTO*EFn>gFHn!KR)9IJ_T$IzS^_#VuLe{z+<Og~{ ze|VY&IhyVBgWQ?NTFrWrBAc(pLuI>%Dl7Y5g7teqa(Y7;j12Z34om&&4?T&HGg09E zH;}UlksIGSmtO1f=Rgkd1wb2+?`hZi_{X3Ka&Wef0palJ@wtICB&(hDiy+4$@IltK zJ{o{vbX|WFxVRmUQgi(h+OHqO3)Ydt;dneUvy9SN`o731$l+!GW@mqGKbZ;S2Rl1A z2bk=hrm15c`RM`NV}6j^%uIV#Rbdxyr7W1VySixsaAki&nwDVw5F<y6oK}7Y3V`Ih zFD0q#yFGEN*HyL{IhTeod5au=>S&RhRC5h-Ju=dzVkbqA`~4K(zXzsii$47lD!+>$ z*W(wLgK-GQ#Z6N}ZR!u;^4p7)_!ntP+d6_g)bB?oJ3eikEFp5|AotJiAc1ZB&Yub7 zAOJrOK&u!7@^tuA&D)|ivAWjjCL-O}tQ@47QBGNg^=DhO5<re5k2iK7{$4#FW=!$t ztCxpg8^CeNbgQY#TePm`DPCc=8;0mvwP>9M<QDDqZKYrRy>&bc@u(;R^^)t~?jGVy z+4ne$RFUW8tk=3qRI>dC-*M@+PG*xL6NqpD;aVFP)dxgfg7uqT>zd-!7&(%>mp~~~ zw+od{@Y@B!+oTsu!g_thIoWNh>6Zy6<!3>08`H<11wEQ^0J$^Wp7+xvHgSwI)8^u~ zF+H23jyxw)N0j^}^yVpK2Rc0m&d%}ruixal0g$Qtk)!mL0P~#UxD$#wUSru@>y_`C zvV!$z2Inlw&ocXwPqr+YxCHsJ4x^7D7Ve8!DH*o?g{V2~W<efzh^}?Iuvw`?E1P}+ z{q*{;-vgm*omPI9XSuQG@ihzt<8@Xk$XV=~GQ~Kj7OfeOKiNS3<PPK*;2s@IXEtVP z4ikSN>JFQqw8+^>xx5vQGZyLL&>lA&CtKtwa|`{FN+4c)Sz_d?)o(_gPk3YDTKC>S zet%ug@#}k6AeR6)XSEiyBYB*gh8!cedxI@bW8#iqbd1r1)WnCV{ra(v9Lvb9AQycV zSwYT#<e2QH&2lEa)??qO5lt+f^{CzUMPE<xa5HrLFW(N<hjD&VLe~2HS=0_G<=&pI z|N6aY`I*^~93&tYm4ciP$5V!L+B7Bhv9;ULq?F@FP2u?0RBLnST${=-fIJ|8T)BWH z-i4EM`@Kn*VEr28L7*ufibXEsA0vNlCpUcrCgo>|pCS46yMA@xxESPLR#7W<s#fF| zlmN&b#K>vc;e->(*=tO`4DeXL_x&~5O)PSe9po#yI`WEaazuHi`b<An)gW&p$Qw~~ z|1{aU&S`7%bRR_x;kal~Y9t-ceb)L6pQ&ohZ$ji;Ey4Od&$!k*9RazB(4w`nR_iPH zqJNoy-0Sor|CQv;D2h};FeLW4Xn~5r(4N&I|5TGR2W(Q7F_%*>!TNExOCY&`T*TkC z{#trw{_-e43&LK@N3{Xv&1fn-fd4?kaglT7%gEh#c5??&rRKXKrJc)Ctl#snwOc4L za*;J_ok3@}bWUy!VZ1O-nwbpZj2aE|S1>MGq}qwzv#R<!@{e%DV8R?StA8B2a5wT` zT7M?VZX$w3UX5=(Z;OB9k+trHoh0^iYQv9#dU_}r7cEpVgvdF7T=b8<bJ=kkhQhEw zyn_LWOCw|?YN@g;Po!*;EUWCg$txslHhHQ(Bj@<^Ph%J^89EaW_-C5hKKAiNz&Car z=ShSUTEmn)FRf?&668co2)C)X(~BABFE`({&Qo$zyw1u>L?7<<yW&qbyJe6+d#U%b z*^NoQ%S-E7e>x)<jBcP8%P^MLsa+d`yx1Kw$+J??2Xok|6*KZ*E&(Tgn&}Pn?E9}| zMy@`6$}{q;H7`wJh;Bgg=y29_4up|+^P7EMK+j4*Z})cx9P9R|GxBGExIfZA(0`?H zuv?yyXRUbrY^$5(Kso+kLjGzykb~rR#=QIT=5<!qhWhyB-JJo)Z*`CSNr)BKk`N@H zL;vx=P;q(s?64B#zG;lQt(s9KEN|44$@s@~xgO-;_@<ANzrgom)B5)J$S-qp7M-${ zm9>TT`@J#dGjY5q)QTB-Qpmg|H$Q|+B9wm2{;PSj+wLJt>#ftI%HNbST6>kOygniL z_;@Y#&5?f6{%>dG+aI@%t#;SP$TweFm#ypj!yW%W`k7?t$Apl?a5bc5;v&XHkdB;7 z`%;p5Q5F$#f(Tq8JeyJ74?<3q{Qkp2Gzg8HmHWSG|IOV2``nV)?3M&1*PP_?9Q&^n z9wRR<C%dhhkvH0QO;c%W)C~l1jVaH_9|z>6{&_O^n*hjPVcR+=zTt!9!trG8k+TXV zuPZnl4txF~aU^^rw7;etB%}O+U_#o`v=0`1ql!qV76CYk3!vV(1R`;aC0&Y5QSYRK zs5bY1%l_|ncn^7UkDq;5nJdnp$nOM6_8$+DV@kemM((W*RA_Z|GoGcc{~F}+W8@ni z?S?CT5}J{-3jT*g+R;^h@WodI`AQi@AsJUTvkx+hI05dEfEwVRBOwkGO7A$tCcaPz z<)vD&NV}q+*)N(+S~LUB3N##6x#s?F+W&%A)zbvI=pUnV8vR%E!EVL+x1Wu=mB3IN zrA%pc-*I$0x32C>BD@_rezXmRovkN^NN2sP$v9G;$}k%TTZe+S*48R@c8ar6;=tx} z<sAiQlG-DgD&wUJQW=U%NK0Dd>bmkOG)iirG%nECc4<ZkqNtT<+1Gstx$}_<jth`? z7I9=}p)$7IKNiRP$3mCVaf%xn2{$Tq|2Tu(afVj>UfY5(WUs!YqF##j7#Z*8#L`OQ zNw>)PcPG2eC#7y9sXvt?S|b&5#u9&&1TSgw%|Z$br7meoiY+h5A#ULkzQu6OA|;|E z)H7FrAbju@?qQSmMZH;+UHCv)g1P^j_8*zkSz6C}0xAAn4t84)a@Q|oeLb8iU2(dz zW!Gy0Ssj>MSz;H#wzIn7X{L2$Lthmk(J`6pk_wh&A*hv-T@7Te>fUg)A3C;!q|Q-x zM~Peo=Nvd5LhNYZC4Wc0Efwy`ScX=N+ED{0Zox4G>y|^v$b!LBrJ;4)5bG>Ae7sg) zm)#U<?kIan1dc~w_~lqk_l$*f+=P+ns!OM)Q}uNM$f?3}>92l87(>Q$g)W7WlkxC# zJ*q<DDGXn2%|jnQOW>q+{=r3*#?pFLR@zE&MxJ#8DN=#ArmWuVW~XR+e&j0?&*?Cg zwM-hGsxx_nmc64iVRFxfo585Yaqg-PU;_6?-LaXoR>85WXOar%$It-eJQA)<a6EPw zXTI{vR03RoX{=$aA?OwvgG?~^`g|$ZaAuh**X~-qG?%$sNp{dy3r7vLsrl_#n8jG2 z<H7a7u0wjGqosA!&;{?yF(k7^moRc8#@zKt<bo$X1oP>EAWvas9j_x_Vtn(*&#o%2 z6D)`$S0OQEde0V)y+;bBeUcu``~xcqMouOzDwBvrVUY0BTFhSF!&;!C#oP|psKw$D zUgc}ipxpn>`=3GnA4-<i<)taBXXF87Q12v-zFY_nnz7f(3Oq3pJYt}cZ0}K2az`Ma z=pz7R*aF5ZVcdy)N=1`HTTDGEQB_C2x$>hlpbWuQJeoKo3<hbfJ_YJan^1ivrcRC0 zq@kX%Dml#Bu|UV`4tL=PNp~^G;TQenF@*VuL7IAuM|-WuSu{-s&gk+XAdfh{%^9tz z7m-9>nzG!uo*zHU+Dg1hZuh+Ikw32fk9+Wf@vyXxZR-yPxjrip&pCk;P-~ecj@9c% z(iv&mbv}Tzt0t=>kOPXP4pEQ{oI{ko_tvp$$GPn^a=N$Ll}+${8rXNk*cMiE102h0 zzsQK%poYrT0p!(pAn(xK0e&z7<?qMB^*@dU>|Xbh-hswL405gkexosDJmWW(zQ%YQ zul3j|b_7rB?~!l5X??lPjjl=EBmcC2_az_hmbIzge0jJ3l+fd6Sx+KtcEk3|-3pLT z0E+QHffw`B>yh~}RYC0xFF!b~2fkxmPeV7vAh*?@g4|khTn75~Iv~oAuGYN?pdPyN z3i2k<vl5w0MrXbUx#_j5y769+pTO#>u0%hAyj(XH0J)R&BSyBo7v!+cV+b?%?m8aJ zdTezQkOz)${zh`HGa~uR1kPG#?cTk8ot3q@KGLi_gZ%%}d_?PR{bo1ZtR<w$I&xrZ z1TRw)4!t0Tgmh@2WM{pkMoa5Gko6mo^JgjFYlGHx<lje2>)d3xVj&{}KDy!G-V5?G zCgz>gG^++J*Nz43Xve%<KgA#ik9%|(V~C~oQMVX571iV1jX)kB?MB*;<x+i60&hQ4 zs@Uh3req}|`pbCRrS%W^y0M<i(s%0pzwEjA^q}{V8*9Drqaqg7J^*fv;6>pOGeWts zL%JE-z?!4#`;adNIRlryRlfy!8A4`glpoB6#@#qint?jmuI4QV!+tN$bj`?up+A#T zadjWaYonyrMwjptG=vcttzS15VmI?s0Bvc=br&2gK;B9X@EeUGnWxZliw$vVXi(4b z8++%^n>Z52;p4spbCGfo%l67gPP@?xBSkBWB~p+`5!z-Ogpktg78s>Ve+7jrsw*f% z5t=QcRGTVwbYCE!;XcIuW?m+?Sps1%#9sV9$(pe}GX{!%^3LCrebnEOIS(3fk?&X6 z7x}!!Q$kODD`aQXI(wYS5JrU~^1M)_qwFL%6>Bfi>SG#p>m#k~2CKKKEvP*yuZB(9 zIk68L)tYyqucHaLQEhzksyILK8=nuT@%igVk|t{V;x|y+3X$ua?`<FA`qYr`0N1@Q z)y9R2!)t!EW+R2aHV$f^JzP}pMPB_HWz;H0cAU!bXcx$Fuu$Zm@D#Mp%ZteFql~`g z;Uk@R@1yTx|5@J!XyJpaS#u3t%u^p9w+SE9(PU4-0ewP{_zp2@{SaTGtX_W~t=Mzu zqAVB}`606Zzlc1|1!2_lvomVl*sBPJ$qc(Di##tB@f)q|_9JVpR}XF5_G<eo{T}J} z+OLn2@;u6Va)8^1`*fY!z>(dDWDaHGvrQ(otB|Iy8MUnvIWAnt_s~*{txy@NQjGzx z$tyG)%)j{b{-mLjHDvU@?nfC3%I<xcB@P;k`^Z1z9t!L1wdmWR=P&s#4i<hF^uc|Y zoGQ>Czou`~qdwA?Mj4Xd;YS-q>4TsseF*SH)_1Y5za$ili~RGCid;`VOEo0dCMQzw zBR6;pQzlF7R1AYht$)YQ(v-g@Mf~Ws)_-gp)BS2SO8fi8CHQl<_Z!;Hl%VPox1Wd3 zsUM*)>4b(xtuM}~@gK|iPd`r=*7eNaS^vAxAKZVsf~vl};G;v&x~RTLEWD_}t+hp- zen4J`Z%Ce%QS0X3u3(r9vAf42&keJf93q!0S8VHk<R>*1S)((03y~sUlm9pUi~{16 zD8zi8k=@UX${!*|xm?CSFgwA419s+B`J=)j&kHgf|J_JTKYP2aBCpvOwVGVmd>h%6 z$d^at@+U=-E$f9eMQ-f9{Vk^PyNBEQRf78M!<}H5*Q5N_G+5;MfR<W^$savl+1iL4 z8;l$rTr`SXN#k(;)kXeGN-mG4kw*)=rM|M8=?YEx-R)I<0av&01d|i6D9bCe`-hmr zH8~>B55;JSRz+oNMb5mi$kRj%JuCZ>?^R+RuRp=<J8oak1*H#1De%D*39u>*k6O<K zMf~V}{`7({EOKU<$WvcyouF782OW{8JN?Xvi5wn(idz<W9;h5SMp?Wv<=qcQ6&87J zp`CdsAZL*?YxR+*HEKOdWn@2cBO0`RcU6Cqt2;LN_EUjS(*O_NO^V#)ruE!VjMiG` zh@5%0$aNQaY80rOJR2*!MItXh)R*wUBHwy;j^2oraF2Ep^Urv&TYjL%b!l>LT4z>^ zJOdst#O9x6Wcrz@MP5eB`VwxVS!kxC5YGlB%-G3g@6r)W_ILxErbPM3jf<Qk^1M)# z&{#M8@?bY+g~$t9<fL&N(n8N<e+<YAnTW{C<yq)`fBz4D|EbUM+oQ<)mZIGktI;L; zQMzq`p;EcyEHOXx+MGKgHJlGgk#iq;e$a!~S>()0k%Iz}s>Ibn54eNIQ(vMr68Ue` zMGlKAVDei<U2zo`c{2>dz_P|aAo8)*4*TP#)ii`~EK4k=X9a?JZPMu>*S+K{^88WM z4eQ0(O!DoXN6x%xA2|s%9rUv^v-_D**(Hz9i@aXH7mB|~<U5hb$+8{GGS(J3-0k4S z99h>a@~n|1ksI8!o)@B~bqsdf=9S%;7mUdDwkfG@e<qI^8SG}xi~QdQh4eV__d=0_ zrqw}&9U9leA<iztAQ(GR@L|vF2SIP9<Y5pxk;pHtk&txym$+qFVQ8S_WoH;TxHt}i z&=;sQK-@l_6(3Sfs5cloet0b$SqNN*mx9@V$o=kV^x~d*ws-7`B-8G>IPFe#wwoJj zo9_<9x30n!lP)-G$-KlFvMMIR?Sh+Qmqng?Vx8m=`BtyB&b)}ov$R4h-b6-rKQs2U z$ahHOntQQS<T|)+TA^h%g$QuOuOp-B5Gji?4K2_dYmp<2ZzBtVg1|w2;q29Fw=Ef} zH&rR2Y6T-hJyjx~O@Beq3$qE4+pWhJ*YhTWW4l`t2?n+=TDIp>HgyUncsa8Nl9D)< ziLN~r{$Mb%&jtge>~8~bDqMN~&Gycp7CASq=LPb(0g0PDkDOVrX+6dDU?kCCxAYf; z*%b;c^7}i*Ut)#GJ0oT1CI-DZ4(#3ZWe50BAlVL0acx1fI5s=Nfz7qZk-r&sqIPyc ziXJ<@JnP94Z9_M$qrQ<NoIsZLVR+N*w{b(7U%mmTp4qg>5nCg9Y9B8WxqUXvc5Y9Q zLS_Mx3*uNMysiMQJ&0AT&k>iGI3mwCMZF)nso=qG%u11`zmI8bt@W(TBR4B^5&7SO zSSE7fn#7D3;5*u_JrZm{p>+>QvmJ@t2~n~=yiABZpj)#z+t(sD5x%S9aC>Nl6yXQz zx*^mRX0syKN$9z>K;#p9I?H|LsRDz9$n|lt$idY1Ba!nw@;oxvvTkxj&MX&s!s4lF zoMxb9WUX~G8nymBk?T?GL&VXE_HEPeg(UJo4{$SQ<Kf0gKjK^m7Rr*ybxvKyWgn5e zuA^g(Iuhyjk-V&L1USKyc{ci{L_T%FsojEVsr9>s*Y8E{PjDG_CM84Kt`xZoN?PGv z9g)W>empPP6OPDp4nlH;Y4Td@%yaf5&q6@19;@C#R(3x#_STNbbssr`@kr$TrUm9i z?pST1({aomV)XAs-U%!ai5y2whXQrvQ8%uwP+DFv8xlF8I=@{K`7Cyx-jw1ZFQIW< ziky_(JyWr}1S#1^KDn`{36U#&ItTVKi#*@J;{>&=^I$jTnGv~G`0Lxe@ckOCzh-Bx z^_3C1m=ig4IwX<P^zeSq?|dh6Yk|nA>?k2}()PILo6We$M;*e{&w<FPv0a2#PcR!2 z`NRiP6_L9l-U$AUUbV<oR%BCc>$8OIgL5hJZr6jywaBB2OHo8VV3Fq?-A8WhnY?KV z^Nff*{bB0`{ZIX7Vu@B`{igLu<k1N7whEZ%M2^dJH$a*Qo7Z}x_`Jx+^wN$*?xQ-* zknV=KL2c{YvQBKek9-P?w_xQG8Tni!L@p-wK;_1XY*|nAkyEev(|zP9bQ+1AmuSr+ z#Uc&{tp~Hm`;jwiZDX2VFL@#AB-do6kNgLk*26iGhw~y2W-Z}b<Vdz1T~>FY_qC(@ zDg%jp6#W6<v;#G7ttY3U>&0jSUNT0r@loqjdm6QY&xyQr<Eh*wZ_@oH=0%P`y|i@H zx>zi7-o`XX6ag>M$~-e7FGQriu$y`ddazr@rk_1))Or)(=){`VoBivcJuh+xSH?pt zipb3oR2<5T(&r<q85mmR9m@)PV@pNkrp%@0oDKV98uK2iS>_>CZniCMSqB>zIS$=v zt7}8&i$yNZZOVO&R}y(kQo;plOizgXxCMNgM?Ud9U+}2)oKpk_i=26GM4lOw&lZIF znIm!u3~ffE*3A%Cg1M%33caoNHKhe*Y+JY#I%0OWqjKtc+dZlfFEU#9NAlXNH9lwt z9faa~$#%hr&5K-|-`KY8-H62^2UDHf6C`ql50TTU8yC6a80Ww{J{M1kyvQQY4YB>m zdHNZ%);#jmMUI0aLxbH`i+m|g#}SM0eRKXwC%WXs3z>9-a42aetJNa!^CWU&10tWN z<d$4-A~pl}k>?xqkyAuo#Ar8;$eGn5Pv7DN`J<B=nMWR*epXl9|2fA!U5Cii#2-^f zItkq2<ykkthcve_J&%jL!lTyngKAqh0gIejYl+r$cR-64q{-H(^_|=L5^hr#IeOcJ zem_uS<(yHQhq`S5_oysVV&~`$Z)2KAio|RaQ(mH#Sv~zME4!c38^~VM`a^vQ4=IaW zF1Zc@AIVF#nmYqt*ru*Xi8n_(Ns<4~5qT~s&KlPZg9p1YKTXqm;!Kg1mEG{)_}x|g zNv`fv6}j$0XMJy!-L!Tjui(Kv{p>&X&M(JJ7zpEv)H@hRAb4b{Dvm@SDxRu+>uvU6 zdxt#jHTE<$%sMvR{BgS4*x>J%kYF&zR;v9vW@elxLI^T%w`K}5yMeGca<j!vw(g?O zqI<0isf&rW?T+crtb>Q3|NK@D|Djv@VRYO_Bm68M=8LAlA_q5wJQbgHc6Cc-(G+q* zUOgW#>i9E+JPYdIe<JXEUqHw+g>{?*&?GE!Fwuls<gwUT=XJ~2vA7obP%v%TJs)4r z&Z{4vyQ%<L(AE0E)Lrop1E$uqL5KzkVZfb2?!4XN;nK94Zp3$XQ$y>NeE<4(e0rJj zbbNd5Dj4M8VU#_DJR1Z*BzN&=x`&WwPneLiltzPZ?=13faV_$`vqIjMRk!~@*Fnd@ zBk6htA<u=AK|xC1TE?^yAP=^wPp#WHa`Tx=_*q{U3`=>{&8ZA6bR0a6TC1QGtu3CB zFCWpIyw;_8Uro`v6(A3G7lr)WJdQl7+dALe>UiWuQ<NU6!jtlr|3>nA0x}LBNjqpI zV3B76N0BQ|2y<D;83FR3x|k3qrKxp)X5GBvhM$ofbm7yQcgtVn4rClW7ClITMN@L& z{TVsA9IcmyycHk|nkr-&Q&!R#@LlIl>#^g=h3XGf0FVg#gI1KMMJ}2Q5u)KZa(~ej z%&lk5wo2XEZNu+$RzEXHC^<-m{h^lv7I`+<)z3&xSZ6o*t>;Wtg*m%fQH=lxp4qP? zgk0(VpfQ0C5}?vX$B9Iq7I~KN%(}P{N6wTx0oKnpOvu^YEFz<Tr?O~@fymh8hq@~Z z03y<M^>7%pBv|CxAV%oS>Su^R%a*<Qq0>&$Y82cnY*JXpbV5lz91L350K`CReHiJb zA^{=K2Uc>Mq4gx>m|V}7Dp<(l#-F{<@29c)*#s#m`@v}W_sjgc@afm!jSIhQ;YO3L zV2anTaor2*CV#uuZRub-H?QwX7=MiMGl#>_OV;rqAva)Zed!4EvR><Qw)z=D&@!b8 z6mlcs@fR|+N*;gpGbiO*>;5cy+O#XXulb&K2Yl@1ym4{f_`HcT7oTf#e*g2=>v{jq zR@1Ie7=N_!8>E&>kT8TlBhTIEd+FmB^X1R1MGhs;mMU1tS<55(x|trhWlU3;TA#4% z7AQvAeX<29?Fllwl8;L+DD%PaF;gbn7T1+t%eHY_fm{Qm81Dj_PLkg*8b68ng0XSG z>Zvjxo=WaCA0|5-E=v1X1mll2euHyz3!hqFnXX+ytX0>AXq?mfb&H(AbMp1Fufm1g zO8DcYd~?dsYPCEeA!mp`h`-$-1Lt6}s!t7{B3r||guLd=%iAO3`rMqojL!9eD--vI zH+z;0+@ib7sb2Gb-mCB3h<j~IV>R0kj6ap}-(!)lQ`=6g-)853Rh-++rD(kl!pYal zt_l+J6lT{)Ob-(BS_dF`mgwx3qHbOx()c~Eb@Q@94k^!%#>n_hAveT!THl;h+`JM> z2;;D3-ek~OgnJvDq2=!q7hP?ywf9DB*|mAHIt})y!5NDq{$b+wJe$<D%H6R?Z7Z&> z!L?+*{f+y{Coujv<Dc99h$GJho+27ydptnMnccQAV3vIaG$Y%YiihM{HyRq>-EEp& zPiksiNv#on24bOgucd;JXNM4t)o~}}09>3}PeaKKV;2(hT35R6klYPKrR-|0=>MnI zMdmZwiyXfgc~^1>IS8CuXAO;>p*1m!oMc@U07R$N@;-}vna`-t_H3bd`DD+09cLwn zkb}VRvv{#*7C#}(x7b2X8jGfYL?BHmO|5^S7>b0I_JQMf&TdL7SmYp7$T|Ki5}Wb8 znYpb;7jo!0NC?uDkdT9~#^r-Cz#<31Q|r-|P4VxU&U)k|bpb#!)G`4fXG?S`%{EKv zsQ7qbmW|4wdk8tWB;*N1pZOYYwsfA6V+m7`5>>C_3wgR)xEMrOtyzZF@Tv6@tcR*J z1Pi$%di<Hq>o)Z&vXINV03ac18Sb^7ih7FAT_Vn$Uex~{J~4jJX+6{;H$VLjA>^x~ z*_vPVK4&*eyu>j4N+cnS?us+CZP6Am)j<S0O`o&K#gc7eaaWz?kAF1Cok<=d<YkL= z>#JnfmLWnO+ijg~al6A7d3>*R)t8=pzrG!xUS>QU-(Df;;DNNgqEL(cqKu^#o-IC> z#q_cyJf;7Y<F}dJI7MsN>SrZne6{S#n?k-x;2}BR**zg=EsrYXB!}X}&*RI}8D5S* z3y>{ct-qAIEB;}SB3#HtKxkKLCiC5hOO38z{4C_bncdo*0IQ|BZ}qe3<I!x~UOEY3 zJfHRU=ke(RQ1ZX*oxg9}Mij@JqW{CuZXMYK&jsxiSyU|wYRHgf*a!^%0fHqU@KRJV z@;7u4T6GZ$xP!JhL%jx_;;D1dwL|6tUK%F|khEjpyRS}nv?TUu*%nptYl%D_?-v`O zAH8?)jti^8qn%sVqri)4bIo^kt!H6=I4d*Q^Z5MM`^eV<mteQm+#LUZ>p%Be&%(RU z(DOYzW<5h72gk>gJom0IrZ#s%|CaylS63eGY`TGb`nR8nxuc}WMr*hB{PxandPA6; z;|r{0kXxR0W@#4IpaJAFj#|HOg4Tcic{0d<&gaP&Qky{RZ3^A2TmgB8m!FB7YA3V5 z9q#b?1?2n8@&ArmU&{UJ|9_>}*=;64>w}JAjhmqL*@E03f_(MWR|$HRgM0zCyz{wt zCo1hMTURSCAZNuuK7X61isXCl+4K7Rsv|hootB?1EsI?Lf4PF3|7N<g8_t^KpJW8& z=Sd(xUmB7;2t!XRL^>vv3B3PM$U?EHgaM6a)|;o5(cDho9)XuDQJ;gax3ATmk^{)y zm!G*vq{gC16U8mA*ON$hXYQXL{}&2ul7}m~V|}6ZY2qAt2ByflWBt)F>$6@*u0g)K zG%&q?`|Wr7{EjOl1M-%XFLb&prDw~OX^n@sNlK_QJx%MfIy!(zl6qGgKb5j#jlj#5 zsHdTKM+zUsKpvz3xwu^)u$UM$E)w>15mT|&9jIcipPx-~SmZ)+T!TD!tS`1cbD1Nb znLTb+pJ4@BCf-Nx8<1m)oG7kDBtKUgOp?by-t(ZQOb2o)LkpwbZnquDYIqAE?@HP3 zcB)dI#`A-2%gaITth<>Z$1Hgq<h~=woe>7+xnO6e^T{G*>G^+t#JX9N<m6h<4f4g- z{W*C18U8-XphX@B`Bz{4h8y3G0lBOr*`5mI>eQ3{n+JJIMs@H!@~@W8K|Ti{_kG8x zbysR+bT&GrOI?g)&H3{SWt95_a~F#|pCMlqO$PZV_wHpUY+b=TE9=NL$d>`~zg{UZ z$DyA9^5q!F+XECvfMKQIZg+vsuGea}1|Y9=y9DmwMW@|i%lNb_WruTYj5a~xdbizf zddTV6$<82oN(K6%D%lLXZE7!Qb+}W2oYLwpRF$X|RCyMlrHAH|Mc&opZDIr%Uen8! z0P@P=fjO0)Y^`tYm%O;n4xjSr;P7eT$u9*?K0hpYhb%5z;lwYLqU;hCCOz3pu*j#F zBNsPCRFO<qants=xJDq_+&{mLTKE6^r726Fid>7KPbY%h_N>p+BG+FM9X_79MLq&@ z2ppdT@=hdu7`!b7!xvIU5oXS%>`U1N$V0{`ADQ=kuE?s}AP0rHB@(>sJvvL-qYeT# z_>uG|Sw(@SY*VV~RU*l1sV4fWy6-`!)FxD^hg`R*-2v$JR8{SB+6*sO0?60*hNsfj z*7M{2b)s}k$Lke7?a`^Seymc@J#YP&<Kz9U!vf{KJmy-Sx4&MZ!q1PNKUoLx$AEm( zIoQqJt337Q<u~4dn2OoZd_TXy(0Gd6!6IMEJ?o32i6CcW4mGP+rl3n;eCS)x%pCau z<iGu@^sScw@-A^2hHqU;#pEW_oZZ-j(|Q;%$Qh9>1?GOh>E@_woz<6ZZn9eO!VV?b zLJ!#C-r`%m5J}Fha7Krdvdvvox!q<Y>jZMyt9bQ@3PLR|r!@-lP*;`eCqy^EPmWwp zAU`}TvE{wKKM~~KldaOA9F^j-d#Wl50p#4q83BI+$b(d_b&+IM+S#sN<s0U!!1p$0 z$>;s~xiNpZ{wzqg$VILN(f!0Z@(j$9qia3^;~Ci5?aCbaPac#A@`{X<SG)@xhjn1R z!n8a^nHD$>i<?jF5s=sG_0yJQ%2ri=5J{hE_6OnZfsBwFF+)PMrG4@G^rGElkcXTE zzTqi=IZmpKfLvE?DX4QAE$4CpIg$kH^}<Aum)2iWg32+-x!M7$@zH>sfnS(pk*5NA z`ZtB%npb@KUIdPgmFNBW1<Sm~GzWREWRR0){4#PAED!g-w#YNGA<XJ>3Xl^U>uhV+ zwOt)l7|C_e5@nd<NYz<Vj({AZQWY}eSv`45NTmt^;M!BURa6Qq%`QOR=F1LjXp6$9 z>IOjG$1e*~dlcm0Jkmt}!SH-9*JO~Nl}Kz_pRGUjKx~{1$oII&*?I*Rhre*{`pZh? zfRX??RX(slj<#;dA{UNkqljH3=T3uEF{RVmy|9??=f}QoYL0xMa3y`Ln@_@#&c4Vs z-*UFd@tK8;V?Psntq0cvIUCrFUk@O!w<ReKa#9~q)f%__ERtPCVy)(&YP-qA)~Zvk zqOt)w=nPp#KlDO&)v49$jDj53$UtvUzB^13$Oqa3gSF|+FvdhT<wGjFaJY_QD(7&| z!yNfbGe=(1ZA`uVOx#7lwV0x;n0C3in2bd+=g%(ya#BFLrbX_TF8==T_VV>mmv7&{ zzj!Bd&94$bo`qmHz4FYM<eAx`HI-}K^CIbYWfNem5R;pgpc)4`oaSDi3~Xow<X9)> zD-zeCfbX34dmK5}ls%nGtwgP6rEXi~2_UblR)O@+7>gXnd;pMl^zd>efc$xdbjB7r z7))nC_$8eI@-r?n^sw)Hu*gfLr*w;2*gD)=e_1dfM;kX2wJvZ-q?$0r>|A$P2}fKd z8@b|U!`A2i`LQ7keTGxy57U9%fAjwJcVqPW?;PdxtI0dNWne=X4Rf5J>{#TfK+cCD z82d1Q;~?*I^qUGY?<B1wR}T09;5FhnH)Zi_MQTGf3*@@fO0#Z(+!XIy>(JnZ53TWb z;EI><$LC5lM}9^G=BaL2;-#mfbL1$=0?)Tzs*J+nVI1Ty*Cz(MO}|B}n9`yYZspu> zrf)&m036Tod4GPe*cae9)}N&Uxqor_-2`1;<UaO!mCGEtv5oImW-k~zW#l!czP89$ zQ-VB@l1>_oEpX8SIcIfv<yZg)zlgdDu=Oh-Zz_hj5#iQrQ)5v})u&`nwHrol4RU*q zye>H_U{a5Q{Do9i1F8^GlY9(18sw&`q$7rOO2f<L9JPM7erBT99YFqsGx+AQ0XfX} z=|GM-@&wp9!%Ey#+_sod-0m{DbShrX_wx&-`#eYP@Y0l}u^fjvK31=DlFzFqTI3lB zc8gDsV<~xd-hP&Dj-1)cG}K`1Hi?#TkSkR76;!(|qG(f9s<taJkb~i2B-^ci#K|TX z?{jf(x5K$Dh49vkcBDa$E@Y=)rJNCv<7U+E(Sdub@I_RuYLI(ft{Qbzy2+h%Wxo8( z4di?{Jli{5KP)+c{K?+l*%Ji2BTRj`j{Nuu+L+oR7fJLJqXZEtDJO7DBAEM5<c`jB z=g_oye}4V;GXc+fvPJI5@ynd#nUXL3`!_mAo{`t4Xv;hsuJz69SmcN)H#6N4p|aVI zgB%3qptY)`+o#x&6~weaj<sW9o6ArgU0ju_^i&eIH7_5xL5}#hb~p~?R7zE)yR6eH z7c?OE`l=?<=r8BEE6Ba4zfb_%)-RqD$Vmi#WbpAAAXnMPg=uzngGHW5IpN@V#uYwJ zwz3!pD`CDV*J_LD)@RT6^9vL0W;TRLW0AijXea41pC_NWd=edQ1LU(^e|9gM!EO!~ z`DE2A!Q`9RUkwV78dU($Krg>g4}&qqhshABc)Llx29?m<)ya`|(O(|1o@%f4La9*N zdakc-Wv_Ktkf&SNEYi;G8bAR&?tW&0j|*LsP1!`)i+O*3fnYbcEm}tz@%MNCp%1x9 zJ}Ut)4~v!_jOgLobguQ;`qwdnOudhMb#-~LHR~5w^c(UC<hd42kM8a@rccu^KLf~< zK;=$OL!8tWa{3CwPNDa4pmecv=luD#%T-zAse|48cduiyZSUTA-kW#-ytSvvOF7AB zCO>#kjOzjaJ@}r!MLsI|VvI8V_A~Ak7*{7KGaz3&|0+S}Imj1KrJXzaS6|-wJlz~Q z1dxwm-}uE=NTgrH?S$A{e3glq?BbsD=QqyR;5ruhg^lqIPYc;lK1)6u8IFfgF$BmT z0Oj95P(bIie|^{b%w9;2Pj;f#MPNYwDhcGTa*!{emUl|to#^wO<!LQ)BN00Yb-*9k zf#eklCsG<d+B{2XzzW+IPiWgExNM%EU$r*e+6}AEHdD-z`@#Dmuiw7$EWI&C`QL%K zqT<o^QCX$RyFDbvtGL@c5I3V@xg5Kq%LE<$ae^vIdfYn_85eWh*YCex_F<DVyZH#9 zE3&5oxxqMpXQX>3m9^KHdP~3lJelJ^|GJced;zs`H*X~0L^mnleg=?>1bY$*2bZ!t zCX?gS0M0~AI(WrJ0-NoQ0K@ryenoP(x1Wvvzw3j|@$n@8U`@gT-jcP;l-!o`@mOM( z%SGm?lqce5^n;Ybs3B!kv;dC|jh;za=E0Q{eiW4H8APV#uMxMGZL<I*XOt_O94M#1 zwNxOFg{{xRCP$BYhCU-3!uV^O-oPZ^I8XAd=OAB5ZSFh@Zuwt+)epgO)9JOM)`7JI zBT_i6=R(o(O$mT!ynUV4Zg$;*C2_>_{`}gto)YA!wKl{xIBt{tQX@VdI9cX3Du2*7 zI$)EVcs`DpRoP%-KBL>W0dgM0KAlb9{ENb<);qzi32jyRbn-{WEpq=s@k)$wpuFoK zxCT0>AG(A5UVN|h8OiJi!>LTX##AVfBW(Sf^NAe)Ciko_s8$~B+`1kWyabTD?d<j` zeG59}qyoNa0<{X)yImlSy<Olx`Xn`&oH5_eZ=pP3rL)L`HBIXaZ$uY*?i?Vu7<y6^ z#eGRMgeHL;x^a-h(vRfsM36(tAfE>@$d^4^OX1MD&M@aMBHq%?k!NR*)_d96qSaq3 z4gWI}$$uW}S3mz|BR9wwRvRmux2lzmkr=x*-x=i7s321Klb!ABcz$Xix{szX+Ti>> zKU?@dKu%(gr?ALh53FuaY2)G&M|ClP{GYLSi)~HJ$5PhBL8DO?ja@09HHw1h{%m)5 zpWs<*M6%l07sW=SrYceXHsy0hxz^ZyhM99p?Vf1XTGho-<3v1urtYD3qZ|WyLsqH# zB3sp}@A6SY%3foe$3v~0i0wuLAg^&<Auv$tk?t28RT=U96RHp!1&y|RLL<fCD236_ zN`6o*KE2|53q!=a!5T-3QJ!M?Sr($!^;R%AXJwAOq!GQkv|RZ0)%jOH$Mn_tt6w*A z$9k^2(^6?oTyKk3F+wImnMkMu3rC!-OjHn%&W{(xZQQVnnlujhu+TR$Vuesi4;kfR zwT#d_ZbGqIraeyJYcl8H`6&?uMCH_5wEAm*0@nY4<8L{!@nLXzF$8&R_BkTxfyqar z#x$2oWp=u=sysW*+U03zqGGwH^Eu;0vbJGlvyKF0s*A_6dZN-rU99@d0(nu&Mj5_! z)TupIr-rDh_IJ4sesc_Zz(B$FGP;G=K#wBYhE=cHdyL;HNX|$Ac?ggjeHm(tT&+K2 zh+p3#R~V<y%!Cmb&-#pA>!l6PkbGlfqrmbDMjJWDbKRvj9tO@9d4e@)m|~OBPS}9- zW7i;!&-sYPGO*&z5zLO0o$s4**tM>(&7V-;jLEmMF*;pjeAVnfzt0j_MZT#xUUGJ= zYmmPiko!U(S?>lQk1b{F*%4ykBV%;C#&&YFUp|T$;I*pUtsM+N-XI><w#i0UAeW78 z%7_pNS3c-*l7;HqRGleG>Fr&rr`X#&I%2@uUV)m}RRcla#WD?q%xNA^wEK8_2=eIU zXg`us(FS?3_Dn{#8bHonolx^!M(~f1Z7MH|JkUn@;DnPilkXS9FUNqK0sc7=91vGw zZ)q%Y=J?DvTW5#^;kIY}li7m&;fis65XzSc=0?l(A&jr)AkTGYT6q{aTjYgNcWr#- zvkesA2UKuMf)9%MI%((PWavl5P!u1W(23DVOI!n`N5_Qv<7)87%8pkuqqbYf_VfFY z(9`4OSWjt@n^3n8Z_SbPMqA|eKnQSGKn^_e#Sydegvks@0_1Fkqv(<1BbVU{aE_O^ z;l4(7%wO}ZuZ1W^@|h4lw#zwfK)yRDQy!Tkuc7@R$QvlJZ-X3t=rLBgkHHwF%HO9! zW3*JhHcOBP0Qp#p{PPF=LC_m9{o3y%pV=O*#>1YG<!2(;EG-+7lL*@=$rp6YDW2<2 zwOWD^<z|t8`sujY*MfHI(h*d#S!2v!o0mTF2Yf*#O4*DAc+eDb?o%4|t`gL@Yl(Pg zhK2WStl@wW*z7gTR27hgOw$S9P<4?{8g!NI=lAsl`H<slDJ=3I3DrM-=P7-6`To5= zvc|dAqe&oV6~8{(uSyvQ`94z_HIab|T(`O(10|{h(sT)<TOk%`hVW~EkB`TJyk>*E zHgLp`2RZV$;b{1my>r=Z8i>L$<t3chP+w$(z?Qr*Y|08nMM9{`8?a)-j`v_wMd}0e zp?HEyT@_FyE=$gtKa-in*og~tX2SXGj9uGf$Kvw!%=H}iz?bGsvkPYy2Swgnv`!H@ ztu4BtvCl_#Kl5hVlp}n67!W2Z^17NBGAtx-tRivYj;Wfw*f%0Cw+x=7*aL~w3HeT@ zp+8Mp<EONa5II?Vu~^_%P&!g(LA!QD4*Q+=iTvc%{1LG&a#$I$uPt&uf&S<~XWtY# ze2qg2MA~oOyisNK!y?D2*?`DRhM6sLj>{QGL&gl(k+Z)Mlp`SLWPC&ppi>u^!C5Iq zCArh0b%f-_L=Ze7ML<5f)p~@DspFL%lR=<8&Y)&*MA5pE_2LV}y<mm2*-^Bv9B+#p zifrLsYTmsm@)=c0zdXI@M&$76+!i^^|N3&KM|RQKKW>S<U5Wexhj3VPx|hi35cazs zkt<hUZbjr==KuB_k8r?n9XSge?bgu^jn<JOcRg#$k%`E?>3&A!VsgP7(i#EzD3M2< ze#yu2L<j-Y=4p$M5qZHy>xv~rPUw_a(hh0f>V5`QUYPD@mdLdeJ0j=f*nhnx@)noV z5#!*??V|NLCBzJeaHCgm82To|B1gmaGd^{O{kPj9Z;=mG<(neM?dXUThFh)IXzNBU z$1<*t-2HekD~tP8N6sO6Q&$qb2p$kub%RRHeY>COvUGc3m8eKY{Cz&i>Z4HJKQkhS z#z#ivitEX5_=$5?9XagE?ZZz=iI=8mozpWV>=Ru_e!h0%jJuSzYSdI)<mkxuTIGdr zPdWRx$S+8yd_;>JIdFQ8XG7$dU6HE?Q(R3c?Z0m+D@0CDhRFFQDCK`?iyYq&zkE1h zxUpNy735@dT}3`JBKKuH7!<C16p?e`dR;$!I-LlDL$aq2>$<6a=kepdI`UMRJmoc^ zBt=aAz&~U8fQRp&5tAvKJch|{Bl6ErCtbd3krzc|Xwh|>B?)nIO0?08$7Y$c$RS>o zq~rAYoGsaD?Dp!M5_4b5-Vyl;<(yMkz7{!OVT_JvqrCl1N95;^K2i1y#Nq^9b;2k3 zsSx?ejIP2pw#fP0ym~d~mvjXp^6a+}IYwqR0r{BjXFiP3YR^W#?ni#)UgS}kH#JjL z4+X&mRaJ3oR+OvnDRM;QFnMYftrt?P9tas!jz3IV6(dA`v*-=UuNUBEyMRZHnlgXW z>IfJ|PBEg(1ti>(IA_}1rz*qiXjA0TJ9YSN8-X)q-xN9LIp@qcgvk9Z_FC32o{g(6 zJ0d^3<Zp`cYxpjBaCE`)hsZGp46ZRE$6>U@b4F3rPd;o0hw%pzIo#c<fE-EPjEKmI z%^GrNpnl$$NmKM-hgH+?|D%r|w~sX~QoTp#x@YyKHb?Eet;t|cwD{P!8ldi6)nXs_ zr!Q^TcwCE@F|PsY&gJH2^8OCrpZ-BVZz_1aLpo4L4u=CBkB=og^vKuO_qSWRjgQDb zFTm&Sq$vx1symb3$=S*F5q03~thJ^X!#;jEwKLd<%|*!G1-I%0&&E{)d2xQ^m&4a_ z1w@`tY;y8AB60>z*IDXKVAGg#81CEbXQ1GgBURO`sqlmTNiEw{yqXN0n4eU-d70UE ze%!i!_h8k{Zr#>S^`>*a^UZOI{VaKZm+xOyIT|MIEAk8?*Q99mRutL6d3Nw+g8e-s zqh+J9+jOkRziVB0r!m!MzEealIG|7+$v37keFBm5vg$>SB)?r9Idtk0Gxr&-cia6e zi+a$bE0w&Ks|_Ebm3Gty2`(sBM@s_Nn@dZbLw|4?j`0T9=nW?T7hu6Db0>3^{#NEm zg+7nFuk+)6g~?aqGV`;w$>sf>zJEy;?<4trL|$QJw*(d^_%CwyR~ma|-q<l4dv#Fn zZ$k1IBzuV*rueonChvG0e9MbSZ~^x}qnJF_<A3KXkFO(gcDYKT@cNOPz#QDC<!(iO z91T(s*657I3bn64l<2F>N1r!CKVionS_&(&;&SYmVWBuR`SlU(SvN9Cq`<CPc*QQS z=G&OO*wt9$SIPT3eg7dI3=IflPv0384<`R7zQo!4lkoy>S+st=09HLY=0CFz=aJxq zq9|Kxxc=+~c=k+r9KkpOa@IH{#Tb$MG5Z;T$J545(R!9df)E;UugKGMJ>xY*-WOkH zyA_y)>Bg<E8Pxl0i>n0v&qj#+$<@N}_2=>n1>?&f&^WkSO3At#P`J)P`G;q;a631q z1{i3ar4EnZE+Th6AGzVqCrybXK?sd$pU9Jxmo!P#hD4rB4u?Q~k+>Zh-p}esKBA5s z6xH{|4!%{T6s<d=Aey=*nX84MAE0mT^19&ylOQ8<0*^N?zf+NCkst&{+AH$oBqdaG zoJ3LaUv)hTUi6ttrYqp_WQ54`<;`M{o29gMa|Y_ubgP{b^=v)t-H)6^?nC#pBNLMU z<N3&?Y+X1Q;%RR`atqaBGkCfEA7r$eh@6S1V@7rZWp#bE7~tx<5|6vXOqo~emNPw! z>PPO&z;5_G!o?7+AQFVInD$5HM4IBGn#@gvFvyT7kJE=4RkV(fy!ml8;PD@gv{`qI znf!Kuas9}B7~72`juf~MdG;U@gpi2)MV^9$6Bc<gxg)Z_U*4UCRDk{$-ao_2ARr$p za+v)3rcdKH*G(>M*283vqIH<u`OGOtZl*Cs4>Umthh*AATybMJTIsV2$)D~el!L6O z#uo|X{WERy6)f^8YkaK8^Je+&>gqQdzxuvxD)D%r3>2;VqH(l#<CQgj=VPr);kpnQ zQ=+%kI+3d6I90=}hcD#YlLhh%iMIGwKl0HLIp#8Lo-ePzegAxOwdUsY*KgM!>P8y6 z1<PI$IaKNhJY9YMbw6_Hf+idQ(?OA|Vcimp2@{oN;<LcK#L4?-`lDPvr4=F{8Ii-} zdDYb5u|n-OO)ee}m!XLK{z~KSVscYMZpMT8SN+Jv<ibHP9TIuYMd~RhyhKI$zz3ZL z_`AU!zP}xi-+E*>n=&Vt=W2j|P^n@2r2~1u>{YZ5i&N?X*xX(BGZ0HXxex-$6zpj1 zh6z)mGJiS|{3q)+TOTiSLlJGv1W<~_gJ(eGz6|V!QgsuNI}kY|-N^<2iKjb6o&YLb zN2~Qi8rba+$&A76Ia9Jfh{!=fD-eYr00ScT#^abr^`B2;Dk>MkCWXd#h#X)%7!i3O zWJt8g`4jK#M=p(Y{~!8A?nO6pJsu1aCu6PK#4(RgEv4*&SCEvGB!<QJ6?uA06h$r~ z_ZVF-Zv6m}19)6SF6@ZN-H!>gda4ga>w*wErjGm=ozF@Uc@Sjlt@1czj)HZG$b}su zcOH=+A;q#rL@o%oB7R=#sn3p64#<oAf1Qoodvr9e7QN4ykepO45xKCh$nQBH5JrjI zeI2<VgbhXH@HnAFUX~J(hd_n|Uf=G1_CQ1~>^F_6Gn3=dw#R7^kqg2|x{ci;ZnQ4l z&-}#1<F>}}F|($`(%4PdF|wNvMe9JB+|-dv(Yhdv#f-JCN!jJn*v(%uv$cP)#)FZ@ zZo=rX)?LW_=yyZHNYT0={6R#X>N!(5A}=K(_YM<;W4o1FCF>HA3%f<`)#PUqkqg2v z_Rd(haU%%BNsxCSty3JD5C|woz*rDG0>l9%k&0laMoEz(l_()aO2NTZVU-t1mr6Lm z0nSK&51{IrYwiuMx`)UNe^E<nElaXxQ?mBIWW^(AXP0z>&oet*?FHma^6#1CT(z!2 zeux6fSqjRng+TH%4RWnbAa5VzOz_p$&vezgme#{Sj;eLNA<O})hHxa(>uo)^&Ln46 z>(si|P9SfI=JH!pYG0b7L9V5BUyxVgVz=HJklTH!`uT3ZXPUi!*W6M)xTx&ojE}l$ zUd(SBPQMB#QI3C_!pYjVrs%45t<4~Be}~qu`44^IQ*Q{PrM0hOH{{mWy+=MNr0VCB zBH@dDh1VVPPCr?%G%JeN^l@Ee*Ze6pFQ9o(@z8%|o{E6*wclQfYZinZTFZdEqa$*y z^&ls;zp>k4?X|9@b=>N_w3i&mi{xt}@>dBdE3Wus1IPj5-a3%a$wQnKMO=1IyA+TY zGgIk5A+swYyyAgQosR0vwiLSKv_%GIjk5I}LGH(~ivxT-fi{oU)^L8{!}gKxV?5s4 zG!Cb}GSYruKU?ItTN1)?y|bH^*8WoKs9IMygi-PQAdr(i>vAUh^onbBBwW2N`lkwV zH53QaA$5)XzQu07=a52|j+}w<RKjRaiD=JL&$+(hAa?@85aABv!0~2bFvr;%`OeVu zWmi10eMICE<LzYEf$)RcYuzH9X=xpxEYdcqbwIrQ*T9A_n?c@9()pyf3i4#~YC+~n zP^6PGS#Dp=)7J{fN&O-#yO`!xS_G3xuS*?Z5(DILAH$l)voS_7n@l?9DadL@<5siY ztx^r+_t_A}7h>Qix#Jxz$bBccFUSWD6B696N8~u6dUz1XL$O;#?g<&2J29Tvb9s-P zRjrXPtJYg9cC)NbSAX%D)`9B$MaQzXUn4&!5y-cR$Y0G0)}#({Zs%qNY1X_v$C~w2 zkegXyb7Put);IHf(RnUGepN8tyV-I)9NFe6%DVNOC5zTcJA*uMe0(Gt<dq%`<Xa1V z9|`2j0y)}t#3*lZLl|IOQ(Wt?)wQgxK#tV9ac=kQ%@MghD<)lT`x4~b1d8QV5%kS2 zuGB$}YY9MZ+V~A1WiMbjHyCNgey)p@#=9=!Q%bEj!ty&UWO5yu^_@T-MpfRJL6M1Q zm>MKEpreehPx)_xTVJFGlz1XS+Bc@7sm})@sZ6FfW5I-EXJBmRMZ+A4X>^aGoJOn0 z8Dj?Ql%04t2I+=4mWtS8A7g6M(k3UHF@_5;hfFw;$lw_6LY|Mv=mI>ur6qAu8euwK z<Oq?Z>>w<AL<09A!lWFxKABjMHTy_#%Zg*n4nz7OU5V@W?sIoR4=3c4c)Fyi90{Tu z7JLIK>`P5~hH2yH0}l@_cH@}1C1GGd{82ZA(HPfy2I_8E?1q?}BJ%F$h&;LC_H}V3 zLCzfS)+`Y;&t^6dov0vBib)OR2*uH->_4AOCi6UdB`<VmdFS*%UddYb7pu}4Yv(oc z%n4*@>v@bn2GG#S2chHfb(g5(MAVLn&M+i~5K?@;Fhq}f(CB$l9=JyCgm8hQXt*3F zV#-d*l<}5lAx!~i;Yx&606TEJF!LNw@NjNv9%NG|<Kc#07DmD~;@t59FcZ@bA|8_{ zxV)E$?nMl}isLjUCPuDq0zV0eq~o$jp5Z=(Cty;Wj2{RQ(8vjHKDo`Y$Oa+z_j&N4 zGp^mc8w{f$K%6a~uHo^Zo)gFfi8r8ud?TTj?OEf{34?@xK6u*Pue^uwp{e!uYu)OZ z^%g*GSzSX*>j-q-v9<v@wpusVRIN)qLjdnYg8T{`uUoQ3N-dN6S_OH(0diKrpngrK zxj&S>MyOuJ@FxXwYdb6c!@6hHdgut^AV4m-jc%CPW20<==CGuPH>{`Q-6<1~d$>c< z1UX&i&Kb9KI_9IYg*@SNTRJ9F_E)-c*_GD>IioCMqlCMMWzRfv$y-?Z95hnvZpdR~ zZ11o;KMHXdd=k9H#Cc4&nOaAW1;`!vNo$h<gBkJ$=1GpzhU3&pcy=k@p<BY1-36u7 z6h7btGfJt&vy#i<z7ujAdAFz5$*j7kq#Qba_!@b8wQe9ePXZ)w0pymY!*Q)+QODYx zT9*;|51T-aVz=vAQ3LsPQS=l`tZ=jPnF4YmcH96t0((ULNUhT_Gx7i<(yJmpDUff8 zcWa^hZqYjS9AY^m0;nZM0U|g=)|oTR&W!;9AOH*q7B?eu<b$h}eJJ2;N{t*QWm8d} zbEA+zjWoF51bMQ=91{^e6DP%RI4MD1#~vo@dCT8F2#!*qeG}wx1CR@JnJOU1btEcq zpDrBNe^v3FaRv6UdJ6C%XViGmfnz}9s$#)aKz`fLC%U;G$PZw%^(q!GY0lzVJxZ~g z=D5}~QD^&Nx8B7T5qVk^c`%>XKwbpJwUUGfnOQRh<m}}23dlRe=uV!=*U$J;RtNc9 zgM8f*IY5q}e0z{XZW=m6P#CBIA;6wIB622y08L;o950U-I0L>_kTbU-FY;K?utp`A zx<C{6VCq2)ko$FzC(e)^4V`Qq$lXCc6;28A0FL1f{A(E933AMRDin}&wx1=OM0GrL zM3}OVYMuj0<2uNraB)Hbc^)ld`*>}!8}3PXEN8kq$iM!keTvJs&t%;?@6h_x5xLH* zYaNv~gB;~<8zb_?D`!D}CAB^w+D=xHkBh7#P(eN`I(3k<vb=*X068llgKM_LfTs*{ ztNE#}ky{nVcLX^?!L$wvM}nLnk}<{oTu5GyiG;#8g0&zA0imG?OXUj4F(UT>Q#XR# zgQs;7xzE30WPu8D99BjV8Rd6^99^cv+dw|W9Fm4(sC+Dm5mz=bD6fG0rlNKO<gj7I zn?N233=rJ2*zGVjX<dA__BEzf$I#L`CT+JxYnfWVJ0i!&E9Ay&YvfdlM$HQH`v}wN zbFP4VLg$(wXJ;`%TY?-0=!27|4DyX@<fPqG>w{{2JZMCGB}9+|jsh>FHXBk~Q%bNO z0H^UX*PQ_5%f1y4p;~Gk>)RF5#FX>pO^{C&kRyPHRFDIR39i*a4wmvQL5y&?UJr7a z`<9czeWe%}m(`p-uWwfm5*<~L%crY=94QVgfv*R7E!}Y+kRR06Zlu;Wgwct0ts~Qm zjUexqJHl)Q@)Qf$vj)h`%RJ|+GH*`GDoc9><lVHG*$T)zd4R*(d*m5ihb?_9qWe>p zrJRsDyGKOsMJ@<Zi^x&VRv|a^n6cqdl6D+`jJ&uFM7acFJ{d@mXCS+XaYO*+R+2At z1{fV>U)5P^r+m_P6p&Y*lfYdA@;oYAfV_DxspB<(8r}(VYWR?=(W=P+ymZTX`3SPg z@mLnS1<NqLJe6iH?j3LCg<|#T-Y6iCF$p17i`@oIkOxueA@}dMM&5q48zS<r`OjlV z<T|mg^?cOXyhZDIxku|3?~(V5*;R5Ctbp8%ivTHbn4}5Ay_l0F8A_06^Z7i;!DfKG z2YO@iy^oQ|jO~h?&0-#KlH*!dT&Jh8v)cxSD|^CJUz)NL$Wup*<1|=VBX@;J{Zt6V zt|;&ZY`~o?@pHyp=G-JnUeZT6H-m5}K~65lNm?RlNJsIM?4hwUjs0A(sUL~h&mvKR zKa72H#Yf&C6W%Q#kGUuNtb^Q$#K2#2F!6)N8aXE74~D|4hG(NZBG>G1;4-YUxCwHa zF^}WQ$zb=^6!WAp!o@?%MALD=cuv^{w>6CD-pdCWP<J^aJl!V9F$O=Xv<Y%I8V>xG zpAWemI`;+n0p!-dS|$0DN93js$h9ijhD}0?zfnU+_$#+8Zsir2^T*TaeDj7dyd%tZ zRqL;3<(px3kORYW3GBQ~f!i5b=2xrVewJrfT~h@)^S>IY)GWn-NjV@GZwE~KQ&tn` z&3JtGHS)1=94ESQ8z9FH?4B>nvfX-NRnA>9>`PJ|`GPvc66A(Itz7sa>?>ttIwVu{ zA|vFJ;R^1faj1fv2r1yR0rEr;R-u3|kLw`E801fKF=r!0#ehB;3|H33GmKN8jNwk5 z2(!oD^orvk;wOoFsoy(}Tsm@_Pgeyw9&OrKdxyVF{rQOaeyQ~XC|ZXw0f?vdv>?|j z<XX^=Z{B_$JwR{&`TI7v_Qj?95M5r_s?#ls-B7g-kZ(}GZ*MZOyZGo|np;XPrmMQF z4cI-+9a<k@jT}ni#8uC_@}w#^_LsevN3N?{DM$5AI80pS(8Xm{uu<f@wIMfmf|2^Q zDT<9Wk#`7ps$=!aot|QM^P{cHUt_m3$eEaj@U<zj)UBn6+<IYXX&J`fZ$}T;e}CJn z7{4SG_w4(t#|{*fcQ!`k9Frp=Z%y+P-9>#HS!mSrmAGadxpn=0<XRiQ#uQ?hwpO>! z&Er?C>rywZJ7oVu82<d`-M{zOpZ{?@|4-BJh3gt;4^+p#bT78psuerCb-P`F950f; zFk6zHq*UduwWAP^*CTQba;>dW>sY03MfI1@<R-1(J}JlzEiL;EVf>x>P`x9Rzo|#h zFWr}&vxf<QUM2a9brE?<@h)CJ<FtNjAWw=S=$Tr(%BqBjT!UO|w_>+8-z3K*TG^si z|IeUR#^Y~)F(0m9|7gVI7w*3POYW_Z{Ka-_<gG>ISWVa3MQYW$2D#QwAa9T2)rU;1 zA1ugiL+hF9@6qTFb3dY$_T@Uc?Y=zQmtMN|=Cbwr>u2BdUhBPH*VH;DHP^^>YF%sF z4Pm}&^+j@p<cAWG+kbud^8VAOk4t^}^#03--wmzjC;PwA=U>hJ=$Fr<w-s_P-G}GZ zC8IADkZ&q>JGaj%BG)=5SryAU8rN&&TDujywG)$9tMiz{Aw}f&@9#f;{7KQrk6(T^ zw4Rx43drA?`_jA7=(j2$-{*hFwrg)0kwb{cHOP-l)>1mPuC-gS8=~<RE8Z~l0j-hS zA3puGMxQ?D6#Mg%O)KP|&Hd@~=uHnR<Os<3rRFO68j#ym>DI*-t(;spbZY&`)LbGj zr9rN>0px9#tz*n;a2b(*-9E_e4>B58^ih-idCBg*9sOtSPj5zVdv=*wzdYNgnz{A$ zRqNd<wa&$E7dj$8E-f&=h{w-#M6R^~<V4NZQ4V4J!>L*?Ij%{5GP)Rz{xtWeccahP zi*1jYbrh~|0do6AEw^qPz3+Z7wT?>5ch3$bBKKWGt97kiBX5S}EpD}rrj7T=A(i7l zBd@+zpMKUPe@5yN$p1C>r+-HyB*9(#Y@f2X0eP>s)jCJywvNb;OO|N@<WIaI%=(>F zJ#Xv&uKsO6(Gy4HEr#SE`QfD2dtZLqp!XW&&q($ofZT2u<nr~i3%y2uTv|}vsxbb9 zAP>buK#p(clv12%JqE}Lm+iks{y%$X(Au~W#qqZEJB-t=Q`<xXZA8eR2!RriWZVsk zn#JUz77FpjV0XKQy_tN0K+_y{4{6z+x_fD1*}~pJ_Oh_oUiQ#JKSMu6-<v0Uq)e2^ zakAFB{%2Piy_u0Mf%EhK&1eM5%vwjyeAas7o3~ei{O$J(lFyHB1LP~S0(m1DBfs+* zh%q&5y>`RC@qN?#a{j5QZVAU1AYbS*kSmIl9iFivA8F=}yz!@m^<tF#|Dt(v<jL)4 zcM#{xa*+J90_>OqPqlK;@RCElXXjt5q^7JdNs`~01mt#4c&=@|fTHOL&+21L1Q8Si zb}s067W{UF7x!`B<3eDC1ug7xTRX*I-|}MDPD(<SLJ`0#V)2FGo(LfXy<!I&i71Ta zv3)%D0_C^9vfIq=KO;X*g_5l7*3dKSy8c~Z=e4o9xsfV$|2oN3?>yRJMYMVlK6`c= zEJl=WR_ekQ1bKC<Ix1{cDqF7(wd%`2zIurxuRg5aG{}`;vKv|QJ9Hm8+(=%TjcUc4 z)ynWypcLm1B{gXsHEC)caomgC*mFlk?m&rKRs?u888cJC*m5Ffdm`F%c?8ssJqO|# zh=hDTc+7iyu87qGx;Y+3z+oaNMZyDo?{RAg{RJT1<wGZ6tcSfgcH&lYC>wggYb|se zATP<Jb$nfV4<$*hubick{o9|f*DICv*Z=&Mj-J)odEGUPuc*{Cj3(PQjLmelVYFBQ z-Rm@^I``PT$+STUi|j;H5%_^><@@6{s%I)>kCm>_dO=mu3)@(|0OU{Bj;ZkT+Wku9 z@!HxwRVSmz*G;XT8l78o<PCD<a<&_Ryq3m>4w%a$wK8O&Yd88rr9S^!7UYwUk-OYx z$Wj-If{G?GTV}o^2zn|w#17#Q1C|)4)&bNQfF6D9fXrqjo4a!B0PJN+SP1f-M7&R_ z^-(V$103Ih=?xdD^;-maiS9p>FI<+D-5T}uob^A)PtsUVXWaj;>$&xIf@)%T_nZU& zs)!?B?E+{_#y$_a&F(6jFS#7$$$T77<U`r<pdk7T6<8Rh<eepJ$p|<MW#jjL!BuC6 z2IYL!3#y}Jyw1wKu#<zly8Waw5y%@e0=b&(whaHE87{V78~sdABt29sw?)ppp^~4! z?3`NF?K+NJxVSaBtBT;d=|kaVgXt0N;TYrr4>7REZK6ALvluCY7)?O$^I#O%!y+Aw zKt8m_Z-fu&*b9)qtJM0;hRD^;XQfH4*WW5$|CD*Ml_LDx3qXEi7<cjareQo~*HgC{ z)~Qtgw%KL#C6`;SI}}`)2y$0SCgMcT0mz5w4m@u4dV+gFKFD7{H;)goGl3ko(90EE z8W8AgE07nuu#NhaAV<9yjy$v0Iz9euxuSFx&ao~ZS$Y0-`n+=OO1$aeoTyf<buaJv z*VMzv6OseQCjz<2odly$j4c#Ih}n9Ox<sxe_!#6Nw@@+nSv<_nQ*%9*sK=9U%OMg! z3-VZ4D8xT^Ww!;$-x0_O<1?`2sTV9wYQ0f^Gv@euC8PDfzuu*qH}ytNZk;mgu-!j_ z^2W~7?d_9I#Qgq_Y_w1N80c=EY;QNy>EGrlY!B`}Lym>bIm@oQ@?&mVJVKDm5W(3T zan}~yA#jU)kfQ`y0|Yrnc^?l<!*T+su7O;;u#<wkIyl7gy~E?<$CbfAg1q|V)$!q0 z&KP-7M}B%V7<3*&;YbD_9Mxs;;QF)Hlg#>^<f$o*Mja@Tb>y|=pZ<e7A0pByjOi_? zRc1r~wI3B#&9Vp8-&xMV@}jBg%%1uw@%g70Xr-xcpid_PdBhU)ZF9?&3R580gQ4fS zy*=f~_xO-n1lV4Ioa(bk_qnfwTnOs#EI_XGjvksq_i@iq*~gK8Tn>=`wmt&*xIhEt z1oFJx`nJ)A?T@&#*)mWqAa~2y#ss?|wZky5FKhSJhp^MFBXmFqU>!T1`AV(>$SG&% zDv&GS?u9tI=2Fn&VR4YVNv-K|AFE;>(Qyl0*rFicf(?$8qyAW1lOTVEJNK(orPd!9 z?ZLok0m%n#*sU6}?#OsJy(5>S<P11oU!KH~=le^=p#qLH-`(ao(%P*!a@=a&%X|K{ z>Bq=DcRZTyy%+@*$n{_>OoDAXwNA2PhKjB6=g>?_5taHp&_J$`y#P6T$BujkW;|y( z7+Mi#wv*lJZ+6jl@9w^?Bsx1Am0m-5HwWZM>ANzszE2>R+4k<{UCD6Vpjm&~g?(rT zf%c>34wXqkGeFPYHO)>3Z6r`<o|J$*%7WbHUPvW{ZiIbdkkbz3`y$*6JRT6p3tiaa zAm4hvc37=Eeoi1?GwxM7&)5E#CbfQG9M)mm9xN@rG)}R~ID&9%Fvaa>cWAa7{-WG^ zef1ON2Nkcbbfl_Kz>(^HIMYsVqB~O6GS`u(EAxGNjw4sC%6a}tC^6*M1$oaKPj<5; zqV1lU2D#<wLENgzZXV5ni%goqmii?5@^fg$4hx_JiUmu9JfM*-2!MKi7UXfVcHBZY z4)QWA2O}llKv@=qK}Wv(HQ@T6F}>4FN0RR<kn6eirbIJ={3&kOCgyU9=5l|dZS2eP zhU~M$5`EkJJSjbE!p3ZdY@U>))&=h)$oEhojc~_3KjE`EqI+Bz<R<r+!ar8|JT}uH zzw*Lf4DzuE<Y>qZsv(eX$?~gdKz>Np`vE}wq45B$c<Yxo;{D|mAP0z#3^|e<E%|D# zup`%Nbw^s6nIo?ia^$3ZM_%spCr?f*yOF;5bOMl@!gC$VLOcha@a<3tJI!qSe9-dx zHr^CYpR-VY)Anu0i}6^Z4{c*heT1FBkGTz)#?p}YGaxs;c+Zx-0^j068syl)XADQ) z7rNas@|n^cU%n(DUs(l5j`}G{r=Q`@+4>mjNO>LPlvHoghCnVo`u5Iuuty-@0Mb)k z8v{?FNFhZT)K*CIv6|1=Jc%Z|c@oB4in!djuoTIt8aOWuatxCE1mt)lD}g-s!WMDl z&+kh;AA|fA+3zg^IRudH$J3<N!HR<r;$*`g9i0NxUm6Effm~@BpJNJ^ypct?ZbenS zW_>kBs`u57q&K`FN3I&FX#U~VUbbba&tDmGoa{FFTI;qO3&)f`I}n_6D@do-^`Je3 z{TC9pCKOHhK*|=<xI@Y7yO#3%P$NS6=wTJhfE;@|_ztix%%;|D3%_t9-WR&@G4fJ8 zGzByoq(_X;9OMm|T8E$47lHgIsLONY$n8zatS2Df*fv1z{bY<B>Y7PA2vEBVK;CV3 z&A9}*)X<d3_E7=Vm?6|fDMub~>l%(cOhAsV-`7B{UD%0J>&I)43xj;6Q3T}1k^23> zs6RA*ueM(<4O&Y#2=e9SdUf@)2_1Q@Y>vEggO0r1=U+>c{Mu`+Cqv<8VC!|JpAFi+ zIj*9bAi#(!>3ylB%g(Pe@kon>u5MvLn3N@-y(9nN!}82p-$i|Wc2R2mpL|D7_L?&5 z1ai>bueRG@%d;RqxftYO)1(wV-757tOtqdT$<(?d`Kr8kYN*^)=<Z)@jNIi>vgdOV z!V49=uq#DCt{nNj0w7;yYyyy1jbCKAW7L-h1KgYb_A^qlCd}BAC(@noG>$YAD&R<S zW^Jb%>4#VCwX$yCuW;n$K7Vb9d?JtsmMy>2_Sr&nrAt9xj>o1*j4PD^<iP5SC%a)> zIdVO>zKxl61@esz*zAK*r!n%jOs7*>2l+vAU(}ahCR4QLD-8u8r>W%`koR4G%;pH; zOFR7($RR#V_-^SSmx*+g4N<DXSWIp6FYM%w{E$MA3pw&aAa9ZP{#8cWM~8CKTgN!P z0Y|O|$r+B4+gnTT#*x=<+mY9<cI36o9eKIWzotEpd@_)G!f|?@SXkdVQ-LK~X^grg zj{KuifLx;dqTA1QNpJ8kwXPilbfQ2G#3qn$V3B6A%glOH2f4a0s@tW-$U5`&VU!>z zORhjZf_I2!+Y~e{ws-D6a+C8uk-C2Y$Zd~D*eK?%s){)rx7dYku+>5!M=SmW_V3>u z$RAL#CFi{T(r&-R@$yHlrRhOV3$9agy}{}$cJRY;_9nDhInw-D+v?}09eK84NzY$7 z@(Rs$OECV)rxTBnTh4s_=~$@Xto0dkoEVPVGC6XRz97t~CdZL)7@$oBasYel=_6!2 zfqbK77?1vf|4aipty>Z*<M{2IE(jx#&wyE}5cfsTvA9Hd;Bhf@VPi{>#}+D}wcA{X z$4mz~8g(w*A@)*Lwnre(y|9xza*V+Yxc}HYpVp?qIF8#_(XMr^X){C`mkRzl%!67{ zJSZYwdJvtU0j;7J4~i!bisD5mQiUOiqKBau4`ag#_TUZ`=|#{nal%f!h<gD(zkbs^ z$<k+gwq+(J&u34cJkRfWk~F(~_B?r(3?JR_Vz;|jy0AI*!$VIeUSA!$g80zQuGJp| zAac*TbzRf;9IV&x=ePX_BT_XYCz#5!S?4CXSmcVNAQU+x8WZav#R*&Fo#Qsk9?|-k zJPtY-a``w4Njp>PhYr(XH&QhQ=Obsk_1%3$j@4KbWt7UtV)%&GQ<xv$MIr~Mu*TJ1 zwT=oN$4(*#2e2HL#rGL~M2;1)Xhjnr=}Y`#Wkn8ePYpeMvwy=QavNH&{(x=SK%5vn zd6+g&hh7f^bdNlr>%NmbU(}1ukxIQ@Z{AOD9mpu6%r=0ByWtV7O5_Uhs&)5Lw{Tuz z%FmmkEHYE;@HJ>VgYq+NR~Ro%kzwS>h<DI_gx+>4Kx6Bw5AI+FVDIX>prw<-LH8op zJtzZL7<~j7*lT^iScqI25_xd%BiAOb2mP#d4v8FZGu=H>sZ^`v@@DgzEX`}lCZy}H zu~cJ;qePx~@+;jV4}WeQC#ADTXw^DIZu9CJUSryR<&I8nmSs;IitTGmLqPHuD=G5* zPo`+|W_ZXOmmiUf30~yzI84s|eyowmN#$Lc*P9F!DMJF?3T^C8lzJU`#8s=K>h$G@ zu(zHwHaS%0EeN3o@Xee<y1OHcA~m7di@Cd^H-Um3j{5cYoK8uJTp<?u@|ks{5Ws1p z^!BsG<EyfWA=f5g9GrOm{MgOp495lh!(Xf}De}R~!<U~tc{n`$D7qpyA#x5(P9i7Z z@@k#s$e{Krpa9hnr3x~;fHofN?d(*Mv4o?$`=TF#DoW_>?MfLEFQY3zEZ-el{ss9N z_;;&Roel`&yF~T+0p?EF4>?_lJn_hioIWAoomq#;L%&DfUR~sECUQkg(94oj>-&!m zGajDHL|5cxpUAP|?S5@%1yn25=ur8`UnWu)FTQ@r-VwT3<oUEB8RX=iwH}4nrt}E= z?Pq$kwVKCUH8o<64;Yb4F?iy{ezuXgM;?_CIkR{!mnM-jld}Y>PEKy)6^Ndql+c0_ zst6+l2_Yk}b@oE<3P7Bn4{>)pS^+<(r;l@d1f37R2-=I6co$0i^z1_^s@Goy7^h?6 zUnufiT9FL43PqlZ&f{QG-Z6QIBF6x2ay64Lmi4qEF065}Tckx^_KUob%NGhHa;Ury z6iznLyM88l$LJ(-0ck}t$VxqHom?6M?$f5Ca*sS+)M}lTJ>IFQne`a4W|99-Q|pXE zjznJCSt6H{vM2*oL1ICC(8jILGqj>RdZFTUMim?MrOX}2$(?hdisK>1``SfB`M1GA z-Mvsi%^OATTn`Qt)$7M)_IJ5Z<lEAUM35JX93Bt#ttlz5(cy6!kq_?Z!(bpH$B?|e z;*h-6F6&C<@j=%Xtno~6+;K#%4+M$6j;Zwm@;noH2_ko>@Qoj|!2Ro_f^2Q9bDt9X z5#nvC$e%5M>tD}K-1}9QY>}(E^+c1)O5Gz5altxaueFn1?6za-bRVV$gA#dBGhuR( z$4xaLj}yi6OY3$fINn+>wKQRx13_Y%vLg3GA}3sesyHU6(sIkYhLor+10nQ4U!j-K zkJ2WBtBL`xg$&55m|9os){{(DM&w&UT(!<`k*B2JM}FyaUoHhCa+tg$(s-x6R}IMH zL{ZmnTUI7G7OXM+rB^lv0wil_8y7iTK05t=X68I+X6F6$V|WBItp8b>o4d%Fn_K!* zLmQ~h{+geE!I_``H9LwXFnaIy&!3G(<C*<)>*wupoWeti7ko{W5a!LIYDv(FvZ&5? zEUn(ZB#M`C6e0X#WUk--yN7M6&^coTk#9{a;!jR2@(A1_CwaSUF1KnOBH!U7P?77J zSzBzi{1$JuCTn{&<?(o-HLU>W*2gXDF+?8hO>*79K|x+D@&W_X>QwA*Y?1GT$frr- zKHjlb+e&{f_Tv*j#O(JQeqMa!9qu*y@a!J>3SIg@I>Y(xYA=rBvi;m4XmVNDJ{aKb zyaAoi1Q0?HhGuw<fQ)xWKjHV{;CdvlA4czCi(LH&T4E_=rAFj%d06Y+C?k)rX+-W1 z1|@R9Om5WLlapUNEr-t6uZ!)PVV2dzdb}v=Y;JwwOePpc7pz;Rjw72!b|5IShM5+K zTzW(f!@OhG7ML6?UF^?NPlg|F5a0QS5=@Q`9~%AnP~uud#@!82@W*+Bvm4J>w5Zqd zz9NqZ1?xEkstAa$#@!E%K;rrxk+b9yxtd&0E?G&DlS0GLc#5xcb9+1`Bl6Erk8GC6 zVRFsfYZ%6M7p%J1)U=}Vc+AkX$CmXn6AZU7An#H%$^$`BrU5ypAiZk6;1Rj)@fm!a z1e2q~r;8#!agSq2jsoW+gf!L=F;)`VR4h_n5aKsAl33ixeeFWwqbfD}7DOR+nd>Ky zBgbuWh+O>(T0+T6i<}5+Kn}>|5IIe)ONjjL>Cc-da!jvl<+5qAM6e?J(KJo{19|)? z>gJeb-5SkooHH*iYm7f-KnrZ)x^8IR**4*byg)yU93>l<$fwVX`9d9B^XhYa1AbG7 z*%w}gqk{Sm>M-6AbEl;E%ij6CHd2Oh+yzgHKhVPxThnQ$L}WWO5H-*qlA2S=9}wrz zL-wFKcvu;bK=ITbiua{>S#qfdp|DVLQX3@%wg;izi-(pJTM!Rk%JvWNdFDHlcP5jW zOq$wh)8~_9@@D4E8)0!j`#kUaJ~IS^pWcOUEOIgVz2$=;A`jGOO>DUv;V-s+lOoq5 z{(hgE_cJFNpGatRBdvG)dw2Z#@xQ<N>O0=lpiKT~-0V6cZFpQU6&8`t_@i+gW|YYH zBSgN>8oB&3oJ*ZJ_xihi+CKAqKG%t(2$3J@LL8I33=uhydGg5x^W(8st@9%>-0V8I z;fP#INB$K*mzGre<TF1@F*&LH`NmIIXZO3mX^dx!2*`UTUzi_T<#P-0xQFQwkq?_A zuRac<lIvAnFMSzBiALB_-aa!lO*1?u->FiErx7%&x-bNT9$t@Qjyww4PCluq(yWp9 zBL`4vQlL63zramL<nlj(FgH8<+4lNZ<MZS8Lf>M@xy6Nr#re6bGtUFe1@diSsdY}I zb8;Q;HdwU|4n6j69`5b!9X1ctsg|x^xM}r^Ma4x|<<?KXRh(*!?~Gw=K-uftSz`NW zcy8S^d(DywO8VGDkA};>W)OVwhQVt2Kx$o7e*Z`-jmInqlU$Kj_4Xiv)H)+mOajN` zj~2F{{Wy-q|NikibAeYw1{3!S<1n!PP%2{k89!ig9A;E%-DveR-dfWf)ONI1Z|hk% zt$9g*30~0@`L_yOT=SecF$`ylJnLLs_ltbj2<WnqDZ1@^26U)BhFRl{*2$Qv=b&Gs zFD8JB$g}YxaxguWCM3%~0i>BJSbUhsZ^>OuJq~{@A(2bHVgV*!T);ksPw0iCk558B zp-r0_ZftMjOsL4o+CKPmIw<mkJx#H9pdxZd<d+(g(p+9RA~y`5$bnzvTbK;j9JY^a zT%T|0{cL8uA}@CsQy+-6q>q3a?QV%2v*dn}3qpv<dn(5suw;S8|JT&I<kp2q=I42z z!e@(%^x`9$pV3kA$Ua3cbn1P;#n~IH74$)b$jRJzDyJ)vH<iZ+n7pYQj<H{8K2q*! z!)Ql}ysbpu$Ce{<BcRi~N94+_<BMF4cDF?CnIShs<iedvt-Fiu5{SqdDXAdX(0uf4 zKR6RS7rX+C-w-JfHb;*9I)j)zAo7+*thHKNt7R*_<<^85Ao7a~I*cW9Fj(ZKwNxA^ z@|B!bsGD}HZWVIm)Kx1}V3k{CoygU6y|%QH<1d#hg-V{&?xnm%tpTH1t7R)wS><NY z9u6YUQ`78;ypt<bmhh9*$|oao%#p+8B61;y$h{$XqB!gA5{SqdP3jd3%I3Dw=|u;6 z^qOhDVt>FBR~UD%;!SBB0eR^5Gnl)l@xE2-j>v6$JLO<(rw2r?66@XWK#`xF9QQ<i ze0ruz!i0(Z2xVIP6YG{aP~<CxN}1eSq*lf%cQ#3?D|xajxiynVbk1M4YWZcomRX_> z6&|gSr&c~F@=VShZk30tbE}it#7T&p4)spWvP%4ue4!4JCxI(+AR-sSSFPWgW$V~} z=EUPSD{`R83K8KhF_j99$Y<?HJUx}3p$9$jp+6$u*NDBx9;xq#MC9QjKhe&6B0two zhDYQOd0#}nLbCLUe6>g{>$)vey^<sI=1jC8Z=c9BD;#2H%6z1eN_MML_Ke2xcX&9n zu*Adhz*e35*(Xa@4k9;sTpTU?LM5@(x{AmR5xEd|A9->rhr-bqZI1l&(Mz;Sa$T4V zQjsF(#chPUcAb456geVt=0FP*`HL6YV)xV0Mc#-ja_HDEa+@3pzUZIEu3LjdPA73B zDs>Y1(x6rA_zwOx;E<zM2cj-#Ok3o&0<Ki_6~2J$31E1(pGib6#1c6`ayuCyaaE%A z|Ga66Y(WzyfT#*^vokO^bnd(bM1G)_xE<_8iTu;<VwA|&u){1$<Qq>nB1E1qn0+EI znhZ%a$5i-Isk~INGT|c66}T%M`TJJAV+KaUcc5=)I9ue)ND8b{Pc@81+4o|itJV!L z+8lXGm>fRf!>A&MNfR_V!t!X5kAE9eF}W}iq(DeS&K9Q^-r#Zi<P|xy=9-*6uF~wy zZ2Z)ETRU+J!chBM&5=Lzh&;7H&5clzo0%o@>}m$?RkPYG+4`o<GMy`I);bXpxn-d% zpDxxanM}EFG@r;ZT*Vf-=@oh18K$N#Bo~qEj>cn(oc`#iWrA>`NKet9>L?;l&f(Cv zD()7)L~D?%iyTP3V&P6Om5SogypvN;JG;=FL%+zI8vMP#hXziMG)I2CW*oaES`F<C zCwKZH@}KPXPhld@XI%X1^+oAct~4mMUg(LuUeUdnl|m^(<b}FQt*>&E<8K!ECQ|Fl z;HwFUJP?w{5qV0JzrH4tX)QI{Vz(q$uB-iLF(dL1e;MTQUp~IF$boDp7j8euphiUG zNT);KAnlLH!J+2m@Nu}vQ(@cBPB@=_e$qZh%adAfG)UwK$k(@?Zav?C$QuEXuXLDN zCg157d5Jttbjl??Q{&H;g(Yf4A!l2*C-O3+Un}Znt%OPMaFL^BTDHh@_DPF-_WtdV zU&Sxb=t+p&Uuiwo9Jxdxlgo5!n8<I*9JxyDyUW%g@<@|^Jb({V!$dAB7w$GQ(0Fue z9k9OL2ekttKk%8n876Yz7x|7Gl2<i**V);rW*k#6j)>e5d80Q+-e8SG<jgZe?<cVR z40c{Bnt2YNbA^sstQ6SU^+LJGf?ew5D^5fX$#<5EbzZezs1(gr%j&D_wxUGN-d?5Q zFh_1JEiczH9f+KMh=!q${NsF~Ld`@NtssnSpPgjVF)F*=o`Br9{|u@1kr`LySYAMJ zjMOU@ZWmm6c?!#!;))zH@8K)a3YvRb5BF><n|(D{<d<%V*6ayHzGE9)tDYJ(NlqRI zJ0}o11>b9ZA~&8km@R#%$U)hnjQbLA8skQuoy|>pE7da@YsG@d8FQ0*6v`Z@bKjhr zaR+&?$T1vJ>nj$%2a%UB3>M+hFvY~SpXnorTsF^6II$!0<P`p(*9eqoy?&7k!lVO{ zE5bw$_FIRCt=6F@wcaue7CF;*)0D2NwZ22XrUyUUr)%2U={Xx54;J}u!{&L`C-UlZ zoZi)Av$9fh8bxY=Qfc7L%1TAk^QCAo+@S6l2B4J$$gKNot&7L+F+&%--GUmey>)KB zyPtjYp@>`%u2tl~D{^%oG*{$5DUo+AU3FYjUmHhSy1P4+meJiQAt()^fb{52=^7y@ zEg}sPN_UM;L0Z`8l97YK-s$hXf9-QWJLf##C(pg-xz8g=MR6ehHRkM&D19%_LSEY0 z`M9wW!YJo3c2B`Z?9e~`zL>`5Mh=z<{mEVE2)f%kQz-*K?jG47L6QGcMJ@wdl)$VY zuH#lBq0%k*{tbmSy_!#~g0a<4g{)<w7nXJ6pUV@#kQ!eMWfg(Dx2IUbMu*?v$-_`$ znWvfA{T!`-N#cRQFIbFgE{{T^hp!1g({G*$=x-Dpx2(GrM*8YQ9b$?d3g^t4g$fdf zUz2FmXxrUeiBbx{%<C6wOlhfzVuv`{sH2_rYNkHLl*A<ukJlaS6%Q74#gV}IPdwT% zECSjKg;XcyXK)=%RpdtP0DjD^91Ev_IS`vZD#3|1uQx366MNV$=r1k$P~wSd_IQ`M zGS80UnQ^++-gT#|)Q#T~=je>f(4(TEkK$4?&e3O2_}Nm2dWzjsEYM+hx>8@ka1g_E zi#bV5fqMcN%QhIqKc3Ey7Y4jH4c&B=cP{ELeeJf9(c&$g#~*NKw(AyqN*4v!m61Cz zYzD_!yak`)*K0R%k$#ZxnbWKZ!t3j3Mn$J+X9_s6`~?TdwePpYh2vXBLUt}<7@xC5 z!A_10xY^Y&`sjBKV&B9>MUJB1l!Qx!Et|~bI;H~r;t)+-*Cm}neqB^D5pkcY0*w@E z1Iwer#`Rm1kHPKV!#sYkh5LTnK+t`PiJLIZUaR#3nP0<x67QiIxEJQleH9%%I}5mT zhNT>Q3%XbgRIcv|ZBk|Qww1shlbLkYF-m{cEvQ3i{v8!bLr+EJgoNPjY(T}9$v8wY zJW6X7*tVcAj;|Y)M${G-?cxy~R|qDH8Gx|Ynx)nreF)@PC7+$CxQt$GuPAjR&K!zw zmit77(x@EL03i;XBV2iG25A$V5DlD}8*tS^a&?>qD$3D3(|o?7`w?-R`WA)90}CWi zfIm_wvu{)%xklRa{JHdn2+d8%28rES4$T!l8?y<?&L+vuUax*A^@&KmN<sBRe&LBK zw0wpS#o0rx8ur!)75hMS8o>95duHSVVz*E*2m#-nLTyu3>_cN8Q@6_36gavu;+R6b z?-~Kre;3uQ@DUQ^>c*g%G;)=ve+AVK4TZxJ(FCm@?x4jUrtv}ab6>&-?n@V}%YM2U zu>m(xMO`<VUD*>Lx~~CFs~e7rgEcF0B&@i=O`;^~w-uFI;Wo5%$E+k$j$<VE^lDUs zcx~?vkiU7uoBI-DZwvo0&s^VZpE0V=aOI0<?p<^G_;m!y9FV9mcl)UuUNQ$jpF^Il z>DHQIXgc2S_ObX0)~1Mf`)rmk7)vT0Ce6SKW)hP89@n@B%dQ!uRT=xi!1>IQp8mt2 zep>gs6l>&HEBHI@^^b<X*l~shQ$>6NiZ?Hx{nRbKgk{%YY>hO7M8N<#XE%QEi^@Kx zRt({h2%sJ--%q5BT<HA);3wZ<R;j#Z9ey|i!xUHRE!4U4=nkx{e$z)kZP&}`{&$#k zwHZz~yTJ&ybcLR`|NZUD@3(m0?#<Ak!=~zhgM*hLFvIP(Uz*4$b*lpmTmKTvf@v+b zY(x-NtCr93pqpOP(~J!8mmJT$GQ#3uu`smluJN|yLaE-m&K1Y`fU4%}<x2#MUtOx( z%*V(Ml~%V9_r>O>_VUi#ph-~n0MKGNbV17Qkly;_ABZiM=0_(_mW=tIcp(8G8GFg% zj(le5aCUP90+v<6r|pJ8;ZB<r%X96gzm>TyrQIapE}zjO)pR!KZLL^qxaRb;jnGw7 z^jCoZ)rOox9rA@=m27Ac14~`wKQaWjNN!iMpJ@wjSndZl&u+Jo4lAqj$e-!su5+zz zuRg_wy}+#=o(WfR35g1UP321C0kbM|)ZJ=a8WUgr)JQ)Tsp-<`F;t79NaLahm3FJY zjSV;q%dGs)B=3-;;M(FbJi;va8w98&9FFj$-;RMU^6K0u{+32Yye-Qxe}X>iN)5Ss zhsWS96A}{!a$RiMZf_{`Xb3V*%N~U_X-{%&{LVW3w<s=nCFNZwW$e#l-ynB+LGaqp z66r<lhgtLfn|ThGjdL|Uxkq<nRp?W>8-1R{2h37Sunvr}Pr#Mv<Ks_`D-OMk>U}s( zKTod|Xoei)0qIeY5ltXET$v62@FUWq)G%#>-d0mo!D^n}?{MgtDpp4Ac8mskLe_DW z*Ktsqyy0&-`4*`Ii^vOXNoDZ^v-&yzSf$dK#JrZ2RSc*rN1aDDuI)AKn~&@V&0wd8 z$*tXMqWI4XK220g1CViSjN!x7)~bD~Xz%Y$Ef_xU14*G6Kyc^MT_i&rC6sYg3YxK@ zoYr1@+Wf=$N5PLAh%WZcW1*ARgDaK_lM;hgpTj*9x9JIBvDPw9CoX>#HPQ>3gWP@+ zDv~t*d+Rw}U*`1<2aRf3iRSY7BVWmA&IGXL!r-?3J{q$ZX@yGsSjC)2%(HM6NLy+l zlrEcLlo;3?O7xPLkT+CPs*09Tan}c+2{WogawXLG4WUZFt`}k%%hC7+^AQLC4q8pE z+>PE8E(s=k0f*EA=u#OSWD0(LwV1(wdmqaE2sk@_9=!6$Lxw2u{NZLgJXm3^UiSJW zV{53hnfBh27>6XnLuEm7$chBYFRJP`0n+x)*VMbMURs4KqS&+@#zG+B@Z0{S9VyAh zqqiP$slPP&oa+o!MPl*Seh2o+R8h}ixo~KHoh6Lst01=@Yo_v=_E;Mh<iHtS!E%## zMuYZmf~q~*sZwQJXbS}Wp|L8akT>0Dx1y=@mjOG$!K2$oV&BvlYu^_4e98%zBw@&9 ziX35=qj?gJ=s8E%dxgqWHR#0Y$A#X=G5)AZp+jq}*(CsCOLTa~_#33=HSrNg+j2@y z+NI`Q3<4&0PA2s?{>p%X#k8i?B9`|=%Q2)oTwRXCMBDLx%hBJ*_eua=lAjPpI|qa& zvs?M$<O|eiD#{)ZVH+1jkLT-hLH%(iH^co`&S@KP6jLi1x&hZ}omO!+Iaj~tck${r zXp_qGFyVRi8?62P>%4#~u!qd%A@<&&dUf|{zSK`pE+NbklI#`lWCbOyVdmzw+Ij~N zRTbnYbB(%8yS&^rpW|}sUR!5<cJkS`vDom1rSzPM(f1u#uH0!T|E%{Xa;RHLNa(;f zaVEGltXESQ4Cldu3FyC^LR$eO84m5`@s4hXd*J7O3nrNY;bai)EMkbN6Qx1)BduO? z`7w!S&_E%2Wpiaox6tUiXEukDdY@D~$1Bu5x~1&W<gM|5$S)%|JB%wMflqxCqXkLc zj>NY2a&x=7g`UApH(Xs^WdmT*AFV9rsCBa{58mC=bv%Ee&`po^#rixlPZl^$C;BZc zFW-_dRp8wclVsmAm(S-`n9+`JA^9Jwnm=iT;9l4qR+`r##{oKJ+}bcpY+D3`{JZoQ zqbg*rWV~}^rRswFA8;<WT-fi_ITN8Kt6Os;rs))!@5_XT3+%3RA$ErbPxwO7HnpzJ zr5^5{G9qziA;YOm8FFuA1*ps%G8dC-V@<zm5H_LGs8ULWTZeIQaF|5rNm{$nfZymR zc6x>{uGzrccJCCJezBZh-9gLlR+B*&8`&AZ3<~D}<!KEvKypKF_*;H7SeCyto)8oI z8r2S1vkz9vvx_vn;4KQi%6jOXJv+SdLGa5y3^yr<2RusaXQfUnBn%@>Yovj?u{F3s z9U@m-mb}K;nT;fZr|F+Of)7ZX@}`xD5lKsY8PY4aS`D*ay`iO4&q}Cvh|E(y*la|d zX1X;|e_}_rAhJRD)35qG<7)&xM~#Gb=W#jhdA!=2W`|xG8fsg{*Do36bDJBA16{&M zFOm|!)G`rAYHR3bXwEP+bC*IEQM6SFhvM>t8Ph<YPwds<LtlA8WqrY#qEqztk*nM- zpJh@NQz|LI81v_-;-26r((9vCn?3amh+{!+M$U18X-(|+x3LS!2r$1O9*mNu_0<uV zpy+plls|z#j0&!%bR$H+EQC28btnp{W4XK(Qi_Q78YJN2fiMVXGqYKk+zPF2J}1ku z&34E1nrCTV8NUYMAE5Xp_3$of131n;)j<MQJj_Nlh$+c7&c}xT8doN_Y*d(h)0KbJ zqf<6T0KRv_gc;aW-den!v%&_?I1&&){x#2eecJsv7t)P+;~v2`;?pPt?0E9t?|~wh z-I_6ly*3pSePnLtGFE&9AnKWdDH3+5wY1a48%H%csP5aYz3#!Wu+PLQRw^J64`uT% zSgJ~~9<GDbE!^m0_7T;~j~;{Cw?N%Br5A3b&_4I`v=2IIIG9Isq_`(WCzs_*xvA=C zlJM=bBVQr1xi>88#ASPpVRQn)hXx~evHD`%n*!&2vV>gd@J51E8GC<n=H&(F6hs80 zk+mLB!vcoY9Gu~orBzy)pp$8degv0=jj=Wz9XlxR&4xCZ<2XJ8B)y4PeH^#4zSm=` z8`py|f5Gjs=U{vlVIw?&-s*WARX=Qr8Moj??PaZ?=VMuB2&8YXS(y7&bL=z*IP?C^ z;1uCdBTtgXUTzr~4xIe9WcItI$U>u*#I(ZrCwVXsl12SUa*mE8EIXJPZtnC5oH%-l zwUDbu?TqNr&)GRXPt(Hym*QjGC#Wv;H|P8~cxHb2A$7WKRV@W7z$B?*_CY&ECGYHl zBLFy&+X5w>04-|>lK;s?F2?5qjQ9VEHz6r3L;TgGI&TC*Rr-|OEW#Q0(PeiGzEsKd zZ36E-6P0|9r)4Qr%5|gAO;7^bvO$2_`ptygLc@}s?gsgy7d8`D;A~@nB&OK{6*&5| zqL=+n4w=1Oc!L<L>QhW}7h@$Z?l{?Z&sm@G3{xxT!oPiy7FS5osePOD#OSeN4;S3h z8zB|S81`(4n4Tx0R(^yKc8HZ`O<>ek+g_yx69W%hZ8HGL+M#oS(J%-775_I01M|u1 zp<7UFc!vMaTlH;Egd&WG(qcmc4i$OfHii&PS2o7obrnVMfk_`{vEAu3X)bkP;?06` zmVE5qV|MfLXy})JyVEEvxNX~^Rzqpj;+d%}!hl|z?I=L;WWm(~X&4kBu5)O|C<Bw6 zXfQooZ`{)Znw?(t?FDErR71pp0)_`v=#nF-_Ymtqz&eS|R1PQ3XfN<=EP#3mnF#!; z{hlJtUem1c&Anbn^YonV1PWnyO1BmS=l=b6t0EC<pG<9MZD~O`CnfJDQ3-^`a1`p5 zO*!H73OFyoJr9j{27K_s^LSfD>V%Usds;5XeI8_Vq_%$<^JP`OQ(9Gc{;(aYmj+mN z=r{LXvyzNOtb=`c9UHWtaK|+V_n&!O>jsC^5v>HXY;2glzXKnS3FNZJ=0KbZ8DwxK zDfdycD2bpl7T_jUY3-MgvCZT*8LLk4tt{EP7;!71l*cR|E-)PnM(Ht<;a9YINc$l% zdYftjWu$zM2e?ORcLF#qM}@D<quu!>MMefmO0=wn-qif($HYQkMW}Nie|)5dCSMK0 z|6u1^H__w4$Oeymm7}A!P9MW|sOmU^(i8$(@z;gayGSfkg(eH32R<`jqn96D&>VQO zr#w%DOx!%tO8aa@G#w#1$Dkp5#EvoY#hk1<Ks^S#UiB5<w_NvF9c->EgQ*3;%s<zj zh3Y8a^@`?tul+A5pEQ{a2u16QEWT{pN!p807G!qkIjU_hcArG_!=n#WY2g?wB#xzg ze1?LKt;R}uBn&NVlO34E14cbr{L})dUl9{^lMcheYv`Yyq^!w;M1Bl2_1p=kG*-Bq zx|naARzU+VlXOV34wF&GuV@qO6&#qLr7S%qZ;F9)*;V%Fjz;w-Si*-)`R(&Tb_!oP zH4L?RpS?WaKmd@j5TwMtC2cemaB#O0XTb_TIBX_M4!dh>;D*Zfyl&{`hTUBzkG@8p zf`;!K1`0#6WmwEC{7fIe)~t~f{EivF+uxF(GF)nAb}8>Loc`=#9QYx5A`CS*a{}^M z)wdvh>L7L{-a_Z$WH?(;GBFGegRdQcWLf2(uO9bB1&SZ^z6BJ$zjSe0<3?AMl>SAC z9cAlb1D6dklgnQ$Gygl%@e;bWI91pkb~pQb<@!{<tIJFJ^YPC{<-s+9yag{T=$~D= zFzqT9E<vpAKod6?Hz68qTqT%eKuG7R7Bn(QuS+TjW?$bsXT6`n?J%Z31c^=Tb9ZEf zt3zdR!TX<*CeEKS`Ei5GSJ}LxdWAGpbWY+C_VxIncI%(Fj;$6oCY!+hSx3Y-gI`T@ zl?+$NXba;L%p41z=K+Xss|J$8t!KN?jYhd!8S(S(ZXu-TMFX)cpPx=>NvH=Zh33I^ zTfHo$jWO>x@$0kxp*13zYKM?`aIuGg$&J?+nf1V`JOXiIat-`b&-sF*bfY)hPHaVn z)C!+(<4<|H`Nc5X_ejs%cDmv255(hPXE)HDz*ch5d3r`SN#~GnE2Ef{>B3=d0$7j) zbiHZXx7Xa4S;3GL?dzX1kgq)r7d2KWzMZHso7UQ%v2+1c_E|o6dYG+~df_alVVi03 zY6FD&fS|(eAs4xWEWRrgl{5~m=~~o;#=P!bW4JyrFR@aEvfKubQn4|UW;;ylup4r# z`@Va};*pBmmq+GZmn1fae?W&(Iq#H@cZO?BN6k5rPW2zP17Y$q4fcz<#3NHl;8eQ& zNAO_i^aE3XU{@ZncH2kpi(wC^*43l8kg!M;xLl<2IrBj(iEpiS6*CQpS+s3kwtWY3 zc2vbH`_dBiPTGiUcMlDDL+Y#WOv)_>IZSxoy%;`9&gR$B)#9KMIsm3#pf(khJn?c+ zfyf4E=*j4<D^VwB+%}47zTij}!6c*DReVA6rp+aB7U(Ww42#>@!~ACiIGgf`$7fN% zoZv32RREj36|}CPX16=8gLp&O_1IkfX#IHMtSB!jV8Wn)?Zs}j>X3$2mPNeu9{<8; zyiR^fV{NPeRZT-xMrwk}ntw?8|1dM@$F16$)S-Y=`<cJ|*{J=nL3lH`8RD-L3c6sk z<IcWo<mV%v6ngsXXO6_`X8qUt%z5r&|LC=%l8-t?Y$ZuMV(ElUTJ}7~{h_P8Z}Kv4 zlzq1?c~+7JQD!@VWW6C~<64w<Ts+7kh0lDx{GRzDWa2b2`Yw<>4PY!FjssO1f~5b6 zUrH`=s-jg32;T|}18Geq8MU^R5T&87G|gl#{&t)#r%jSlk88&?9z<sxA&T!F|7*JP z{>W!7I}@-TNWlp8H3|Vm%`W6mi@FXph#0K8Z6IUiU$V-%X7ghYn}_+?<9B)$rSEjj zk~FRNta!;xt<v6ceu*l*=Q?ai0^|PY3&N3sYG|ot!f=;PiDzu`dK}EM=G6{cXF1@Y zZw|8e;;jW)yX8M#8+T1yrspWXUy@94*fF_FAb_#y94B>{|L3Zp^2ur}0eX`u%~hAM z0#djz8{Y8L!QuH?Dd@vORab}VNq{+-I(Mb+TOk^Ps3>+I%zN1UhG2RAY2D&jtQvGU zmW$4M;m|o4yPG8Kl$XO)XfmRRd%Jt(>TS|rpMfP?v6~ExTg@j=-A9;M3VtXfKA{IO zQzD3(W6Q?gmz?E7guAbr--X<{AiJGqkLkIPjFr(-$b^|7`%S^=sF_@3EWvpgk}BFD z$R~t=Yi{2@(95@>mXXR~tW3X9fUMeDtS_*h`6i{=XA;*76r;iXqBi{;z3S!uV`$H$ zN7%&W(r4e7g{vN7U5~-v9XhE|>L)D8+M2RavK&w^TcriDT;3BmWzTXg;o&P?BK*(F zhQfX<9Rhy5J8feJ#*UpYB};R2b1&9eht;Q?9c%|hUkh$jUq=E2t?L%uH{9xOHUrq@ zoU!i^A=90qaNdfO@e{NsF4Y}3@?jK%DeE0Q-{r-F);6IF$MlVG`z@yW=x`Yo=;t%J zj&NV$Ae>}p{w#GeFT0EZz>-<VNriIOY{wTOTC86eT6%80%G&if?<S{dp9W+9!C)U{ z<GoY}v0eDT!s>GxNXp2~#sK1i18FTDW!EvV5CNx=qdw_l4@&3w_8KR3zbx&U$o-^} z7;S*0s4B#bxzm_i^h~=utK}`;>ST9S@GVZp%$v_It4W?WAC=R^yOfudfB6W0sT7r@ zqNdqW&VtqOBnOG&i#!Wb7Ocj~=Ku+00hZ@6pFfh+)zCR@o$KV7^|b^>SKEFy9^%Y; zLXBg}N4*)3H2Y38iu{UuXql5PCE<ye>Q3U=;q@j2DOea`PeG96j4u|F##w3cs-l#l zJ(BCd(yn!|7K_q}{lCS;khvb63BH}Gbw#8Z{m_&7srw!!dNb}#5AM=DqPPczFG8z9 z8ebCBbriqEwH0d<Ef+i8s>D7e{TQQew4Le1W7l0&dcb<i%xmi^64tvR%r(~o2~;W& z4$#*?*a3^##E54LdN8H`^Lof`1!?~gv+jCIHf|oA>dpj`Om?&iPEAMtd5ceRjs^(^ ztpi1j)4wI6rwJZ4dVXEtGbJJ#LyGhvCzZH}{J1$D=$ST<+R(Ms5n6J(s9qZhx@h&| z&FqeN@SLps7EFW!)~ftsEO~T$&QSX41$AzAkU(mf*|gQiA7jLWVVPP^_zoFEIbuq5 zDTkD(%A2pcPP8oqq;~B*9)y$tGz7{x&WFpFU(@n%wmo(9@MMhO(Q!mE>W^JL%F|7a z@IflcBp7psDlw0X^5l5?6Dms{2U6(PCCEQZ@Bobx)4B!sO|#w-&)!Jy!U$uPA#6ZY zZzoR%#Vgc#D4#oaYs6V=uMLe@-`fy{mjwgRv;dT@^dSefkMW$ou)`hhiHDJz8M>>A z3pP*aQUg$-+P@yh9pvY3NnIaHJ>&9m%?5SqMa^NNgm{MPsCY6C?f?_MM}KUnz;2gW zodpHzYZ&TrWVkEVn>F8}-J5n>HEY_s8QLDz#SAHqL(mG2<_;Z5{QEbhSkJd8e))X1 zNpeo4{5dlJaiZqy11{Zvp{)P98&;On0aPha+a?Eh^cp`wQ)S6e(0ck@OLr!gg69n- z;bP|9DwC7+$FIt1hMGorYpM`jz2x>lDQ{%6tqfIS>>D4y9bzzmV?AoB5NqcHs*|&w zCkJfkk)eP+Uc@|&KE03f2cXxU<o@?n3fkZ1hJ>a<95sR9HpBm7`P9{<!ip0Kc7KE3 z1`_16n-MZV5%l%^R|DdZg@cuZ5~;niQv0#{J@sg(ae>~qemAZ8)2O`jwqb_xYf1(J zk7ERBMHi6i-oW2U=6E>dCCE6m@>pUZxrm5v@doOB5n?+xqRQ%>7--kpAXKHXcU5Fp z8<kZtJI*O^wfF^8#|D}9I5U073fu0sdO+uzQt7(CQP`%)$3Sa%US$R7`mrngRrq7L zjoCqTgzGCd5+TVV_9vw~_`CY1kvs?qo-4;ZhqnBi3OCpf^jN^R#sR2@mSU6{s4EgX z#$S-Jl+8D})*!1%$y9DRuY=t1G#QSqdn|!hj^Ia*hD{(sW^+|S!^kAV2g&!#pO3qV znq*MFf9IE2U()fl2v=6U?dykn$JYy*j3>(&wK?)wO}dm1W;iZ?B#6DEz@iyQWOm_k z(JMCAb~>I=GYe{5+g|TZ?U)a0x6ZG9T6y;OWsJ`~Ii6+KhD4%?QS22COQi1RF;ZJ@ zTf<Es5_eJyHJUpj>ey|lf1xS<P(YJVdl#kT>xzB&Br4ZpK)v<_`^roP3mPb(q--EU zd{j<^&QhluiR*EO2t$7}wBU&YU`Z|9;`}<C<Q6poY=Jek7EIs0PDrGc7Lnp;ek2gI zYJu>@7d@zzjq$Wtnp7?2&yKRG_4b}j6-L4DhFOb;A)T2{1KM{1xuZL<0B$*-&tCZg zVog=L;l)I@8~*PB+IYjo)#R5odGZVb9kz^^RPuu%Zh{`IV<~J8Ly{ucx=oI4Xg-6q zxu6mobyJ@7vG3Xg1fiYWUIPiy@iF+zqQHSe6Lgb*0(N}x#_Vc4KJkHt*C7cuxXcDk zm6t+Sst2^-?wNKn^`Y9P;JZ<Y8FM4G7Bbfe+nSU_^|{}r5lj!!)z||+-5HKU=f9nh z(Y<#wJ|R_;)dD<<IeC!HKmn;kWKSZ?EdPA|akpl^KCn1^jf|3vJ0$#LUDk~H@b06? z>EI)o0;?S0=i#=AUWP0ct9nn@78|sh=U+J8arAxPvxpO}9}O2@r<C>4j7Tm&$|k{_ z{!d4;5W<)55T(FBGM%B>qZL-%xfAJl2E99l=^tkR+cFOwscBG`y^vN!J~AeSdbPNR z36*=8?Dnv;q<RJE3ETQyab_)>vPNMM+FJC6KYD1+q^(bl^g|2Cpdx;)I@!^W8gN$s z(9n~NdbU7Wfi=7?L%z7s6k2)~)bV_>Sy?<%<YrXhMy5Mo%h7!nx3k)VW`EG833q_P zF{)O5q+A)}V+123bwa2_$@-M0->~*JvJnuA_1Yk!i8Xdu(7%k{Bf;bY+tZ`p41G}M zIm+XV7w7Qp;!LsqtX#ewfdF<xlqzN+mEeHWX=00qn+yDHdV3<+dY+x#j|!!d>CA(8 zQI66?Mi<BLxaSfD_#?D<wjjiA+K^x2fiLX-Chl!9-V$(KTiC3|mF6Sg{c11;TR?@9 zPDaD_bE#c#0;7M^^TFAPt}i1l=(jTkx13EZ=&a>AkPp`(iFI0M=x|!=ob>6)95;Z$ zH=V_CrCwWg-3-S8ayl;zYwb%?$*;PgsGPjze{wb*DI76KrD5t=9|`7vl6*HMvby~t z4uM!4PJP*_YWYCA_=A!1Go@!&+eIk>7w4P7_|yQ$u}(1^^Z%F&lBXW&?39zOyWE{5 z;JQ`{sK0&ZkGNFYk`@bX7f+tDu1`;NEH*Y2Y+Cu$Za^N}50+9DhF27(Y}w!rG0X7% zGaEi6c&khKeb747hV5&jsxdU2+>UBQSxdLqKmf98drHR1;NWnZT)2JeIMba?UJde1 z)@S}%8$B95r}cfci=+0*$g2*I(20n&^uo9Q5hj=+PmRTMy|?PxdIyYFz!8TpD@|AH z4sg}4ar)jUV+v&Mc}X~wa!DV2xRdlBPw*7X>E4~#b^~nn+_yMV%hwC+oS*R9+69Dk z*A<CfyDZ>@b-gUR9>k^et@`KdW)St>eAE!H^&1YC*`OySEN?W}0^=t5AU^7k4}Q@u z6VW-ek?t?UkyOoAhTCJ1Ej;4L0RB&X#U(K5^&7IJSJwv~H7G;lM^c^-7g35+H{<Hn z<1Zsgnp<yuB<|S(m6p{Xkr~78Eh7+SeaL&IVh^ln?%pWL?4SvRfdkW?Se&StvC9#T zpR^yjFZOIg!YuFe>E7b{>HMOb^GDz|dE$9lnHPSdpwe?3jAZ#7#L+3MAO+t0NQdJP z)qo<{6@Ru@OGp%>qo(AVRw;kTKAJs$m#x^AmLJB7Bo`@xn>*%6EB>$2HMbWLNu{X` z-VY)YZw9irU`oZ$CAed_ds756_J1om*#KE>J;Pma@QQ8ojTI}ZpAOA^(fICcDx6&Y zHRGlYp14rtx!Ha!cox2Z8hN8|V|Ljodh|ZEk0}-@A#gU?`1h`k*r?v_<L05R4xSLt zKYpuZ!9s^wVRzNfc_<cCjefQ2ozVKmAtr*?iCj+Ab5-5c*#!&3R#dygK09`x{-c)| zy3)qI<kvftXStFZC6z`*CU<i7hf>0Z%Iqi>FVRF|m`O{=z^Cz(u<5TPU&fm83hiBa zRZHr>3~4OkW%7_r8%wuUDUvR)sA?~94KAchEHl_E$pF_sVVu@$t5W=8w^Ow%NEUAm z>#at~;?FBbx$We(KN*{H4BsS>3J1Q;f7v2vmbL=n5fKFcKCW}~xg+vT?qe*}$WTQ? OU7D(TDz!>Bk^ckbMx1Q` literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatflow.png b/web/public/screenshots/light/Chatflow.png new file mode 100644 index 0000000000000000000000000000000000000000..1753de776350e897373585d4a4f3fc918f5dd1ae GIT binary patch literal 28423 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatflow@2x.png b/web/public/screenshots/light/Chatflow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6b72a8d732e311003462fc17fd2f9bce7ebac45e GIT binary patch literal 81229 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 z�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�Rh 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%0D1S3m3PRd_cLQ^%I!W(c9OW&E{R72i>@ABi3 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Chatflow@3x.png b/web/public/screenshots/light/Chatflow@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a059af6a41d373591dc611e79462fdd4f49572e GIT binary patch literal 160820 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�QRRPG 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%0DFLQPVGEf9x7cl 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/TextGenerator.png b/web/public/screenshots/light/TextGenerator.png new file mode 100644 index 0000000000000000000000000000000000000000..14973451cc003c4e8ce75e7dfa874473080968aa GIT binary patch literal 26627 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 SiT}3%0000<MNUMnLSTYH_3I%3 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/TextGenerator@2x.png b/web/public/screenshots/light/TextGenerator@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7e1baae97bb8d06cda3ce9a86b8a2c88c33a6f18 GIT binary patch literal 63818 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/TextGenerator@3x.png b/web/public/screenshots/light/TextGenerator@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..746e9ac1beadcbd499bba818c8d69a1f4bcfd534 GIT binary patch literal 122391 zcmbTdRajfy6E940m*Vd31quO*OYs&c6e(U@gS)o0XadEpK(XTPRxA+QU4wgY&Byyc z=lZ)i`(i&?JLB`4werlK{QRJ)jE7Byjf8}Rr}ADw8wm*mf`o)7gNgF;gxDJX4haeQ z{)4)%;>(hYi;I$ylAN5JmX?-^ii(t!l$e;9fPjFWo_>06;qLz7;PB}54E}OEIzGL) zyt=u)KRi4>I5;{yI=Q^OJUKhRy1F?#zkGOjp*+2~xI!Qh506jq%bUxq+w+U-^Ye?R zr{}AiySuxG`-g{<OT>$Wld}s#3Jy}kQ~1TDh>Z62&5eyq*#6=1;o0NW)%DTw8LzOM z%7-tcpAV1V&&Q|dd;7=RyZbvw*GKRtM$0obJ?pjg&6)X?lhd>2wx0D3*w*&GowLut z(8S)!-Jhb07dvYkyR7WJvT{pUvp~z6C#3qj<5Tl~p^34Hd0YDz<i*D!-{Q%Oju)0T z*0;~-*hCIa?>Tb7zYD6DRyX&L&LrhOyg2whDly&pV*B7~6Sm{(6Rj5s-`P7L(cg}Y zPCPw3Z|{bVPtFX?KhU$i^$GlzmR*vR_S?YhfX?-FWNcd3cptTWm)`zNv;BPY@TsS7 zkUH|DwxKmHG1J{Ath)!&GcfuSluK*0(cL>JtM)}J?1JIz8B0c7Xk-HX`dPK*oFe16 zw6bA(b|E|}-6tgBjm!DT%{5m}0!7ZTbJ~@msY7LLGj;R{dHyj?_z6|~Nn(1zzg|dG z*-b`n6=mwl;?fFL!bwR*GiB0AQTJVJViujpY2WMvx6MImb+eU|zup(SfN&5^;AweH z$JN6<YjSkwzX54qI8DfD1N44s{VDLz4Xw|qXW&mgW4pAbTUzgvk<rPb(pqEiWqwH` zt>5X_ge#ih6Q+bnBP(|Sr}NRN<;eK-&C92}!m_&Nf!~YQw7w^CgFWrrx6ysqBNOw! zlgFlZ-aw!5_VH`F-UFeWv#H~|$mI)A)eTzfwlwr8KL{Su(e$VC7`18Btm_<Dc2$*d zv9fjU6>xBN_%u6s@78-R5r6)-y8ErumelVQqp8zxY5Sio+<MAy3@qGoCx&wiN)4)t zM5<4%Vz&Nmtm>LN_jcd#_@BiUuYLHNs}l-S@;gxXSrlm-ym>)Cjfb|T4iXv$HXb1{ z894>xn!d~8X;yboW5Tzvy4tGm5p-X@>5*P7R;eh+>iR4mb%(w%A%*;YDj_dH{_o@e z+humWF7rQ52%?@y_tXFL_3ewqtOj)yvcS;-GL7u7zuH<zXwXl*P+*bakeP@Yy0^KN z`Ho_0kC2DirG&sP(O$xYMHN$xE^fUVvpEW$Y9hKRVr?56n%HQ%yZHa_O4s?6!_`!x z9`o0xF}JH3G^BMO3cE?e@>#p~LWjRohrB(saV=jS?vUruk=FM-!t3^V3oI){@fr`) z;4U;qNJwHzg;TUG>_dfZcBp!KZgTiYA5zGhG&B_bn5z^bKqyEgHh9$7_}d~|hX1Yp zb_v<1Tcqb`Fv5^Rq68wNXe&jP3kiWpGM+KNxO_**{(H_<O)CCn4)1>?g41`K<&6B1 zFTARGxtyEBzf$BOuaH>Hx!~!>H&#&jH=XfYVvF2y!K-757%%EMDrI7Ou829Cn!k_- z(8LN&G;yc~r!DYw92382G03vR9_JlYWBVwaN`hCDMgD!umW(~&KamCIr2+|atS%;y zTLzrlobOuy%GR1wm1_Zv7)ZZ#zi@ZnBnZX#->FD`Is8Q)v4GvEs`<jTeXhwZt@V~v z;(7k`vXcYXdju9igT&QWM>E#iV4AiINWO#Rr&>I(E?h0%7ar}}6%;`WtsLmIwz*8+ z`=&-&V=-c!Dft~=Xck=%MG_r8svLVg{5zoi>{f)ZtTrw$taPe3<m*@i_$Myobli3X zZ=VVt8P+J@nI_Cx$xFup@l2HiYW&#<dK_)?2Jv2mk@3+HubR`=)PU%V1K$soyFmB1 zixAtumZqf@OX!W$MUUyD#qNo02IiJnTx<02hl^C*3s)^ZK=ed7dY&!wt!9^sszBHW z!U@f=-@2uQG{~=)6<mq3gnxuZ^LcW7$HbpZH4|^D_vGm2aXUAG_wEjUvEbWX0pB86 zX6Fw}mQvQPCf_>-wP+0uAa?6cx-wM<ulXADR>(x@cG$-F^%-DDNC@ysRzwezcPFI$ z`t>8Zs^yoY!1~n>RcL?&-EmW}nlffXYDDXbm&K@32ZV^2&ucm0O##zOWY;C~uBgeH zF`_fEh$KO95!MIZs~JPMF+Lt^O3zy_XKL?9jl=Ru%4FB49y7<dLpYQd6M)pET((sO zQ8s~{sPTzt|K)m6`=o<c;vK&`4g#jQRjOd#@onfeu1c)TZ(rqYm)mS|n68GsKrVo6 zk_kV0IYV*ueUmgi@QdEp&XR+RTGWeQ!c>OZ-DIr|u@X|SHC3LC{(O#r$hMV}CwxG# z(-ZZ7mh#JS@&L!k0L0yaoCKdlLO{?1t=xXA@4s_7Rl@w8*4~~pY)PjVXbvo3I7hoM z))j~vx0z-cILp1j>KS`N;D5}u<TqD=oFGu?!6ab#;|>^Q5R**95VFJy9n-U6bvd1= z>vK3<F1VUR|4(J*3ll#%ApC(5Pvo~^#aqmqwI&*Q{NC57IBdKyYF6i1@5Uwy;CZ_E z3pF7j6U*cBuAft^eyP5`c~R?U7;bmqd+7iIKn9F}b(ruCtt>w14h#1#XvsT=Qa)45 zx1-)>OfP$-9RH;zP<iE=6-~-#DsKLk2NtfXjfo575RQ5JO~2b^j9-`fWg5y0H^nB0 z3j<j+*iLQgEHpXC#49GG;9NdheYa!)BbeN{8uX>~Ln>LE!7deF8fzQ&&)W(XV&n~Y z2Xy+wt+VK_T)`3qcR#PX$nNg3hC%ON0}^6Bt9CdoFGK{42H0vb!kYfQaehnlQuml3 z1&M!`LUV4iBTE|D93<8@#VAt?>Wtl4hmXZZTlBzBUerLI^e)g?wP<!)dQu!&Kks$R zOZB}tGW`X%?L2UpbCRC~CwEQ^hP%eIV=EcZW}1_vCmEL29Dh7)e&z>aAsGA4=ylXy z94jc9kk3wL3kGM1wt70+-m#_HYSF&US*)Dxr};0m#e`p5HY)Ox?CaZVv@7RY?TS_h ztzYZ%AD;d5i>-ZZK04xT&G*`Ef$_nr_t)hshAbeg8K8mH_ID)l!9M<QL|a|OsT&!5 zGmUINf7=4gZzAD!Hh<pZ^E;ZH-vS9~kH1&0X$bv}?QeRg-HE<LV!+IssQBz4?+hwF zQe0hqGe7If^H0~|l8GYl11qq@*aB|BPP5Lmun<&xG;Z-}<Y-UY6qXiGKZW3em0+M7 zum?%8b_8ABw+~N^QYI|cLP!N+I5?Oq?c}FoRvNx=>CZ5~zJ-jj^oTZ=n7f3hW`I4U zk|rj-Vneo$zf0cG*jOF+k^E{4DMY1*%=c#KJ|(Hf&6758@ll&U|C43$+>oxvVSujt zI>!u6EEPVFZ6$$HYw@1$B~ramPFmq8xvvjf;z=fS*>~Dtdof(X-T-F4RV*<J>YOj~ z6_kVUFGV~GzFGF+iKff5**u)viye3K=s9O<B=D7t%kJNLShdRu1Zrn&<II9ACs4l! zXa;-eLZDKRMk4v33;SQqAXi%8bpgumQ>d*6QTW<XmWG<8KE;5<+E&A-Bc{3Ut!JxY zXuJ1hSREl5xe;>VW*i=J7Qb;Zs|9trLw|l0Si${n@F&7iT+zc8Ba>%QQQQK;6Q;c{ z3Muqh_>{Ao`OxbQv~07RlDmAgNw~<I;|YEq3mk1$RrS_5mDsyze~LAKRG+HI7B=&4 zAH12aSIa(OTUu0ZX%>9fPB=+U2_YvVCl^%@M6vkMF&S)#TCdLUJ{T=?uPK#!<W?EC z+$h;oE@EGppjpIBbju}Rq}g6qgXDH_T+5sz5+m0wko>R(A*jEysQx@zr~gGZF7ENS z4TyNK)wvv{<;kc>S7HSo>`g%1>=W|%NVR;XHF+nE(u_wFU#@Vhi*%Nu&!DfZeLokM z8Q%7BWV)_DF?#qbiftTj=dkdy?_q|Y4=L1<19e+?ou-be9~<R?*|b$pW9r}tLewbV zE&;@X?Z00HgUMty^AD3U&5y{eF?XO8S2N&FLG06ZeSuY1o4B3Fwa~U+gK{TtG{9f! zxMe&bV)o+j;DQ%1cY_auFSrq{1ik{CEy1S0OaM%ss1Lljuo;s}IA6hZJ{BkZ{)Yiz zwu_3zS<o3()q$(dV>1v~=$9I(sO<B-_kz{iZ(+-rDC(G$=kj(=rsKjAIvXy_;`fQ( zP|L<Gj*Fs!qO-{{tg&EIILY-5*ig*4OuIH3!59zPJev?p9$*;<Y-dAa;G3W-a`VSR z5w7p8-fb3Qe`9V2!8b%O(`6)}u8KcE{G(MvK&wyJ`a8GJT(s(h5L3&;z1|JC{oAfr zfZo3L)f{l}I`SRAg9Fcc_HyUd#yb>%&pF~X40Gi-u~Cb&Tc_iI=Q|{GrowQZ3>mrs zKeHH1$q>@1!4S0w&oZ>T0NoJYRKspXy8_n)1ny9;9Vhhe6)S5&cM1#wUc`mPT8p4$ zw-tUNgs}RTBNQe)uBl+r_xmD{NY?1AZ){MHdHNcjm0|3-Oa$x3lE~!Os!{j#DnR!X zI<*-E5y#Lryy7Eg%3+r5v*YA$M(OR4GbsL)iuX89=d?UM>yIt)+Do}(xN+9zp|)O= zf!{t7Rzpz76n^s)-7v>Y5Vv=>-IKSrqWc5QL)3k996pD**ue-m9}~vV6YMvT1D5s~ z9|UiScKMZ1L%i2ZZ9o{{;yCTDX+iW&QhW=JCT$v+=E}cr+fuCge-H&~2ueUe=6yIa z<eS}~chaw4=q3rw!KET%5Ptg+uEJ)K(ldy0kdjo)pVc!gCJ;X)E;AzL?W@h?LA%b7 z)^o<_d(8f>^*0t0<aQ``mRo7v`(FgCAqTB8afwhRc947At`E3y)kv!`_`zdx<95nr z;L8fasfIfAQ9;5MrP&K8>{mBxiR}AP;u+np1JANP@p$6cGemq&K}q6w*6nci5u`ON zAXWwGt^_gAdIDKt*kuC6cS-*uVT1(VvNP<?W;o#fp!&)X*SE>7646GdRS0jPqq1a( zH|UPoccoS3{)(Z|?@Y}pEs|u$tiy@wHM9fyp7gp&o5x()jdj>yK&6C3L2M)r{kOr_ zYHm)v4i@F0l6M;nodIFG(hg=*Mk&m}*swxNo68uQ4aa*0kc|f0$v-VDm>vhzs1Qwg z^w-v9Huvy*hRC6&k3=%73t;K~14~gz?za+?-LDI!%$3rL3CsgILHpY@cSjkb&<~em zV9VU&`fwV%wsJdSWQf|L!{zFD?ZAVn1$lV{i;WP$OD!iL!Q-C@Tu|=9z0r+DLuqW= z!{Y)FeGtf<>8^|mW^g1D(=7u;*$=%Lje|6CJmF|5bMw<Gx%Hmc@XhC#TnVi3Oyg$4 z3%L2t=@ypJd#~EPJAZrD9FLtvxtfe`YN4B-xi~rTT3D1<Q6B=)a_muv*WRQo79<|C zNx&5~Pta(s7@K;Mzka*=poe^SfJ_Yi+2eu_Y~a=^G(iPSq}TeR_sK}19Pj@?f-^QU z$CKDvccZ~+mb5ET(hNw>Z(}kOGsRA>tQ$K3aP<<81lijm25-!E{5>|%*4#bRNpQi5 zx`id76@X81gAI@8Y-)@Pu(Gn+4S=DMRK<3nGVVQM&>dM~(gq^?5;}am9HZ&srh!d3 z5YUI@)`j57qmigFXw}(3iYjEKl$P$_?m)T!uRD;;TnuF|`GTkqky^DYU>BxucOPpB zQG78o8?P_{nhYs*W-l9%!4a|Q1}3E_G>+68^}J0GtM%}zBCgG%PS@@<*31E4wgbvk z85fWWUf#GpL-^KGXEBfcA{=`IiPn6*9Et@0$rLBG>K>l?K91&8#9;-C?w&sAsBYO) zc@-V5WrS?VpA~;}iqeRPc=(L4>VAzner`c8+p*TlOz?wYH<Pt9v$tr;S-f(5>$K`y z7(m5_cqNMc3qz4Yi!Bo<@|z+kKc2v#Sm5;+6&1U2R-5upMS@i^%ccF48Fst?nK+Fa zW>Y)^i$&^p%tc8Q5OWqga1J*?Bw3O9KV*ba7ani|tb9=X1=SaS6TrMO1D=abJ}_yV zjg<5S!nd+%0bk&=IFOGO<(>(+a7+9b>aEn20nnKj3>g4!Lm6;!gAok=2tEQmHX~AA zYHqC=3-;23lGuGv-#u%omG-HM=*Gbf4yk0FjJvUc`3i==^TUIiiGni3e|9g9UW}`I zq27@w{Qg{q2V+44vKF*541&X-tVO$p`TmY9qM-l+R$E5FM)$&kejkzUs$h_B`8F); zos@;R-bAqC_v!M@Jnxuugj1Qe!kBN8Q#9M{R<pMhOXo7!*`-&bnGqdYyAUkcA}Wa@ zK0Id1gC#Vx=V=@bXo%Nh{Jl*A5^SY%pa2x}eH(n5up(gj1s!k@FU?4mizF<^a5@3b z=cXeTnr8(?x}f?}T+GmDnAc`OA_v`CW$3#8G@5w~Ibt-cI4G=r($=Q(7>sKx5#g^h zM7f?X9YM$NC6+qgh14<z1vpMcB!mZ~I@@e9?0(wkyRJ$bX{cFNcdw^~ecck21EeI@ z%;NO3Nb=?g?YMZr=K1#0l!pm?;V{^MzbnjR&`6pFz!grhI_e6Nk6Agin7zk>DoZEJ z@bP0L`gy>Lg5({*0kH;`cmAy}r@$!>5lmv07O<1k=WCl0V*3jA(L(YaGr24sgHodH zH&SxQH*`vv<t?Gf%TYY~aujQ@cz-JW#J@p9h2ooU_+rc8&qEw)YU%x4ot$+@q_`N+ z{*P7TC!tH*d*L#daZSlk8bW6hy0KHLi`NkM)-wKtlTFC(fgO{lpY!C>Hvu{Yew~Ye zIdShz4^efOxW{~IS$y^$EzP=w#G_=+b}qX`2O?PI`sJ-TR$R(YhSQ38XEm<}R~#Nd zAMO!>2par}d_|^XYH7q7i*^I2rYF@>GgXmjE0=KrAI`Gi35{AhMMv2{)q{)m-~p-i zyi}2Wwbj3?8Q!h8s;a7n^DTfy-y9k0dC5BLAj_CQb*X7j3~#>P^?k^YLcRmRAc`TD z3Je2jsYi5+AXDA`d}O~JKn^Bce9@!->^y@OfJzk3`G(od#F*09w?aFzYBys=Jno1e z@=-LL#(m)pKj*^nmH2eX7BVCh_Iq-oSRcgP=K?iEEOuV~^iVu}r0vYR>K<W0-0kM1 zv;g3=6d??2-SPU$qZiY|0Z7=re4&{X^zT`Dd#iAPQbXzsoJTO~OWCFGeD4Mk$Pfe- zDUELot&r9PrAOwk_ceBYlJ@MsjY5r8?9NyLKy`!8f5=XN@wSo;1K<LfI9*@#9JjgD z02Cv~)`B1BJw;mn8CW(pj9Dw;&?NNN9i2mz^Wlo@N~JBXeHFF>ZsqsA2zpd!Yc^Ut z`dQEX_otKc+U4yVxKVsgAbY3q*W=Mn;q6cySYAumqn|0Q*~tr3UafrOVQimNXj>S; z11|kBm|rwxUQH(_m&snwDy;P&<W4?Asme=8nCvRuhKx}_sL2->KII!s*<)S`)oneB z6xOJ*;t`iD4dKUS`f(OsFKnOd*>JB%Z`=z<ckHd%Kyxmddq&YJJzLsIOQ+SO*^=g$ zFqBt|tVEITI35x7mqc!DhYygC4!3mh-H;=lo_K!g)=s0tY?+R5`uMm^k~#{|R>R?n zm24uT=z*#i$^y-5@<`g4QaaYqw@7?sz+qf<?l>rKg7F%~{Ces@oPxEWbD=eSt}s^& zf1NE@ImbaT9=qTdS?^2_2Y#+x`MRtu+dC4&UW9D%zq55&1TrFmrrjqBLzd*-56k?M zj)UBoV*$mpoAi#<xs*RR>3c?<Ie(6m8|%(5uO1Q_Y-GnF(x(q;?H7M!I!1&3V5~jw zLMpz*466WsE9So5eUriu^>t>-Xl~+0@5BL0R(aOC3C`<3bcTr=VmDyqQ@#b>F}iRT z&R(bki8cpgjq^?!bNnCQQ#*?LfikjS$@kYnH_pH14}I)F(Ilq8>Wqr3vkmlU1yk2q z3pcv&81x)t)z!BFKw%0OH2&C1^;crlvtecV*e6R%Oa2!-$D{Zo6=RJ@LE8Ryzi*3T zGacVKLAv{H+3lGLl&D1;VI6+s4*A{D==o_PKu%8(v9zTSvwUVUM5&_n87?vdPpRa( z|4<vyA13)s<Ey+(D;4cI56&x`eTDQ!NtUm@NR=<p@1gJv7D#yf;KFY`3yDt2(Oy;R z@4Tk!wv|7Uw|=mX4KUaB{Rl7|E(7xuz=5n>kgpJHh2WriunSp2)}1@d4-}c#RvV}e z4pc0&$i2#bbUGL!hDo6UkYHs;MHy|*Uzqtlp%q{quC?VBZ^3U@rN8=yI_#7$TwwUo zAI10n8f5Itg>jtH)g_f&DR8^SEzgD<A9$Qd<w!+)JhsU{UTiUq62Xu_qS)}Rxu-oE z1XqWNWUZ2>Z>y(JK{-@bbWK&7>d_tO02`FmRLM^Kz<BC~@B-xsi4O7}|GoOj4ZX!> zt$zrl*=St?TQTP_KwdHEYl>M*pPU{DcC^X|Cwyd1>51*0A$iLWwMl#^q~U#5j%|bI ztEsGN#I3+WFZa*}<3E5TIE!XQvubA``>35{Fp^Cvk-wknM1<#MK`1gOO_T4WUtal~ zL>`|6wy_S>+QaG!^E&kICtj}rU0|7g#dLVBZ-y?WSbJP%K7a^(7}0E2%(*VYm*Z?< zv_zZF@-@dH4=-&Yq`OJ~hB&2KCs?0w^u6KFe7Dx!HHZPtZbX=5Cr65BW=w}zF2m_3 zY))M&aP0E>!qvBuD|!87H`ViPLCw<7sHcSg2{F{sZYD|Fv?&EAE>qv3kwvai;<a|D z0S6V%F5P=3@J5j}TMgcukH=vH-Pb~_4RB<ovPI!(I;eMEUDV7k0Wy6FQ1pG6(z7TP zz{bsIf53Gf4>CMrM${6zaaK$s6$9)v6cbr312#b3hz@WL+I?lzsl4#Ff9I>2rRT=( ztMgy}9W_c;ZD9t&a2%d&cYonO9Ah(}7-#(?hRQ$1uqRaj6GS81ppk4f$m_^SC+Y#Z z@`ofP@!-wGms5%tCjeWvuryKN=;rw(7OQWzffR`nJ8K1vQvDovrgo*CXR4CA7B$s& zGOIJsk*{n0QjJu_TcGzp!vCORqQE@X0CrCfN%3D(>X8xEk+-`n*E11|x%WH$1?VvG z7Mq$+E&-hAgg?@Lg2Q}0!5b{o{eA5>`2R(3Yj*-7<Om}dQ|moMIe;}&#cHB^R?wlb z`j(I3sC~+)_v`I#nTR#Mbc0%(j}<3)YhE-6wS4nQG{OWT-I5O}3d75&eA9Tlv%HRb zCOA5I=wpLSO6>~LCAROMcKrG{S=N)R5mMV?HsVWr6h+}SQ6-Hl6MIR<J57jnKb`Lk z7$Lzu1`?(`N_wAVmsk`<fg(sV=#?(RRp7+ndC1%>pRp^2K{hP5bWSrah>j+v#>@5W zVh<+YS+Fg(p;`asugF72#t27U{aRVl;tYgF^x>~3c<ZfBtX3kd?t9Z}D&tElRF8nw zcKi8v=lQ1Hj!E16JcY38ry)1IB5f0=#-*gs$A0aatw6HAH-JG!PMeYh$)-^!uQf0r zjsXMdvtp)BSh8WcNo8_Ozs}*6VXR5zobAMy(iyHKuIZAkxSm`dtq*(yeNFp1haQ%G z39Twl#;b$EHyi^mm5fxXs$iS7=xSuwRW~{wPGdhNs&5N63d@il*UQe6(l7V~wZJP9 zU^gyPcs$_0tnIQ`Kqm)A>t)y#5|6FKJuA%i;j9>sxfkKSB&%vjEbVJ?zt-ff>>WG! zHmpEdR<wVYz%gj-E`TB1DeVC)Kvtc0GTZu787php{oQ7VfBy?akj(g?>o;H{<Y*5` zTKb?I^|sH6gD_Xgch*!d$VE!+U6(sy2RuOkNBVkcnWnLK#5$NVj0Oow-2z_k+^h7` z#qLrSx(S3OzXu8fk&r$+{o1rv0&I)@N28amk!EWPir(s<7DqxVdwZB!l6Y7v1be~9 z3t_`oYAV?7=!S*p%gVRm>rrIgCe4dhB(&xdKoGvpVduPrKPh`2M_fi*B#|3FXRpGP zf(M;UYf|^nKP8;*A-TSOu5ZbFx38G;Y`+rsp*4P#CDhYHlRZX_4h(Gzx$)b51lUvz zswbFl?cHg3S)a@`U+9ZPy4$=F#O)Dy_D^rC>KI6##p@A>L1gJ!u1y>W!ISvQ6W3^* z$#1`41q7OOuV4iSotDxBpfmR>`8raZLM4%|C%S{>Bntb454aZa`9i|%-VT4IW1cbp zfpKp>$_&eRMttmCBEwMP-uG7aAVg4=sTk7`@3WVfmY_=t$x8oaegfk?BK+qWaLFrX zE$=lD%l9k){B(jv`jp`_Utt4{jb1^^sp>UTiYLPZ<$z`YJ;9K#?r0D8az^~pwy{xW zE2$5kk5Q<N%(>y2Id%qs+IeYt{>&y@qdO7X`0qEUnn3!9kE9f0XS=kh?gOUuW^k7; z!c~k$A=5KMN}e*9Xs-my@w;rv!h*X6Ye#{7WiQoEH$}a3KSw9HbY_qIUl|8z>N*LR zC}2>g11{zq8c;2Rzk>ziOYjen;s3xIhqwyO^lg-~;VF`Th{Pc9AXfd6P{saSZ^QJ@ zfa9KO^;>cqMa%C6dVy6J0UFGwr)<%+?|~eVuWWHz1KxTNTMN*!jejRIM!t;5E?m3h zFYH{IkDPs?g_AzrFI=;@t4D8<K@cM{&yMFY0XkJ1jgo&6wV})BJN8!}vX7)&I;k@= zUHk6ny7s@jPpIO?<BKd82e7kN5$tjX)?AhyXwM^MRv@JyTlRfS#U)QGru&r|G}YPk z>{Z&#AF(i1@e7>O6a?4F3VpoY9d@_eU7Ed~s~iyjZjKuC+;+R&S1P&%-u0h(A7tg4 zw+{a1f{WqRFSe6()_+@U@94TNNtno~Of8;E;j6u&{uR5=Gd0v>HA37t(D@bXl*@g} z<eIa{RWyuOImsXPRBuw*I9tgJ>g)sqqzsWnW9*EL=>aC%1s(yexurs^e1pA8eENBi zSc-w9_W=>5Iu!&M`$2;IlC1YXA~Xo5e}aXx2@92o0(-8^L-s|Vp!+T-b7Oxy2zS(7 zj$wwUx?e&c+fDV>ss)@WYH#;z;aBkYnk(H>O&m#nRcrFRG|U0T6z|{vk(8vEMaGin z=>9<yyYMMJ5-iEN{Pxu9FI(OF@PA}{LzfxPU#~=kX$i~&v|7Ie#XlNXb~dg_G<v)6 z+my%zEf1W#(Dn#eUjT(wq3&?!&Qfwd@OJOm{cmb6g$5>l#_e=g&fp<lKhNn<`-w;a zf=Tw_Z$Br{rp%f;JXV<G!e2~RJ9M$98PGXwrG^Zy(XSm)eE--VNIq!#aj@sWrZv-Y zPa^r76&7A`{2QtT^|K9uupo-?lFMNh8m=9N4M`PNWpTl<5sFlqUsxIc1>(>}^va-- zaDbbqJm<c>E~qfO;EESIfS1p7X!kNIa^&erKCt2aX*G;ku6$GzR1bLo(`B{(4uAWD zP5`CzFKt814OVchE`AmA>+0VOQC2u?Z=VV~(Vs@}V9$p(txr|d8a0kZmJ~{8aj{b# zvra(OQLl|^;CpeS1&%2~w>)D&Kd1hHe?y6m(B=B7u`cmpCO#H1X`m0RaYC)M2VU}G zr01SXea5{-<2xVw_82YpO8T<xLmSv@_~2ZeImM^jgu?x@UyuK=s)zT8O0ZStNPR_A zdl`XAV!u_=mBH(_ed?(^EpAaWAIy{9n@ITi{2_YZ8xml1uMy09zcdo)7<d!h|Et1k zVfRJaj95<Ljom#SJokQ)@U0uOb_XR2`|=-`x6i&$MELr<RtmP^OQ;+~eLumY>6^VE z-Wt2#Mq&Q}_HbftUbMA-*(PPJUUQ(9r#50);4fTEV{Gczdrjdz_-j@Mn&^{H*1`Z| z6ymc33JtFOP!;SS9<fiXg>r(bF&{#?DCNduQ2Gw@ja}}8tG#)7HBn{fXF7@Ge{re{ z#N8t0Q&<IrWQSqqr4n{ieEtZ=E8b(w!#wOZ4)~o{!}Tu;``nlClBL6pG{R>lF<YTG zTDi37<;Oq?<se`9sBQ3&x`w{~*tGd!zWB^aKf>y9%uy<iuqcPMcF-t5Nvi%UG`B4@ zv>WvKoBQF?){lS<Njl_LpVj|hshXtm<a1Jf6tgx80w<{t)ETlVF(Kr}Y3G*|iAd9g z4$LBCP3<2=pV?v3Ky$rd7INs=>%acdW018}ZPD<$ybl~O9G_3GUwxg~{AtMC`a!~8 zGIXsvP24Y>D76_Wx%FKpHJ&XWX5m}MF}08AsFE01Iod?4Bk6E%`#jKyyh!gzd6cD) z0t?y%4FkzgQY!l;sY&Ab+HDR9!EC?={8*pe%jR;f;2ikYVGMWjC+V>#H$vR2KAMPo z+*xLLZ2^18%jXeR4#X-qR)kt>a@xY(d@W$!*WVaqj`n29juIn?=1|UtY$wNk`h&NE zwV!Qn#z}7Gf0-A~IuX=~4#)hYaabvYqodo&n{RI_UbqL-N0U|Z!0R3-4w~MXn{B*~ z3d&Vc`h~@W3cb%?dme=p$tm*S%`gx8jIH)^<=rJS43oe4lZl(!Un~4fjYvF~h8E>C zbKd2!00k7BK}sZ1tz_HUVTy-hiKZs8OLcNqB}*K%dk`j`;LQQE58*c~xZ%x|W4}LJ zkOVuT3t=g46Na3kz7EK%#5u(uDh!Q9^dov7$M|BI!O@oL#0xN9DQ1Lu)GXd)q;D%j z3RPEyMX}?Px-i%%|FV?z$GyqlcWmW1EK%Sl#^?;kPM(jq3gX#rga25hT*Y9uzvBMA zVf>)Sy5shL<SO$G?`Xm9A-^a|TPc}DZzDh0@(&kasx5ZA=qNbL!kFOS^d2ii81mj+ zVcTvSvtY^7WaQ>V{46!s|BVk9;>ekLQ_`om_UF~T&3_=-3HG`P2lqK+Il;-aU`;X0 znWpw2K9VSI_Yye?v1U3g7<CHL(z6_!Xn?8X>+Q6J4g4;7?$2+Y-{5p|8$??QQBaPT zdg6E^cat!rb&>xc8wc9nmVP}9_OlWFppY#p@SZ&V0$B2IZxeaxkEb^-nE&?~CQn<< z%dLc{Ky_N--S+A%Q>TSJ|8FHWr4X}9i)%unPkrJR=cJ*F>|34Z(t-#Z8!yJ@opXTu zF4c?A@gHrA3MVys?8&j^3GXDUq3B~jeC8E?05>6)LVIbBkrHpiuZRnvEQ#g;M1l_{ zZ>6*-|FaDCI3T1`BiZQu1{m&`SN%z{Z!7gUpUtCBIH`rRt0ngh{398Ttlp~&Hp&?p zB~k6D49S$2fwREGVrr$Td5z!kc%&?DIY?IG1tR}J6N2y^EuhnL`*NV!gE*>WroWr= zFCQTGEijoQkM(QMJ55YniQ*>wpmUB^1C#TfEV<J_r6S45Qi+WDCx>U67BA;E@_lPS z!id^8TsmrV(L(p)F!@RRY`)h2&{`cf!3`-|-Fe2}Ii(7Nyi(#cj_SqY_>+JuX}(eF z8-lxiNAjH1&QaqC;L6FvaNc#;moPAW&N1|*4tc3YmyggDjpP}-1v<Z#{rjAKi$*Z` z7vbG85Rh}44CNONPJt#y>9{13^5qt@o>m{KG#)HY(&rtl@@IW$`AcP%5c8|Tu;W<! z+UZUI=ypxGXk+Q7%YZ0ZG3~qEO<P_U5az6}?OsgFY$`tZwEB4Ud)Gx$@(NUWD@}P_ zVXs}umdKY6dn>#f>N*u!LSX2(Z*KfE8-8Z)Il(|g`iD;crYGWD#wAVw%>RQ0Uce&- z{E1U@BwC#3GmwHvz~iP%hW?oU09Uso<gbyFhbnd=Pb_4<xTW=azQJ>(K~#dYYSv4T zcTHFWVKX+wkr;2wq%|<zq6LE#D!@EhW)67U+CT~wZh34!9~<oFo|t~Nnat3Re<r^B ziA~h(@Zl*ch1UG78>n0Gxv^1vH`8L3;nh4{9A}MFu4{pyB$&P@ATxKO#-S71?_i!r z$Od;yNh?ApCdc4m5B5C}w>VQ841bv_$W{&*+K!`{XkRtCO@Icr1S6hlBVN;UOWwh% zFJr5#bD{<a>@y{O;YugN_Obq9kjOMcQ!32rGQ*Mu?}>9}ryMf_4K4eYSLGFG3K&UL zPx=xBmyAta6tVa;#YU)ItHPM}cCO<n6WroK<gSWcI8lMfzwHK|6mH~^6yM?J$L_`8 z6YX{;P)^C<O7y-a6hN@*t3;=6+NZ4}yG(V+fp%gLLU8($C1=31nI^R3EiIxp6CD3X zfSF&PTLJcd^~<l1SEE|#hZW<Vq)D`?dN@qV*3aLEoIhQ;<#Nz&5CgbObjLq;Vz;KO z5rgw<{_d=ICTqa}neNn*;+$Ti0N-#_*S<bMMcCNU>fyVhk5uUpe=m)*t86i*%IXr& zfM+MA=kvc7aDp6mHcbsQ-vHOEdo$Ok`(C3I2s=8q3n`d>ftmrHV@i_E#iV?`o0wrL zoG498P2Cd|dCG`Sr#px79yWH$d6fMM99}Pc8BYI+`$~-pIy<+*$Ki)Zwy#=TTb5Oz zZJNQSqpElh^&Ha=J+3@}>P~55kN$1!2Z}(vPtDh!*$&26<=4cGxY{Sfr_~CalD~;} zjWK>6NeC*Rr1`+??K%t@=6OcK-Ir#3JC%qwI(?J@LQG=^G&M~W|I9k(luFBvNa;tI z9%YR=P%D!RINYpZo)AdZ<(cEu6SSn}sY=0E`~<(pvB)bDu#xp6i%v)Ky5Tf1O4aFM z=Dl?e>;6Z|F|MX|yz1CzMy^c)jMh5mM4gI`4|G{QsZ|;?a`;-GWJdo}xKlqK^mOFC zGvcWH+=DoNWG8<PPVkP(eWa(^b5L1zVCZZfW1wg5Jy7jy$Ax{rEN7VOwMm@s#D!r= zKTxs|!dN<A-n5je>vFmIo3!gjjK#0CQfP~qL|M<ZS`M2IsK~uJRgXZu^Qe!aozj|| zL%LhyWpHt%Nk2`AP2TJ$T7T@@*&zzc>=O@p^w>v+wdzJO48U@Bjik*^@G;@d#Fh3z ztH0@GP8f|t9?Rd##LbiV`v@AfGI+av4#^Y((8J86Acw~9`fen8y~v(tZ{y-wtrGio zr1C$^paMUIGwsP$X{EIk=7gs?@>mN$;Lc8675!3V0LVhGWS<G#_h-b_e@Y&Ts&KG= zV+@QI<Viq7(xOUIe)fh*KdyCnAI^S5V6h`)DG(SBZ)ZoQV6HlQStVC<5FPZpJZF0* z*$!se?5^zoA&HbwnhXbN32PaAxRF0YJasHTZ!O4&-VXm-5cJiYG2Qqyxxmd%LjG{+ zD?2SdOeFwY3;&b(!UHxaI^b;jextwNl<oWof*rWT(7`YAHr@#oo`o7h)7hYDXZ>`} z@4l<%6!sWct;FXfHXsDPb|N$XGT!o8m8d-ORncd8&mXo0Q6Zc6Rd5nOC{2e4ZY%yF zC#*`^18)YdEL4rWhEXkopYZ0WqUVEHH@<u_ZdrXWbabSb&Hc8us?J)95iiT<53=1g zl@u|@UTy!}SH&Nu-Tc#_XXu<YB$bnY38=J?WW0e&zy#>|3RHHNiJ)+>t7L+AG9zd$ zHJ*cyS^nKh&o{Er@8uSI(!-WWKTM+nBaY_ds0mO32_2-c2T>P8L&K0qk$kH3bcaVl zbVXF)^sVJr$~vi!>0MB^H)-F{A_&$cYfi9$kLt+D`ualVq<8o4itc;ehNixt+{s#g zwcPsr@5(2CgFlzPF68mHw2}@j>=6U`PSl-UZPz_s9Lcwesj-o2B89*qkwYeIu%t>P zl%~vTQN4PUO)(pubjx#{OLde-G>#^vk!YCsIO@wFDqr;L6`=k?EH;0S!plriO0_c+ z(<J0l7q{%a7ACNK4nIpT6YDG|W8QqUoBf;7CkuL!4ER&y4^HI2fDw_)g#&Cxg${Wh zc&8A;<&(=NL10z}OC}H#@!(7EOHcuJk&jr?K?dZJl_RUXf<GNQnMr{b&;i?FvZEJQ zb?Fr&7`QiS7{I4#W1#YqJc*jAPf05)$zH*EE~JGG(#@u)KX(JaJ8zhSBnH_oHKDxv z`)TvS#D>8o+t5_pxeN&+>f@Q|<hzAdL<EBl*kWM9dz4LAI=8|fr+=+o%LeUw9HMr* zh6Z>$H<H5QbMjZnbPin_^C5Q?R#5)$^>T{1N$)j{!2WMCWa5;fmd}#=IsRZj|0(F_ z^PJMIW-9XH<WU4!mV7^~ViKLPcK&iFbodtwrkdtAePo~m7U?X)Jm%3LJ6pu9VL&v0 zhUj2%l!i&X{i1&KE8(HiQ4Y20gQkHH(J{_TK@B3BY8R6cfztJHS`6Xu$m%;{9p;wM zVP<}va_76qFssTf+K_-EQrKBnRVo{(XI_G$E-r=LG9W)tN;A~Cpj961>HPZd;5*`u zY)5KXo0H@g!@z`0s+OrfIQVV_dlCKfRxv4z-)*)1RfA*R>}ftNC1`CvunPL|P&$`3 z!>n;-Wy-X%;p8`8j=v-FT#BKL=5-sfVg*okq6rmP#uGC7RWUC3sm1v1+dN8`Drfl4 z>jO*HLQ!SQM9$)kH}<h>V#F2i!PMB5z6>^4-`x+-(2k@2K#q5@Coj1$m}4yVDe+jb znB}t3sGiU3DOJCJGNK)C(!4$OB#hEG5KEw_gHi;-7xh{p2<N*~F~-N!t>P<DbUz}P zyp{`JI;uec_0|{~#Pkyvi8Ec0{gdYuD;Dg$I-?R7GAL{e6bzz-m>(LjA^Vc^YJ?sP zezM_DOB>xyWR%H1FKE6QGkWrteg5}S7aKb}*7={nYho`QV6ZOCjIho*^~vYtLBcyo zD(B&w%=0m6)MFNR_{uLo{<#(*^28|FxUaR=3skc?%CSl6E08@~uh+<<q@l|mjKX7Y zl-)RzHT>9=Xa;x=y(iZb)lIX$x#YL(TcABUq45ZH?}N-0N2LdhYph--NZpD_SpGCw zBwo}_1}~&)?C{z4DozHw`J|0-o$EBk$qrC98%3u<3c!f0mk^XcOK86Atme+`T4RQh zH{hG)Y4P9w=Q|W^n-xnW!F+QN?q6R$q!mG}ZD;|VHO#W3BN`2I45IDBTVY;bkiDW= z==q66j2FYN(R!<tXBB0oj?0LnZsfGe*W8QwHOfu>V;|S6%-?qeM5NhR#L^IFKzSWt zkqiy=%hE&+u%bqn(@E^RV?fQ_7xX*N@D-$Zk6Ka*ci;QvXn7sMwNZ6igNBOFU}A^{ znVLxb_;X;zdSBC=eQ|xsmDQ7DgTT)KWsp`}OiZs2?J~tkiO#a$ilo7hV;dWfa%5vO z)T;oz{t+&~6!$9``d80JggT*9)eVz%<Tia=0tV~CRez`&UrVdjRb7A)wD+9{y~k>S zo69&`h;^AYd$@@)GrOiGQ>;2ZIv_~ThdRwpFSiKEF`}IxtyxWOl_4NQ=A^Q}RZMTO zHKbnu(bA<SZI<SN%wP@`;LKbJe5+nXeLXDUtL{N@#C8LwXBhlB35C9~r={q)(+;Cy zo1-@-JM!{(I0O{#j(T@@q~(~}<G@@RDUZAsz9h@yD|I`{%yU{Q>ZJUgvA-fRVb*Uu z&{#C&L<hv#is4)MYjBc`Suu}LkB*AvW6h$uSBuy8HeZQQ#gGCJGy+!MZ<GHS+;Yl$ zdgUjfsJhDC(o+=C(&+LkmPvw)6g;EB1?srwdS-^O;K=8ctcc^z!(TnO@%)0vYO*Kb zwi_Aes+L%FlZdhhs$wo#%|K%XQIL4~7v1yTtLo!AK6x8n*|>kS?@#Q#=@*GcHEQ)S zf%(Jx!jwE;xA1I!Mhvo&<)O^Ang{%a5;NVl)Y9R@whlFem`-(z66IHxg1qW#CV%(# zL@LiR`EI%H_rJ;{c4v@{OFVoHyKVmFKT0=61~0g{+s)#DZ<s0aS;mOjXU!EpVS0RT zYZMv|Y4Z>?&=iE389MBx<xi-F1UZVK)z{;I!qLYH)gk`0RMUqBI%*#eAC2}tZsb!a z)CoeKM1W{Jyj$|r0VWjX^8XB1@$!(nmG1cgY#<f|I`YWe_;SH*<XY^Gx&YFKf>36J z#HI8`fc=fB=d!@_&9RyeI=bK44?PsPm~0xsXI492nF{h)mR;+I>`68wmU|q~0C>UH zGF>*#awBz_vUMKgUyLaS+`@xF-P>_df1UC(yh5+@J5s|31}%vu9+Pila8DUN{0IZt zH_{TTAt(l>QVt0RpaE8(j2K2MFEOP1IbfXR==$N5rXD|m#%A{Ca_dFwTgV`tH!7T< zK%tvJkzs&FF_#&l$UyVTdv*^Pr3&R*ywS+F244&<9h8r-|8V%bRqW{~E1pfZMhVNF znD!lt|E}}F20?RQjizH9rBSh=Xw)F$F87A33-Px24-C8Ph@*~y-6|SN{X^A!)8b`| zxJPKNstC7&UG?Peq{ZfoDw$750%4$?2qQrSK8#~#et#L!k$$O*jP`$;q_!_W!RsF` zK4(M+aQe<whL1Ngx+yqJNauM<is#iwhh_3K(=pj+Jy>5~vkhCruRO>}087v$8xKC* zum@1IYz)fK{=6R2UEs^%6933f4HL}{XOT|3`0#|eIn#;)L}MUm;jB66KNDgrD$$dI zkp4Kx%&qJ{A~~By<Z%F0eG(`;W-W|+8T4-l)`F7rB9V~+)G+pD%-2z}nos9{D7heg zU9+f35&r+g{hfZy=-`@(etKmqyuJLH@6aUa6HR#^+1*+-LQyO)DPxnU+<EEw=4!fS zA#j#EO0sLyPQP)6r@Xu@&UC^AW3Jimh{rTNA@vry&eD(3&u*yG;*zY6kYA%@5sgyD z-<#xa@|D{|Uw;p|nipxuN!ilu-E<3yLcr|3VY{=%M9n<1ZJ-{8gamb=I3(7B*4C=5 zG)Y@fyr1=D{$jz9w)kB>KOIhuVgZiFJau@c%XgZ3Iuw9bQDIIRbh`>m>h+m%%d6&p ziOYxc5nsizy!dmGk(k#~Dc3ub2nfAiHM&nIP1jSuru*ZPWLs4B_9d4Oh>S$7Tg9Jk z?%bJ(K!1keF6wtA^{WqL?fsXC>h-zQRW;G6G*in(->Qs&`2EiK;}EmPhP>HulZ=ni zcW<Mr8u3MU#Ti6&_lX`HJx9j~zy7Q<Au73HQygWG-g1XEiDYeR%4Num=o~ukkdJ8_ z)3PH^j3>=~hZxujl&TJfaIwl4q6{Yly!mlxPp0&2+7m2Uy6~h>;<KqUa3}Z&5&qj@ zZBGX!22s@Q{5M_}-({F@wO!)bjb%XI=th>WF?QG7LW&T^%T_qM)}C23Fd+I&?k_q` zRKA&MPe04dsXhK0_Ss-u;bi&;V^Hip_t03(K_T_cFV6JIs<>yO@Jx1{Sf)-fgLW*K zRD0SONcY+ujUP4@`evbFM-IUI=wjKdH(QnS=03f2JIzeB;&2FOh`y+7;+x{LDKyx7 z=A6eA_Yfh|*#Qa&*_mC7$dLO3VLp_As?Q5ugyQ9h@g_GebzC&JOz0FQ=$|s{(?R;o z4K3oXhBCfZ>kW&nS$S&gHYLH+Z4>dylvFc`*{Gmpx+;1!wLSyi#JXB>o|lHriBW$( zp5h=@;O{`&+r1LGPZ*z;QfQRrK{uCFzE;7t-d?3ny)q<mPc)hzRS7V|3|d4RTrzeA zIzD4wKAHYb|AD)LyG8pNtuo<aM(^_Qq<KOh!An6ZE8xD~i1cB~DE@Jk3B0nN{pEWJ ziu#zLNKVa$2E1V?CoXAQ%+eJv{%v#8wARz{r8hOc(ovJE>2GDt4sK3q=_9?qHA~Iz zcR;k-GJ4|PoIg(@+Qgku-0!ppQmBMtk2K<U>QB>an!)Gx5`j-gC(iG{E11osb^)v9 zQB#Z*3nQk25w%oQnYd^YDE>NsU2x10a<9pc$$cdcik`{t{cj+1Bo0|1BQU;Jr#JWJ z`L7f_z%;0*6C%gGH9t7^+B+s$sVC=Zqr5`ytG4u2<J6j+apOO0MMgucW>U_02l12d zcEcazAMO8W+Rm<s)a}U_P1aykEEiFtS}RUt{Ld%yqJ}Z@!R=h%`B;#LnC8QZ>bzF? z{P`Xo;1Nx}mxkYerZ#r*IO5o&azwyaY=y>xt2pO=X@BkdFo9fRw8t5?ln6IZ{VtLU z&v`Hxr|$(}+(62OHc?tL_uC{K1!hhbi|WyW+S{{VU#JNR<4l=ymHfwlIuCL&!2`Sl z!m~J&10*$r3#XjY3itPYNhIh5VNFf7<z$N}MP=*lTBt71k>1>FS31GmPhY6vtyjxI zN)SAi=2ZB_wxsd*EvU50kTQjRpF_h=ow*+Gns^O<%lm3=_eG{@gvIzZwAmG6F%V97 zN7F0%<~S3BVvMb!hBE8;m_lsI+lM;&zN9nj*{RY9w%wz17=g*TZ2?XCC}lYkCsLwV zuD3&5&=hn1RyxgHTY^rk{v`ajba;p;TH^OYeX&!f)?0Gr{Mk-l^p|uI93rskn#Ev} z^_uUiVREC}`GfM=%vWK;^Y|)DEJ+DksssR)qDE;jwsgepr1-J~>+<ryvZxP?Fy&Y2 zSgm?)Ycc;bMWd2G0cvR~1dD&wRHxZNqS8_MzC!oCQi36e3h%6oQ(5^Uiwf_vXwCCP zkYQP~VR?ikoM1Q%^AfkdKa%0v;fF;0OI}AVp(2ItN?xre;8T=wX7)cK6Yt;!;c`DT zodiO8X&<XH&jz}`W1uASP5gl51|7H*1-I^dIR*BF2t<@+gfJrN5{Kv|d19*KN%w94 z&-YWOY<Jes9_NTMs`jU0L6|v%ihtFI$i8!dKq7yXwEr7Ne;9xDN`o*gqAWG|Xhj2< zAwbgQ#xNH$_(S!AjFPSA?-Eb5;@mLI_?-=J=?sNcXp~U36(U%}K|RLF$tUpMM_k<D zUD;>fhuGBs`QPughH;OJo=j(+6GSyi>}SC!zR}+0orhi4BC#;iR`bDf=7rAzmvC3W z=%?4p4|a&T`p#uR_#z)mkpeeJkQ%}YVAiUvAyv~?xB5C(y$nr-oP3fXXU%=8LzFI_ zw#?#WHJH@W13-;FbN8)UDflZhaRM1d>i4Y~5yGcl->;{h&#XRMj5Z0v3%PUx|DD*# z^iNusQ`0i;b}|8jn6AYFM(#^^#vV$0b821e=$H9XHW8$VxQ$&Nlh(&?5#*n1d}`0+ z7PTJQzfyZKKdY6zJ8W=y3ZlFt5d5-s!y8i2aVpL$ecdRyvU9q=Nr!j_(BChe4Q^&1 z(Jia^FPfg*W|T0O;yivMPcaQB3_fFD!3mTk^e)(r=j&{7ncd8=Z+0B(RDMx_kZRc# zRQHmgftZRA(ag`PSt!u~8=Hmv9eG{GP9k=5_)dE_rdVkKu6#^=_rT-e$|oDg9|29B zQa(3Op}L&w2ZUa4S__{~Ok2r`pu-o;t*(w|k>;8V>6X0!9?ekGwCj|~pyME9rIgON zwiYNwv)!vd;~9x7c?wn(YroP-Lwxn7_9o$&maVhU<$=pgaB%QXy-hKYy7B;I`{~8b z6rUJX4SD4;a@X0kk0bfF8y5oHmC-BD!|3qSG04v?nU=MsrPS{*tLzrCt^$*tiLoOb zVU1k#<yphdo*)=+h*b_2t6{A4YX|K=n=-{Yzfk432?Ug$S6B_PU|qQ~bOLbhg!s~G zG}qXG+dDY7#taG7K<OeA2<0vc6)t5QWW9XWL}iFHcja!S;@jMss^_W5fKhXuCa%O+ zL=Sf}GZJmhd<@0@rz>I!lbMye@sbvbmXRVF2<0{WNs12tI~^wQ7L*7^p<GIT`Ii!` zXBm0^O)L}q!<R#LE0|2b)RbCX)DH_!_NsD3lU{W_r>8u8(J5Vy0Rvt?Q%}bR`-@iP zlnJw<{r^aM>VPJ{u7@ayNGqKif;38wmTnZJO9Vt3hQw$==^7#-r63^PF*+0;x@1V# zgNP$Xr{8|>_xJ8SJNMl4+|%a(vD+q%HdzYfAivy<>wTbHV&TTGY_yx~kQA<j3r1X% zI$JN;eH)&njDChNy@gYBZkZ7priUkqFah=*>~XKZIIyTc)?RtjSUBH)bpExtB|(AQ zj+YTQ5~6YO6R(FH|B<K`bY@O#y)d1!qXAS1^tN@DYA&^PBck)%I@^QWC+e;Kp4T>) z)D+jtJzSp2VCn@_Oah5GiE$n^<_jsa^*MU>61Qa9_C46?((s1n+j|Ggm|TYK`*XFy zth1wbnC2Tfi+*L!3&c3jR~P#1T{7g@lvbXgE7NHz;O#{V2aN6pJjsPMELqqa{dPWL z|8D{IHrRQkLWnP441V>Uu{ZZ70>3LJzpeRK`%%fjD|y6!f9Dr%#MBqLpMR@LFTUq- z64QdH;g?%BCA0n<Nrdpz(MPzGDI*Z}mRUW|%HG3sUIy54K$gM&^(@Y86_P1GlN_5) z|5ig<59Z$Ub*OjA-@EbA?_EXBUW7Nt9ciKF_!JfBan$E;`n)QdY-R23!rH_w+7Is$ zjilYHlBGAgLcIDtA_-xZb=LDaU{qo62n7g)yGUNr!h4{N-u8{N*FRCx_@Dm?JIfM7 zi91`JWn<o;rptf&Jqu|lxh#8B*2yG}(FRR^k%j7is<g;6WP>Kk-@%tPLLCy>6rn<* z!TOcPTCMeAD`wEX2{%Z}i&o{*tojNSL=-awmKCcmq)_W~AhKg#dGD;szLPSu5K@I4 z8XUEQo<QG}6TWzeGg(S*O~<}+<gB!sDeubLsknR#5d5N~hY>G_EPsC_G~tim^fSu; zec#L~oR8I7WQGin=)HpqZ`w0!YGhJjG^NHT97o%ocTGB^VJb9Xx^x1ZfjM&`vn;1v zj{c>Ate$+3Uurnzb{SQ-VgPC1h*Q2U9ut+#+DP004_7s$m4xIuP=r<RA-Z>ucFpv9 z_Vl9$g<Ch)u)^B!UPlfwWHi%6usrjijrggk=>FiF>?CGafmnmyN=Pno)0+E6Xj^zM zP>*N5HqsWu)LdkFMV+K9z<qVMo=FjexDXz=YQs?>7CboNDHYwr5Am@U;#W|}FA2@R zfU}qucJy^<Yo4=Z?I}92?M(zDe#^JZ(MN~~8MkDh$LDiQs}9TWL?qX=%E;I)l1A=2 zY2jvI_XBu5=e@5MrilC6dgFxz@Ce6@HTD_oc=H}$LT4XcF02{L1`AZ`4-zSphYlP& zl-B}=A2Oq5TCFi2@^{1IW3y~!PJU~JiDz>s`&@fMwnAeb;hM9(FzXX;1s@$OH{FX} z6zc=rS^Jl4YnUL(!?CSsL|oQ6Mn`#(yyy9}Fw26Q2AIcoOj!L{iSE~$&|An0IzS2+ z;S0GyO{NJl!F=_W_y&w_Na}g6(F<<2tAeb`<ef$Xqj?X-DbE@$+TK>I^a;dV=IoSb zFtZX%_maF^0FP*-Wp#NgYXNV${_nCh5<C{9AWj0$mkRdW>kidjc8#JTN8cPJNj7KH z!K>P^ce|gnHlIgjxtC_*VYIw&!DxWTLgQv_7a6m$g7)pAsv~16Z^}tmXen@=>l-D7 z6^PErbLl^2*n!?aP;g1Bea_HbL8t4<i*z8`&l{@81C<vLo!^vMIN8k00304db3Gj& zBIG6``?>^CwHS)LgjSR3a+kP3apgsO-?UD$Kas&Y$|KCGP~XgF%O+3e-;KKVHC+zH z#woLc=enX~)})il!KUoe8|xW$nxLM|sm>oRJg|{(6|lyJ<W{FA>26v!=N8@19X;%# z=Ut`fQcuTStt5+XnCKksIIv+J%4@|=JLrS>E(q&V1zd9su#M<9j4Xc4Th!=_3|@r! z!Rb8cK0pIkaXXjT*JAK2I!BHlruPC1l2tvcaRF3whu%++_*2<9)?_+xA^iVpk!eZ& zRX&K1mf748fcz5qZ3{*|Rm(A`c8qz<*QN>5I4KP`_kF|zp!K2Z0gViz=J`>5ub^~7 zHck9EyLO*Jn#}+uD20_`N^JO5zA~6fn>#H2NPrG*@0l?79_S0VzTW6s)<ZRZ9Y}nQ zX=bv#J=gTQ6Qnf|o6)(CPCF2cSxbBc)jQXMZm=F58)(K>zh4?sS=<#Sh`x-o<~~Fw z)*{~s-3Sd@`%Deb#M^41r7lQO?(h$N^qCuRz0GQHmVy1nt#VQtw8TIkhZ34XWpW|* zpL5|9GQ!-r5JBZfa2EUWBayq2;a5E*zvt3f70+fg49`r{Le$q|02HtQ&>T~#38UN6 zcY;-eu!T@Mhh`vpxyJIF#QjWa<i(@=kS#U@=DZuk808MjTsKPLcK$xX9oU*t_Vy}R z1v)czhzrxAHymp*)9d1GDq%#Cqpi-CI$$a$=gOYR0B)a6gSLaCa@mZb^7RKHaK3++ zkQgAo8MCwwC5EI&U2fyW%(b#rX*FQXh3lt&546mKQPk*wzqgq@b!`yNC|gi!&=N}t zhg6!)=rF+=-~6kc)o9~I9Za}o0p?4&xw~e(SwQjdvnf=Ij+TmB{|)gM@%?VvD8M#~ zIaEx=s&r0fTA)Z7yu*pJZkM;DhO6wu=0sKQBi)z(Suk7J`>rlA97nullGM4IY#uv9 zU9Jv7T7&HyBWCN}u*VLE!`S+gM~KC`Iy0~wJ&<Ss%3tj#zJE*HF8@iZjaz%1Y3bBg zksz8mJyyn_7)AJkAF%*ph;W~>wi?`^+|%w4Q2`@4)S{Xya)*72_N#ig)*QOChIS2O znQcM5lv#*<iI)!trr59hgx_ErXt$5v;AQP<F2Tb)FdFIIS=#OA~c+`SvNp+0uy# zs16>#Oa|H_(g;z6ds3*<=y^=B8#lKK!&#;n4P1z*_KPWYgq4Ob+Jfdxk}2`K$ET|# zXs%s*?s!2<*VNPt<)FQp*B;)m?}=SgemGbrSj0+X>glQ+Uz@{=2zEHGHEumv;c7Xz zvS3@^ZO;VRIEffo^lFJYA|%#I_gBw{A7)M%Xa4r>P=d-+@~Z6E#4%sK+KuyMihTPp zX4p!p>ju+J(o2Lh2L6FufpE*@n<2M?EJyW=C+uqG!PLnDYPf+-{?ST$R8LdDsR*<F z;r4NDkHz>W8j?&goR*qyIUE<gu1AQQ7GjSqVSXM!geH2U#8t}myBi&0B)Au@tCZ&t zd85o2Z`S2ldlNm1a^gqLc2n;tB)B=QqU%;L<PGChg)YTZXD}yH76CI)uy2eA2<hms zZpe*>(M9hdz>fC1+%}mq*v6WJv=jK#DgF|lnaRowI;hDh8b4Qtw=Kd1^|9kq-`$m% zrIq&bfAi+eCQsDszY?pj$X)?N9={Siv5*k9Bf&lEleu$AFFE>;4lYWbpJgWhuE819 zO5zUZ*mi)92df1K)y}Q8hxlMCjuKfCF4y{*<cD>tvw?1>&?eL}y{gjIz_H>dXAh zp%%3cQ`p8Qo{0_0Y$aOu-0)e)cAaO1ccpK7f{|mtu@2J`E&VnUs6UI-qX}bb*R~F9 zXB%|c?mht(jAvP9xoDQpQ7;)c+z4=sYNUTinf1Prdq_nSl(MtYn<`k1a<~>A+y``C z*WH>GUExzL{KlHvA}zWKP<*kBT(|@LK*cIwu<5|n<6DygTM}FE^<S9#mZy2^Wtp)N zq&q#R-}#(JQOfTAC9}*>&5a*+#hNrto2uoIbaD%{KhaePzP;_2*m{U6Vmw>Y<fPud zaW*%1AFyT>ug_6$H-vHL#$Im3Tq3V|Sdj27)fB0_eA^C$d8UOJQYV;{{)y^^X_~~} zG<LSnB5kCAj-k&H!|uZ4dMhQZiy2fM83Mk=MI9tvZxsXfd4NLEpuB_=Xn+dTIyiFI zyNN43770?ETeIuA0XpGErryIOo=)0G<fm|W2elF5LX%XD6XqW>o}YiWWQl}LRFFkP z@5DT-w@(>-#&LWDr}QxV^5~x!u2Fs>n2UOw=*(tz6!+z5ICDXc%d9dcDwl2{%`BuW zb|HDOQNfLwYNy;)=*bSHBg*iPnOJz1OoXn%SC3G#?1<re4a3x+EH_g<1g=D1KK?uY z<xSshoLmeWaVOe9``LV_FKa{U&vTB$#5S*K9p<R+DjcgS>X^5B;I*vl1V^RleUbPA zz<!=T-dsKuHqIVX=SWE{dxuAV&rSLta{z{(q9$D3ZZ8qyu+!&rDmgSPcI6UMH8<={ zfwO93bo;bwtXA&pbDUum#C9eikf)o~UKzkX%jL9*@^x`+Y|yH6`~62eWU}%g?FKmZ zIMacTapbrR7RjKVSrOTz!vOk?!;SAJ1(a^fm?!7{lVV;J$bI^kF9s?8Hgj7lU=lrc z&)~f9pW~Ix8;>XHt6tyOwlJl}gI#V9lGfxmOG>rsn$LlbyTK;9YuoLM57h2GI3K?a zjxo4?N_O=9b&Yak(~{A3Jk2EgmhqxtMteKKVN-aTm%_BbsyybAyFpCRSMMdRiQ&4X zt1S!g#@SAo@Rb?1&A*-it;b2+O`6zR%ih=R<~=!D5u(KN_LKi0pB@kv>>u5dTcG#3 zkfkSB?YXbh`KN+Hx`0}?qZHC-<ZTrOwF85(r2AaK(iX>a={cG6tVjm%)kQ5K`v&LI zL0IQOpst?2u#cT0V`PFhiz@FtiNfG)45?Ld`x7nZdbyhd{3N{}4Whzyc|*D_X+;|` zjMH-K@1!RKueC{bI^5-Pl^5X)QqA+t&gV0YOZSa-Hz`<O$R2J}KUviOL$>6`M)2=A zFJZr^Z)Ns=qTHMBCl{#P?Au_ZvCl<D3#gmqr5YoX`)HKroS{b8f&N3q=mx}*k<TTa z(Xf|y{*3-rx3j>PVIH33^&YO(q1Axi?%q@nT7&xpd=CqM7XJ$WYUfm*qR4roi^$k= zWUl@08T)HM9yO@nMhH$XpN<srWM>EY7*Ze}?lN(k(KJLa{8%CXO*~B8VkroWtH~`1 zCiZ8yu|zFZY|I?|NB6Ctuk9sfdk-mre8`;@lzCE%EJFD2J9g{OhZfpn*hj2q`|NCb zW+v1(`@*uKjWlfjI)u&BQFt%q>k=Xuf^GsK<A)+utyp&7LzL3w<FZMqMwu&lSy!nh z`b3LS*lu3%5xxwU5eZJoAtY+pNfD)qx8S!uWq>dFPp);f<mkaM?l5L4i6q<enZ<8M z6=9bH)fWu$=0&+9_yP{Kr&AmqEEeQI$G>eTRmUMKGEyb8P}F3Gj1@^}_u$!m(CJGM z7**=mP!$-Jkpc^~08Bh@o=MgeC=Z0cY8Gbg_oKb{E{W!Yd>(UD)t!%VG!;t^G&fj9 zQT(d3T)idgGEcMu6Yr@{YI6ixF7oH707YC<xq=SL#RVjBU&T2_D0JXb=+6ijn<$;H zdO9F~`X8<Y9ck@W#aq49EMF)IWPwgQ)(x^}u|Y}l-|`-_&Xgr}B)M==CR|EBu{-R> zIFxMk2L2p4NCn=_9Vj8u6XW@ax?9MUd((u9{#07eb?L}9V)!5T&P+DUS?LyYd|_gt zWiKlI#2*(g9wnIf0+#LE$O#xROniy)EagN((qJ5G?-QvBZ98(u>X~|$=kGic5g#wD zl1OPI_>%)d&;rfXcp2nnu#k9JQp%~;vx1ubHVe~rU*~XB*;@`%xK3;n>GNhH>h?%= zKIMq2ZMw}$@b@OcU4my1YM%8#-~UpMuRy6rj_LH|c8H}q_CJf`e_E!&D&UpD5g8#* zQM|5!T{s8#)*T!B&FuFN0E*FAD8l&`m`@3KTP{h8CAB&lTHC#Sp6z;PO|0EtmRD5i z{jX+nCz0J)=376%-62VqTH1KZ!&GiLnf{cUR6$VpUHKh*QqfwX_wbW&uMO#8qw}({ zh_K!_esod>V^)>3NsgjpPP46j98VUN68{P=j49;vZlbhJ2L-!e>Mm9aPYPyDJeXx} zYR^ihj7->&0P$TWu6EDqHMp-w?zXXeeZE89d@q0@L7Qz0E$E;5fGpt;Tf=axjeCKK zLV~>C2d)>TB0-)xqH%w~<u2C*H>Hr+U)HRqKMQx`?kAPrD11uw<7=6r4fXi_rn9fb zs5@0XaDg=rqBw%FdopZh=+7v^u%3LrzumsK)Vgvon)Wg>@r6kgor32WKdm{mVV`w7 z$52R>n%oJ!!5z=x+Mhy@90l3uL0Pi6tBX-=tn10rqI`MfbS8h>rMBC4VTauTyAW?w z&Mh>rEqjh&c?*k^IE3!8zx>`5T~we_c?{}{hC)JbJtf=AyR+V}{2f{T);HGmro6n` zqzm`a*_xm#i7JoDxJlo!>il&iij|{;60L8^Mtpl-W$AEF{SCDMVL;Ih&E4@IBOiJV z*p0W$$@TtJbC)(Gy!h#mM4{39Q###UI8d})m?lBV(ZpLg_T|FN)1lVicM&Y5XdC~> zN!~J!_nG6|Hh;RN-g@<Ip_ljY`vc%UU!fLOMZ459AR#O0&s}mBd4e}&fp6~;Uwm5g z9lyW*+L1*?Hq3j;gD5K||1FR0>Hb%D0l8P>K4=*zF~E@@71-A36L5BeJvVh1W^rI4 z(Z9?wk*Jq=6Iazx(XoZ$Iv;GPX@6;2RX5^yxe!*1sWnXs=<;n=8>#f%jR34p2U719 zRVXahJFL>Q#0{46Bz?#jQD-o(&8Cdm`(in+K5`I{^Ht+0Dv7w^wu&p=Gl2I{UGG)~ zmo~9T-8-3&T|$#oXM565CY9DDB{?1RlO|c=S`QfmR$g}Fm8n_<hy0fWaDR4|R20EG z7mG*XgbXcYV#S79_nSzPRY4iON4L&UT)Hs2qwszUZH&?_ll57xn=LGLV-<J9R50-1 zbQ6W<OmW>Td)1rB;88N0#eZ}G;6Cwf1-V!RNvF!55kjs##9uf`zAdDs;fME?4=FIs ze?SFK#i*>BVkMwBuJ9qD^2|(jwLK?}k|sOz*4`P@{E8<Pcg>sL+WUVV80vQ$YFt!o zg-6;e?zD@^5x^fy>lJjTRkLR1{FxH_IB;X_7v28t8Nn$*g@joG?sl8(d*Jh~YvVW1 zeS1Aw{mTm#bOXkc!<h3C*&R30m*PpQj{vQe0zagvBR_OmXo1UBRW@x!JG8aw22wR( z6Zr9!z6<hATOrt|qbbZPZ8Xlven;%@K_t=suvAIfUDxN+X&pW+$a5K78ukJF1aJo~ zc54xSc`{?HXKrje9#_YcpQ@TdE{>}#RoY*nqGV9fk%jXRw8y$zk~v+0Ol^F;=I)%_ zF1NyB^^bl;^*u0R_}uHB&Tz&vjF`#|1k;e{*-c<rL+^>e1eSmKyTs2Xda#1@GLe7R z{cY<lz<jpcBpK;`QHUnNt=$JK=?$M*hFO$p?9+p@bgM=LXzkgm-p|B^=BJPK6a-~E zD8PweM(}ayI{P$lWhai8?%$W-8wekMcd`bGoh4WZdbOyql@r)ax|+Nuc#`nrDEzuL zbr5~b)*g6)Fwt<3K%d}hmB3RGR@?JF1@apfn!9J-vkZ`C^(VUZ&^%IQGzo%->6zGX zv66NxGa*B-h};Az8E?uD#Z7{dWOI?Cw~)IIPjX77mc>u*@;anpq_whPj_6Ej0>o^% zV|G~9?X;4icN-7&`Pqxam#l{xzgN|akg-J1eeFOfvng%~y_I1>KG52(sk0gg3%-N! zuQB%DI<m1`ICfQ!T**lF2Af4p-xLS6(1YiHN8C!~rUf_~pR{w=^o0!N$^4p-vc+u( zxpxFvg$I&KKZ$g;3|e?hfvfCiMPK9kptu$0iZY7gF}u%<6HoFR_giMe_)T4&e3U6B zi8vHUiXCR<`El6WKOO8vfY>a`+DawMcchk0(Kn_08?dIIMC0@HsYSR2pL3GWD+w}$ z=x4c!0+;27BrTRQY-E2wiDWzK<v+QBdt9Og#nDt*1Sp=XC?_<wy@@>P`(VT)eF*b3 z?<;qgPHJ`%-BNon_(brN9r!YNV>&xJ*3BxsmEOXW0N0(#^|e<*Mk^tk_3vR$eiaAL zHz%a>_3yuBM^mccJT#<D_;Qh=l7a<AoE%yCR7ON!UN83EpJHhF<PDZ3u72en&NZ`2 z+V}c?e*bLNP6ys=VGja8MCs8|Q(eM@__S@(bbD#d1pTA8Dz3qqzfGs^0G|6M<JlFr zd234!GF<$Q`)nyJ>DW)WD%IH4qH@_vjil~=<km;q8hs;8%FpGPR8G36fOoSVy@vVo z@`+BfGPK?hAb_hsxkUoNP5RytfnO%McT)xoP1oYzw3Fl?e{)=6%)gUR9nm(X6q|Pw zWE>f(Zq)f#RirZ(xK+@^6wZAAqt1po7a7wp*N<Hn#dDeuZb=U4WDy<?y^+APk{nxj z*0wz;yeYYI$W5$ZFwHKZ;?X9BptWmudS9kF9wjlh<VnPtFLL?7<8Dc&^$aWx3s5-A zJF`%omD*FmsoR6;YglQ(mY^gG1Kf2FOU<{dE1#T(?fv?}3F(%$fRl?<jK-+bU7V$B zihk;P*^}&MvNK&#r=pbNXig^0=JR>>*L(30CdIa$8(@Y(nZ%vQNI{+t+yP)bNrwGR zq%i5+v_IpRLR8j|=horOK}BKrz^Bh}yrm3DEf%dGtffl&T8P9%VlTTg+^UE_Zn7dt zjMw!)X3+BybN;x27*Ug2dhB?6)$;YEH9G!kz2H{Cp-j(L@gK~9z1<8wIKfJ-V|JXz z<ru?2qlJCQyD!J={j!Jt`j>QK;nYTk4a_-TFySQ}SORKCA7X<}8Fal#|Ao*d6j7l; zSuQ}&27aBmu3?2@*NK_bmJ}|2WPX|QJY6K^l`Fk<hcL8*1lQx?(6}Wr+h&wHHF;j^ zbj)MNPgPv2qSv4F%J}R^xxy~y?Q=bM+Bn}49E%RtOpoplKf_^bTa47#lGmxLn=OBJ zbs3-W#v3$#VV9kdF}tMFn2YT{y8~7BZ(BA+NE|w{3d+xHd(^A7V=QrLNptMn&GPK1 zY1w?7T0FoLa7oC85)RLh{=&_tZu3dv=U4KEueANPgzcGb{JRA+XCC3FAsn?7IvP)| zcaQ<BXLTlx7ync;&z>chgczr0asvM<_K@Hxc*=3z=3l*9;JrArU3mL@zejggTuA4K z1@RfXx0h1|-WBE84Kh$<b#Ng>2y@{=c!o#{UvpG$pRM<{3T`+QZM=%YQm~=iYx=V; zU6T&ZYd1C|m;i1S<CcF`k2n6#t@kakrCsQxh6D_Q+eI5II1yyrrjz^a+82(N02wOE z;zj%0zz;fHAe%C{6070PzGU}7dUvZ~wsh2w<18#n#?;6Gqm;YV(9h+C+f_)w0unQJ zAKs_sk^mHZcy@hshLgpCH;?^V{{s_T<$Elp*YlJ<0>Pwe$n%h}1l9IP_{;6bQ&u(f z(O+nlQZ0xK1fkR?o!%a5;Hjva{zPygCHrB}G9Tx6`E1sNAcV}1%YHY8SQ)HV9dw2) zG?#Z=lfOe5YkPdU_FWeDXE(hqIPv2GMBVN>N+y;7t_I@WmBk+ye(q?4Z=41cHG&cY zDKk#kq5uN*SJwqcE~Qm!<O+GfsBDg`m4LT>w%3BuCIRxfzqW1eGjN6|RC;y&U=SK| zu2Am%vIv6*<`@8C7j{D6qVLl%mC=`%bt$J*vhtaLFB4=ZmQLciPiBy#C7tGwc6)~$ zLAFu!PT@7fd(o~7yk->r7GM)FShvADFoOvX)Ij`>yGLG7HnvYSR+S-M7^%7V1eOf4 z^6q|mRg13v)oG^~kAG(SzULBml0!R4bAxGRa|F)EQa<k!t6c94-rRi|M~)&C4hIZQ zfQ+Y<za@52X*F5W&_;1Mw8Ijd@8D0k)z5(tmb`K~qk>0*6w!hIUL{j-@T=jY9!vM( z#%3FK60+fd!#kB==}o~1pbM!S+^%+QR~=dCQGV1%5py|6(Tc47Z+R~D*(6Cs0Qmig zy4-M$DW)82Mj20|cwbc<ZkZ9Z9`6y)?!<Sa9<|tdKOq0TxI5{Zxp!3#<M%?;fd86q z%ukG8(NH_~`?$ArB86D_U+&2}&lrVtPC{MLgSHzDvj>txi>+5SofH0gYmT)P2bI8& zlEO?I_66@Mx{v!tv11`B)`j;Qn8seS4k3K+%icjPF|3sx?agQe7CT~HaCm~O4eNsV zYdy`RI*Uylt^Lwp$<<Onv92qAwKDa<HBh2`dk5ucZ#!FJt(o@m_E^V#sqa;0m{dWX zXAJ%i#aRxm81irCw-uKZ7Cb78--x3Vy|whNZ?5%7_fL2Fs$Xl9czd~@^!!gtFW5;~ zzoRlX)~&O|x1~-dCl$%&O1HpV3Vq!ytTX5RRN_s!;y-&1*YV=ERM#)>q{uJ}qolSR zxQjfxvjdvMv^KTiS^&-&2@s@PgFKbFmc?5}1Ao7{-#=WJA;BpS@Hpxd5%Vo2(B_(M z@gvmY?Q|*7&kPjNV*$@A#XiZYK{t5zihO@I8(xm`Bj_Sri?tFm@SX#U$X-Js-0V9g z_@N1y;C9}8!Katf{!{MFpOI8d_DWaESf3H)Sy1)Nw*{Z9hW5OVM+K~z6FPDlU?vIb z!vGcDhh3yHLU0yq{B_SjHvOo;4C|twR~#;F>e@j2&OIEA!j$eX@Np^UL@pbWILW(6 zEh|t^#kBB6LfLe>%pasbM4WH_6S8q~6QMqP{cxk6y%!oXxb)Vy70nd9tPOe!n@00m zkP@So=rT`Wi4KEuqU+CoE$UI86}j&g!Vp_{1SG8F13ax}T!UN_=l!+(m|6kP5{c9# z!I;*&14BZwSqsum11YWxer^m(USib9tgtUn7pFh6MrVE16ipQzRnfI&N^|xEUwjo9 z@ItZWV%mU(2PnQ7lf0I7ndF5XD&E^(KP9jD@!!zb6TlSAU20{>$ojD077IMX$C7jT zZXaC603z2aed$)T=tqK2pN^SVaoYEsAX1raoXA@$V*`JsR8KVXhA4o2Jau2EF`A}# zRdivL$6<iVCZoovaC427nRh<mEwRwq&U6dfq4o`Pe(aJMSj^>s;@(ENb7o%3;9v46 z=7I%C`ZD_TOcuwl3eGwAyLrQ)<y7r2#vgH`=&be^u+XAHrQ@2I@qHf49S>@xtKS{M zx)0}^xF&7)zm6!H=KYrn5AdOy`sMiDNM%;ywZ7`Q;7Av%67P;W)?hE?_MfdsBkLN_ zL@qWpP*U_(D1*A+)s`tGQvBiV50*2qN|OjzhD&Yo2hNj4ZburRW<!lO<=N-W{)Brd zkp`+DHw&G)o!Ru2dv8vZj)fwjjaHs)AE5GeB}-qqORSbOrJC*VA=Rh7F{Ds;J%f7H z_h)?1B8+C$e>%4DC45}Sp*RNEghbi@MMt%+O)@2)d}oCxJi7IQNZ(36_UXiVeVMnt z_H{#<X}#6#b&eoYKh&X2v}dbc%Gdz9vD3uE)Dc`t+S7L6U2Lv5jTS}P^B>I~8a!Q0 zX%>AmdRAgL?$m60rm7vCrS`2g-uxQ9)9kNB<AZcI0SiCF+uGO>OcA_2zEWc^0&GRS zpL&-wYLGQIEX)0YB0jpV3Bs?e1jHS(mD@EFfdyrZ)Ci3D1rc>EhQZ2g$tobxLYk+b z^5!$<_)=HjN}eAI;Kw)l{tl0GDbK2S3>bKZt$ycYlbOb=M&b%Rg!MH`H?3e~v8nDD zCo}NnsE+Cq7X{0hD=k`lVYsb{9pU<Q{Ve6`F8M-zUPX*d)I5x{gKjkdEP9DeG>$Fb zO8vCe%bFXQ$gG8h3@PZ>%t=D6JM2(;`I<pji_dQvWY1b6DPiO;|HuotXa9un>=qkj zhEp4S56Nb>+8qCu#=w@Drz`UCBH<&%_eOLUA?_jWhkq6=HT4M~U)yI*EdC3BII9Wg z^1kWOnkA38;_B7LCs5+$+^+#wE-cz3)Z9jc0^7$Ay&bP6CHme<?t7=y|0h+5HzNz} zZf>KT_qBe;^K&3Ph+V9XKQ6p1Kbq3_1>ke8N1XLF=J()G1mx9&Hg@gQqX4jj8O67u zxqtE0(j9X7;pvm~u410UK7C_MG+5^STg+<~_Ma#bJ=jGhI+yQu2jJ%je7Du^>vzlU zr8~c7a83F*u<7uhXns*RJ!*Buj<B;NOrl4*hXVmM57fX!X*a1vW>YMLQ+SsZIlr_v z;3ka^EdDI>zE6nTdWc(3efK3=o)VSj&b2IyXvGWm8(!Qk)xdvG8_ff=QK#}sBT~Wf zfdJ4Ld18O#<Q^W>5CwOO<vnDtJVORE9-pt(&z$<8iI3p@9;jGswK7(R9ZLMd#{?9r z5Ge1H#oeWXL;4?>HJY;Tpekt@6MQ}F8#5I!QV^0Mix~mwj6hNpp@))v;~sj*L*|RJ zv!=rJe_K8bSvz0V^{APH45=6bbvk5jL+}vN{I4h2VdKbBluIBi5*W8>r#u2pB!DO5 z)fa2CT?!qWnyHt3b-@n1E{M5^w+~&ar=N2Cs_S~MNc>kYc4uwU4yE*me&LXO5%jnZ z7Z;$@&`f~cbZOU1$Yzt=>-7s3NfhCzVP!_QSB&h7gx*c%Eg#JUzhVe*#NAn#-0W|G zjspS(-u@tjfj`4cFJj(b9}BsqWnd9kUi4X`Ey3awxb%|+w~&`GUrx|YdDY-oGlzUC z3Ns_nRI4-d^}Zewt?$KT?hV9`J1nGbp)SNar(YJCe4>7HDf-Lx&%<&;Fk&IA_Csiq zPGRBVFaOD#kERDtlM@2T_I}Xgy4||#L?6tOaJ*ZPNnrl002ny7U2i+|(zkI?B;JO1 z_6a}ib~`BGkxgJ`7pV_6LKp}9a-C9+)9m#GA-TNZ1dQ&bBa0e&(k}2%w_NYBRY7uO z8p~5vjBgQ6N|C&(E~z8ej3RZu_Ui6u_IkI4scR7f*VnSakVnI030V_Tokb+bfz2io zX1GEzY{}{+b}9m+CxEd0r8APd0uac>efh(TZjqmhR^O0*$IKoOUtA{N!mm^O=4_^f zD$ZYuPZklXCsf|2%7({Y9cb&2QnRW|s$9J`tcU3>;pZph!axzd9ceuL83lSI@sEqb zMJ}{keDPuLR6<sl8>F(PW#u&EXvmBhIF43w*pN1GVjFj=vys?DIWxoa7a&$PbE#4Y z-vY2FG>OnIVxjCS=KU;p%X>WzMg~3T$gxQ1Eno-5&B2DJ^u0r1@=SzIaPqk{)$c2@ zLb>p7zi-1s8Lt>82YF0V3n3|R+~CALB=J<)+U_xM(TI#YOq6xjCZJ_+sbh7ck{^Q+ z1GWM*W-9&m_mm!%Pa~59{l~{qeCm#kkJZ{$@C4BW*8Xy#^I&WqAOu<9J*V<OFZVq* zyIwHZf&&z})rTVFkG}iv%s4UYr<B5q0{upEGO>0+KIUWJ=(}O<F)9Q^z+Y`=C!a3y zyBByHuF%hD5Yi_4qpYN?T%uUbYT%Ocj7W{V3c@fqIx&(G`e2JF2@4q5%Ptp|F8=g~ zZH%Un;TAMTG|CC>s?-w$13W=I=^k3zexjvtEzKTlPNqep9jna!IJbzZD52oe5;ZQx z?1WjK@Sz77?)~<Z_Rh)Ch*=sfx~5Jpu?>I4b$_(5o3~v$&G1*$0NdUA$l*Ixh~Z|; zryp-d?<9L&-hDxUP^*iOX1F~G!+Y>QEc`A$DoHC8UD5xDDR|PZHRa8WCvi}sMbfrI zD*i2*Q54i{&!!Zp^kE%(N0Mr>0Z2gqOsY7tyx;+u&#<xxp0c8ChlRO>%N50?RH__; zy%3IKZ$3>y>p~0{@@_f4i*WAde?<7a?4u^9)iU$tz@7AL;k}Z1?`TU9>0U^+Rb-X< zth%6<!QbrL`8?%X&t!u<|A*!=s-+WMx3djXBu|=yC0+mqzXYUkQr@j3^!ai@;uo|W z#830s#{a%D*IwvI$c^{)b%k(53h6y85AdxQFK~1sYq`Z^3`d~*Va47MfpaggCA)=A zgw>s9QT7_3#$9hV$*bC42gt}UpLEO~pEa?u<@8m{Um*j7Re+7rKt_s{$h7NAY|*u2 zpyOQ6>BV7U&#raC#ns9evP+xY%lZ_eJYn5cXJr`Eu{KIWCdJ^ZQOR~$LqoymM)q5J zFR~+gxz&}@xcBVKvZW<NTofqQJSf#VmYPG~ZjA+Pw1mh{lFTg#O6Nd2gO*=5R!7hK zBo}E=Z$x3(IefdkB@qyrrZYwZX{y4#H=re7^cPX+f;ze%qd)mqZGF+|pE6(wi&kAS z9b9;EeP^=<X*gX|sKnUr=zG}&wU?+o<!hpWG||X7XPcO4<rJb+F@5)tj8cwQy$KdW z1gAm|>895KOEz>`l0?nS8?!o!!y4CPY$6{|=2SzPKCk|gjh1^Qm*UROb7ELmefxpO z>#y^l<mcUubpm)n=^3}Fl8-^Dn=}zqsW;`B^u`9r^~iS!BQdd?RYy^Cz)Ui6g<MND ztnxSHQb;BOj)*TcuZ$Vc10;y;3mR-%EVLX2$0s!#1_GPp=y35QA1G=X8XxkUnD(|? z^c!$2xk$|T6^Ijm6bO1R#@4K~!!l1|Wos6NdQU$$nzzlVC)$;eHHdLHtd}ER?yzAH zbq-n~GN^{(+vd~QH=1eD;^ZdlF6+2GE9$*5dy(9VBff4F0;EXSTLDVHtwgf!z(ZP5 z!-F(6Yb35jok8g#pP7+e>v{a^p3}{iBPe<K?B%#qPRkuSGyDV~kCDe7HB56P++c7* zYidOHq<Oy{A2sfY+0Tq5-@uKGB(J1P88xd$eI;W_m@eASe>9oEgTl{IQ>+113rj>g z4h-2|%oP1jS-|#F8=SwzCtUg{UW>47j7do&63UFN6f3^E9G6xgIY0q<mS3n4%SY?Q zNu@>&=OgFJfb>XFE-BJhuHBYniRJx#b`pUHTT^0|2_-)J%&DJ7NbUM()<mw5HWL4$ z?rpG~dDfVJH2!G(I!ItH`NtdyQYTGv*Y#u5rN+ffs^xicQkrUkWkT!v^hoi^Au(~Y z%aCM{-REig%R4&}G`JtJB}d;{Mw7vsB)#i@Iq$O4B@yp11gEudoSN0A$Gpg{FW%N1 z@*b}je*C=9-PVx|vdvqz7b4~c!ykM6k;UpNVh_zKT80&-`@MDzCDeWXGTE*%1<hn9 z&Cn3dI6&raEe5}8ETo4g`o<S~f{vj{(nr4`c!2^5SwxXGCT2yJUmT%6B!~wISia5{ zfOiFf(pSL??Jn|6{R5c!&6tJ4tJPtJv;m*Mw)`~L4riTerlLjjgZuL&b9X~qI^hW8 z8r=@)tXN?*2N@N@$o(3roWLB4#ajmQOt5gq@-?(WHIsKpW8^Feyt*VaxF<o{{DUCH z+?F;_TaNbf<pncl$%d`QA6#pf4_WX2!5o>1AHPdLfIBzqP~p;D_--`a<&UP6Ew@zX ztODO%UIi<gs_oRQ;RVRN84&V_Qq`8bj#h@UH@1SW*6ZQCRl+Xck~B-%_B;KKOGy&6 zG(o6z*S5n)N}=h(uls_W+)6v^z{M*t`dy&Z;<m3BNWVqYc|>R<siqsJX!Vp0Njc~L z*;C-&O$r;?!-mdn<FYLhC8Ex&j1VBLyQ<3BV8TQRyVci*0IiQ<qe9H^(k88x0BJ;= z58;b$=o?J4Wu~G>wfXImk2Swr{caNvASq;?U(vmJa|5@!?A{gkTA*nIcK%lQ+&R*) zT#vi!kJ=WVJsHF1MkV=ygg^~N*07R-LUO|yLt8iFG(80?=F9s}r~KD@YbV@WYcXQ& z+YSS`^Ldn)JRFmLgHrp?#J%HHRUnp^Ta8s6z4FFqZ@Z*5@P=7mmvz_(YU9U4Fi!nt zc74v!pUg-Q;GWa3>b)2GqWk^j{z4d41n+1)j2LoC0yjs{VPa-blW`abhXa+bml<BR zNg{~VDssKDVfasSnH#*1J*^($%pQJuAK&4<pO1ngw-j|24fBl$@w0up@y0w&8CdpP z3qOVF`iC2w^z0N?2TK&Ks~};%tt6vOx=3k8%pT>TCfM64Mc1;9-*cHh>Y9*6^?ZvK z8;8lr82c+r`AYWA*-4vfn|g8&ijY#Z2^LcR-r`rDcVpuJCPI1Fh(FMoG_B)|4oSG2 zdk98wJNMuby$#|U8_!9@Vwmx)w=^I8o2w<-?*gD%1KNnYCDpE7JGeP=MRU9GYV|Dw zJfYQeAL}N5R7hZkxN}sdP7Ru3!!YTpC15Ql86H=~;JDIEV*D|N%9XGNYVDK}_6cKB zkn4ojk~?#1x_XX`&c&HVIOlisA6sqkDa2nathZj(wSFtXPbUiPNNV9ibp3Fns+4bO z6<vqLiue3*(~P~SJy<=bgX8IR+ZTLkw$)$(tt0Pr2LacaW@HRf*?DyZC?4C+a{qwD ze#6r#Wsezd>PcrYS_+MX5qBB@2a5L^US>x%#$M{P!4Edgy;LhLUS#Jc;d$pyHzwU_ z>$<RHpp+VaBs~tHJC95=lfRoc<WwbDubyqbbC~uOzgBw95(?>lpQVH)T_NiJoQS6s zzR|7A6D?cIPpd@T?^f-ytnd@5ZbMrWE%^Cg#XBOO0Bo!(`@e@X8zGlHt;i3teZ))5 zXcH5TL=0;5)h7RQpeTV^%K+jrFQ+zQh!vL~q4;r2?V6o^Wx3;vUsKgp8Fk(&lm>%v zl8>ECGH|(aQro%iLj8NO8;4*b{_@btMBU>qEu-P<?{^9(E|qKl-O|}Fjh1&})O3nI z&l0WqSs8rvr`_2P()}cQ{*0_Ebvj-5HS@^#A0Jg%x7(n4Y*Wsh#xHRWoVZ>3@(aGs zXg|+-=%|ehm10xds%PkZYqL);^G=Lpa!eM@cD)lF2iDB$AK;K?C&}`@b*vSTjh7Xc zwtsiI`(4%Zy=BOgJb#E4V$NMP7I)#ebqe=QKxKJp5@k)Gt6IiVu9dY%+Lf*d?OXGZ z6P#=Z+%do3rq0(_NRxpj)v#RUWwGda7$Q{mr6DvoWYCp1>_~iz8;86p$yPXqVhXVi zNqt_?91r$`%^avoig7rUSW+E?qc+mq%1PX#@#Q5|HnZ}<v^`D;o}%ZKbEBN7Qf^Mf zGyJ;O97aMq`^cIcDV!xr57x=xc?)HpOM~?PWAn$Wp(5hTiemcL9T|OxI&zQKP&!nL z#epf!>LA|-?@+Sf4p@jDD7dmTrqr14UGQe`bx<ZSDMShHv=M5F2Bvdl-c{uSSGPS> zwH@o)eZVlIW&>3002B2YF6%*Nnktq-nS8G`K_)j_11j_e^tmYsOM9s%DA^e3-GK$n zrEwM?@Y&9%44tUxc`YuzcQ2q&V!x+guVB7+nqkGqovF2+X*H~YVE?XKKN}64u7w~F zu#h!NOVG3O5xFp~`$V;z5_pX{m$KePR>{@n!g9saT4cEp6+VQg5aX8K=bVBjnIkAX zVf&Qblyb_1*b4kDKP6M6^~s`TIF3$nJrnmJE9nJ16N!To5gw(wV938Xh<y6OZ}HxE z-~oyvy8;%HTi$pR5xrX4Z)$sIOu-v^;;Suu1pRkH`k_a!@Dy{7S!=Vto$qa~lH)2@ zoyhz-dY07Y=9!uu)mg~#2=}xjeN@j_z-Rg!C9kNy@TO9d+T}f@)}&of21@zSH~UHa zseY1<IeRc*{A7mNZat{uxfvGB=DK<}SkL{$ag~87G*g9@xw~rj++$1JylzK%1Rupd zMs@skp5{P6QoTZ|&3#=o{i5bK9q^HXMtktdcP@voc5h1iP!}&77jSVF=Y7&|mwu|@ z9V&ZFDsm>U#JtyzsyV3+L4v2~*Uy76aN@|7n%|x<o5?>u>7W_ifWavma%rx;yY*XH zPV#%oG|)J!e*JS_{lb*n(+-5xl|4l0a-JewIjz%Cndv23+GO&51?8eM-{VEJX5TwY z{A{k79oA0>E5qEY?boV7r+#a3yuJ@98=6bp{$pFBsvT=_EArbMRj+l!T<~#cgs{*# z69(@!H;4kPbyz=5u&J{WX^G%S?>`2$wuapd3hIV`jRmV0Fp0~IK3%`j>r|lMT=i>P z<2v?7LKbt`Q0Az$oR#eL`hm09tDUhF4|y4J`~1zO*O$@eD<P7w-L!%6V4_aMj*RH~ z`sZH)abZ84!H7ui1`k1A-EVF^V)iaxtc*@3GjbOCtGO&Ze6q%IQ+GnW;lVZ^YWq5v zr=n(#YZdfyX*pNHrK};Joh-jESV~pr<DWoz4xGc#FHje})VqBW`2tyO{^>qC%HmOZ zx{lHFl!pbjKRlirN9@lgx@HuYo|1W0-w8FO`k?0*Xa=%{DRuIo)w5<?>oGbq?Wa@z zOKOXYNhm`0vRaP20j;AzT0?Guy|!{S9r~kR8T#8W!jBV|UXc>)nayw9d;e!1#DwnA z*}Fc6+0m~~ZENd3DkIwt2|pMezW)XQf<LCEi59$WZ9x8V)th*k!poEbjZBoto8KN@ zj~yS;B0t`afSG!7NPPMHnCcz`3+2k)JKbVD3;q?{5YjyNx7Q63vpEqL_{R<X#fc?U z&BWt8<DXQwu+%&Z*DZabSo}DJ0s{m|=IcM$!G2SN{@dI}uIBX)-&(Hp%-TD>w8B1< zR0mF4wo}WO4C=2hC6`@Wv=ic(L#g=e!Henb6^Bc*{ENr9Uxk73hUT@YvA}`&v(azI z2dYpZPK%s)P2Ps~m2VC0Y?jk^LOVJ=yVnk+Ti)|~%oKR{NVlLn&X40RCmVeU+vVv# zP`nW&z~{`rDj>5tzk0E=1*_z#Aa&%MY*5#gqD2`a5zSSz225Ul7F&g)Xa+KL)Cz-& z3PaI)aMZELUgD#cX@5yP!_=NNDe20$46b$0*=#n?TYvsV26<I3hD)oF+lk%@tgmS5 z9>&N#c2hp*gi0{GNoILU3iU$um=G3{x$^sW1ODQBV1UbPYjoyyn$a3_YVA`h2uJyr z@iprUZrZcupyogj@0Y7GQeDL1M#K;tB979Uad#023RAY!@hH)LRe2!&=3GN~NWu)6 zO|z_7Mv*z~*@)+dzCI{hYLhoxs~K^q=?48I)(9JD-o!DK&U|IN-0`v|u~oYFO^AI< zWMNhR!rW1&j9e~i&_NJJ$BuvmPeup_T`<t7+IaX;pu*X<vY#YR3R9}sdXe#J@)y*7 zuG>qdNn+uv=uEZspxWt#H{Er<*SO$A?P50^SNd*=FVTVP;%8~)j**f+w8KXXQ2=f` z)b!Qq?w#fXA#ozFNup)kFNbmoe7cC!eCsOs3|4K;mC370R9QJugQXVnYAEiqN3yYf zMbKRtxy3()qs|zhhv9{gMNRMM_tpKQO0mM@n^ju0Za%faof^=}L4MTWK*}u?_R0AP z8{YpsyB0aoP$7V=w1&wOZbgXWjS%Cla@7QYfQ#AT2;mw(y<e+7<E)L9QUTd=_2xpN z`&E`EU*mrlr$#eP7yf$DO-v0}_yok0iT|NQa{ivxpTm?gl`2;l9z4Wt+BBbL;n6Jy z7M`w=a@EyBPq^_CSYPlRYWJz-7CRcBOolJ1=wqWso(M%VzYsyS0Ky@(Wshp19a)g$ zDC_xPuD2GAxh$G;=GM7@TH;`$OxvUe2w{r0=x(|+vHhL7@QJ3A6+JYHn!B#>Hoj&? zyU3gKAdXJ2EU{#Gh!?LKuh-*U^8p88?ogHqegU1$i>U``X$xCMhR!M#tj5uUuz!~@ zlr$boGcedOzW9aGTth9?mpk;zW=UuSb-_9vefjiTf9Vm_I5C&_!=Q6AKn3rd<HimC zs^3utd%r8o_3huRl1LaXv#O}+ea?ftEHmT7W006wvOOh+5cDDRTTY&--?{H>7r%Lz zj4N_sWpR`nVSAx07w3U797hFa10gYe_VJr`56(U@!i`%9=2vidm9fbDd&4moLYsVS zEtNdb`%*h|A!gefD{{t&3c0v`mR6`e2wn-{jSMi!5XM#nz&Pd;FpuC0ea~d%tYOm? z-rP_j3}~o3-5i`3ec81c#mpWar(AKOuTu6C*l=X#ja+!~=?85Yw!YpfsfAuM2UZD1 zL#NMAKYQV?)Gk)J0y-W3#M%DRCHnVjJUq|qv=Yu5?_07z14oF=Zy8;V`+KWvgQGIj z0C6o|18CI7mjhJH=%}zZzmkAFrA@@dQ&>F=anuY0Mmut4uP<cadfX_&)}$e^LaR!1 zir#dJDCQS-=$T=nQms%+W0?Fs|LNu(m^Fyq;Lht~a|RoI2bj;&P9S@{!)}jN1i#4q zqD2vM;+s14&a&UxRk6CC*<Y`kqa@NU*dNV|A{<JpzjAqvA?fm{BTw?L3wABPA1Pgq zVvD&8w)K0dRP3}no4DguD_Uq8{%jH}^o_X$3i#?MDiqcm`$JHtSn98o@fxp(D-wnx zbm75KIfp+1AsT=jLcVLt`wJHEPLNpwKLLI6jCgjLVm|xT;HDU$0z!Cz<Ju?d6@T)N zG%={@Gscjn34!bWaj8zD=)khwvlsaQo@e=}k$W^TZIp#EdRI01-p@|h|06T2khQH- zIlc&#Ga;A3wk<BVpS;T)T1oMqS}bRJi)+9r&H1qd-uu_0EQp$q1~$!z)$gAfrWVEx zyBQXf_VdBbL(=AIg2$CB9w4aUp;g28%iREw<K}OGz$j|oIr>snyI#fL!XoDbAQq=b zgCrJ1gi5G`Ay<$4<q$|y=etm1b(nu^{onnBmzCiRL}N9CXY7ZOYu@-1K8v@Y{2&rc zloUMe-z0(5u7979+i#COiw-<Lq~3VV@?ww?pLIu$5ymf(3Fd<CdOqOB@pd?0eKED% zb$Eaxyq!6Oa?Y4<_&qQ#rGPulXsblg`B!E}$s}h2MZYmlXM7moieZ@|z#(o<oKpGO zGc-{+Sv}vkWkG^e{@a{}-v<o!(YmFIL3c`*Ni0gAp_smTZqR^_i)+EBN}AOS`d>-P zF0EfgSKG43@9p`%a#*DL@;4LESUn75ghSe>(aQxq55#{qBT@7DvEVc}BJ~74Lzf>l ze-qLwlp55SJ5Jq8?f8<poN!DDjPNNOi&P(8hzBui#$qi~;Zs5tNr~wIA!L!kb644l z_>Qez96ow<*rMk4>~OsbkflDWA}E)cFE@bxBf<yMB7ig_P)wCk+lTOTUzs=SZCg(> zaN4I_qIA`vE9>&Vc$*H?;j8csF$Bc_O?hUsgJm(g^Z|}RNQZ&4zm&fnWLn49!da*V zP92LFM$1^?xo|9qJq}gSv!DlBVeK0C3^A8=-zMQ5czzL{8E?)La!kT&A{>Yk)IlWR zbp%E3FS*g6Hx=?7t_~ycQMl*PS<Zo&HIq*_6pY)xcmGlrEREKz>-{;^k1ys6sQq>t zg<k|hH?R(^;wpDUTL{MBs1E??>3K%21D2KS9r}|oSDheU&~Y^ft6C!-D97PF;BW4s zlT<ZXJze(a1(E{}oHG|B1E;BXXSX8o0gqOo274@`3*OZ6>5)Z1n%T<xUfPc|<f6@B zLJlp%8wXUYl5KCaLHcc?PSS6DugXRAzyAs*QrJ+o+J$vQixnzSBeT0o`^X7xs_+5r z@rGQ_ufpl|<O=^Pyn7cI(Q5e%5!{FzGNoO-GVYFd`_Z6FbgV?n*YMV}?#-2E&pNk% zW8=;FuGlp$+^snld|)p|3~zd`=`;R!&9bP;C?jzs5AJM8r!~w*3_-p&|1Ton8^R@R zW^Blxh7YI`{HacyPp^F|%w{2LT2y=VHhR8Wu;@v-q#5z@a3aPOJSy|X*N>0Ivr`&@ ze4;H^nZV3%foKc-QxTUA;8WfHpNz4OlSBp%m@81D4n5S!w&=jF|1dW2Egv+wE}9XT ze?<|%26-Aaul^Wqh7LmL=;d0eD^-BEFbf1@BUv6kvS4X}LJZRJ&wz@}0u_QQ8~ z4h==NP$u@<KalYj_tmg&JC6#)3Ku&W;oM&5lZ*8g_>1Z-MpZIKTi{zJrYc{%2w0U| z_J?H0V}eOh34std2p@t&upt-Tavi5ECyMg=(t1uy4Tr3axA&$nO~>DJh04EX2|Bsr zpK7@YCEm?`!IFj#m}deT2~L4Vf{$1ppv*sgFvFWgT>r<?RmVlybZtPoyJICqx>*`2 zY3Xi|l<p4cT)GjEW&ufQL4gINVUZSCKv+VSlK%F2f8YPR_spD`IcH8?7tr)T2j1$} zYF6QAD&y9%`7f6{y`tvLp-m~ry_CfJYhc$G=^2Il%Y`R#uJFDoA6ZG|?y${+y3IW- zCX@plG@BIR2OM4ZWeCrOfC~&S_!AW}$=jt3<FYJ#BZBzqaBot5)rq^&O%X(W7=0O1 z_fNw}<+SIAMDLxK?$eI4ng7-!PuK$1x1gjD*v`(~irZ=JSUmnm=bql+O4<Lm>O^V4 ziPc-eG!JprbY%`t9%Sq^sb6Rz?w)RoG4ONR?YesGl#1VSW71{FVb&HiX*%)w8U~#) zyX=pl`<7%rYcDps!BcJL3%<ak7@tGNAcYe{gGwO|W^HDl7cOG1i_=!hv}Q#8&$LAl z84^3!N=Y++fb)`zkf9UekFIuwO5S@2x%`6Ve&z6+Kyk(kBmqL8&)JFzqZI&od8eek z{b=W1?AHY=t^(N+@kgJ+92rWD^)9*^Aq^72?^jmJ><#}ea$$jD*0#L?DX&Rye=bGw zZzzQaXmEu`)M;-11v33BM;6Da7HwqLUxS)uyXe93juaO^I0W)Uyfej;r4~3uYa)80 zAVWMlX-+w<Pw1RA=}<{1B&Lu5-!^>tp({)r9d;f!d4lHxLm^&ZN8o;6o-r-jNSljN zdU~jbl(l9`D-ybA{>~zv&zAt1fqHu~*5N(Ed+|#*=e%E^5qqb*k3+Ae%P*(8`%GBI z<|I(`5{p5)kle~E&zgl6!C*tmu{!<mKvmfN#N9RWz3iEly*9&JxKS)^%qP651k)*$ z!L)k*oNM>@+^A4_N~?>l2a5XDx;~0Oh5Unv_p>ToSUq#9sZT$bvUz(>?T!h=QPonG zwPWPJrVcveucTN<lYf`I{%8V^Sdk2|@347=Yu8GU(&8|RAt3acQ<&^^=4*?>cQsWI zQr#A`BjMvA&7Q_@MdfLYuI_Fe)Tl!=+ZWRB|AzEMpBAxfl!5e^Zk6FzowKG?vEw`O zC#G<Mg5t?F@q9Y~KFTv2$dQ4$YtQ9J*I9P=7VltAz;8`Z1kdwOsGE#w;WodlSz_Pu zs~HZIK%&Gx!60wS?wYm@G~B&qLMYNdtD3EuAu)MuUp>^*H(4jW7$(;TzmU5WaFwpR z0VUt)ANxlU`L6~KRA36<Po}Ht!9Kg#-7U2~1a>(khJN9bCW^fIRmEBNSxv|G_-rNE zni|VSOw!`x$gO3lT_dA12i-Vwcz?Y#8E=$Q9>nJr72euk;Fyt{rHanQ?Cj0=9knvm z@sxPSvM-t=4_T;m7xSwB^*y=?`xD>lp2@g8o_CE6x{38TEp~$z8>p1q(Pr)LX^eVv zkc9v!T@<}+2Fy1d&)l9pEa@pf(j~;S*TUSTE$LH#ovcU<25NBCLs9>nrxlN9hkBeM zsiNEyrPR#~;C5E&Pz%iA?0L(h7=hq&_4IhGeqrw|=uV*2fg^JLvx5*eus|#X)zjQ= zwaN76+FrUP6^Y`=OoZ3pNp$@&44gbG^Ml(f7-{e1E+g7YagaLPQ-PTZd@ZzfKQpW) z<HaoNY@wJ90Ym6WRhY3NZ;4dk%w$OYIh|<UN!mTg%qJofyc?|Y<S@8Z*kx`M0JA^Y z#|wj@PzTqVmWeIrzeif!uU%z{2qz16^Ha*ekWS01ve*ssU<CuX;%(o;<Z24^P7`>C zGz(%Nj?3yFA?u(Qzk}N?H$WVHqrOrIUjRPRsnCE4qp?r;F&e@;!J$-7JfN{ZELf3$ zdLK33M%DYF6es*kl2XOl>MFB1VM*5tzH#W@k@vWDsqA>nAqzxeNHAl4q5^RoXz*6) zenrNUQz7~0@9ScfPLW3cTNpIh*v`Vg+~if%MbV@D7dn*ZmmtSC+fEE9%Zg3eZa1Ki zx^qzfO29@qr6AU7IF$Za85b#x-#E<LNa-UZ$tVYkydVFaoc}mbbQh8FURMcUpT8I@ zz6N!jLI@0mRhA@B6lGmCvV87okh|yEY??PU?!L(@TiNDE8YDKSLl<@?R%B<xc&+2$ zbuGrlfRrC`SbLd(AjNA1BqE9dOwC?13o8y(11e_k1-9_|Dru!Uffc8_VEM<GD03I{ z<gv(exsElQa4}7OmRF6wsB-$_x@G2Kx4im1_s8Mkredk`?-3JLvcDfIku}Z#JzWS~ zH5{N)rZ@VqB}AK7AfKDJjKiQL$dM#4Y@h6JBMDg70U3z@cAI8imkW7hI96tlP~4>- z?w&mvP-Kik{lxy8hFRO~o(5^bV4UmkxhJhdUBi_@S?{6SMY^goeS40IEs!dvxK zhL~Lo=8O5QL5M;%wBwg%;!k$(GmhQ@zQ;%;0Z%bxd<S_*knu=nZ3bxmge!Bpo-sW> zCe7As#FsJ=xZ&PSQXgpeaHT3;Dhd*huNYnfIUo#x?M%q!Q`2H8*cO_@S*V)7r1w3{ z-)w=}27w?wB=0B`RdMrRE;w_ZqFZ=v=C>Eh^yiH*ScSo{C}LqZ&N_4u!sX$^-@N=q z0Xg<r!($3rHwjRR5GBjEvkd2@m7O!LhitD9=z<Ud<SNlfLq1_ZHx|e2dzY<{Z7+VQ zYA=<gU_DskSQyN|$?UH+Ge?Y=!!)x;jG~Ma01>eko-3^A&U`y!+jWZ{x&6|8HGKaA z$1TeXo4_R+2k+e5r4vW$V^L#%;{Bktna`vy=Y&!8k+kP~Cyr{h+~93jM%ki=DdZio zsVrEpd&IBYz{FK<-z<TAADkr*LT2neF~1S3O1=j>>JBI}0U4TPvmqx$c};CUkpbMu zQk8aGzo1lSi5J!h36seDOQJIKP5W)5sqLNhlEhZ(1=D{?uz}=_&p$tYm2$P1{>FDb z&DR}7o3umTiMlwOZX>M0Bp19KC{=np8h#a1+D96Kv5Bc|BA+|9Bt2dSt{(ML2Pk2^ z&Hi&Fn`PC^s&4YE^7ysK^)V|D2Dr6Mr{`-<{|L&%M>IClHG^cIp01`ukZm?x@Q6CG zWk>{7hHOOU*o<%L!?pz@u-N;dW+;>?$PfyyftH1brL94qA%K~QLf1WeF>@q|)X9P) zN7@<MEn-ectI084iVL0#s40!zU16D-Fm-Wok+xtNTyUJZwz5;pyilY*wViQ=nV3As zsXVdj#agwgl;(7hz;-es2-D47`l(<a19w2rnbOF)nKgng&V@>6@9zB=yNya@h5bV5 z?glh}5(lIsmiErfmeZGELSF|$gjx}KlZ-V=^ur2WUpDdG@@~97SKC@FBuI4~6!vk9 zH%}%V#qAjOxG&$8Y(`xFox1l2`{X?Q{Cf;?blAXzHK#fC&$Ect&;I*YE`$|!lI~y| z_f;}m49_i-6^t|HY{%GcmB_;vu`!l*@lYYKx_4ELKoYnmop^V?!sNW-K^^LMPIiSw zvvZ}+-K+|aSOO=lQ;*$0Els)4Ojd3%4)h=NyI1s+J4QAIZFZFAU~D`95spZ}4hC4$ zhqY}dw~xt8yRII|`m_Ogj6rDLnK0}=cXH$F+)eZ#kz6XdO@FfqA&55?q#*~?nz?et zcpKT{JF4LX?mHoQ{g&VvS<bF!&a7PxJ-fPVGrkBY=@{@FVapEyBUeWcyM#paPO!xL z7+_6q`NNZDD)9gZYyRN17qGmX=un@IbQ{ILrWwsnXTP9-6sc06hhHbN-eY()8)R_I zfVRL2Pc0#BbPQfQQX$A)TO1VZ2nVZd{tinTT=LVS{6O|*L4VJ=+)qww=f@hHu<0CQ zZ|vfr8mxS<8XXNrYs!8gJO$W<lJ?@7KvN|F1P1D&l{IX(MY(=XWA#2Iqk<notcjtv z(Sj%lm&mBkU%vPSUT7rtRi#<Z-_0?EZXbXPoMiic-5;WGzeX03;5^Qy>bePWLRP%c zyhnfHI@uNb>dF&T%S@pX!<;bjIIDeTy6k?U*f@%K_?KF-7WumEStO~gBIXO&?jp*6 z|9wtsdw@B<*I2&W!{+Eu#8uM<Y>R*T<4Ygl#0MD+r$~!PbJh5={Nc<8=KC%2%nEWH zs_1G6osvd0F9*ZkwRn-V^GHxd`xwM-xzFTyC1$0I(x>O1)}U~U-%5?75OxOS?$1Gg z@JWc!QB$_4K8@bxJ5cQ`C(}U3KknDgwJ*A~5~fPW4P*r*b{G@-7v77zW)n1tbxK67 z-&A{;v+ls6LC|fmOpTkc2j^1Ic6IyrkE)h0T%o1M4UBAcVJtS+3Ut#1$FtJY6`qmw zB{u1C0tBR=?hJP-7#w(LxtJkrWWow~&Qsmdsi_+Y&K|iF(+aJXqOD6`lyY)E9J0Ex zid{d?AGm8&^~;Wa^lNWW;1*gGwh6lU4d3+jUxeh(_BhPZk1?#`Al~rGs*Cn+zzxOf z{6kY7dLI{#0uSP@LR-y{0+D-iMF(~SxG=O0SYuUNspwH$?7fpCfA^*kf`*~gBET{d z9}*=Mxb<Thny)*qbEL%?8=Xb<xEeo#@M-=>5c7Gyr^B`zy&LE<70LC9bSO7f_d?!M zzC)fsnUkl$l&K&Q#-OIzkUwuEj2|6lXWGG3(eI#V_rgs0S`fnaes%}jTX;i_qwP*8 zBhNNXwhG%@#70O$sr(Ei=E?9nm)7d;weHFYI+(oy*x5+B7VU*U$9x?DR(-|IfIZ@e zf;m2JmOW1RCdiMwc?26PpiV4yn_}28V~tj+vVwYy2s+VpwX%4ZcP~?6z(MNY1bVUh zl_%DG#__*Pg$<K^Moi*C1{L!j4&kMBevbvEQS{t8{Bj9CFEJh04X&;EI!(3Se|oI# zM3p_EP4gIYiXS9Xd!$V$N9$fH<AI~YOly_g#8flcRh^>?#r2|GY6YTwGK_FlKTy7A ziB8|b64k&6iD<>4eDtBDqh5E&Fxrm{jHb83ueMiTx8>QWOjbk(774sM`87TTlxoqx z)|D*AavuIg3UgEcZCp1PR`2}f9R<OijK9c)lSs%Zfpw4`RmehR2I7r}gr3m6g#UeQ z$q%mwYcLb`Me(Leco*ZXSjZ_0)>pnD*zI*&BljOeSD4i_)-WV#ODjDT$yiYutjy9R z6fbz2dgI`#iHd^4{4QYlLg4R><s5x+`kmeY8XgJUEnCZ9j34uX{2dO&uI0V_+&7hx zOn_=)3Ws5BeT@JH(1u%v9ieP$S_LTMmmQJ~u7$R{9b;s;%Kyv|aFU3IkV_EACt^p3 zLh-MgP6W<)NC^c!<}=1u*-?X5DMP28v=?t8yYVuwUgqvrwkPp>wwI)utriucKFgv) zOne2?B-`;|pk3{Ytc}x~r?w48FxjfT_*Y)0R-~Qr`@S~w?{Y;eeVwNUdcL+gZvquB zp%-m(I9kQ9d&B=T0l<-`{6414+s81Od*-53GduqlQ;DA|NLy|iuqZgGRB0V!F2VKX zngYV%!0Q4S)wribw)!r&J7T`|q=6+2Vtc<CV1rayHj$xjBey3?!-Qvwe0Q{O4!`zI zD?03?p_4`L%wCaUZFH`&y)ACxvPXzGzG$zXv5O7Db3&HEvHMk_SG0G0@$TXvFzo?# zbq{nw>HQGHFLNOBpRxYne?L6s?#*z!99Fckjt2W11Z+za*AYq0bq>YefF<vvK@w>b zSs@k)=C8|L2oc>6i^f844O!q`<17b1ukCwC)o4YASkkGzKUm!20kB#+V?rf5z~SFn zB3{4}tS%rcHW19rUqA?*Xv}EXv+iU@baA&xW}}9DX=iM~o#8#x&L3^f*>eWWt2G6j za@wP6h2odZMskEVPZSVf8dKwyx}FRYEEaJ4B!alLffs+6>4mnnx}Sm0HjkkNqNqXJ z#brZDzlT@bTu|E5sN}T#uSDa9Vt;2yUedy{i44Ic(j`7j*xp)wA>1*14qtoH-nO)8 z$xjbb(C&6c(r0ZrdE$E8+lSP#Vz11|O-J7?0~{q8<WGS>X-c1rT{vxlR=b-<;+e|+ z6z6f0`V1!o{+Z`r;o}w+o`KDAhi{0dK)veBm`%_s4t>{WvD@cq`&DvS?TyUIRtKZ} z(^r(+t^mmnUe<^)TA)~8iPO_iFErwj6Ztawyfx5A1{*v>y#*Yr%gf|{PtHpC`W+!h z9O$=ci55f=obP)+VpwRS9^c{08?!EHBV&y+IkEZ=_>Y<u^2HT5`CrY3fq@3jP|lTq zxAl4zK(^*`c!B`1?4tkbk^&-9Nl8-K>G#F8Uv|U_rJEYRFtTKW+0~7d1u|pl5u-83 z>I*r%&kQOP0yj2&VCh*3R}xI;bufFoFz?JyXen|V?TspGH+!sRFCi{6cVxHDt@3O2 zh!g^95tG3P`tMqJq&}SAo-fzTY=a`WSfAaSRnn;5JRYQ5utYo|7x-LdwTXU9giMq- zUqSAh;Dy$~R-XaQ_%zYt#~%xowbl%WIvrg3z#y)P>Q=nYBztfFLJ6Cqd1HjrPdY%e zo73c>lLP^w!&(FA^NDguan$-)D^`^bk34m&PG?qd!J&S6B~2CNlV8^A;NQOY>_u|C z%5yTt&$uv^#6PTP1jlL6Y5BB|7UBb#-Rz#JcvCpAOZTWBG!TZOmjaJAnV>%%x&7CF z#AoO>*6n674|TZY8NNjsn08`VRX#I3%LUSCa;IxxRxbTG7N~gVLHjw`#P`deZC#I^ z&3X$XZux22j>jn`*^noCJ-B$e-=K<??*)e3bA|<6*1_R%=JH-7y^N<>fFj+Ta=dx< zn36(E3rP(Qe8hg)<Wg}3ab6mqIA~IpC+rZIA0jKE{itMl@u!{*!g*$U`Dw@wzf{a< zGS8f4`In__NR|4B0%eCnWB-Ki7#GuEPWg|n4tRP!J-^Vs=YEJ*6>W^>VXhiCkI({1 z<H~!{5fv^a($E&NATZjScp#*KrD(1|;(FoByy++@%UFR}Z;*IEcCx$7Fh#?U&W!37 zxgL2$`4L%LL%wC|3ta_nJ{+XTE+|3G^3z`H<&UngLlSVn{bhmE0WA<`0C2a}40<k< zN4~Pr5XgEn#f;|xGz5GR9kZ^!vElaMtMiHGQp-pwFRfs@e#&)T^uVe$b^&{?fY{YT z{wB~=Xs-u)vd}XyN8^e%3EflIwtN37(q0@)3@>gk-D(zLO*Qu*?kP5L)6UQBSHG8k z%0~Lv%_{8!cB%Bl2ZN#7NFFJN3`d7BVn~GQ8H<&)Ygq3engKJE+mp|LL6)H6&`m2Z z3e{jTb!ffe8B0VcDe|q=i*XwxgEsh_09|J6CYAZ`<=J%(sXI8h5<#34O5hpynbE-D zv?)sthh9EO_y~BrKhtg1*v#qW*Q@^YG8^2-6A{FJ?oB^nD<bu9nFuw=@s6m%1M{}0 zr2yc&MrNO3Rg?3=hS7l#?mXc7=w2oh0)T9tfG#jVL2bzAjVzw`sVT>}(K4j%sVK>H z%jCHjI%Aq=0WU*=otdy$t()R%7r&cfM0!QYSSISN2MuzHX7W$}@*^LLLNK})@7Dr? zU{b#bw)>PzbFPRYAC?ENAZ18r=)bijikjQKzKa$?gs|Pl^uX@Z9N7jB7;ke$5TPx| z!Id5nX;bdv#OyIrT&`r0h=VFltJ83ouxF8Ky!7H%RL-7ZsZvZQxjBCFRs#`ZyN)y3 z|35q#lJ0_jE_hI-S32}X#+eL0rZ~ssmE8c+DRa&9*9OZXkA{&ZIK<!!bK=J5B>&#M zwa#^GLovx@HTa=X41Sx-bDS}OtQK8rLqIwO_(`6ii7Cm<`O&^>=8JMuMC36FkcsAi zF6J)RLl&vr%EK6e0br}3R8HZ6$K5lHFY=+xE`xnS%#sh_?Q@3oJf6~6pWLlglfQdT z^Yfq1ub}k?PyLj2#&biLYptU0c1(@%m{Qk^C9~(=%dxtzsfJSCD;=flDo>t+tYfsd zgh@V1#eC*`GdCc|$C1r$R-m?m4t3Ipzx>S=?mGBApSwNl%#~F2h=dVp#}t8dDXr1m zM2DsSvQG#PS$*RP|DfDbNH@E`8F-#(HMp`N0d^!q277O3$?4iWWk!M0xG-_oO89#g zkDYnVn{;0a$U>$R8q7j%VO^Q{sUq53=z*uAJlv)E7F`C3{#`u7q;WxQkp{V7Lu{~^ zmi=4IZoFslW(}+=_H70<*Wdk0C<fFZX6Bi0=<R5q(uUK~fJA4PoFYuM4RQmEo)v(A zQEL~K{6KjoEQHvVJwU88D4$n~SlL6?EbF1}re`nDOkT_L><r*oYncaasAt4MFkMkE zcz9p|)3<4fu8DPKF<mP?C^N=pn}ougdcXB_n|MlQ+?R%R4`hoizGr=%@cr9w;M!$n znVTEC;&-1vtrUcmt;t{E;F3nAUySeb78-N!L+M}&t#36evJP&4i`#|KhD98eGDh`S zv(|bMV#-m|8fqB2K@y2AS}vSRH>T|#^_3F}$*2^<@+U9DJ_{YP^x?(ON0)|}nx-?d zJ17Kq`D-$w%S0C0^7^8Z(Z`IbkhP0r%huEQ`0;3%<I@zy?H50K{{XOS&=*sVW#~dG zrIp2yCTBH)J`XZ@hh+pYA^{>?6fF&|GODf~%Q^RC5WUO@t(h(Q;mBgk%nsWJ9GJj? z;KHF!fpZJa<nI`2*PrcZz&i<Bp4BQ}slvq*wU~{#w91q<Tv1Lrum~ra-EaXj5-5?M zoYf=-K57_OjLv5rN~7bd%FoTk6Sp{s<83zj<~5{xmDOTgdYFKk6E-KEB<cEN)ts$b z*G^;)Ao|O8#4Drxul7Xa`=4a)ra?ao-|dSMj?(%)9BC|mE1k==^y%#L=x}WdWXIKv zWxpEwEJJPLL|XD2)AVzel?gSQAUKX1M=wa^>1=?$f2uoWyqEPSALHGP{L>@eDa*6= zu_+(Pt@JV^NV=E=D9|)Q0W&a2Pl9y2KJMLbd0=!i<@ol$vB@+XI+=u{Bhe1DgnI4O zTNl0AZ|Cs`kLfa)s+N|`-Ltrai3noZsS^>(Xj^m(6xE;S=_SuiKkV$yqQFQhqut+* zR@HnKpZjV$QTzZPY~#EPrh`f3Mys0`j(*%1j04$t#pJOZl?US3S_q(QM$K+#(;IbQ zDA4PLA1F*$jumTl3uApB@sM-B^a0k6gT0sM8s6e!W&!gk^|o<dseK|Urq2tyln_k| z;ZyCyoYP<2v~_ND=81XP*|+0!d^tIHI!OO7dT#vG{@l^Tluz6L-s{4?>p=RU(amr2 zc{3z7lnLYm>W}WLKk_Qtpw8TCbCv!>x0m)*Y=-W&TMI~kMMN9q>~@^{wSQOJn^{Mn zHdVP`=<OxJxkcB;@_zJN37&PekDLw<$m-y^^41L4$$>ekvCW1wz-?tKlJfdP#({uN zV_4wN9Lxeioo_Sa?MQHP^p$tL*zXn4yDfsgxr(KUfW=R$6dpw&>H^jC_34Y~2>`L5 zM9Fm<???a2zpZ&wgX#2P`W1%8s10I3T#VPbLYDI0X65`i&+Y{RJGoctM-6JX4AK4= zlC)<gIOkz<jYxCFf~c7!$YAOIFik-ZavsWU=R*dGA2{PEEkEoPSG6ZLwP%~q(Hrln zkaZaK5PP-oa^(*)+CiSGZq*HL8t!B?X!n)Kna;W_9HZoA%%ZNr_faB+Fj`L(Zq%kC zbh()1Lm?e=uOKmoCR5IRXfPpWs3#-r`)eM(<#*OwM`w)5RQ>sXgq1R|ehKz6`>Lj| z{J<GR>yFu;P;HkcXx%uDBZ-r5_-QVf@!b|3k41&sZOT9-fM0?pm@DDHO2w_htBQwP z@_ElViavvHA}oS31AgMT^?@0|R~qR2Sjy3R9{g`5q0imFp+5LulV2F%CqvOji^NF? z3$rqFc#?K2GafDFmp9q|iTLLWGI13_8%Dbdhp1*{NzCe1%Th>Q!&gZeS=`PIf0P@? zbjsiM<`z%0gR(^d2gN&U0F_yqAE-YQe-=2fN4Lv5D(e1X;8c4{Ga0A+!$~@tUPf}f zQ3|t{HzpL$@&_N1D%Z{VVN`1MY7ED6hO~<kV@_rzfOXL-Ds*FQD|)?pp{xuG7Q1_& z@Zh`*^}1i#p#I<10HvR3yW?P8NY1Y)^Y~x4XwrjEw>bkU-*`J?A4Hi|#QQfo+*yB? zq<;e!am0#J{MZN0jvE?-2<G1~I5#A|+6dNn${mQMg;XuhME<3P<^K=?#FLDcesjyJ z*+?S^!h-iw2QHNW#C%^brKt!Yy(5+b)pQFSgzEdw*y+enr<XjxchKZY|9S043yYL{ z`hQkZS4=zQ@JfNCJIYUQPRA5a-|7R#SWLyb%A`+T*gVb6_f#K=AnNOdf~6pXlf9l1 z{aDDZNk5}lMw>l)(Ow1z#gZ(;!KIHe7BTBDv(~-|(^vA7zI&^AhdH$URyecMG*Vbu z+8W?#SIG!Yr^_H~*rv@0ImGMyRtkwUq;dY{$D<<ZCVvo!e5UyOr%GnD5d|NcX0)*! z;X@96C-5&(9n*_pdd5;C<9{UvuhC^cWidcNI3-v>S*k~X3?3vR?8?5YrvDyaEOUzz zM7CK3pdY6N85zi@Tbc5W<!`pNZ>kz6(6jOu)faz3=@zR~cyAc-3*F*ZPN~mF0LS+< zww^8;j6ZQ`x5G)_)<5p2{=--(vA7tmv87eXX+nLnj!b)zx|*dfnV}64HHz%JtOKH4 zpcDct?P$XeQqMJu2-c(4;htFo+i$((t|5bKo?H3;ZY<LNB9N8bg&+b1_V@c3v-(-A z^?g}q8?F{8hsY8E3;S7?&cd7-;%M`n0x~BwNPi%|Ng->qK7)qn>n!C1J*)VGBfJjg zC2FSt<`@6jDGcfNZEJk+goiX&m_nHY+jdipKOwV@mqdpbM3wj#+phZiR}{mde~vN} zPx6JCYvRb)R@f7d{cTq=b3_4WnID5rK`WCs?)RS!X*x;0=$8&_*@4t3cIAdYi<7Sb z0qm(Cg#9rPiw)j!CT!r&*;5p6#~;^T5-YB8*<hou$fDMtpsUfA&Aj(fdeut&$Obzz z#0T<{Sn=RvwG7v_?L|%%nmhLwh*3%f_Hw+iQjReGZ)*D5HEKfKJ134`@;5nl)#mqG zEmI_4ATF%Z1i__L^1;SJ!c&e&MYh6Y#qvxfRdJ>6iBx6$PZG>n^XJv9@N!NA1EOR| z5aaD+DoOW*2CY7m&wOckv4U33ufOB&ws}9t&%ztbvV6wEpXI1YB-PAKuef*Kg589` zg=nwRRtH?60FPt>`XvHpL0`5?Azf~3?KWC+e?YuuST9<)Cs)3WE=f%9;Wxo6<=6Y4 z%D<Fc4>A@MD#jOf>h1fsR)A1?{}M7R*eypFf9Q=nQX1ufgk?1THc{#q9l|PQs_8sA zlmeBHz<?9u**J&GfP=BVTW@RAy7H)fU%44a)S#f&waI-M#GCJYrTSf4Do-!A!4URY z*Z=J&^?zJwxsKqoJ=3vvt16>{64`|&$*i@G(>GiJ0|BtsM~AsL?3{#OyT--DTxFH) z=AMIu`qwmX{iF}9DER%VcnQOA$$TzR@%XOPnxlTEIT%F%i?_PZhk8O&AJ~|-2c?Dg zOpKs|eSXV#!E6k|W6U8N9hL@4VJMKnp!;!m+3<iv>V^6UZj9S!Jq(z3eKIl&bH6wC zJY3FcY&wVm`*Cwkt(U!+fNb#zKF-?sx&n@Vcwr#_l+uHa$YZ*A7URl@I4^!R<B!B> z0SR4WF3P@Ue%`yUuMe1QmJNIS*~18n(9ekY{2EfGlULgDgrtIu*q$XH`KJkRBu-=1 zW%5aV=sIht-&B!}c>K}xH0~bpa2|qzv|)aLh@nTv872@C(g77FC)!N_IzFQZMOYbJ zX$9ZjCHh@uZTwFy(J>>a`tMWjj+}`!$6pN|UJJbmVFFz+xaemXg}s)Rg$x2KDIiE# zgiRGo7Ni=3=Rw6-XNV)9AK-vnhIA9G4iJp-8mTbCw2(iZQG&^y<wC9g_h~NqQX^=@ z!-o*2TOTWA54Q(1(C+V&X-F!hK?eL(1XxZeo(S<of?n6xr}CbeK6{1SnV6VFK<)He z&y8Y=i}yb`{Rrw;w!BKbvO>R|Nq}^BKCKP5yY{DhEPFLYNs%`Db+2PA_Z9W^Ze9l= z&Q6-X{EY8s4vRSnpa?lQJ9_9Zc?z_U7!~F!v%4!37v96`?~AzCgiYcxof|eIXKX7i z4T%80K!hniIc3BUmOzR`7_{&4cX**G^QTzyZL@tvXaw$C?Hg}@C~m2jkP~@Igw`Hf zPFwAkg*`qsh6J^&D3xEuCxppb<{_Q+>y7m1SOq=zzI6J0_MdHkTcH1m#rwZOda%9S zOe6lj7n|L#PmoH|c)Nk`{cc(FECDt8p(lZ!EKDpFS$qv)Gv6)yz()aVzS@7^h4h&n z*?@B4S0dhm=Fh)Num1a*|09+BK<^`d(FP*{0&br=BEK0B_0UfNOG_N6c@1Hz8yuNT zMiR<Ufn?zWS3eOA@>&{Xhv>c4O~{kWbZmH)d-TEv31@U1|M<eja^SwQ+u6Cls4-PD zf$hYb*2W{hWWQn6Q_X*<1Ix@iH)%n~&6#fWfyr7po_BCGM%wM`wtXQgAez1-&*mY4 zo#WjV+0m#}J&4#`w9>+)O=$iGYtr@4aqlI~QvUddF%*bohoob>M4Q6c06UZF9JLg? zg!|N}r!Vb#w7IFOk((fgB5YtR1dx9MjLRqXFDZFgXq|~GQ;Nub`MdV-TgSg-QeVj+ zy?S9x%)twVz8X<HTf0JMX!CCP2LV`XUU%eE=jDEM9Ox<;XShJwne<Bwzn9D^asva8 z$Eq(7Yb=PV1(RE%t-sdoVrc^4bpM9n+R|qdu*YV2Zr9dkFyk$^bIZKzF_m7cp+<QD zx{z^9LJQRtbZ-w3vsAo0N50O8C2;NQ%Z}zw|HZjV7%RD4wOCt}1I2rvaOjAC+9`|i z(;G3Dw+nl2uD!(!+EDxvT3Vnp+*ap^R;?jUf1(EA(w<8gU@W&;HN<k7Do7y<(NM<( z%ZK<?6sPBqC#nB#moHIP>CTyH@0junvEN_J&>I~N)xZE)b;MWjoGqyq3*xfQ8#O3r z8ITElm}J0dTu@&et(}>f%*UTaWk7?4%8JmAaeOvPUAnV(Tl>iw%kp8==)2mHuU5BB zCJCVsG+*_dhY_`Jc+A~PYHCDNPrK`5m7Bkr3QW7#@v&M#FVbx%cq~Bq_(}?SyOGsH zgU?820P31QxVHvh_K^W(NUiLF7L5^eJ7P77)Az3`oddT|zackK4X?$OHQEFq3zhPR z7+pr!>P>b}CQXis7m;_|42eU(sn0u>O2(EGZ3_vq!j9nB7l9J0cx}RoyhG<?5P>Rr zmE^k~R3N)rTS$i^x8@(bn(uy|Be3Kgn>tCh<v<|i!a`r96jddu+$n4JbvGAw?uTl8 zC7{VK+jkvkzCYTh#tEUa!R@w>f{@zUGgj+~OVIcGO#0+UwKeB8>ggF;{;)=amN@!} z<W<MagBy86faA*pF=v17m7Ss@-w4I0;oh0R)CcFXWB<wbVx&l&_u_ajhvw?Ct-c=1 z&A*opHlguAQiyp@8onhTWx|{otTEv1px8#1-i2f`qnjd2P-8D=T=kG=oMZTxF2ftW z4v<W+N=e}-eS8NnP4?bfO2FmdijLexzy0c~u5KAq9R0{uGu6+xl=1oe<?Z^#x*S7= z=}ZDW$rlPDbgW%#zwv#PB2ER+Kn0&lff2x?V{5V4UY%i<28j%=y)6u!A*6tL${Pwg zY{p+%)1$0t(iW!nVQuE@w>0jOV}}2|e{;9}ZRPk%ULAfv<*q&HW%2ea66p8G=EIjb zaiCSY0JuJy@wV~GOg<bP-1qSflhNnmEV*g5*<;Hdk)P&tQ-rW7{dYptN>!b}Otx55 zfaJorm_!TJ$mefMY#AZnS_;_QQ;yl%?_UuPu?6q?3vP|5)^Yw8m*3>&*(Xyv24?7O zPDvM!HV%mrhh5kBuGo?>6y`75wW0t&8N4NeXD%rNWO>%K3V0%22<vmOy*-Pr8<w{R z-&31|{NHEAbKaKho3{B!>6S$V;SG=a4g_<yPZ_#1rk0D0w3S>Q6RnbKxysJYS8`VH z$v8PbB5Ny3yFSpT?A{<mys4JDKYb#i!T09=M23wT)$a29bN|-2n0BBXDgk4UKbL1r z*Kgu)G<O?mu&r=r&U!61-vP+YgWeC;kvtW*xiY2!%S~h@7ii|jsf%fp036`Pz;Q-D z?m12a<AyrRhx@eAim5cg$OJ!&ziJQ?Bv(;FZ!@NOnc^Hx-{k%Z7b~u^_9cr@gSjHQ z_w2an>#U4FyD}kiT2g6rTcT1dAKy985_y+&2V|pkleCh-uvh7&0esouv42{w_#YLn zWGan*z<T**&@)&fd_#F&XN$U^tDfU5@sLYStP&uU6|M&D%OZbd7rOh)t66P^27~zx zXxXRI(*J5#q9T+T-rc|a=^EMhwz$F??P@FBf9Vo(Afb@9<SzRtm9z^E@(yJt$v!Ce zqlC9(4O`!@?A4w)hUmTMPWjX_{g&sN<a5~iYhm_=Vd$)cxvaQF4uts?;F=f>MOjz> zUx#jN!dRq~ON`X4K_Z2TG(h_YZ>rx%Ym)>E4#>T<x4oV-eZ_*enn*87{S8fj1<}Z% zWx`h+gj$A*R_qaawUK)ej9N>;PQFxy81wC4_qtciwJR9HxG~$g$~K^k7o~6S(n#=3 z^ld(^G6v0IcnAN&K&UParuTV4@61)8CCW{v9PSHerpMH<{}yoR1FPiKEWcfR%bJf7 zPn+VV?W<QF_5v38sjB`<{6}X~F6UJMR?hgA{=S?+=m>TZAYMcmq^+#Wb%|L5!0ILf zbh&v)i9(#|zdEK#<vmqGoh3dVVh>OB2)?mU4DZW`U$rx?L40Dv2QORFs1Z?4(5F`5 z4H6;N>0iH{1Am@(>aN5<Uv&QS@_}H@Q}rxm*q%<6t`C=>v`emOgz(BQik?WoDm*yD zs>yUY-!x^$_qm`5fXs{`zMjwhg>1*_k%s(tq>v?bsaxTcNm9OTUF`#_CxE69*vAv@ zm-#~>gk}oxZ@d)~|4M$~N`30ktZl?Z2#=vQ7uZD+ks7F{3^U0!r9by`$e5_p2&b&) zpeV^gbO5Lj>3@}?5a|qLa5kooP?9*CvMSG-ZOC*YxNMu^+=4CsCAv2?JF2uP%<A+H zTZ%*`<1N6oac<yo_?cNTuHqOS_?ocl{w+v$Eq1fMzt+0VAE@v3iYGOF7lR;Jz?rhs zi@cmrzVg*C6yU&EceW_x@a5*&CEz9=Y*mt|@>IF>_Z~u3Vs|XOIL!!5R+6|Hch9qv zBcvU-uoVQ+Q}P-VI0@*g>nSf;X3M16n<&Lz0+!#rCy_gKMNzY3S$H+&8Z(3)MS$*I zKR&8Q^)uyi2=an;d~uU5Gtr`2NA;DC&yuh%j;kFfDMGeaF3mg<kP+Xxhg|WwKC^>s znmJv8f&LfxE6&=5>;~NfY~3=pKWz_xlggtGkzfHDlvSC~BG<!-g+xSc?>8<MrmN~! zP8xrYgT;Ye4@1Ambwl&jxPFJ0E^<<W-wU*f?7G>?ef;xSKFj$;dN#f?g&LJEXGJPX zue~wM0O_gCd}rvuJEflAhtdebjG3Fa)Q<n0()&)M$+k$8=A&;wZN?lJx5#Vuu5ado znHUFC8La=yo)s!okg{Vu=zyESoMWp3;7cP<s`4};uKR94qX|%PUbEGZzxufOX0;Z{ zk-015$A;e7ww$`SIjWn5ge^gMo)x~ufw`+0b;+Gt8IS9V$))907pgldq=3#cH-$A! z<x@OoxeR$(xlE69yNyICym&t6iNE?8JKJFtSNw(TZbD73a$wm33!)>xBZ+&RBuzU+ zC5{XY=10%-8^r$EG_-rgO<GSorBL9dvxEkGk|uZNfas_&VmuQ-z=dlw??V;ge}LZi zdI3Wu-#jckrfuc3`268mz_(8oZO}v6OXC2krBs;zKt}YGpbfvG0ODmrp~P#bP31l# zo!{9P>uvr9CmgvNX(#ZCAVyK$WfHkdfNq2eJOkl3h>h!){|nUL3vyo|#)8a+I@)}` z>_g*pXS=!l4m;`|z4Tv_aNQX4%#DHDr8!|VBraypeqCCuX;GQB)kLO}B9MqA%cm*y zrejh3x#5l#Zxx%ts4^WtUr@@)L|j=E&dU(LuRi^{lz>b|8~2|^FARaRqYfY@+<!hc zKvnqszh64<Im*o_#^PJnDYEKhPqd-@a`ig}M1-dz`OVJ1sI+(TO5P8s3|OZZk4W5_ z!1GuRAOd_`iz}W|wU#ps^mKaYjlZ8!5C$(`KK*H-$d<@t=)TaK?tnQGn7W>EV`8kU z#=SIxtGMII9UnrJRoED}^Cxs*r6qbG4Aun>(TFHK!2!FE-%+RcDSJly!|%ukgkwkU z_~M{^_e39UzC7g}bqhP}y$xs2t4=9mslk9-ON;;l;e9S8$O+Z^;e(%t0FGZ=jwFdO zZ$M>HDru^SGAwP7tdf)I13Kd^TEsfhPO<{7bd4NOG&A@!2FBlyucbQWye85(vbzj1 zGIeN@G77k%hg$yMfA#bW?}`4mRN7OJm57II5xn(^3A|U?Sw_+#f0Y{{^GJU?9L^Rf zCb{wCKg91?@^3y{U958&IRV-uS>kH1*0s<)u-W%`0&o`}7se9F{jwBdgl}-Lw}6R+ zYPritxadkbcEnv;0X|!0z`rsZTq~(JSuYv#xSm@J+p}#Ht1NwCGktX3W^)4~YcC>J z`T49Nt1|HKWcO-BqvP%|504V=o4hgFY`PrQN1<xu@)~h^oJ!Ya>GLCHpAWSWXDNiK zo555zdBoiqE;`IobMBiYYxY8{L}eiG*=yAO<UT-1wDc->u`T_<Ag|iK0;_NXu<StY zn=JRFmM%r6;SIGvDq|Tm7m;@tkWtSxYwO31?AuQg+r?h~CsUvjF6}|Sxjwxb3N6xk zuHt0v^>q~Cgp6SWB08vHjfqP{i2duf6<*UDD>+PLow)g`VN5W~xXYXLPyvs$wFu6( z5-RI{PJ;f&pIW!6zrw4t%#TSU&h)Dn=Ms7SUE<9~vs&~guo_t32E4`zE1#%RJO%NU z*P+OzJxE|ryjgR>OAU-g7)rDaL25>2UXGi`;%L;;7%--)shjEfI~~!d(b|=~d-Q=B zrJgvpS+u8dB8GfmmpU9`!`X4)&;eHF&*1_d7SA#l9?Xqh<!7fX5zmFL8VYPmO%Jhi z>_)@ljYsS3s<I<I*}n1)F$Iv6H)-$eWrjxBPS2)!Lb5(#dW$dVs;cg(=UM$g#r+fu zdGuzA<#Hu8D-Rc}kJhPcFh12R#aOkX;Qe>04^?EmJzAN))8LbBqh^v&(OTF}5U$<a zE7C?mEZrv;z;~lnrzMtVdn8vrq^M|#d8!kexM1mPYuTv2rWfq+9@6;gSoapi`<|=o z{Fl7M1%?`lG*<UyV!hzZ14KbO0O#$r=I@yDuxzJ{{tww+%G;#Ji$dn(kt4KC5d*?| z_;RQ8-o+g<DX<M67)qd>^F28rLhRmQt7{qG8#*2b^|0*x#p72h$P2+15NHy@@{U~` z-b*$Y&trsHHyiAIP0n~*7PD?kdn+FjDJjuzz4*nnE_&BetgV5DqWo6D=Q1)q&QTK` z@f*?V2fa(bC}DlJ`KY4hI$!ny;IWx6n5Z&f9NL%PYuHy%>{oH(_;uv+8UwIZG&?TP zMoJ-#?uBZbq0fLsU;o6;P@_r(F#w0sqeI@I%*xxk$?NP$MrIK<ym=+4Mx*cGukXcb zKLP)3T)7mX2)}Re0ah%zm(qpLO9(J9@x<vN&;ie}^3%2i*AP_1+Bv{z=M#E3|Kba8 zsc7M*$72lO4(|($7~PMb{A?dux`l?R(SWI+4iI&=%leir>eGepOFe5U;p`l}-5xJv zUTLBJrM0<<x4m@3&9GXQd)jjkkzeH<H1CsxUqxylg}1iApRtwFFC1IEg^e5Io3G;T zpY6(*DGZ%^mBG^Z_^(@3^*34&N&KsM^ltsDq)LrMDeEunMJyg4WQ$G``D2;|K9mgM zzGn$WGSfpIOf&e77;kqG3aJ}JYkRvd|2aP%+9rI9z)j<kXatlBKukW9S=sfN_S-WB zaSB)DXZqv%5kZ{S&Elh!o3;VkAGB)BdvG-p1yCILRhm|nW0~cFx|}<aBZc-$cSnd( zp9cs6=(B!ULqhBk2>a)Jd$14!E86SXHsd=>FTF!dI%Vk1HB<4;mrc%Wg<bpIA|)BE z1qWI6M;y`zv8qw2=2SKhskOCJ!Dy}{RcV~EH8Eq%i_Ci|-!%#U?Ym+Bn^^xr-_VTE zs>cgOqg4gp2TIO(>*BY-Xj*ol<?VVYmrj4lo|HwT71#_Km|=PTaA_-M%kSLnkkR%e zOFQuBMi1cvIevNJKx$9`dP$kBgnb<;1+l={`vX>_G)Sbu^~SO_VKDWaidv2Z^G$r# z*{rpoWK2;zwyPJvC`j=g`FAM>g;VveoD@2GLnR*0BhZ0723;<##n_wdkJ$=v>%ZTx zH+2zS_a`{8qTaoY>+_xFlil4Czxm~|u7Df=#SONHj_%&)qwe07%@0o!hOM2uh#R6Z zx1SUp<7ES%G&IW?-AG@ZF@{^Ned{_|jT3XFYQ<opZx_4#nd3R+vB`)DbPdiJWNP^} z<+2_ID<F=&=YNA8n`%!w6rK^EIOTv#rOO*3K@XEx<1wa*lG{H@euu97lC#p=PpBgs zd7>Jm5mr27MS!wH9e50~*Li718c{8&HCwim042<bFm4*;mUY915!SCw8Nsp4BqDl^ zw|K<Lx+bv>s6AxXJ#r^yc^2}RWY*jwDl)I2j$aJi%yo)_2m4geoKIe_1$W(VQg+_T zbPqjxFp0|ivnCTu&pp3hdEadzE8W{NQ!I^~gQ}Ew@v$<kUn`xWQR+xUTYzZq2Q(dO zo}e_<laIztP5K5Wv>o;JZ#S<n<_)UU!e01q5<C01S;HAfL&%LkB?WMOcWnCm!@8bS z{m0EOO&fmk-mH5ep&N6K!Dk8O%q{WWM~pHif{23qK95tr*mApo@GPj`Hu_c<kvR3K z>GL1q-u?my_YFEdmV=e;M-lIEg%iDH$P3-v%+}FjcNgh$Ko^H-D-`uGIC9vuL4T>K zi;$>|lsRI;Keg<;XosaJ(W@gn_D%(fhBNir`D@!bi0RtUXH9TT>Q>fchw^jXXDCK| z+iCc9_*Yj8V%`K2<}L0`zK7+xj#Hbbl>{&(gxQ;eckG!=1%}~}kb}c$L^2Z3oK6v0 z1&)HVXpXvcd%D6hBo#|Z7|l83&<wIT%9CDorQ@L8r*gJ$B}utsW;-|S{j-x(<P|Rt zSjetc=4Gb(_=V)Q9OBsf22Pg^8B>Hwi+C3Ui$Fw5uz+Vq&=`3KbHwUo&!2?itAf+| zW6-OQD<ofQ6suo<H-z=1oTwPX$Q3CC>)C1&a<m?5P!&sCAn+&%;+J__`W6F4H+Ltm z1}g&22)aOGzwP3YbOTbzfQJ4Gp!KqQQ}`=Tx{H6zmyM>YgKdd$jY3ngc0NnJRm`b0 zh}Rnv^Y`)0Mm8W4omOPA&1$-$1!#<5Bob1&%iQc)<F3R@(*3QNuVeZgy}FD?2^P(- z2BS*|J((GF?H_fwJ4#(mD&9Kw?!sx(dsW8Ed|)k6nFKHw98+Wzev?WMTK<!X&zPwb zoNr2mw)ctCDbHVke5ZSr0;mf|is#bvn$46ADV%c=Z**9*%>sFIcxnpdHtfU~%px4n zq|FGTN+*X$YOGTPsbVD4SC(g)^1a@G&=3jO&)|Q7;JrT4G^oh0?IvExS{2de<J6r| zN^8b$C}BaoQRFSwfeo}dPbe$$Vv9r|yOR0&)9Kl*gxV~Ks`n@2VBcv2wgS&_$}X<* z^1}`DOAJ-tS2RKNaCh1%f)u@UX;okpN~)wfQSm?Y*;FY%4Xyv^#?=g4IQ`Nonx!Yb zs6W-wZ~Ts!F~OY7<jhe&r>a~5R70+>&FpOx3~CN>g@p$&-fAL|psE1ogtA?0+Ty{I z`Ybm@8sQ?#%s~t7)67h+-sr!@eQ#LDZhtV(th1T2jCA|G{%y248#Av8hUXv6l|)0n zCney19>J?<WlTK2;#hhqqDUU=5+N|L6a`tDezz3HpG-ff&CN{p%_Pq$780Td4^Wr? zO1>$*?lH(cWGe?_+R)V7?`8g3w<xhZWc0414MO+)r+ruxWIA|K4OJIZ3g8lceXAHi zQFdS|t#DxDD6G-p)1dWzbPnZ%Um&5o;SA2ztO!Xr%5*Q&ZLrRQWcoueCw6n$*_!lC zS?=#9D`fAzt6R}9$*q+1Y00UntVXHAzI(dF!&F>ZIGvtglE9FbrWWm)&U2!MEZMi9 zJg2M2%_hIU{>YD%_CwB?Hal3lke9qPyi=_EV5(zfsy@^hw&5$mwShCeveSTMnc9&3 z3_VCoFb^CGf;BABPPu>51gpDSd^Hb$XblY<dogg74iP)O6q+eIAO(MC#^QFPXL)#E zV3!dlqnS!y=ZCxv#r2^385bC7Cf=LLH8YX+)Wcy}H~%8%_hDAdgS2fHxGFFee@VM? zZE8@n`+L5jq7LM6=d?g^PK232H<D?+E*#|J((f?303pdF!h&(b-76)M*HR%~3+N=b z`~8K$L8Be7?a+Hr<%*^TFSY{XK|<(m(!)g2iH5hwJ6PAl%!%n)+=1K8lCTAw|MpIK zst8_`qX-+uYwkE*Zr(q+ck(C8!W*`_o_;l^LycV_5JEtWNjJ$vV(JwW>P>MP5jAq? z*04)VMvnDi2C9w;Ar^?xdmRvPJ7H92#`jpd8v7fqvUizBk0lS67jHLI%g$y;sXW0D zE@{=UFC{$d^>^D|EZBj?lqNY%?C<mJszfG@EFF+&l*ePLsJghdw`^STDrZ<cplbu` zdtXQUH1|xt0sJ?L0$~!)ZDE>EE8Qda8<|o*GcX6C4fyxL#nN>rySEAa#FGlUaw)T@ zktHwagP?kea8df<i5QD%!Kij&j+A*YwfEm<)?QQ;-Ir9mj_1a8r7}YM7%Hbst<b~F zvxK#$sV2Wp*rN$JbIpr!_6SqPjOFIAnsZm|BYmV%?E3h7v6=w7g$9;p4Jau29ko|= zCI4>XER`n=8Z0|);pFncSk|)Vw+&>-ks;{c)cawbHaa8_C*PbOc?Y9(_w@%2O__=u zeaX61j?U1R0>>b+*y5Z%rfT;AC%e*`^7ynE7JpegbG(;W0JgGYb}~}~vEGplOK){} zuJ-X@Rp?}7zIPh(ALn7z<fMHbF4(|V9I%-eHuMbUlAU@1b*Lymq4Yt3TIHqy1w_Nk z=FVXgvS%KaWhTeTBD8UL-3bHRxfVj1f%a2}|4pp7XoE8FvU0wsT`PQDAE+=u`(>I9 z;oDiPr9=<3xe(@iaJe9<ib{I16Nv<a$qAJ}Vm7uYK%ApPhnxvN3hW0dHfW-m8o9u{ z1B+({W|16JyUDzNF0wp63=`Qj_JJZk_78TtMvylgMv7}dOvcAS+DKH-K4X@e7Qa)f zrJ|0~WTzZT$(72>@{v@Tzeb{28z?AjqMGH;a_0$1EJc4wL@qwiru{v*NRPrV^gHOH zgQ9SX?;J!(H|37Rmz=-`E<;LsdBEDnNbIF?NAPq0#tgIe0i;S}@{PDvTeZ(n@g{Oa z`U8lCC$;PgYofl?x)lEgEe`M-#>cO>9ZkFA-wIM<RHgpevEn25cqYB9+cSjc%s)Eg zMN60KqeswdC?tm$%x8~glNr?3QSnvy6d{8IXBQs^sX#KufC!Q|gx{LpiwO*w(12;c zbD(BiV6Q9GdC-u2kRhwskQ@ALbC%*)j9Kx@<z6zfrNCJJ4T(1v1F2>>nhxOQxwbEP zC<TEC+a6_L=*d`MK6OY3qwqZNnmvtywZ1>ZakH1mIs%DDD~T{sgbRJ7w+6GEDZdQJ z?by^GX<ZC|&%4HysCj-^X|W4ITH$M<?-mcU<j7v*6hAwS`vpBurl1pspa|Zow&?{c zjZTF}_Y?LsdTXke+K%A(@SWe-A5nh^3bRd{Hscx~>fPtlq<%)vfqs!|BL#0O7P*lJ z)r1(-e*Zs?&N{5guZ`n~NGgcZj2s~if^^rEl<w{tFuGfi+(;!=x}_N@qB6QmN@0L7 za^%Q&zxUcdyRJRw>^}E7=Q-!OpL2h{r^1m0_}`7^f-6hGRD?~;8?1A#&(DsFW#-wj zdIZ<hotoffa>9pSCt>OX26kU;+oA`GO5@A$UV03K>X~cbg)1{ZmS+ToGsc<=iafHe z1|F7u=8E}54ItFxWC*JGL)A;?k(hVe3JPZbLMgx33*r~BF+dSuH&v}F%|n^jIgn0- z=NW9kVE3=$brF4^-E)8JBb9QhP#OO};2~TIi>i@?7<3kR;F?;17lR9^(Cum~&8Bka zDHX0^H~3iQN+$_Cdv5dBd*?@i){SNniDfgNxx}!2>fuy2=}i>Uh16n_kYAOB{P&lV zXeYatyh#caqPnW`nW8L7^!p2hiuF7Y^xsAAWYBZxh=P_P84#9XwGUewq1av;9}+<t z1iP##|HcbzZLhl!Z2_eM37!T4;3x5IlsTW%ZZrvS?zb|i(OT~Xbs<JMu7fC@!JO~b zdqezefBlsWys)|^_Rk^PHLkZ4CpQKp*o*s<P=2k=2cfgUl|CBXOrE>t<c>9(&1Wt> zvHZV4{=>aZSV)mmawWUQGpy^eazgL~r-<w&knGJs9*5zv^XbPOKj;}%hu`zSPW5YA zc~TH~I2!Lejyp9Z>w|^?Dvl0)HOC0wX&Y=BL%`JM{T$TR8nIRO!>(l^7o1;aC$XG$ z1w_HscuiWDvAS%soS8q8W6EDO1StcP;QT^q?a7h@B+I<<vc97I=E@Qw`YK&}rc_I= zn(vFB3k|%^7IcudGrgRz*FwsC&XoI-Lj`Lwc8mnruxi}T=^K1>L!Ai@_)fy|Hnk35 zC`<j`G3-Fo_z7-Aii*UQ`b8QnyJRePj0fjdEtH<wILPcEMq}f{*3TucQ*W{N)kwtK zJr0&44a_5~q27#edIrqV+>GXD#X`nh$YW*cA>Fj{;sx^6Y@l`w^r7@`M)+WR0FnVq z{ZH@Qo>wZDrx7D%bRA*<6|MqvUY2Lf`c?X5Vnpdw|1(26)%;Z(wo}}(L9Np!uI&Yq zph`(g_Ut+K$tZ?2>N%%3dmMi__Uy5o`DYLlBKA(9G=Q}p6I^fh>QWE=Jvc(NngLU? zE4f!3z9)Nvc<^J@PGj7W6EFzIF^e_t11l^9TjWTJ{FH+5)e2B{{2WC2Xs@cqOkh*e z5lBS5gI`{_D)ZxSY6q6)ov2U9^ENL%qqtNc)BK#L7%bj)e=<ueL>i?C{6fi`0W`Y) z7*1*N-(+rV=4S|KEi(vY*2wTedVlD6)8V^xU|gBUC51IY`JFtCQxp|N=L2_22xX_l zY_7;ps#>G735kH>B=dS5LzHyV>}s^=D=h1N)mH3X8IH8GbE5uoL5LayNS2~gWe{98 zVbj=QsjD<7<2|=z%Os&ldX%6jd&_8QvgZ%548G#AK&^U#+V<+|PHT@X){eFPG}3Tv zQ}=fuaNqlw;msLFBO>_qH0a<0q3*#}AM$JvOtnmP2pfP4N`9vk--10vK8H|e)(Vio z?Jqau=b6^9xV)>A6Iz9M*v8K7MN#j;Vec*V!C^!g=4!+D2Gp3>IOkCofh9mw5oY)! zJuayT>ddwSDeyoI^xy1Ag7Q{@a%t@big%~`<>TeuGv^E4!2#j8M|s^%^B#1>{a$q7 zjfuCM9O?TUL(o25pn>fheq14D79j^jI_0xWcZLqtAt<q<{!>M6J<sS;^)|I+cizjB z?R)^!;+Q9yP>|I_*#%YGDA3^rJ)-CSc4q`rE_r>5TD9zhWqeUZ=l}Np75Ld$V-Utu zXO`A5J^mxC+}Ms-f%mz(UOOiFp58PUSl<Iq0A*Ro#dF2SRxHbi6hzd=cd9vFn<zs} z9Mg?bIgM(C8!5x9H>}xKTHf!KNSri?Jc{;zf-Z^B@W(-8RG8)XWz-4a24^0}3zC&F z$hVu@ADgJJPMgv<5%BwD7RGbfcFSCfL|xn*JM<N(Zp!@1%g>mHC>0Q0!WhB)STCO; z2*}e6UKG#}oC|xD&eXBj*|a4~11VpW?rh32sO8xNV;%*u*rZgd+25u7)~*wWU^ryA zpI|F^9JyQ=lYh@-3kokZ-8%nG#c^8oB%P_X=9<7sK%5b}9Ms;Xo3xTjUy2_iJ*34z zc_O(`3w_&C=hP+9Q74wJ?xsc1El%1r$AU-zI`NQG){3R-F~I#GtjUPrTYdTXnxXow za2iM>a&#>#ISgsqVkXq<fO>C$;?8GZ#EfxvKhQMO#R8o1XuXhqQxp>19l@r=$TCTY z70r|cFE)qnZe=x6ni<oXqyBpwDgFTx&e{1W0;LZEAM1F&oK|0D9Ry(kR|>pJ4{Zpy zhB-P-%KdC!`!hVWB{i9=fr~MF;<NQOy#zHI4kvk|;Ab0A&HGNKlpVz2xFa?8&gd|4 z2x0om44{*M5LxYWL<(rm50g;K)VODL{ScB^YxSFpIVVJ;diJM%TNlUR^QG}qUJ3P8 zOd|VmOG?=b{}^U01p$)6r81`{4>qaSiX#$2{6&x%XUSoULy!?w>e*$yb7g={TBPZ0 zhoqH^s!vebMILH_?2xcl>FG|x{D+~Rn$oV_1;l7EN*gu5WLFvc0@*z>#2`#AzbyL3 z7%WGUwNc8YjE-hBB`aw(V>l@T{l<j&{aI=(<-(D`+jnNxD6LB|6==~@0F&rd72zTY zYQk`XrU!B1^i-V&n5yiPuG{2`4^$cJyA5F*Bwgy?hmEebGUc7+Vwi<LpQ&VbQP3od zVD~B1zkFA5u*RnZ{NMOPIu~XE*pS*{aJUd-q`8@0?u0khYm11otahO(gDET)2agE2 z@1#>oddmwdEI53Cn2hj8xYj>JkB=2s?bt`&#Ofi{fI;8Bhn68+91@AqnKm^<orp8| zp3qkD?c?YXaR`<wQ+(_G2zp(hm8M;Hh=mzGfLbM{Q4f0ZD;9W=pm{<3^F=B;wfXfz z21zT;L>_7?d7>5;qZw`j6XEy@->sbs>Vi^l*!Y_76z$ziPjH`f_#OmXL;_wuH7&wh z(|)!_NaY=F23pm^o?~1{Nm6}il{epb2Gm`KagG`oEe%li*8#pzi{gKmhYCS+*a!O; zf`<|e-MA2I1W%b#a6ioZ<3OmH<*Zxg@!<c+o-2gQ<XK$&4D9?9(hBrcW-hAN<l1V5 z<xAWt`yd-WRueB`)My6k!rucV@MwLIk0J218+&2sHQ(V7yOrz_7+YJizm#<?5oBtQ z^#PJ)wf^V800e2i_lr4a-ziRdV6GH6PgV58AEusPP0(Shxru-&LEk`|vaF#5YCcGR zf9xBvmP;?CctT{iPVL-Zx%tkj*}8xKQtOt%wIm?YeU9d_U8}Ol&=<c_PwdWtHy;A! z@+5NRnRc2Xsa*vPznT@81?~yLkiXA`ZNEbF7=pSw%|l+0Y<^7xM2|#u@y^4Xs5(vj zv8@YYkZmtW9cCsAKf^DaM;C8=EA|YnKN~$!#gS;10*wtGDMKTuqI+^DFhH4StT)0N z<DCeY7^{+&(LvHm0+RdJ^Iy$BM+1^KU02ODi?Kl8Xn%>P9HX!t41rJA%4$X0@|m>J zYaxV`Wi{t=oe?mYEcnz{e&A2T;X~xa0YJhn9S^NOIj?Z%@GtZr$<2w~K@#FHCwb3H z1yMs66C!h2jFJO7fZDIK1%?)cp5jMqV8we>`_4x8oeV`0MB|DCnA-VbpA_))(Z3+s zu$|(CC%+{SXJ5ovdPw8@2aPp+p;qt6FYeA$Z%jI8NEI02XlW@lkP@lk<dH?YV*70l zAR(tWy-{Hr&m3cbl@(}$Aip=xKZ4V@drgTQa-8l>Utp8ru|NAWnmUCUD2(MwNFuoK zBUrAgw-GCQQG&5vx*ve!E$nIXbsp-Iml|R#Ft;^hEEY$B%`VlPAIu76$^fpFq%A+8 zsl^fyw!R34@U@fSKoArN_-&0gU=4uO?3hxxGdzb8aAzdKYyFa>;Rgsz9onRAx5^^t z)&75V@hV9`9A>UujQ9L|bY`#kFyM4Kx;M}Z<DP$kG1X%;De|dNf)mf68LgzXWc|5k zNgjY8pN~K%==9GpB%B=sGi@o%KbTXkb;|-DYe-hju_V~@g2rg9^gByiiX0>$iUGqZ zq-~EOLdG+_Du1z3EdP!Hm_W3GfIraR$N5%DhOV9r&HfYoL<=@<Qn)P(;RDraYB*`} zTy71Z?ZPM}u(JWCAr8S0l1Qxc)Z61&&JIwwT7H{G8*?*6A143~AxC)PK%BQzr8{rk zX;%4_>}1KM#$cWMm^q3utxbvMaQz7Y{GjIJl<Q93l~#`;cIl${$mQRJ($Rp{jV7%G zHs=MH(Z5yASI~0z^sC4HMnYVh23C!EAWvG051Eo=W{S|HB|L#~bQYvMoJhO2nj3=& zcq6g$9``mbiFgvic^>V*73%W8Ff{<+BIy5mT;&~Bbzoyo7}V?-lb^Bi;Agj~wjiRP zlktglz|Mn$GQLQFsYG)RDWW&ROIJRed{ypZu+cLeIF5^1vV-3yJ8|ozc0s32P`k3| zxW99fh$aAh50oJYV#3}Uxc!02JgHsX*j~^qucPuh)U*itK1Jbd0BsUA%S~^coiQ<T zM>Jg_s2|!yTZuOpnrYV|5qvH~Z@Bx|Cor!QslN_@2AM&m3aZzLCWWz|U^gOly-$4d zJyo1V#&bU0kfoMfol^Rk&_!7Yhs3z40CEZnVoOVL&dM>Zu6vbRDb`J$GKO70ZXFIo zEx`%j#ShS)fE?Njk(Ziur4uFerHk$KPfSb@-I{xgtBs%bc-=GOdgYB5OrW}7C`5Is z)D|0HnLb+*g&|umj^@4Z{$76!8c!DXX*jy-S@S7ml6j@sFkr-z7BK@;pGX7TBtz?6 zh6Lg{5c>gt!ZVGlnIC&-Kk0B8O5o|lbT0dP3;QYLgdh)|+==}Dfcxp{Iiz)CChdm) zk<A>zEuv4G1fDT{-oF=q&0#tv!{>DQJ%W3Zd@s8Zn%7T^`4!cQ4H+R<`=<8mzg|B8 zH!@3E@F9Q%pUS1t9+pd)-q%yX3p)rF<e&LDQ%++olg^*TYmqli9ZMh396|QK{_@uv zEjkqf+q~+%cMv;6<6#-3AkxTBOrWvrkXAr4bqhZO#=N>`;iEj_-fpU`3E$%EAjomR zQ_^*0wX9Yh)zx~?C{AGZ)UmlQ$<&F5Ke28;BxBm#VpxV8q(Fm{aJTdUJlJ-in{vv9 z^dZFDCzGR1k~FD=dmmt=#vR#^3@vlrKhjcu&4X!PsQv<B!Na?JF|%PstC<iEUdgF( zoPX@D1tgv9W>e=f=p*GXSGM)<p!WmHMUJY2PM!C-j)n+16%R$mjP#T7?~~3IPX@8a zEPCFQz>)xv4o_1R&kEw0Au!HUnM~)+4luqIg58F;+MgNuCr1eL^}{WtuI1pR`>|F) zd67vzmsp)YR8q@yEH(dDl&9U@k$d{*${&;@cjtp6dO*;IScW&!eX#8^YlY3GL+>oM zPziDGbPD1@Mwkveoqy%E1cR}0NHI;J$5_wJdV}qT)Rrk~_;bIQl*}xdVP%{WEYA@u zxz;n5U$S_<pO)4g`wGY2$Z<%w+Ou=Ylq&7k=vy-0q`eL_l`WVh6IS5Oj_(%*$*$TS z`AWa6^Z&HtRJR~GSYL7VeQH&NrKQk;0Sg{|+Px2(X0$2?&U2PkQGf4#{_pZ$<3qS9 zucJoOjHsFb6Iys(XT$T4kXeIq=xc*KASX+}<4%{viWV?b0txv}rW@end)S>O4Z+c8 z3PLVD-b48GHs+1U<pE}@$h0&X8t)>C)A*_1EiyUT7&Fd!DE4%_<|<Y?oid0_bb#5A z_z>jF{p9(Ppy;1wl8}&1POK(l<Ue5AvZtM-BTG)K<jPX~x9kv(isrkB=VeSeNpk#~ zNr{^S()tXKY;=iD18DT5MwHPob+-B}(~IaO-u&<_&%`9$x^R*I<bagrf{^$*phCTw z;3Rgk^Sf|u%P}Ag`kp~1tj#=d<jSGJ76Yy_z$WS##Z;;_lg_7`F)*djWzS%aGELdC z)j?wy1*tc$b<E%5MEb!$Is`0TAO=&VKw6J%Of#irX{y)M#EUrT-rYnD;Mvn?-))=l z%N0(1cC|1qKW$2oh8v(CkYEr*L43b7Dcnj;)?g<kdcKo4HPf(OfkXmgoUi=zO?!}H zD5{{^m8z?GRkeZ>GnUb(e9Pe*Z0q^aIkx8hA~vu1`Gp*B$UKB=qv%k(_-zZhmkdq$ zW(*aCyhST|grK^K&}-w3*Z@_596k%dp8#SBfm*XY71dgG#bV?e$$}#3_JE#?c^^nm zlLp7p#wT60_1)!0{J7^D|2?7STKL`3@$n$@?`0NbU*L%1L2lV&zog~anBxm9*MsDu zHmK$m`}`NG&Qk1q2U{I!J*+2!U=Bu79Yx2CL4`>behSVda%$;pen=6d%X7@GPGKjD zl}rZPJ3>j)1g~^_sSC!1h<&n#i2Kz7havAAk4H9v9xH;UrGC_VhDOdE<P18lK2L}? zQ4(k)mE+eBaOO5!Igt>Tf-9NkZP>7Xnc>~p4{}XbpWJGh$0GWA)k5oSmrs=JKUe2X zO2#I~%%Zh(2Nd3B>nXe`4zf;7ciMC=TAB>8?BJxz6(K0_kAAmHhv%Ii4%~a`C3)~T zC@WlaMj3K4Po;zMJ)1E*NLBCNE_a{o{fk(m_^I>=$2bSOk8An~^Ra0=IB?RS$(;@x z-rXhKx7NNgw7eygZ;B;%(LAx#uim0;pU7vi2h5b3qjm}U*woT1t{`^nYapr);rQ+& z-rn7A6|0*cq^CkL7po;#+f^Netr<|y_gymRCrY(@b4Y~Wi>r@BlUwY57>*Teq*snN zk@LSXvE8({WAC%U2%q)Z9?Vcfl>e2yADCKv=L)yc-)Cec%_X{jQI!XA<IgK|2R!lj z2(zy|giXKYSv2%a`Yw<tCbPCW`Ri0i$6OyL@)aEFu*kB)i=CU6G9SDJ<G$d2^CgzJ z0InIPOggvcAq}J;{>UEJ=}h+$MbJKy4t1x#uNdAX&nkhlM%f%L>q?GJ;8B^L3hpAo zhJEQW`-Wg3uuE7)2-3i#Ev34`@AGV9Czs|cNr*{HR-E~lj3$+1^Qhja(Rr;lVWU6w zfAq6gj$09%j1sdk-dQWrJC2WVE;%~ayVT@-l2G^Z^m^NfMct$V@5xX3Yc>0@Vd)cp zmZA@uXy8|5#G_8F0CJuqYA@m8#`z9Amx9=3m0E4Ala4gYj>S0{wzbOoSAa}9E@Hai z%2|=G;@3@|sZtDXO!vOSNH_*VVmoiy0pcqvmEVfCzo+na<~K`0c1twWQ5&J=9N1d; zL=O{#Tnf^~U0lLG*`Nx6PU@OsjT0U9Xurk!!>_~P$Y%^P+|a1=fTu+Vf1Y)%tVO<I z?L9VihpDrqjWqm(rfuxQadARPEVj&kndxFhN?#+yz%(2b*p&}1qk<APF<M~;E?-jU zpl}PiqSEi#HMVN^emJ7mz9sPv*KsyCu9CNaKUufE#NJ>$VcExld%Jz1qkor0X0rTD z&745sBkGwrnVhJ-p7#NYy&e0{(9UZrFC=hKnBzTv?#FNn^eiJrT=k9?$L(pR8GNS0 z!t~xKdgbQF%WR**byL)+D|q~j0mBw_zWM?~f2#H1Q<B+sN~%@1B!ArUM~JEUn(Qnw z&V*)rQqwr=)ysZokv}r%6ps6mfOXb_ku<Aq`f#Op-`>lhwb*;ncM>IlNYOF#vHa9F zlAs@w2k7xuI}e6P&u5x3fl0%%8?9VQW5D{v<~fU&&XXE=sY_{rzIkSV186ldH9gET zk>_2LHlu9t>7NIUlQ@?{aG&il^Iji}s$+WqXKBYIUmw{0Mf*Z9oFp3%3I6UvoAw4# zed{fmoJ!V|=CX+x-I@1wO917tufAT~3|Xy5zygBN0(%AH>K+CZ1JidY`qIINL@Lu# zg2%*<VB+u$`WK36uXzJS-QG?i`baEw0^Uxf5eR&#(8(~O(m!(j1Eff1uJ{&3LzlW* zqA)!txwbzamVIG)xbM<!hw>R)l$)~*S!*J>Zav4m>b>3Wv^X{l=vrl9^8E&KI<X<> ziV!{Y9pJG*TLy%#J}4>}4dA=nb?<q9S@O_Qn#uBNpzF6p(|+JVK=H;_L;@3$(FGgq zG4&wN-NL7hW+#1I^qsSVOz3UR*CM%Ms4$x+L@t=^@7K(Vy_(-DLBv7T*0%1D@as*m z?{eI7+|3##I_D0n-WPhkjS=ds1IyV-QiO>*$kQ-%n;vsc0LmF$Hg}zy8yWfE4o(Ft zIGC@s)R|e?D*sMwyR~+al`m&<OF%4f2XX7lHl1uR)pwt77iq(xo!Acnc%|cP`NAsv z_5^){T<|hu*mlzJBfF>_x2l!i5Qy{6pJSsWM`JL|8-MTPrfsc&+ZL$Izv;8!lRn+z zHDbSlSA;>=n`ipXp%6<NKfrcukb-{x-#}F9neU6pQa?)cB#4L72r}TJvbOPM!`y`I zxSdrjoLYaNpTuUp9=gpWPC}cQ=^Z#h1TIiTmXw&v=BGxzvF9bvb#R*c^^s4!X1GM2 z9%BF6MTkr4t38Oh>;cHlv#59cK2tk)sKpz&ksW(znxpCeL{J|=P;XdR6pHZ9cYJKb zO{OkCrjC4_xgP#AGoW_+i+gs(N+$S3Wg1cNeLSGHNRvzOv09_eJRgno%$0YRmd;dc zy1%?D{fCBcwj#`W_Pz%3?gI}3N~CQb{|J8}WW&_AeRv`!lhrfzF+vuT0Koc)j8yjO z^tsV(w_vK$>z9}xr^PWHUuC%@$MRNAUng}o@~bh{!IpA5ckq*72g?Nd?b9<Z%35m6 zak7B7fz9fq&q+rWfqU+cXf*!3=u4oG3c&{j<1Q!~`IB1{I<6Qym6m)We}zky3cx?Z zT;J^9=y>*>2y`7QAH)d;2I8BvuX%hu_q`peP={|A)7JCK`fu6<N%5@W7ne-Vk2Aj5 zC9#Qy3QsvY_JjXPjkI!YkGdgKH}b{o)`<HjyouqALy_SRJme1~DrX&c&v=Zs<FCy} z89;B+|2FjToL#Md&r&ck8VH$tlRIRIEcJUp9@NagDzZ2BUV=Su#rks&34FsGCx#mt zlZ?=_WFdH{)=P{Tfpl9I6&8k<=mz;tc;AgnTUJT~BS_HH4PE9|?X1)Y?_o&+^}iAC zLXxf&(2U_C?3UEy@hk41yyz{QqBznJ4DseA(CuhqSImvA2N<lC6*}pipWN|PT3EQv z7?qPC9T5d^@wB0yGx#+M(o@q}NWn!<+iJ_P93GOxHzJcL(7L=xbBi2kXhUnWh**3@ z*F!4Q1tRQB_y&Hx|APvpVuR@dne~uu^>#@EU&^-W*Pnsr2mGYUzKz3@(&H1PV{*Dq z{?obcPw~S)k}$bQSoTId0wK9b34?ywde|zKn75e2&VD#Jl<})@sh8n@Cr(<o-8D%s z{T-dJlAH+eKtzi@fpCkAPvkKWx%mY)rU3KwJ_U3$UbAxD+|0g`I?8|(-#vO>04T53 z%#Zl$eFvbel{R~vNTEq1uSwh#nJq3Sy6Dp%<b~@fQj$+Ypb$)YlJk(8f5z=3Lt*eu zFfZ~^SeqGHG&)eBfSW;%HudoY-+Q-(8#?#~4Zjv*+9g4p^Z}d@bNKxGRQ}5h_QW!i zkDY)T6vu)+slR+krk$6f)bF=#q<e`gS3mZ1Mcst9m8^XHUr>hKnIy_+s6;YxmV9#5 zHvM`sKK1x~c)UpI7|$kA`mN(QJWy@mRcZ?Ntq?e}>Dw6Nkwg*3tx=?nErN13m``BC zg%16Bb-k|kg0Nc#Lqji>82T(Fom4C&3-D?2&@=$hud=eI$^v>Rh{s};Psm%DZ)R<) z;-8I_r+j2xCDLG>>yX*bGX%)%jkI*OdF~TP=*TwB>LT)jPp9(o#A?_6u40QfdXA8D zNM^~|aDqv5bbEYK!aLXppuavnk)Kf}Qz$1j`PXvW^8?P=?}^CwzhG1tloQ#hA|h|~ zy_R>|@V586Y;5wc@_{%KH#R@5NM`^eq^c6zWm>C<aIpH`Q}Qaar9z7CZ#-@;4n*Wr zXQUbpk(Q}qG=%}_pkZI?r?Q0yhL7Y1nTQPv@hw_@NK8FY{R<f>;=@MP_9}ll+B@F) zD))&G7^{mL6?R7^Z$BR|3X_O1g`60DfMh#!UWi9rHtD@eLd5G2Prn`}hf$wlnhG!J z;N743gf1!u@KsUGP4rV^vC`yMfB^}WbYB3>$FG2wUrVzxbNFt&LhGg%&URA2ssv)3 z16Qv0-fL91*744d6eS}o2HDYH_-i*>&jJkqor)fg^i`*yV^5}njmU%2GpC}$2fPVs zU#q{F+T3u0`VqppB}&bor+*aAL%PSt@mH`E3*XqJxjL5tp9y_SGQ49AQL*?t1o&1& zb&U$1U=a(SJtaRW{n%R=Um#Z&%RQDSalL?XOMGIuF)A@7F|&80^COBkS8jZAjOoDF zI-Vpyf>LAD+GXW#^0nbY*4f^aEGtAU2mk~1i8H9x#$1%-xgp=Y+~YnF-*4^`kg#(J zBRt9yq(DPBkPyO|XV+GiZ*cNHG^hm3DAeVR{s~)0Y*pY%ai1oHS<mCDHM1yXO$~{* z`|xT3XUdElPvRva9A)o^U){U5@J2l8(9~pM)!zJiN_C5AdTPG?-JNeM27Cg@^)8hI zqJ_VB=XeiD#QZJsP?lv_tH~&Pq0W+oP#GrAK6JltZo5Deg+$ymXH?!~a;*CV21Ep0 zEI#+YxVYCPaGBEV#;MxeXgq(i-@wytqtYp4=QZlAO!soHgGg|)Na+&?!SfTIJvE+z zv@HRG>!!)=h{Y|rES+~yGY0Lme_VCY>SVbi>zY4?wI;kRp^y0vCKq3!+1^|;3`itJ zoeRXi8AW|zpDwX9qKyAge|rgee(qnT_qP|OemyQ~b0HvZ{lUF{2)~3)DgxM~ZXx^| ztAA(sx9lCn#5LF8?>l8)Nmr9+{;>};arrJ~^7Uq@4=NrSFED-Vu+8_<lJ;<9>8{@z zw`q}3Z?cG&w-W6iBCUA7k1uQ%-FsFhl$=O6<X-*|CGuBel(xZ5x|PG%sh~V$>_lLA zO7e};J4J1q`8kzAa_pMc!Cb1l1TA=VLf1|TM6(@xEqhDaeDXafvC-9BKNRPi8&14) z+N1up{>}qN__?DsgmqOs`fnX+q^AD^gBC}r=OwQ8N_7PGI4(#!-m(IjNul<*FHdO~ zQaQ5MCj-+fe!PsLD&!3C=lgMEBTw4=fD3<kl!;1G7yoah_ukE@yLhSid$VM({zSED z%t^99_}!4k6Hh~e7jAU{wQ_GKsK5Uy=1M?heAUTFN$3aTF=?GT3^eG>W4oP9&7&SR zKsNc6mpsUtZ_2yh-{hm-;=9m{x0q^E|NP;1%19SLMw8)bebL$ZLOpbeb40}M=exCL zVs}p-WKZ3JID_znD#8FOIC7XWmjKZ4=v_|le)UA>Ko#vV8w#%46VG`}4jB@gZ#X(@ zD*V#3SQ|eM6SEK+x40>blcn$paSAbGp^nGSM@ff@Qm8f=t-Es1d9IEpefl`<ts`v` zD%EFEURmo)qV#)<*R=DI=A@M9*B!KGdGTY;f3GB~Sx`rmwLM=C#8(8Dujt?wMxY@# zq!b0Dv1tHmeo!eH+DdeNtuP(tu>$u^fSw4vbB4E*2XSnWDU-v4f;y;lTIv%%KMB(? z>ULY9o@3a~f6>z6R*)0}k0lTCyY{6i+yhWsWzd&nV>t5)*jV4`^&fd+wb`25`Ge*6 z_c4TyL)+L**sOaZ)y_YPjFyxXh_#(vZD^DrtM;^`t>pq1sOKRQnzqdSN|epJVC<Zz znbeB#1WJHRou+glVJRvLjiG29OX#AL34R9}jChld%;{!E_Ucz(o8T3i%e_vIK@F}r zU682^WFRFoZ!WqF>(bKF#Hfa%X1%>)cV%9<5frb`_WG=wxS`!PsvXKdgi5@G@UG<n z=ZCg`deZOL!Nh=_^R=H?;O<*=5^JlDR_kSNTk{CE+&zHE@VI5~4!a8M=AmMZ!cP^c zH(OM(5yAXy?T!WB6Q+h>r;rm5#Lo7W&iRb~7p!Xt6(ovBd+wkMu3P+xv6lO-zvAH; zM9fQs8huaCinRK2dWOIdVW@$5^n7vB(5)|M)(DYO(9Y&7u>EpwPh{2`zy~Z9$0Jsn zb~gY}&ZAbFJ@=*rsiS;H5O*_=l*Bzj8u8a2YG@`vACg0CE{^1RuLtJ(UA5E=c$^Hu zdT%Rhx0#WE(YTxYcZ3*TwRvXbwg_)#7dFadpy#Qr5C`z|A67yBz4N6{7@+e^zuakl z!Fpk~0@zlJ%P$gY8UKN%!~A#;y@%pG0!fpy6bUNwtC1?{vGkfu*La^apU#0r4d+VV zP32XuFB{W()+AkIn|i)3T0)Vas#>d2Jf5~CeBRwyebD)~Li2fr*f@7_LU?<<+#8nO zej8U5504nNIf7(32iOF(a<)+-o)@_f_c@>Q)V&NmX-lggUA^ki07|-#Sze#+k7~a< z=n?J2+^SNmfq@V}#TnJbPw-px@)>v!p&h?<s$7i;=W^W#qOsGX!>&CJYDPq`vy%`i z1tVGGd=?IX8KpoU@*qV|Tc*t1L|R){0TH@tJSoMqc^hV%zjcbe*;r-6eE|h)<}S<P zrZ1RM){MJXoJSHG)7C7rHkzSga}MqAX8hXu7_{PUR2@T~Df0K%crpwM?iS01_s89M zo{xPhPXQ)w#D$ZYPG+lQqaa^+=$YQCfU952Mm`<;4BLqckGyhZ^Lb5r%-)t2T1Bzg z7@VL+3O5D_QfB2U1718MpqSBz|ByKUeQ~~jCnZ(GCF-B$w<c%rzcm`zH?_`mIGXoy zX4hn^L42Lyqm%g}XFe0ak<q6jOzI?a`IJd><NL<Q(D~{RV_(rdzWBmejWq2$q;dGK zQgcC2;nbOvw8EHN7xN;HkTYK$yjy$}@E`+r9=;F2<g1m^X^nj<SlO#xDKTl3zuWaK zWN+Fad$jo&9lZ%lx)SVB_$@i(9w>k4ou-n{@k!T&W%X)CegEky2jcy}NT}%Rk8X`d zt1SoFoY0dtgwai0+$;DB5I^Wr28+l1Cz{0{(PW(*E!`5F9n?cz(#gPhAdDDaIIgRM zzTX;o|Kq_{Q9mMM?S>T>6aF?#@m7pgLS9zhrGRz&M*0D~0nfY+M~b(C23V4rDDkt7 z*{JeY<#^r7Q`O59Tt-Y|<jrhM(7((F;oYD+$GcJMw3}L-X@sz+veuO;SZ42-=M8hc zSM6{q4R_}o6BJ|Aa!xPJ7yjNpX1Ua|AzI{()i30x)F}nBk}~RMU_|)5x9AZw^}fUT zBCy=_m5(#cd(=2P7EZHUUS<5GfI*R#CFmuhpnBj#nXnUsS!dKDZ_MPk<^@3(uqQ># z-}d-u^U~ZG2q94TtG}aBph7}OKTx0xzkB<-k^1rMYUni`BYgC@4L^8Zno8kxl7EN1 zNhD%<*#ilA!|eHb>zcn>F=fO2r`-8orwx@XjX;|lVITWfCiyO&HWy^OQpU;@A8wGJ zL+Ow-74$yT|Hzm9dE`wb0UmQa%x<^jVF%#tpMqxA?7#A|n%l5xGLKrISO7SwX)zL> zEVxTPH48MVRDO<&*?x=`AjfX42l82RIzG1CO%T`mY(!f?-uOR6Tu0nYZj+?gLgoJT z1KZ{jEJlU5F(}7RtKUsa*8>7>+~ilGpDo^b22i7ZdAHFZ<{?=eD+k<&ysWYW$+>o5 zJ+pQ#A@cNofK%B6SE5Z=n{2Ewmsu=jDSCe&2f0KLRrr|6R4l@w#LH1mjdOr@vk4c1 zI(<1~gHx?p#1JMJXGILja%CkM?1f+72I%&qg#m*JZbYB`yt~;K_j5?9WJ6!wt0j|- zN<hT7ut5=rXNZvWT*u;hyX-{9SLl&H5%QKhzZCe{k*|DK<)It?j?Q6xI2dpCG-RjU zliG5#$7ol_G;{X{7@MbDYe_NY$<IvXNR&{|9H^gU>}^3GC#u7?_)NX8XcIi%4LsjQ zL|qz_0yJzVCpy$#(L$A8`#0T?3<Eh2rQUwMNj577SURcmF78W{qUR&nV&~?0Mv+-- zDUpkA0~lyu3Jx-DVsldw+TRqu1dQm4&wGp;R7&5B<)-5Q%4h40GncajF31r}{(k`G zlWVq9LG|L?I1rk}Y@G$zwAAsJr9HQSGn-DNlojQH3_)M(>9-Kr6vsvUDV+v$zhbK% z-&E|76Gt?p0(>^!4&nq=SZzlT@%MgpyQ}_Vp@?ei4qihe>Z6z4kp9MQM)Ez`Zs%Pa zYB4^G{#}JuHqZbcPZzd&(P9T%T*ybZHIqX>qE3uj@%9<rljYjZ{@stvYnw~Qv6AEc zVj(DBZN?p;_O&{7AHMC2F0hh9p{Wq!{h&TE;^HO2_&6yav>(y5@v*x+Uc_K*w!cYu zmky#t!@N9Zs=coUS$xWo{RNC!hQ#%K#XUVwMM;9{bZ@Dd1Axf`aW#Gqk<=%>$D2_a z*-85%r-;D^oWXg_WbhuV*I1dBPb*4BF?*d|&Lib&IZ7z=+P8}%o7^bES_1q=KvRr> zK;yxxh&+F1X8?P1&(;a*D~pB^SV^+%T0~@#ubUOB2Ukp{f*wAvHyW#%kW8Kl?+Iw{ z)`kU!?-PGyGKydNGAkJmV5x1s+8`g4qq@Q!YG^@1vLw|$tz4Ef!qwPwc@Zq6wNh_v z6h~mafrJ*XlW#8wPRK0d%Jg{UP~%21zk_<21Z7055<%e)YwNd5*Uu_ghqm|ohkh)d z9I;kDp#sMrKG>Y^u6Wa?qnS}CU1{l=X)h*pXcR9a@^k2gw{CB$G;v)&LEGI&7qB_# z{R6^*f%Hw0Ma|MH0Y%g?EoA0!gGSG5IiaDyUH=7in-3wot&0UApx>$oGsAb4rtelC z<aCLRydLs2X5oENnl%1hNrMQ9BZ}ZPl6pw0Kk&$$n#9V_Ni0iE1Y<825^PR4A9b^S z%34K^xWA&p9jv~sC}TDX^Qw{^1x!)ZLTrCKGn2_2S1vB{vBKZd8RK_qib>VvF??$y z@|zP^ILICbcNy~MRA$l*XIUC=+&afSv;n1=xz(-~=vDp_koG(m_V7;~1rkghsxa59 zNz0fB5F%$i>vbYrf)q-xCa_0&;+LKoGf^VNJFGIVHl6Swtne1yn;{pZ?(2d$1);R% zA2*lsmcx!=l`V~nR2GI!i+feZjbCilgWb@5AAa&A+VqY)8Xrpr{WO%JX_740O)(23 zUAYvtD0xO^hcPrkz41X})IS2PETh#6k-5~_B<i<)0J&cMc=K0&9afF3#&2DXisAr8 zLK$;*r`aTz;Kiq2ZGU7}YtDjCE9bM*x=3x>JRSrM<6vN?!vxOVG~bq)9z*2vYI{Sd zXAG)fc(QF7`{-CL9OOY{T8WCM!fVS4%g1<_dZed-z=|Bx9@Nd=;#C;;%D`b#X8Tx~ z?>_BZ(a%(|hvPP|vN%`y<#*TZO>=3n4I1muJKFJ9-7NqBn-kXwe8k7)3jfPEmEAV^ zRPK*!oxYXR@n6+m5kUhQJ$7h&L5u|AyFROqG-g(k-84UrN58)$YnNuieu-9{GtlGo zoJ_2g()ulf{`ip)X&9NW2ImMt&V6>GNi<6y1%liySW%G0F9Ht{d-}Z;&|xp)>}wo} z_rG!oqC#JVE*hFC)a5=#pcZq^66RX8uI*pp1z{>yz(fd;Wq9_Bfn)6Z)1II!R-wAP zr7hhkf~SL4oWEx8fB)y!u-~V$ElS2y=@RJ7!U)lmNnUBRF`Z;pWK)>FL`5pqtg4)d zLl|e(ehufZxuwMp^F+LVtwi>Y?G(>~0vuk*uYPu9MZ{f$e7I+k@~cBVMW|Tq{2~WT z-}A7xv9sExxH*E7T2E^SKbw=Wog_I2a`?aaq$KKI!-pCqgNNqlRz(BM;dfW{Q(Nhh z$f_MZmwst(!LpBwBHJA>+wB7LGejSlYf`mH2ex~}+-o$r9}5^a=y~sliFL+r_%TS- z<?j82Ip7bB;7C>ol_|K#IRax+!5r|btS6b}HrM6SAha9#h{}eiQIKE<ox2fV7fa`w zL9ouXp7-FRnY_G!*FkqV<7-69nf$zV-*l~qPZC}yde7=t{aNW(;PRIc&Y0U6zvLXS zL>Yzx3gMX#Wgt}CQ?IZRyxI~h5+1XcdW!BAe>AAyovTCa@erJ~hSf?hR3lOz9)V>- z?Copk%^o(+ExD87Q%Y@0WVzxp3lNml5omAg(6Fu(_!}(r`0+qvmd{@{KdFBT%YW0| z{6?Hir50!7Eenlx0>O&`gXxOl6z!2U>bq!N6m*<<@d=(NWOY3-&7f5I1%u3=YcFPk z!3=T!NnbAHcZVfBNW){O4~@n5qx6<la9dLBkpi<*t$$)D+1ZdmF>o0gcS6-d`xm6& z>hPCM$efq$!jQR5Z{?G=w22!33#+m?#|L$lFQD0cY8g>A{~Qx}1`PBny4q-d&XhYd z1bsk>J}0S;nL6r=0>1^|h!MQ;D>*?ZK)jX{Yjf`3*Yuu*-4}#jk%upNB<gke;7GJo z+{e<t1o78fY32jthoX$?byH}OXpqy9@*E~AnaY}CThJq13Tg()e__~8la5UQ%nWT& zX`RrZbZB=~%epxDn`Wv1cC75xY)ZJhrRtrxJA=dvzS8}iVkM1#q6dPZ&J1k5L*Cw| zH_&M_6WFH@YJDQ|tBMf>%uXEv_)$0D6ifE6^M5*AZ$6(j!d?18juCElxbThdEl`2V z_h`#EO=AXCGy{jjhY1v<{HYnce5Nt-xLXLj>nio>KfcN9=gxuaZA(wLIAb=l^`5KF zB_X|<R=xEi_tKw}LNhj=pU+!F<{Nz?!wrfjNN=S;R=vS;Y_IEn?H)BPz`TN!iWc~2 zE$C^HCsv`y2I#U$+uPrrT}_{KE0y!uFE_p)#hxJaP}rm*>`8X}_T~F6n0i+1m4{d? zh6}c_9?#Tp&r3aMPtEKjkp7nqCrxELy~Wbar`WxuN<E9B1}F!Y+OC^>g&pU3h@?fs z1(Sdsm+Bme-gG8WBU_DqAuu8E2_A{u;*nZ_h*q60(XR%|$9LyhqVjh-!Q*oMmZ*{s zpm25w*s0?qA;GtSZWSI|)I#AIJ3TIMe-pp0Q(JcI;zP0SQHIZn{EGSRV#Njf6?J*F z)xXHlbgd@!PHoZVqZwMaY-X8!B-*KoDv_bh)8omnS@2Nn@3ynlg0gn+YoF;XcV4{D zqEAG0i0E~thN|Le|6Z8=$tpZ(4PWG1u~iulR2XXxV^W>7seFih)j^C{Of+i02js4g zJ;B4|TRpDnnC-w$oWqHlRK&JrTLycmUSpo|KRD0Y98f#88kD0=eVC<2PhY5Z7BTzl zm+H>ldincaPCZC+C3LwE2vV;@uO(EgyYQ<wNux6hK$dkYe%tz0$5EkQmrXHhVfJau z*wb|qVg~`LT`TRDTg#{CS9fQ(X@|GtV`ZYvT5LHI5QUbkzxd7rU-{U7+12d8%88NO zvjla0pZ!AKEz=(Rj5L@Pr}@AABy-A%c@n>KJ%1rrcTogR3(bCg=S`taEyBsm3{t|6 zUVcgO4HPS5f!&~-MY%B}>T`THw6^CCQtX!Ug@WIb-VKx<TCLq1uSRs_6g_%_5<Ws; z-2UJ~8veQ_i**N_Aq==DOB7_snS0*@ifKgF%NR)cm4@Lu8q}}bC&#P*D|@+m?~Yw0 zVS*q=b*l`Ho*(w-HeCf|AU<s2s@}!U=w*CG8sk>EN{Z2j`MZ0E(O)~6)<113-^7UM zx!CmCOHtSK(KJ3~BGh|G^Rd8Y+-4N-vLVgvYa7mhERz1G)y>IejzOAp3r$c70`=&0 zN%kCa<k?06XC4VamXAwS;pZ1FL>1De0c|H(3scBZ#h2Cpu2hbx@1^gST5Es;ITV5Q z2-+*h4AjYXy%lPB-;_F*dVoRYV0zrk*MZ#NNsriD{Q=v2-Y!b>mXP065y#^jz1QDW z(#+aUh3gWps|QRP>(N(P@K-ML9n4QNuy>_!d;y=Q3#oY8-dO2&XHk9LgCGByDUcUt z_z$u3Wr<ffJM*7N_4RJKe=P~FP{_PwexR%6l|Gdhn-{TD<c8Gerx*g?C)C)#TJQY| zbV^=cOZr~mmc`meJX$eVj}PEh;U~PWM4SXrglxW(U8G28a&Do#u_VN{3hynfw{{ni zv=Z(Z{+kP}>NjmRJ#yvj#ZXEEXO>oiMfkm^Fa(Z9$3E{fcO%8!WWQT48i?R=FwpL~ z-$-FCH*+K@a&K!jg-x3#nm<h#%v(|A)WWNVDHNuSUoaHj2np`@8(^E0aarHpJm#jc zQ)HrRXEu4cFBv|Tnt^ru)9LB)p6Daim(->kSc2nU1LdOV-h{-2%7os_?c=qf4p3)S z8;9x`qWxqhv{dcly)%<8GFpDb$~29gK=Rpp^V`D!Q|r*mY|(%3;fcMMoX1v@s+L1P zGv-%+7aDfpdG|D)4V>HK|5r#u?kPv%^0N@4WHyez?(at3qZ_j(|L@w;8q^>yu>7z` z;!D;O4{kcMo#|4<BNnFPFeE9_=l;ngUL3Z=fZ)rJb%DE}o8j+mW%)LV`E|KjYG2GI ziG76|8>rp5APV9eaeyFB!Dh8wGQjnR%cKa#`_hY!0w((66~D_R_?habylxrpy#Kd* z9J?_pQ{ItTpzBsbv;5z!W`;1cgq!Z}p=8<oQcB+oL$BmlmOTHre6=N<CeZf<L78^X zpO|ldr1`J~en#wApgLLCM6ayX_HV~sQ&`(tx%E;+4JQY|SPvN@Crc+0AHc;cJ<l^~ zZs=L<j_(~0T_Mlo`<yf2s*-kzP#8C_rr4^k!?cp`AO{MLW2@<dQv&#Ggs8iq%S)4{ zjdyvz5p{gjO|@QhND@ph*Zo6oM2_*^mrSlnZ{^<v1)^Ece_526@R&^S5OT>N5#uev z!ql3>Zi^o%Ao3$#nJaxpFk*`-EuygWDqDIf1|Z>BBcZsmHu;2Q=3OAMBWTPTC&vOr z3WTU2Xow(}-5=ym(gx&u)h{Q5v$thH2m62V+fpKYC6Awm%HAgTwI>6agak?VX~G>} zd4)Z&xf{6;y$j0TYdQmCXh&MH4`Jg_9}$*p?m{;*A0)1zidoBjg)Y5C2kw^_CBrS` z&Z6@CDol~qQH(?11pX?u{n)QaakcQd&{SD|CPsk+#yq@OwEA$La(utK!NiO-qEmN> zEgdS(@apc#7QDZQMHKG66AWx#l|wxaeo~-{NB4R}M_vO8r1t5qsdD{pz06$YTDi@t zf#@G-I4UoAHZPB$;TkEz3~Utb?FyT|J}3%TU8}RU8*K-k3gbzsG3_DZjJ2r99>sWf zwp;P?kZ(#uXm11GNUW>A{7uN)n`nJEB1d&!;#6y<T^O<rlcF4n^kHABRb1u!&H(>l z)D+#<?uSrI_?xlfmAo@C+wq{-M?{!?pgWU+YW(J71n(V@=VUG{)hQJS+6jCD2mT9Z zE0MWjfLB-&<HzVo>pv&|s^WIJMOR@#_;MHD?*FEG&K~jWSTjh({wBA-++WS~H<#vQ z6mhc{F&Usuj!7r+o-6iC*10+>F8RX$$}h7NgHsk$_fHB>J%xr%^36ZULA4)|^6zNW zo<4=c>u~W85npbaq-Qx%w2rmoH&0B%ejXIL?jmHk6;jRhAI0=Bvs)z!10;UcKx!Ya zwzl5Xtyb#HPP^1fx@*S&tm5)0`tl*5<s<lMQ`vs=E!%FeL3Q`ly{;czMOnt5Cfla_ z?<D$=k^cM5^Ub1Nf58y;0ZB+8N{PsTu&WKmqam*L_DV>RKX%Im{8%-<$P`Z;;yJ?S z*5Yag+@iNaES0$!x;ph(X%3i8@3~^djak-mS6iw^#n{g?Dyj|Ku47u>aKWau9zNYx zsOg$$V7c>TyyrjB&WtErDdpN+>`Q0j<19|EUOV_%@H3U_pZLpP;^;xUK5Iei!8k%c z<hMN6X1KK3_#UxDik+KXjm@mb8O9jF*NXi0K<-VhoJBR+(pzm9n#ewOpcEZy_X5N= z*x>#l;``0CjEIB4hDmCrdn)#*!qOHMGbTax7a<F^;&61IwQu0ZBzX|2yOf8A0g5EZ zDnqPFf)7a(cKzm(!Ghc1N|9elL&w=XurRq!c0|tRZcq{(!#@6b5Og@S6V19i_OUF4 znGFFWIrg;@q)8?v32TM6?S3RKt&*dL5FT-{5ZthR((#Cq)Ext4-LEjn_u`#sf4Fb6 zC)51gJtxddeL<Bgff|;MKe*`|B#=a7^!luo2l{OrlM@C^ytzi2pB52G967P9(N410 z%;YG7XD^$f>aOSve|i!Rp5W4dW#MWwpN&Xe6Uii+X|3;wPQ+LXcbm`F_6jsT=~ZY3 z-dxhD=e5753!2vp66n)qc#zG0o_WSj9TS`&fNUhNf+!k1hLDN_AWF4g2&=_N6Aa09 z|FN%!97~_r-xq{6Y_z>walC7A+V&d&T8B%YaI?k#e4?6Xqnkc+iWq?jfMJJwl7@!W zb4F`>wZ<veia|e%CRx`CaUk+JzM>4s`Up(vz3G{0fH6}0d7SdI;9BJ7N7fhr<U-Eb zcNTL_pIQ}Kb_E{Ggbl`t%PU-6COHQ*`a{0>hcA2<kO=y{yu4_i!%miJ3qmG#HheI@ z>o@?4QPnXDlK#CnRMtLbMbv#BI1SQB#WUV(TqpdY3tg_P;(X{A*pk6@t1N|_k_$d( ze?{4Q5w0I<=(dSH_Xo`r`K8tLqtr2Bgl40pSp}>BKI^TT`t4S8j#%Tn@EZ3!P@#<Q z>H7)(_c>h8<9OKt=63c%<O$N`s;OCJbyvq5{rR<_>?A#F=C-YL8AkXC<ON6Pq1%Pl zm&4rEl|}Y;{DCIsw5%hdRWX0jWwUJ0qj(i>`n)EEn@OOc`SpfW)bf-4$)^O}m<Mvo zJ84vNe8}fr+1eJJZzY*HAFiP(W!{n0CUh`i+RywLO$1OaTqsm~nt28d7!XMiVIAh$ z4-eh8Xz6L%F*d0+Oi9C8+3)Yp^$|b^IMSM~723jj(<W~V=)!O?b-0Lob}>fw`PcY} zwQ&j1-GKU8I5FaL`QnFbkwIeTN59XhYi=E6K4+DdUp!&UTcw%f=v46YhNMR3&9jb2 z-drv`?w0YdsoBctY}=`^%<5O#wiH>KxDw^_&zr&AKFb@d4^p@ydSGY^%J>+n>YYAU z$bjVBO-_brS>GnHRyzz#2TdIm5ji@v-m-%uTm&@xWFZfPoJR^rMoXAQA<V2klRM9t z<!&oY!%*^`RkJ74l;=lJI$drbRGfJyn00byEUztpphdpT?dWY0@g4uyur!^tVCEG4 zhd1M=-1;*sz4uZIV1Sg*cNJCbw<S2OYgMPdV<le}dRlKuTx)CCsG%El(`t^S%hG`i zEXb$J5BF8e*yY15!|tXV`p)FuBS~kR#eH6wF{9t5&X(5^KSooc@~COI7y<T8vuQW% zeCQN*EEDlZ;qCdA#@Q7G^GsDvsL0aC4?A$?wOMvc?#1?Z4{atM&~F?&378zVbPI4r zd_q`otE7>BzHJ(6?ftRul$ztWBG~{)T8ZsL$L8H2n9|9gk*#Or1hsI}#HUuz>fz<C z=CfUNy?caFng%uHn^i_!pDUH>(>PzwG5mY&S5PUr%ceg*0vmtXY#F6eSWe}gcXV42 zt2Opw;#x_(5ErAD`PN)fx6BmzB`0&UhTSBDkK!W;(;fVo;N2nABjWv1uc2;?v<)og z=Z+5K#E##7eEGvW4J1Df#Cj<z(w_uU%^E5Fs;8-5lHg9khym6+?fog(D_&)Fhn9w^ zvROy&<XqSo3124}`m|#8G`Hrk$ISsq-6Oh@!JOi8-|uoC>@r_7kW(fY9_8RJ(k~n$ zLHs`esX$i0Qo#NNE%J?gkpKPacc%B7SH~vEPlf~UYS<@Vf2h=$d)15Kbz`i^CL)&} z<DpBDZgi!FC%S+~1sWNUUsLg*p);IFL6Q_}1YAKRg@!tJe=L=e8j(@U^_98`9IL_! zAU_I8oi?L0)Y6pgDb?|{J-yGF4(K6Y(x~f8F;WZVCxE;Y%A*I6&!TkZgDl857hJVI zt<x(25LPeSe%t=lwSR5Bv?sga(i9-r96blQk%o8x9g$|PWkLQ|wOakvacJG!xe4;f zV-Y*Yo;MhHg9C!Br<$G@ITr&?inPVvpco2{;{yE@$lV*yYtqNnVe)Za9ZkBq;tG@$ z@;ol1EAy_oBOmC@$y%(6CV)Ipmq9R6^ba%)0~T?7q&mT6sEFZh)fSMpZ@*CxbX8c_ z#Yn#PTz1r`o)7Y{D+ajl9E3d;c8JiIN1<~3aG$;Vo!+P|za#98T9=*KK|b@U^>XPU zpv1PnwCyh~$MrzM8Z2^l#le1Z_DUd5ODut#cs2QwAU}O~{=E9;UG@3-+q|Lmz-#uI z=88e?-Sis`N+2uwgxK2POk<Zh8%!8lA9^<pr=h%v!<5&Jbgm)4wQ=L6K;H1!f9(x) z^;fRbms+m8A=g5Hw<?$nko&h5Gf_5<I$~6Yy?Pep91O^nVkm#4f_#uiy;h9gAPfU~ zaX9K-29B@VTqDJV`kh_XZFhT}FadHU3IOuC7rT`Y<a4X=eSccE{UvVydU=m_`%H$` zu>w80dfh~I<_Z<;S3{&^TW%lun|O}=UG-PlhejZOlb$2LAeRZNLC*dYugUQNhx+X2 z6qO5dPU5(L(<5?7Hw152Om}yXw#YBEcOY+eo!dGuKGb4WFeN}PE<i3GhIlT>$qf=9 zm$CDDF39~*b&gu5ksXFyKtSFjZ@t&yx{maVQy}jI{0Z_c@)dv_U0~4$Tvu45ZNF{* z>e|0v)){hH?Y91T0@Vhq#h*FxC9?%hp2)St(E9Pu)psCz_3wB?+G%F7n|l$A1>{Wt znqmpD?C-O@!Q{nmjeej!h47Hz&G}g>3393IB$78@IWg3)y(_83bF2!c6v#)4O=X`{ zC&r3(U00X+AU{(3RP2CrOL-mF0?3nUkCY1A2FN1^AlKe5(K`}?kCGri@EsM9TkN6r z0^eAb_x55{V%u-1SU)XSWgS^(VbwZVE)Rqd$c~{SlX+O{au)gN^XfT3{wlW3pC6|{ ze$5lx1Av@K909RIFV+N*yU~DC(;(+C`_mvN<a2Er<Wfsh`$b%VRj~w+%N)0!BUh}h zHn_FOpEpMysgR4YLV&!j4gm7Bd}4X<0pwkPT)f>-lEf=Qj0z?$cDrYgXM4pGy!pw~ zLcYqjzpU*ijF)u(nH;sgp4vff+UKmiwQnZm0egUb`JwgWU&SEL9a@jP!8o|MFhD-` z#@KB(CW~A&0pwR+^ZKL_WI*0@Sn0)Xf#*?WF4YWsUZ8#z*J4#L86XeCp2lT3Iw1Me zE%F{^?$o(hn=&677I_}Xp-WYt3i6R)J4%7P9;nVfJr|!N-!8%&Idy>#dM4Ml|C4Ed zi7j%yXniedk!NPi#cOUx1J03-Y?83lK62ss^Xfm7_L1Lc%$gv-CMw6X*MWC6bsxDa zaVd~<^o6cMKpsd94E897ci;^ii6+0D951XAL+b~si>Yx^k39Q<hWNe)IX(6PbB7nf zW#-7cDtC_DZ~G1m_9-Cm_Oe6kI+s%2Nvqb2wb*Tee)?1C+->_GPW#u_%6lY?UbYTM zgWoxe+hTr$^T;C^k-q#s^3&h{tp56@`uz9bPctCz!;JuPy+kdN9bpajA28boL(SiQ z4#-{drsl{w;)V*3J@Qk;jjQ*gvG<zaCT})skv9hed%{fNl$;~)s1`sjtJ3}6Wf-z` z-Vsdu069T9$bh^}yv+l7oyvprozX;)@2fzY_2JCh&vpt1^8a1sgMw{;`P#p}Ug9HK zjX824TlkC!;GG|m0c;1)<7}%q+3gkWB0uI`<keRxkSnjL`h?$Rbgh~IxvW<oG`%q+ zmZ3Y0t{BKt;35ffj=QGfNstSmn}eoef1kW+FqEP7!SH%G81S1<Jc{S7=Tgg6L^<q{ zFojbB<ihJPY_o{IA@2oKdLj8GdD|VrG(avZ)B|<InSI$%-cg~S19B<9f3V+Cf%XUc z`5<S~M?n;JEXb{_3M__UDF@d-9MK9)!y*UU5fCSLnmk51{+0vz@%gJ$a^IbwAE!Xx zQ2Jz+F$1*$kn5D;%}wOoj+!?){X|FKZ~+tK@)A#_ht~NOsyS|mKWb7IH$D)?8=Mfl zQA_hfEd#raym(5jTJI7mL#4%(?9#K>Yw7eJc>@O^*S<?Crqvct7}O`-*%O5Pt|Ru= zBh||XIjP+VBcHtaN3>dyTUixA>+2;o$4NNZ4YbZ$<Or~1!aPoZt0R}P$WQYwO-Wuv zs@?v@)T7le`VFH%GrhpPf#ig+*o}n?PqUQ`P>Wr$UPRUQ>QmEw-|2+)TW@`lv(}-* z10N&pcf2VYO}I2A@)ug{wvF4*rmJpc_0aYB$qXu|Ic^@&Y8<sb=>QmhOuh;&IZ?jc zHKx@+PYsO!^fRt8ou=sK_Q<zfHmh5?&J+b~8Swyn|BhOIw0p;kt$Vn}bRPLpi`_7q zxxmh1XRYT`yjI)V+P1QKu-dBCW@33+uOrXiM{ZtXDgn%qa~vG)5pNRa3tQyS={avV zgWguFKY{DH!sPjw=fxvuQOVT$c;MaKQOl5*yjc}lu$)&bcdxz>$V1f)E_*$H<^mfl zIuM2+zFl#wtRA{5Uu+S~?*e&gPiW;O>qK(QhG)-#NkqX)mtfAFD)X;ee*};N<!{Z< z@#$=R?9f|o#u}5}kvpZ9@xacDmq6}EG07{3hl>^TFFRp)Ii2IHKiTbZ-BR4j3i_fp zmE<MAG{u}F&pVhkak-g^b2z~Lf)@D?&T4dVv8)}2x$}J4dGXSy@exQ~Y2ljl)ob;a zrVz#*D=VuHs?_SArbRB3<ez8e$YE*oH-mXV9uCSZGDp7aSXr&wc;0(fTd6s^{na;n zu5&M{VAc8(C%e_RD#jbxkAS#367fi!95f45#6fswWh;;mQcwXhARdArh2TSo9NT`| z{&f4dYqck7J^cXkvMyU+qhFq!Bgdw3fEi3D85X%jhy&{!DR+Y$vLLtm2>R-9Z^deC zIrpP4{Eem0TCaaW-50uR7P)2+9jFA%3>+zvuzZ}@3kGOU{6%cVK!s6Me0ZylN_E(} zyrkg=-U<{kUW0d_LF}R*x9zv>&uRZOqkO%*%huP{80J7Ra1J_8SfP$TL~bL@&O9LZ z9V@HVtM=6@<=)>w_4e{dwAL%=<4pSt-JOn=2y}Gl{?H#HTbz&oM982MP}b<{9TB=> zq`(u$A|BX4Cu~N81&Ebu5kO1$Yuj(zpWptc6G&d_v(_2o35y)w<OVdBdAyrE@*q!| z%OZcg<J%QER#qQW+g<kdvl@&T`X+tsz<5E|Ev`hOUyO^PhfXjcPL~f7;lk`fmkUb^ zh1oF!0EGmMAB!}!0Q^7(0~faaw*3>^zg7R#7P}F~v5!3OBvud|9wUT@h<yuM<Tc02 z$|{z-yZLCTedOlq0Cdz4dhhgXWF|)@1wuUBNtx$J%$*Cx&z!5cZNF{*<o0h(*+*VV zlJn1Inb=NjDU)D2WLo7QyE#)n7sxkuHytZ0D@^b2ZY(vlUb917R#sC~n*j3CE?U?B z1G2sb13NV-jwl^K6#jtk4ASQU`3t*G#>y&I&EHuL<n}+O|JXa19JgU0h$cCQ4cI~g zYZC<UX0r4$moT)}{V$NFAEr_oG8$O|g4omL5Bo<_y%_bBERl)C{9|Z-%ewHeH?7}( zA`ch`M~nsuli!d|W2~I_t4j1;g}gtHyF?;!Lw9~TEG*=wW+DH&OC%C=_||6R54!o; zr_X@h&)SSUAe&xN<Ra`YMlSUI`PVLyNCdhIgnT_C&kO5`#5*`WRUt2gJl+jPF8Ym( zO;#xicfP)yk&BWKS;-TLKsR1r?kMDWVLg#pfqip7^2hy={8N*We?#abISE%>&B*n2 zUm-vAFV{=*h(zM+nL567t@R}2iNqS5o^FZOczDj2ar1l75s>(*mUqL01?fIUu1Y=} zPy1aW@nI2vHOGNEzL=5cFXV~D8tk8KWw-KQ$eX9YRk~^9(TngYJy-8L7`ad?`E?kE z%jK9zd_ats^AI>w#}^m!B;<+28gxxY{;(^;u#M@TVqG(G74v#qG%2Pb-Cf8FDL<dD z*B?KA@{UgfI9-{8dxwe21YsP^iuiLFCWgTSZo_Euh-DbO?b$*gS`*A2YUZ!}-8%=o zKlmUvI`|+8RHW<{X$>FqN&m}q9ySNYB<^~RD&BL$`i4vEJH!08DO&E@?NZ&=NvUGx z+`cGChiBbzTH_@1&-~xdzkO}}k?VLs`;q&ur4p@mf4y`J5%)84Rr0_~BGJHk0#y5U z$q^l~D%zcLRbCTjF+X=R$`4p=yaK(-_y$IPVi`(ba$5Uc_|_J_rgeu{t%pt5SC^L8 z2Iw}4X3$&#R9=dh90HxC+lCp)mI~%qg*aP*lP;Nm=D#TaZ|zI#kNG5d95jqv)j8TJ z-*#q>QH|c%u-^R}xo`*^`(u>!V`<{F7Hw(z&_W7Fyo-)}i#$Y7u@e#R0KEu1-i9RP zCPjE@FuisOD-HA9BA6-E0%l}@z5tQ15{`r8D{~QFM#Nj3A(LF`fuGP47O%|zFZr*> zy52{V|4nbQr;Kkb<TvPa=cir_f?E|-?TS(ND-N?TQ9Y1?9Mvq<;L<h5Gy@_KY!r3N z{4@VW`R|`-t#$Z#VdSFP^*!k_NpqKqw=T!8VdP%R%NK2VhYfqc+;~bmF$!3TLYGiv z7fPc@9|(asIf+NaXaO1$%}mo2{6GWJGyiw<7o@pmH8g4MX*o7d-A*L(++N7PbzQ|s z#EDGu7kCpQpw!_~<*yu#>8e@k!Ce)q$=y5|CiBnym*n3y3i*RBwQi4}z1_hSVM@5s z%%%FT??u0nClZNytX|n|Uon#IJw`Tnifl46*<0t!t&FTvWirDIBg_0V|7H0%Z+83i zkk{7PG)0U&&|u_fD&p?)#aoF&Ut7pU!BC2BPT7f}fzaSZVvuMxfWpy4E+<nk4k})o zjCcmEpeekAX0$LJx*||%Gye~tzhUj}XZxCw>td+0mPzAW<t@u`Tbnj5Vq`i5@4&Q^ zW5TXJph33q*&!><%s=yAl7IJ1cddWs`7`6!H1%b3l;*l`-V@=T-Ov1C^2<1m$3)@- zVjM4Hf7pC!{m*Sn+U*(L&wto)VxFG8)%vE?@><tdyAR|O*kGplaS?|$DI~zWz~}N2 zb*!0x=D#fex{yEY3ay_C9oG`AzVeIewlQ*K(QgIO7D>((cdcKJx%*<`Lu3E_G9ES- z^8L>4G4^vDAIUh4DAA3MMKMihadf|hIB*kaoaF_O6r|Z~D!-)|H=b!vO=o5uqa0W= z|IB|`{?D}5IzN$raYjCU49!cq<mz5_g|BAh{g_KcClaUeaM*Ndy?b{GMQld*7w!N4 zhdlGo{BL-oyVifRcReq*(@<FbJ0grh@tsj0_!4+L(1*l8bTzt>3qlp#B$k$fn-{th z7w+wD_U;A$KyPx|)6*Zf&fJ-KywQI5&TVhbNz#)H_v@E7O@1KE@#wj(X8T0TMAB2D zCzlM`yS*a62>YTbJ9Zo)!;{-6^8LYXJ9eCh|I(r<Z>QHnk<$(`I@8{>=e+f4e1R2A z+amIv$9L@5V)Bcf$an0R<Kc<?(LN96h<B1C=PQv;uXRhZ<jpBXPWIt_yVcKv*s)_r zhWz3#M7}RPv}4D)ME+PWlINS&kDwLCr&qlZ#MiVIIeD=K&?xzgWlW#%GGfP$0iQm< z_%AE+;G%dlQM-J6HVScN4W?byp*Oy%N4-RJM!W`?H?||sSLBcPi7+^{zL-NsOwDg~ zqwiy)q!*TPh9bXs?<28e#||dR&s#KQsmSH{Ddk#Sy^Z+?LsnzRxUp=;?QW?us#gA_ zhZI--YMQWK5q*~%bxAU<#c%!0L)rArfD<A@#5AqY!^71wes6CQzpYPr1Xtd$*`f>L z#_`wMDl_dPdGr2XV%h)Hk<CW@>)j9|OT+i1{$&EX%~EdF{}jJurc;Xiaq{@v?5=f^ z+>;S=qVkyqciD<)e0w`0fBvD^v17-8ub$jtXkGH9F8Hz$WlSjhc|WG}X&W_EF?)*P zx6Xl+0yBc9^!f9*`z&P~e6eH`Xbp?>HfZBd?x>v%hwP$jOcAYW#+l3xEMGQ*O(>>V zaK~$tcPJGzjqwi|O-^7D_TJF(Ny?eXrD&9bO63oIG&?{z7+_fZ9q?5`f^)9%-dn2! zrendNDgOQ)LbgTlXdpWt<ud*n%p(5f!XOxbI7s2^l)W50*5el@1{S}hPcg={(f^$j z*pbqYsHgoe7X4oxmdmDy&G->wBmP*~t^P;DGX9mD-QIqzH@h9F9EqG?1Se7_s^;bl zKD<6t<d}AIBEPtJzF*hdv17z1&o6GK$k!jyD%dX?n=Py$L;1`i9^kk!09`j*TEc@F zen=CSiTPp{d@k`7KtzK9oi++4KvHfTgZ9#>oIB+}A_p(1bPFXNJ56z(GndGY;3a{~ zi}>xK8NLpN5KCiP@UeB?dWv6JDNSslj<JCzUI}3;9V;87t5h40`$zEjEeN*Ymw|*z zRRArk><a4Hk{}KInzt>)34z8sHD6)PJbvsG0wXEJ6>s6@5M=F-wzATO^*?%QH!@xg zj-8Xu8nV%y?V)Qtnw5^s<?v2710i!>Wk;@*q{RG}sv&f4=)Ud#CtF4X^{M{H&w2mj zW_4)&aXzAz5jja}#?A@2W#;^%H(e*6J<jzuiu{?_vE$w$KY8zqd&EZ{h}VS=o;|sf zB44F9slXjkD^Mm8Z|#oh9^AsYJJ7Dul%F;n!UA--Yasj9)-x#ZE9|Z-FG;B;M8E_r zN6A%i0hj;eHHLz~v^BU2>e<mp7@>ab129H)#st@Zb<RWWN-4E6vQ|>0t!$6{n-Fw@ zI-&xV(PDaOa?2`J${tC+JE$A09BaXAXp${<6M7C7Dy_lll@k;XhAj`eh}FRas=zMp z`u1UTTEZbvHVx(J$DmtYU_i^FBO8ozEYi#i<D`v5KC1^Nm|C~{pU1&CdK$?3sxBF8 zL+g)pWWB#c{tl5gSJ&@uTqEaiCgaak<YLE;`^FdM<vruY>!Nb`?Be3=Yvl426bz)G z89~H_Uy;mZ8;__|Q+KUA4W;xU5Rr3mQf}jj7K#|q%!!<FQej85atom*BHw~hP)z+o zOjO;qu{4YgGK|)sv@W2~F0p(6SDGW*G7M2`n@~U=Nw>Ta+iI-LK#!`pmJCV<uaFB% zc9eCH9Rz7CSWL^cU`1WhtL3Q(c?);Ylws&zXcnggHSJf2t;VH2hlMOUQpX_IAx@_# zB~K%!z&T3QoGg);Ie=oRy@mGpX$&{45&0vYMvju4UlixhW}QFHZ8D{N=7$bvtVjN2 zC-NQl4f*BE7x(+f-}gWI>E(mpl}SW?uZo<A9ML5i9(*fHufh68w!TEA=o8&kHBvwi zb-ne&TQ|@wiQKr9$*9V#Ws&kUksAdZ?j+3^bf2+K;|VQuE=K8I2X+O4<JvW#T_W#P zYlO&Tsgi*3l7MD8M*}vD75gL9p`ABF4OL}b3w5oAB7@4o76-IrqrwbP-T;~f){KX2 za3@qG!%NT$lB6+f2DN&+)M7_&!Dy`01xnf`@@C%QW=s(5wQ(eOROD|z+L`3EjOl#b zoCG>iJn{CzPfqCmmWuqzdt%3q`^Ad~Al(msdijZXEqM0ip@^J*zztaGdX{qFdxkHi z4E?xog3{ZH*MbS4SBM;J=47{)rQITO+vlkYxe28vWot9UNU)Py2QD(;X(yDJ82t69 z2T_dUM=66boifHq@QI8jL>|4@3nH({g-~f~&lrXii|)ARpp>TQIoskEG_v|3Ol34g z#%J3A#U*X!CBpVaI?yY$xyi16z3*cmvbGGm#1M6ty5*4fL9>oKICGP8kZE^q25q6d zCq@3a?{%Z;XLJ>ueIr@USv&*x@ozD?{7yvv>J|U?_bahu$L;XZ%ZE5Slt29>UJIVR z_mD&`)gf~&4XuajFb+{hX!$krEd(f})DTvQyi_v+pt?7R+=IfB$wq2>`n^%0&2qfh z5Wr3|k?t*r*3bY+Jx5y+mmZAt2}<RS$*K8>pjOr-A`fGoRRtg!kfFWx6RL`-^r@on zAUABGh_h4k@s{v#J&~N%LX4km9tU>K+(1Wc*_W-rpvz{FMyVjTI<iv?6}X|6kSe{# z7GT)`K)clv`Tvkc6rhfu-FD!Wl4mIL|Jb4_Z{g}^Tw61WW{R9V$PInSM6S10<j<$S zxxfE*dHJ^>{CRo#$M5G0vlsgu_5UNjd>F?4<iRC55&0djkqiDgCvpv8LgccB>r4SI zvqrojkz<Ay{DR0M)S-Z8MMt$@X#|&YxWUzdGD88BS;N}>P{snuw{plfRw%&E<Htbj zVW;w@^k6kqbtI0_QpO{SVwBHTx!Sf6jZ#S;>T)<{pGt{S&I7!@4mMEDP4;nZJi?WI zxE`)W32xNI4q8dhNa$iz)hea)o6tDSl*KfZEB$XOHTYfoFlGD*GkD3+Ep<EP7OR?? zB9H+rD&~nIF95*CSzeJH9k~@cp#qgQ$!=f<D+T|T3XQ>1?sAR%u}bo{2SrZg&6gn0 z;L05Lhi~LZ&va!he?F1_arxPAuNbfYb!2kR%;Gk9`tjFuW*29Ha&KFAyb+Kn$nPKK zhXv<;_ubO%)1RN+acKSGd_^wAT$bQB1;fM~4Q3>AAu?}f3NS(l2PS(Z6a{7xR2IGE zkRenmr5Mm;5D~nPbe}a>MH=GBwL1ACmt~K#f)f3a-7u0)O;PlPxnUCa)iK*3w<s6b zS^PMQOX2)vk5n50bQ2_&6P4;zBcQ^W<W*{iy2#vYm6FnQ2CS*dTs+>}Z=hzAreg&@ zAHVTXP}Ew@XS*vcL#3s~sajY@4MFCf!J-UUiX>LbIEVuuSv5sv&`pr4UFm<Lpk?cI z=R}3|3lY@}o=rORP_Okr%6T!LG;Tm+nf-+E&ZmkLi$AxdRRBdhGA*5KP%RlE0{A`z zakNfh`}`Is@j2*dt{vlU#^<y6*NFU4&ptacIn&<D`QcogGdG%Q&Qb>2zl9>dm=pQs zCDJ(I)#c?V$v^-2#a)Q}#m66uJ76_8JGNiMjyC}hrkuZ={r6pc^YrP{Z@$jt`>7!O z{PcUViJ!ln;L|gS{DV`9oIOW_De@sfgGfZ4nJs4T>X1@2PI5Me9EpT*!-pwz2Gmi% ziaz(?(LhT))Mpp@?V!WL5<sIZ3EQ4;V$OrYjwpivKGU}`x+@yaJ?{GfVCV5?9ybDo zZ;^;Y19aJvAgxu_9rAT>os@Yd^4eX6;4AO}xertyQK$N=>PTEUXjS&{i#$VH43tdq zBQZmp4#f>)6TNE9@k5tfNRf-&AIeAv@nrnda~K7V?3~B_T%>!jLr(U<G_;YU@Bm#{ z>3=$UDS1wt<IXQXobotuEPkbOs#DZKOprIk!u??@@c-KXmBKF?;u!W)kyGT9|39>h zX;S2AY<+w{8<W_W#Mzmvb4(}q1T^C73`I_~EeJ&IJCXmx-ub*XZbWgM{vQLSfgUC{ zf>^p3nu~UV(8=;8EChV151JS$f?O(mODOKe^ibbgSVBYpfwqJ~ZvDsl-h89y(T_Uq z?n2WgUvI3@=)EV6wD`jtjYh9}2_Wxuy3B(4`Q-c}xTNxY?q%fZGa31O>0x{uoWI{- zx8Vt4WJ*gZU?tQ|PC}WF+Jjt?Xvs6WDS$kznI%<TEkcPQGhE^eID|N7Ycg_tb~=_k z4d!r+3mwa>oHki2XrXNr7z+f0v#32enKZB}+;O8K(IV4rzct`E)x~8@&@aMuXxt_w zlQpeXM|wd-e`^f2p*fyBZ>DaE<EH&NqtP^bAys-|rB~M$J0%$79l{Lfnp<lNT_FBU zmx>8U&dh(<kQdr-OFC#?uciHxweIOF?Pol9uRpp9WX{s2j^Z{p2;B}2%Up*$YFFp_ z<3geWH4xw9kbdphB8GK?-lhE^Td-t4c!Y5K@}iOJiac@P&~W>C%(_BC??V6W|9@#e zYCfsgn9@=E6T%E+<U;L%+1tcU+`;q@$jAlcfBf__)BBg7zVShRv$-8VY_8SyCY^2q zN(81?55a?D_5Ega{Sa)XT&C?oa6c80j~c7=VLaY!Mo$(gTZmvr!IgL*)XnssY}tFm z-qR=VM=p#uk8H~Ox~5|bHm@ju2@;TBW~BKUqcd}IlwAhFeB$!y85^C`0)M3K#RP7o zH{w4Cat?~c5+MJF>KdO1=O3|aT@4B#hZ1d+133WB;{M&}?bFtT3Nb%TU1*JWhuF#v z1~g8^TMPC=Tn^Qc;!szruQgmf8J%>e>Gr500-cN6TlEIJskUl<n%qB_f=Cwbt;_;z zI>KN#!yq@269%zE3i={+gWalqyq#4l*+pjN&P`(%X^WZLMaG@yo!(*9kzQ5&O&O@1 z+PFDr3JZ`6@(#%LIdo)8IZP3EW31J)Dmk2Cl0SbTQ5_G&Nc`0>{HKS$<_o0r=h|)b zN+MKhSi><st-)^mwig09OQ0>I(OZD-&ED25+q}o;13~`l@$vEZO3}EtAAFEsjajKm z$H6HtZ*Ir8x8w1ZONX)XnxQ@(pWcp7r%xb%M^<FMQEKB%rY;cqk%gxz*^sXG#e1gr zc;i;Y``Y)OjssVFIwC_H+pGS23CPpnE={*Vs#KPxEaLb!n5TDHFjML*I0Hz}p8l@V z^diVkoEvH43U~8hdom32>;eh+M4e~LAe$4R?=G`IO|lsmXY=Lu49Afzw{Py|9~b0b z{#%gam&}Gb_CW6Hh~hJ<09cr3k^5COTEDG$2?n-VT5ID<+%qm97Y>V=2#KLcEaFhF z+Le_K+eQNOmXMA|F^U~^Kwd{$m)19Ppq7kW*&+eR`4}13HE%DCQ=#cZ7)W-Om@+~K zg9oEBcZ`emj_Xn22F-l3S#%v#M{+fkWsL1~BDe6Jvw;yneuzsbB7JX*?+b*rnDsA( z)b-Zm2$vls_pZNqAGL#qI_U;NQ-(n<o^t3?DHYlr9pExf92af8u8e+bhwYB!OZ<jG z{{MX;xl719_sE6mD9Wm^y+1LlhkvYmAjrS_{fDoPfBF6Rs~>(F=vrrJ2G`RO(|e?* zx8rxb;m>O|{c{{pZcL12n%@KDwCUbiU88H=`JY}>*3HHunB9;W7b$IjcRGG#)7$$I znR2xfZ%6Y}7w^w=c6xm6T7N<EKt6fOn2EAY)g_}cTb}em&Z{YX!%h4zgLD|=SIajI zdebaRDR8!3-lb~7k+M0}WG?1KaB+6AoM$bN2T%%-f3$n#YJU^ke;EdY+%4*b&S`_Y zcMFh%ojX_LTew`%C0+_blr5inrP&))MO@R|2*1%0$BVGV<yNf`P;lVHFyG&AhbuUq zdvDdk5H#AEtjiyLTHWf*sG?HMhIZepHv9J5gfPCSVbtt-5z?ZLRnw}~5raI@A{l5^ zM}^U4v4~skM?bdPhoHjkbVoSJb%J){rg5d~{e9gVy<3-r$Y{ogw$r(bSaO0NA##bc zO>WT)eu+-{?T4|npFj#2de^_s3u=bNdD*u=r%D76zQG64U{@8ov`<$$au%?37gCxd z?Y9&(frU4`ff{P%gf$bwz*BaND+!LnP`V-ja`+CkKduwnfr-LGL%H(XFAj()E7&#! z^8ahsI`Z+)I?s{I2MhU#iMK^oNaFI|kDuXjGZcP5{vOYv5y*e(f}B%e(ul|@v`!T> z{Fb-=$=lwIunAU_Pd^IC14b?u5MuJ;F`z^rMFitA0s-VG!<*wx6+?aV3i21E7Rd1} zAV+~AJ_K@JOIsjE-}%WP$R}AazkK5-*;&R80Qr)NC(AkS>(T}8fP9|vzx1Pbt;@_I z?cqr12@ka{Y2ADL3_qoX4rN+V%;v>O>4NfYgMmn)?YuTcev(zF?f&sI3k<<j4yG<S zF+7s`=F8@Ui>4CGN)xpNIwIwNDO=|R=Yo>#mTD0b0NgC2f-s(772f=b-o{M@aHaUA zDKR-BK&6wIE9*!{R9nY{v&3(|YiJV@iz0HM&PyF(Zx$1o-RQ8YSF1Wn05`3Tbvx!U zUuZYi?zlB^9wIK|43D2#9vjzgzt<YbRuQ7gDYumg`4nMny5~WVEE1SWIQV&5N4ls` zsq8|V#ts)!c-aJq8O5vi*&ySEjw~u6fV?%J93gdS{YK4nfq`$lV`!-TNizZN&g4lQ zTb@WBE$#jPmkLSGKdA{}=&=2n-DE-+lu?pZm^6l{_3IIZ_5NM!-+X)gyAb{OkLH22 z@46tDTzY!*=ok))j>cn0>&?wb2D^#Xm4KY`Yt{p?U35>|AtdvpTiRJVe&FK9ZEbmP z$a_kd$ML*^`~|54@@>GW@`Q9kj7`xU9^4Is{4$u4+c{gq-_^b8fgC#920?b_f&5AV z<W2E{=zRr(Z`&Y0pD3pI<YR&SbAVh1D)~Q_=vrrm26PaR%j3uSlX1ZiT5DZ|c#D^H zfw+IQ^(&ol0953<0?4VnE-+Jz$9zz#$gQjjw~c082uV22CV&Vp(F}Zq5w6DaL*Iz# zDb{<LCzl@?X0;557Fet)fFV&j*FZ94T;V)m)Vf`l)SQ}E_=^s0S6ReJBHChcNTN!I zJ7XNDQR{{y@G{g+c$-|E%s2>#C@MK9%Mh}KoGCeb{_L!1zhFrelV4P~&XS7oa2?k6 z?N6v0V-bD0wI9FcaqcFT3ni1nC|pQ?suftf>ds?t?skUks5c>y^kd|@FfrOCW<Of@ zj=GgLjp<PPZCMe&{W;z$F%fqA?f1vMe@b($%M`7WOAozryq}TFN9wzM@9zup@4h<z zK|uZ!O4P&t%`nK{1-E0CfE=hLXj7MW3XnHew*qqhhJ@W7^M%@onT|L6s;>7d$X})e z<haMp?9Kw#g-f`ds62F!{3^)UjfBDk>HE2WysHVZJl%u*LO_n<MTSi%LQ)f?AO9Zt zU=sVhjE<X<ab&2BDQnMQQU0?)c{NaJ4HKoW7+`Eyt^Bz=pnf~nRXnhpM5K*aB3@6i zS%m!dvdA<Bp^<4=E90gni!fUZgB&j5u8CR@;Crff3kt|S&`M}nuagAO5v@YBzNMtB zyLEYKOmg&$e#B0d-@vsUG+oyR-*BSf+%j6lhc9Fv_4l>bdf*fp)Avq>kJD;WXRh_b zTIIb+eIJQ4kdgmi=US(Jb&Oh<#9MBXw<*n^&aic-eLa?f^bhV@|K@un<kGd?2RYyO z4$_-Z&;_{~-P{L`(zJ<3t_6=b(@hKH*ANF2dO!X%kdOA>uONS!@<5(tONYyBdrq1h z&d8T!JU?N#Gcx|#%gBd7F1ia&4uX6OY+rRiev$_B*$09A%U(wQIfJ~N#A5xhkWfD> z<$a{WlR9A9uU7r~ZY1CKkY~S%J~R7!8CJ>EFl$F4Q}WUZ^jFWHllK*TpRZI0K8M=) zoMAUq$4c~Xuj9JzTVwT^1NCl{tfc<%eg~oqH&1r{sb%DUv3LHyN(4b1_s736hQ!L; z;U!#bNW{hva}|3HjipptTtV~d_cYKL3tAIGB=#m68?5}toZXSh?9Fl@rwF=Ve%!J< zv#`7uKAF9pTf9cAACYrV&8g!mA{Q|^Rq>IXTjh}x#~&x(IFCFG@(oRUYmgIMZ>Z^- zjK4C-Y0kW^iaJ{sQ`nFP8mAiM(mR6uJmpQTk1_TZi`^zz7!?lUBL{Lkj2Px%7s07> z<j=F<Ir4m%0|)F4Ab&myO|3)jrU=?c<Q=^2i^w%_WsLI*FPr&{>cjYG!Vl<oV|#6( z8@MCiUn4?kp9S~?P=2bSQMy;fJY}{2LqZK<y7CaQN3i4OzXj;7)LCZrWrhUdPGP^P zu7ZaDR#xz%wTZ~@+`4tCAh+@O?YrU}In&yU$TigE>2p4AUD~Ff%|Cof-hE6SfA}z0 zAfMJj-mg!sSA#XUwd(|OGVX8Bk*B;kEggIp<Xv{VW1vNI>5c1bhE{cur;L2(?ScGz z_Zp(kK_1AV%$|Cy)`yT!R>s)qyd+HL4042Wp+G)#ywxD@p+9rJe7h6mqpWaYz4>$L zXPxa+AR-5eS6Rn;B(JXxg6H9YNk!!Bz*TJKS#X2GgzOcXBXS+z(OpXQtj5NY{WMF1 z5csi|ZPH16L%Ue3&;%;d<f8Q8>R=ozDnzC4B*&(P$3+#wLolXR*7`lw-=Oio6}+2n zQa1YCcSYo#4o2h`I<=0HyPwg`2X%e_Qo_A3Bz&_C9a=`@?=g$~%4U%#?`t5>x`S*A z1&7SD&HCo12J$IZS8I1pJR>ZVRb^p|{wYGZJE+!}vF3;5-LGqGPXRWz2Yjo(0J-)a z)FSdVw#JzJ9OQwVcx}wk3h8TXE?DLklCQ8hED_TTa$2E|DQea@r-bq{GkE~y<UbmZ z%B*nZViW|qBYjm=rZlI>BiF%|CkVwjv_XhsigIizP!$dJ@XH-)CWCI}q9U7UIDE)( zc#GC=_dQ^a9>hcYz;0JK!5H)#xBre|XBDzrO|4(*HCk;%?w=#)DRqT#8IcP^YV+2; zw~olK7Vqcy{AIDYs)4+pb-Np0>~=lCMQody4|1x;dLWRKRW;*Fy)5xCvlg=yq$=x{ z^&J4XC_ql$*UlS--ag1vtX@OZ-<Jfr<LDSn=42`P9FG&q052w3EC9UpvlY5I4XI#? z9)v*-g|U6T1XQoeCc8im!_rha7Q>flJr?Bme2{kt<Wat0Z#&-qO~FB}|LgcedE|F) zU97~ab%}3p6SUgIIUA}Y`y37Od1%uV5K8+XG+m|;P=D%KErnH|T2k^v_L2%=$3?AF zdh6D>|JhmS;geotd!9pSdO*cqtL^VzjB}o8-_uj|cE_eERjxpO)PCd<<WW&d%^>gC z$ED|y-?kAs-X)tE$$U_J*XPE?_NOf)a#$qEr@6rR>o>^){+Oza6z9bMC7om&)5Dcl zPwlg*PO^>Z;euajh87*_*0YEL<M{vU@dvjty-<?ln)Pi&j*|G+l*R);b4kYXsADeC z`oRCuoiAj%8GKHX*K>%9Qab(C@adD@Q6M+j^I|ob<fj6;+L2mpcBz{58YgW9o;i2u zUx`(odzRgCnVY4&I-REEx5!%XUvCx1AIE>l_`_4{m%7yL=LKPy+;VoDY3*%nO3hpn zmF(Fnj~q4s3_@2C<59n=^pAw(_g}n#qm-{oV^$3uKYFoSCmfN3{DI`x;IBD$ujLiB zK>dJ9Z}ulC8thI%hQ{O}lKiLu`gb|p4KPjEB#!?FduO-exDCbePM;%XTGOR_D9ge~ z;Pxg2RiHjXZpIVnjf|1;Z7}SGpTT!|*;@L?%JIi|lFsbXY5m{XSeA}H9sKi=<#_G? zRsElU+^<@H$FDyNFHIS}F@>`kN&S`se(a{-{?ZhHJm0KZ^|t!`E08?-<F&6je`}BY zm;c;7^3ByL|AxugBw73ae*6EQ`au}q^2u+l4_J<9_5p@7L!SAcc;vgys#S08Ja0dL zO5U=>4?DH}b@NS>JpA+x?vZb1cW%xOy<zrOE~j4mzxMwsZKfc9zfX}*pCgX|=eNUS zDhqK3oO2x?H-P-(3i4HNuianUH`ebzZ@!IwxOUb0hk20mnbPrVBX~?SiV1uYl?%~% zm3IjWMzc3Er=d+WKm!IANXH*S<9cHfPeEUXg~iHl>OU|4<^G?`eAE78v)F&HH|T$* zZaV&zF1~jERo;D+Rg7c(FZ3~~Sut;Z{O3XbewVG^0py_Zc-8vgC)mAM1ZVu~Jo1kZ zn^mjcUY~Yvsb4>AzLh>a{P>Eg_08avHaQ7SHjvS3ln~K^{i13ewOugV4^FSTOeQL9 z6HCIj$ot(~^|0Uzr<mq`cg%}NO=FS5nZ(0GFmhX_+5W?H9vIVF=9<)_k98jr^Zk#b z&a2^ix&J|BIXujYj1Sfps+K+8O+h3STGkt~BR#>ZI_8KNnN0f6vt^?D5OVJLAIa2C zn7Gd~PQ}xfzW+RCc53~-zBDENAk5rL&b$yk*}woAd*n#E3FOIU)v8s!KBYh2`W!hP zhwVOo7*l$l1#pL=@Iuq)r87sA*<eDFC17_fgTiL5G!+A251CaQgO(>^kHxjqw)s&F zafk3c2j{_wVk%p!Yi6cZYm+4@ClMGok>l_@5{lXM3AwS=F}X&r9UVfE<bFetK&&#I zDqGrdJB6rSmcMwUD?5M0p<ESc_^cFZfPA6=@<eGW^TB8!G%bk#FyYMifByK-f&ATi z<llYwy<hDXeeU5ZH@=u1e1_4yN6wb8-{g`1`0#17YSpS<zXIe}|3oW)ZORXe7%6IF zOD%;UB0U265*^FZ6l8HC9cC=3oSIw8&zQ)2D|-RCTBt}+kXypx7A?3&N3u8HYMqk5 za^z*N$YzN0MFUCsToWP9a44wdrK$kN5)d}YlJaArR9Eb=HddECQpqG*<lTQXL-Yp* z5@U{2kr>JpkDMEJDJCG#)zMV_my8yUc1gzx$kkajRo!Q)RU8c)L!sTW;su%6i2#U) z8O)!1{Oo-?<aqjQ>XGx6ZHVTSh5<7f`|US?9M7MvTD7Xz?iP>y9{+lxKMV3)^pJE! zLTg(GbjVJklOqvSCeMj%*whqHp(>ogb)_?tM75<glEUReJdNXh-cY$nIzhoj6sTlg z>Nb$ST82bb6h=_FYzNd<%LXU1%yJRr`#gp*kh!3&Iv%wkyWHuEghrg`0?KFOAjf=w zQkaeza@?TfibXDiyg|ScB%~mxZDsO>V{JP*VWGmu(O76$O|&0^9HRqCDv~R-^c*>^ zhVS01OMVBEvwP&+Bj-?Os7C}NI^%lu>2Cu0!-vhPRjZ&+4<D}w`AGNAd*m+D)*Mx? zggCMjv6QXuB&oEv)Y`lRa!XD0jL&k}iB)rs6PYeeUr|McpB6qg9frtQZJ$56gD-BM zzm-S+YKi?e0Y>xW^%9|HxpmaefV|;z6PA%#g=CEZ5L7Q+Of<$AYU`#@>|&%$T9I&& zGYL5yHQ`YH$?Xk5Dl<nUx|TPUwe=jx)j1%`s`eF^R4xyfp`k)elpU;BNzw+PSWTKv zgKvmsmsJjszg4&yHCpWUUf*Nt{qgVbrXD%KJod;L(4m;&H6HoLhxJMFRjcB|XDLAb zinpIFNC}~WL#Rfl)$Q|nQrn57Jy?~r5ofuN75iF^K~hZo>2lA(Pwub)ay|iHRJt^M zu?R<y7dGrQrLKalvZtiJm>+$7GY0vQ6<C+r#<ufH)G&(V+1_q@6QImkUrX1J0we1i z<o}~pi0$l6$%{0;Nk))7Ca`=C<a@V|(b5lxA`$OrWT8F2Ew<@fUg}FVmed%VGDK;i zyrdYU8E$Gx6c^WAZ@q<RwWcbu4(@h+0eP+(Q&~w;2&Z@<=Ed*f%tZw0aR5hL7Nkd) zdQ`;Gkjd@(Z#_pI8jgG9XUBU)Z@!ovaYF+Hfqi)NNV^H->BFC!RjXEYN_KF_zt(f) z+HL(U#=Mm5L|Gm50>~MHn<UE;E+@lkqsA-m2?-uCNuMbXMw(QL$R&`sp*a@VP=PiM z;U475iOxhx@;ZQsnGa)$mJZg2gPauzx0W1@a8sd@g2$z_pO~NsNxr<~MDlX0HiYv~ zJAB4M4AGa1eVviO2rYqJSUU9>^G65eL((U8kq*_MJI=+HD_7>l7WG+_Qj#@xyx0vA z*pV`{CnKq4FI|#2pr9jF!evdKq(=DamDM_P1UbrDt=UpN^lCwx%o4~&i*@qxN<;3` z!8gQ2d{-#xW?iP#FZambsY8A@yhqOF%BS@Hz(26z+3@dnj~p)f<4W>Xt2!n5LyCvb zuJFh|+z#?DIKyT(btbZjobZfZR7nS5O=F**un9WEbM!cK)-slY3yUB>1<;tlyNaae ziw~!k1VHW`I$uskW$Ia32a8rE+blGrBp+^F*nv>ssV`8IO*{N~JV3F++KGfqQhRA~ zeQrk<5`<OCZ+B?>?hNvhw6C44Z>KYPV#HouMw>A7FM)hZvd35exuo>c(8^njGEa(( zs!%y^c}5u#wcXH^jx>7FhFKTAZ@jWg7uA96<!UQ+u1YH1%O)p3(5TZ%3si4?Jq3}F zZeN*3rM~F#z4K+A(5wl_h4jLsY1`gLcBNNT!JhcV3}Uvg068d*?cKX|$?q_?4jK>N zVK!QijxdKkwlSj@wl{j@Ao*^625r@<pC6tuv3{FJet$K{&z|>bzcZ)kZ?|bu0eSO+ z$0yUk9mAumfF4tyIyj&}oSRQoE2T8s1ajroAh!owN|N4aTl!CMGD9{^r*MAX0xt#( zN}UWKM{ne17Fse&jtT_x3X}5m3Y83-m};V|Y$9LLi`tiiu>fN*`HR{!v`R$B^8~*c z9=c7FYe4SFjSyNS_AFEBtu?CIr~VlFaD6<Fv9m>CNlS8QcvI5BR8EfXkv9@PwXD<` zsYN<D^!Vh9{Yom5RIzdnl-{_EVY{6Lxsy@~!o^^P;Xvn7l0%T6EUGl9>n*0%@80X% z&wRV%+s_!A`QQAHwnn-$J4XKGHjsOgKmGK}51Uo1{<rEbe}8&<0LQPtM}7~I-`^wn z638=&Edy9Z1x~0-ItU`qu!BE^7cpAyr=|s!l3c6XEKc<@SXD289MUj~)9e6Mqy#vQ zBoJ^HeLNxHv7)j=XK#XvL4jDp1|j`4<Y^ruYq;Us5eai46t*(d4#prCKz?9r(L@%x z98@@rN!00ike}$_D<^#hxnLmI-Wt`EbV_zEbO*AOrM_fGS+zqHc?m)35ab6Ewjymx zLDVj<%5RA#chxz_6RsLfTU2U-oZ!PxI&=tM6Cv2+W%06x)f64_S9|0Le*fKf?{jYb zF1*Kdc#nL{aU@~OA0X#YpU$-30&?6Ze|-A<^t9Xkv})D=Q2FlR>FMb)a{Oy8b|X1u zG;Mu?SoEKqAuWXR<Yv#DbG|Yhk!<=^&nZZEV6(!_i&N`GMM8xFs_+z>0`6j^vR}5H z?RAi#!rwHA$UM;LGV^~TFQk6y3rs2^SvD8SfzS=oyLbuqMc!)REozdek=h>QU<~TT z__l1N8O0WcU0i{1ePL4}8qJQ~aC=;K%y{HBK_uqc(VfE=T)hO2r!BFAqf}x=l4ivK z<cCW!g+FTNrfJC(za(M+@|uBMHL6A1t~<z(qJi`U<a+N1+8oHh5*@GTFbDDja{dDW z;ZgS<<nMNB-OsFhkTW>H<dK8;05@W%-uz7<2g$o7Z;ua;kB^@_{q|e;7d}4w5C7={ zpRwzAkPKl5Mtx>%xEV4b0ruGEnR$`0g$1|5F0Y*zjsUBI3Hzuh{_*&}zP11VxBh!| z-~BZG2#!zm%QI8!_qT%FW#br3`yMDJr1=b-MMActP~xQLay#(M)MR@6;(i;T*BXuA zB|B(3z5sG$EW?^<5^X6-0ag*@<VYx(i?bTAK7zctfIK~&n$zj1E(HQzts@e?*rsWY z%}I47OCpi!*5@vo)3Ip^2A-_LtRW|$0CLrjV1)?*fLzipwl&%dzL@)}sdZeBC~AFz z!u0_gS42ji-bmk_y1#)?2xlZiT&WIXTc(M|h&h321@?G&6<0Zkzu7yNT`OTI4ErM9 zP!reGHrX?>Lz?sz91({lO&g|!*?tCQysWgpT`mw2ugQu0#{;WZ=;p+4w_Pnk7bz;# z)lLx9kQX3#L<Hb(dhEw)vXsX8j*rXXk1hR;(NsQNg4!LBKhikSuSqf-ze}g~iGutK z%Ecmb(ZNQL9nsel<y&&22q&Hexg1`HZb=_*tQ6q$2M&l-Y00b{!Dkpd#YJYBuy-%0 zWI3VK60u)n&XbRbLEha);amz`?f)O!pY(pgxa7D5`Jb92*VOI!u?5B5w?;1}6GMQ5 zK2>#(m1U-oDkJf+9!H&(+fr&Nt8C&@&@EAm?0s_p@;q9dXOjUePf>te-FwpLk#C5| z1ROa|NK}~R;eRdo6g#n0exs2-$?b3i$ZtWTQh*#Lgpc)LDgxu@`ylT~V*uS?48d_V zR3nn9j)`z8zI(M&4W?0`8x2m~LSGq-5CoMQ<b^|kQZ{H<M%+=^O{igz!v#Tryqia! zso7f*Hu|HlZZaqSye4=OmK!rPnIt@`HOPH9F^GSD`PtKb9XZdD<7YcW{%&V+c}ZS@ zo#TGkBd=aSJ1F1Rdp^K`%|UUN@$YjaexMwK$~fvZV!x>^<&X)lw^!qY_qYIGrv&+G zEP3n5vyQ*of3+VN-_hG+ke}Gu4MJCUD;uLOG?-#{i@K769~Ze?d=T(yNT<@|zkjt6 zI8z_X#Pvv+0iWrk-v>F@OqzMw1=x*k(2+D0F+IEoa`r7VOi9p83jlY#s+*-gu6fF? zY&?X0C%pza6sb{2ApMoNqfO-QvVE6Vka`?|ywc>;8O*+i;`(lj-#wlfd9;RCsG)#l z<bxWgs<?J`vxE<mzYf&%F391s7iqQe8#JkES6Vz6Ph?Mme59fHaZI^&u_<nec&HnY zKSIj&XF&ckgZ!y-{27MUR~x+WKLoc>M-XSx89&=2uU@|RkzV1L4>-!`lCo&AaM~6` zN)DF;ry&U;1Y~XNyFdzlzs4bgD}^oZzho)@5QS{`l`Y{ak?U&zf7^c6X^=}-9p2gP zP%Xt~Z#9sDQD@SGdJS?_e*yUf5b2NiuWNxV&DFkmMmWzegCQeXM+%eF_PZc=)R$=h zPgFCtTB^aGu1z^+YVVmW6GoVsfM8y&5C^R)Y=SBHk|58ug%!x>bhoIiW>57`VN7<- zc@Phfckn!`lWi%=E$Js<d+Y4BKS!S1N0!GBdcwy!hEV6od>Nk}oehq^2{5Q<&$Y!i z&5_T-*$pjoxlyGSXb0rcuvy(d33{5fx4MLP&jB0Ao&$NL+UPcYRt~e~WZ5e{eUaIK z+|fynAFm^4<0%iU=k;fM8?6g#Ju@z1VDXO_kv{<Wn-`ZZUHU1#`{8R$U!LCCjg*<Y zO6u+?)GLttYMr5Yo(DZzXLO*M!IyZ@58lt#Zm#44{x=8y0Oxz^KlWHVMyQ1a;xC#) zMph(aZ48Q<j8S8IO|f{6*Wsg2b*kPvMQ#J~kyNxU7{ozbVGANB8)$?|Z2@DrGS>8c z%=p56Sd+_XYJ|6a%^<IO)I&pVy6$ZZ<jYX78GX~#e(Ymkfz>7}&w6XvkK#MmqF#gA z9ns{XreFcl371*YZsoSv$K3O?1Dg}byI4z*SB{so4<R%MAg`KYx|T>i<g)sH9_G>Z z5rsHGk&1)wN~`S&kmp8^#<+WD$Y}DFr&;Wz9%+^!pIhAhp8+|RpFP!=rlcNu9$IHK zGpL2N_GjZ5w!}<2N*&ITzkPA((xso#%jX9}>n~5g{S0zy?VRKze8(W=QjYz-)?3O_ z?L<bb;I*kjS?APht>AkF#XS0}C@is2xI}&Q`^(Ri>&gacp$Em99B}Z_0s&QrYcF}k zrsW{unBrr-2KlX2n7$b-HXOBuTuvA75E1PQJ&=ZSO$Cs1!3hRwF43Zv7*c-NWurIg zCoe*#*tRsok&&;Avu(N&jewziFKxzZtpJHYcE4%S)Nwx_-wCwJtm|}>AL?lJN1N1s zv_3Tkr0pUFFL7#$6bYuMye^ob5{gvR%INa>jtF>ILf(B*P{s0CRk!G&C{|5SzNfAc zD+fpmkXt;3Ul(>-mtFE@VEu`{jy#i`cXm7IkqdV=5wmq$FHwgeuU=fbbm_d{>vr5D zKM8VZjCzy<;B7B^?2DRxkQ?Ld*mT9q%$t&L7_GGfm$JHDU>`-t4ZyVPx3ZvTex&;0 zI}UUM2c-O?*)8jbZok5#`fkIpe+_Yw4s{$$zD|6AT~c~yOmw|{+^V0~ZD??D(7k>% z`?pn_HoNp|Gb18{TobXJcn<3?G%Bc~KpY$QA67TmMGw9$kuo|{Y`ZON=^NRyEkF}O zk1RAD{S`l|-%|Si3ykOU%O}4f4Ccrsym5pjBW2+E2HnNtq4jHQ{nDksIkJAdj{Lm3 zb@1VLbD2>DtgZfpy6V!e3ghkPWs_$?!&-rNUD4FD=`_y&=1JEM=ehn8?9UYYgI?=T z)@gkKd79v7e>I$ilN*jW;4G%n1@jr=#~Z>xFD_lWbY5?s?@EIFC4>CZXZFr0w_y+n zq6r5nlB1|s=$(3tp1iT2m`wPvP$GXI&r4;N#g5_+m@X{#NmzwEypQ)CnDuq!Te4dr zBG)82#%qqcebm<69CR(!T_In-zd{I~1>|I{GY*M*U&2X<kbj2hIAtx@SvQh1vtC-X z-7kTo+A8{O<&?S-&u+4tcA$k2obkP9F6935rcKlnk)MX&za@NtX*f*0{j5C@M)G|3 zb#Q&$)JfKM$KOTdnOqOypo#T<jl9;Hsr3-X@veh0X*iCIUrO25$UVr$Hq{3Fb^?LA z$vNjMBF`4I5DwCDgq%SL5|M{6jCzg)eO4WRX04k%_nXWt*ru%y*^zVnSVZJe@(_;F zag_Xr=|LlF<RJ{<eTTOImsxY&(D7^Wh@8TOxf$krjon@M2eQ^t@~o4GFt~$!JZqf} zyZ$X4v1C6kqXup}tt&r|@=~Sd@DIOg)+`^VS*1VUYMiPcZGLY7_vHR_|6})G)p07u z#6rG3pj8pM3fFE57j}K9;gz`KLCAMW?s^FO+{jnoTO(Jt8zU0KSR1eygl$~IM;on} zT%c97egN*i)dp0xt?+$V&1_#sT^HI9q-Y0PL9)T`Qd=(}R_6Y5|AY5`1Ire@mRTR{ zc2U;4?F47C+@+dAo)vuWM&ytu!~C;%KDiFsKp0osbD&DJRW;k%Qg)UVS@IRKLSCjq zAhs1!7C8euF4SXnJReL<LeuoWTJgO+Fvi$3_Ivp;hJ-_h-eCOO3VL_fdO1IM-0XJf z&}Z8H9Ql9uw)MwjOcmcsWEPg#(45E5<~UIP<A@yZMBnCqJZ9Ms9a7;g+Hb!_H2y9k z$5*s!NPgV4e(2E0QjCB7pZ{hzw)#0DFG6mGddYWS8^SI{x^f*6`JqFH{!ZyN@~<Di zI*EuCQkYCsRqMLQ*BmXguL?g};9Ys-sR{eLk$Rn4^|7rg?_@)(&_v<h5Zs%V)qgJJ zo&W3oA6s6yvV07Gh5tHe@BPPGHDB{0`G@}@E>&HJM{{w^Mn~^A{`aG7j=lev#^3)b z|Dn(S{=fN}wRxKVe>NUx$<xn3X=U~9$I3C~zAb@OS!~TeKz``Z->dKTzoHd9&<V7a z5%~vM*n<ru@LOCa)6`NI_Lgt^l2TLjAmk~PWQC@%(47^_LaB-t8hPg($=-LN`mr&m z$7NeL324xe);AC}IROjjdA{A|(>16Tqh{*)H*WlI<NS&LVX>&5EfhJkMKXA6tLjQ^ z;eVjT{}fmM-K|~iZJq3Fo%U*+b<EJKI%*mv1q;Vt{U2Jmgjao~I-BDj<4<AfaBFq^ zT^G3QOtXnq%#sq0g47%?TmNS}E)DFBfBVPBUu#|ck0$Q<FWUECUP#>gwq||&_s<}I zeryV}@V|PIeEab;z5J~Mqiz=wc~Jr?pRt1NBO*U^=<gOl&QS%wR^k76rIW%za!<Bj z-fc%SNTzJ+A>|9l=t2_x<g~2*t8b1)d){gMR5p)7)uU#ziN#P!bmc^#nDG)=mU3p> zn6`LB9%<a%i6d&s3>4PpBZ-{t7_!t@YiKbbkgM+$l{P4yIPshQn<lZ0ts?a)U9Xff znnM<uig6gaSo$9bKC)M<|B(jC^FuXRsnn7OUvf7Tj8RkaY=kneYhccc|A`Esjpli~ z$_w`x{|s`pXjiA4F^>1%=ssLLWl0SqwNj4>TmKWaI)pFd-%@%R|1r9~@%P*D*V-P8 zHRMn|vef?);NFD7f3zv32fF9go4<cnIsOa3i=h0A|1!vN*ZSt3^yd$VYc9$aOfP7E zMC6AK{iDJ)@)hDAe6t(byadAPciOKdkRJ9{_7ZpV@4*m}jjo1Jn+c3O*-iN{KS)ci zK6TW%+F6+ezPYmtbf4qUhq17(?TnL$c0=xdZ<_nPwt>@huTe8=q<{ug!0RXen;=eE zF7F;@N1tntyn{?z`$npwLY6tc>PmN6pG<O{7|}J4`mH8U=UW_7m>Sa&k<)DIxnp*$ zOWd}$kxzy!Np7FAPGVAE?<1=*c{$f?Yv<74+)+B9^KCNoJfG^BLPSX&PPU-l*S&+6 z8wGkD{}YerP`_8C>FgYjG+f;k&K$Hiyf6CL)xS$}{##s|`Y%5;MIM{-MH!JJww9mg z``NZ%sjlgQ`^Po%Lx=t`;h`z2KML~C6%85pL9uSH`qokx%%yM0MC4FsSQIjkBo)Op z>!Q$Mq+WtYLBm64-f~>t!y7eA0#AVarw7P$H45@kdm+{z$cUL8gB)gN=fp5aArp|z zJT+Y_HD*~7Zt_mmM5lI;!WTCrp!o&lz3CPYi8>p40kLo0`8?1ROyCkvo!^(kK_Y-0 za`hY|*=&)@);}7y^}c{yIp_$wYhPz`+w<9-yQa5X?Xc5X1MPL8p;zuVQ$1W<{Z7to zpOwC^k!G0N@t7<n+jKv(-QfGj5_*H<|M{n%Nl1=s<gXDqG8EO19NoVGyHdY8BJx9r z{$>H>`fV0?{e2*ZPT>QP%UiNNz0f^}qMc=!85&^D6j@ycc~10zLTi|uOJsL7)=S<P z<3wq`pEuPGE6A>rC_rvPn8=3E0OY6|AU_34zYpX#vP=f~kW-Z4Bg?^x9w`V!Nh`;r zWr5IQNsCC9h7#oG@x)G;sUODnoFi&=b0o-wF?U=j+VPgcb1x^f?bH;JKeHNp&SHxg z@MH;!3i5$>M!Gu+QqJ^(WKn0YIc-o_b?S9OpwvCPu5wl;D`w_zW9xUa)JKthH!fE? zNz=hvJB2V8on#Eb^Unl)mmvS|Vq9)^(`)2PZQa)F7rtX_Q))f_h{z8e`rCz%pMCxG z*p%=7E|9wuR?jinHKl8kY2C3X+&st%D7BJ-K-8Iw+n-v8aqF?ChMIz>npTczAf6eQ zUO+yrARmb4wShZMGSCoA-qri5bwN|-R$Ml|-hkW(4Ju<}4Exc?wuJ5|bM1{`8a0T7 z3sm9QaS$gXYX!FJiBfU4bbZC#7UWEDnlilMfXbLQr9dI2RzZ$aojKrOcsa_{!cr#c zd4%@4-Q#8`yVV<l&B45VTpQem%sU)Umz~VhJ*Lit&?jGitODZ8Bs;V4zj=uqk4({P z<X9@TMLLhJ$?aVF%k6GQM1JVdKO+4?7{&P?0eMV|2KO!&H`{n@MW`WFDEDjV?iO70 zwg#dzh5e~@Q1@~_yR37ocosUHZ{XQ&63`jytttcw7|+f&&Mi~x^Ae%99YA@b$nft5 z^_=d1cxt^KyUTcX=PWmYaFY>r#4i-JE4E`@J<Ulwy&s+ll;VT(PJq@&*Ueiy{aNM# z9y1)u%W5|whtSnqkS9<(S38ERc>(#2bS7c#d54UXJJtS5^CRxIM18#@M`knof5j-e zp?<5RhTf3cmAau)|J9mLmH%!2M~^Z6lJy*c7u(A0BIw@zVz)Kth{z8e`X{7Q>t7=p z2gvmX;^IEtHA!~K0>~@LwzMiO|IS|7fVI!Z4~8bEXYz@9w7@9KFaD)~rtp%3Sl*D6 z24ik4(VX|y_TqU>Q_Q;6t*rZ8=4Pp(hb);W4LQ1WVq(oDsFe`^UIkUGqiL2ay=DXQ zia9<kAfFiiUVCPsS-n)-b9(E)u`z3`Toh#^+O3%lo9Wh5qMk{fpaIqO+2GN1V%(`( z?=F{C^>*^r0Bbz=+ju!8vy6~2(y2Y=ZI7c883$u|pQyJiLsGfT>Z=9h)ofYaB`>|4 zR~P_u&ckY`Gh+rh*LI`WyU}HH2;k+)=G;b`_t!1PAA`_QEN(y7J`78?jDMm@<_^+g z=i}aW^<QFW-;=FflzdCGl=V_YaqqfpcawfNeB-~TB%5#k{!w1{lnBR%KRB-auimz< z&m-5ETNcH(=;e!A3v!qF)e(^&I`j_-H@j_bTmSBXQY@F0WRlG*R+Kkel=6<nEWXmX z9BODQBV}Eni$j$e1)S73a8w>D6>_rzUGt_TpSSD<*-W;4M5^YWW5jFD6sb;K7k!L^ zcyo!-MI$XaLv}p34W*9kASVg4EQ@<}oUeRjoX4@eMxMbCg<0GH*;&gAqhRKPLwJca zWkS`)pV`Eie`_|o_NE)Stu7<pl9<`K3c4BUK`S+{F}yW~z>p7Ca>M1(mbKs>wjBlJ zCVz#ck)l+V804$9K99xL{{`gYS0f;oe6H>`8nPloPEKqL5Aw*J(r3U@!iUJ&y+rrQ zciF@YcIi}OVHWU=bF^f0PbP}!xJ|b?GMZbBWPHvuxeZu;qpfg)&`@BP$*@x+P4Fqv zlX&c4t@iD*xVeh!9c8<<=~w^$H~m%IwayHe)tCR-50Zo9Uu`1r{cGfk=;!(NA|EA> z&ygQG^!E!9`76lrPpjgz#xrD>ci4f(ywbo(K)_go8nabXLGg-pMnPLtj9M~)&@>hc zd>Yv@7H{%-CD}9HlLM`?0`jUA;8V(xnURp+Bd#CvDrA5>9Mq8Q;izCypw^JFtg606 zu6h=RTnp|9$P53seO82TCU8krB`C>O<vn~*AUW8<o|~mhx<Qg9ZU-^3ph+-D=KRL4 zMuB~^B-{HslE&c3L~0$=mfAi46A1xx%gWV`{IHy|WGc^{v0Ni%kPq1m36~u~bGBd* zkc<CG01mK2E(ha1my=xu0$`7&sN>&u9s0n@_(}3+o|KEbX~_Go#I_i6s4|(Yx|u8R zlwQZ*P-iXK5JJOaPs7XKzv8?c|8iy>C&c{Bl>hSFI!ELR=ki%*@}p>eY!yFRssR1* zIr2k?{sHOKIxdsT0wBk4RWM7oJ<}2jG*<=vq~Jt;;W}O=)d01XJ-3b`YG*8@RTLCf z`buQ*u1vPZL;%VpVoZS`kvJv!4DuCB62Mub@4$`3VK*b7Q4fExg?eNI<Q1w@|1-!X z2NtSzt@<ykUH=8wGErZdl#5YXJHmv_WYVuI^P{Cg5%tPVbxLvt`S8O+B4d${C8n}# zwNp?kisZByZ(If(uEO*?K)#ggjX<~lp|k7x6A!cthW)v7r`+;H3BKTF8G<<<MJ-Y| z^}^*A8rJc*b~vH7SRfTi&a~QpZATG4AX)fdlDNosjAXiQ{g*<TW;>lP&P_%0Fv$l4 z<ebx+i;m&C(q<v#azKt~oL{o~FMs?DPe0p4<Xc*AGjzrsOU+(UkJYCUIZh@I9Xj-) zy8aa8`eFg(g-WjbIIe7>ayQn^<<*AW^gvzIjYO(YJ;_g*<08|b*=5tx4;4b&73AP7 zw=yIaSzee6E;F;{1V%)f3xgaPy9%UIkfS;^{0Zc0yDR*E^<Jmeg=n`bgIvu{tghij zLn({h?K?6P%?^ra4c<Pt5iX81A)1P5j67MgF@l{0<9r7BL#?4CHe!J?V{>VyA|g+A zkYT9>;cgwGV7M=S;7;*$tKpBMsQu)-2C2HTsLDB%QY|2V>AQpxhfHzIOgMMkRpEa_ zG(7K7!OqZE)ilbU!vCHgHq6g8pwLr&ML5ns|M{EUGRfB-QAUH(>iE+=Zrh1?-CYv@ z6Oh;Sci$fmK09>i7xu1Y*J&7t0{>C2WI$-P*b=NPFD&I3SXo(CiX3GhDGR<KyZ$V; zPcodgP>RF`lyiIA_z}lrw>g>d*!~$_K7KIf39ogfa{Lz}e++2G@jfBD2d7-K^FTqr z<F3rbO7c6GeGPP3FKJ^$=d5h2sSe;-*ZjV7d57n>)~c5?=tbd)C^VmQrx090!bowc zD-$^j!zSpV6*VD(03welO{{Y>C@tCo$#7DysB!Mn)MfzU=zzkwa+#w{dw3uz+G!&P zgO#P^fu=ukinp?clVXmkDW$QiY}(MWON0>Cd$=2b$fvKTrIc*D(>;-&O5J7|Y75n~ zL!YH!^}ix=j>?p4aFjI3*WvVA^kTC_h{fPO&zDm`Q!t`vOGu~u{S!r8gPW7+3z^nm z{i96&n%7!qyV9L<&M`N0(>RkR|DMQ=d4I6@fdh}Y{A8ZnGzBUJyw)FbvDqlVlg^KW zAS(h7u4&p$-Ffxv=0u4Gh2ed1LLTCijJRx#2uV5+xoOL)$0#nw0U9~%#xqRoyso!( zOvU#^js)YZ%R?-{plM_xSId6;RL#|xtw}Co2bG_Re2h-k7;~yKwWQzVA7t7XgrAY@ z4(ZSua8`3p+uEpALwys-ww}K-V}6cfsa;Op<q}0KP6B*l^>@r}>_(YQa}|#jvl4l! zYfcs;3603jy0%71W9tSY@=gA!c_*G-xq!>(`7&jZ(W_rz!99_CSKE*G+JU$gr7ZYL z-i_J-I2dJn-ryY9nZ(-GlL#@9@78vhLWtAYm5aXdFRF`!%l~DK{56Q2D7YQ{++7{9 z8o_xv6OEBS)W#1QKXBkTcyFFqqLsHz`Jnf`yNxAq)Oh^N5AMJseGT$_q6*qO1-e<D z=+3~mTi9?B3|;eUrV3ceS<X8Ft;XzLRxxd+b+g}{;ofCH<e!$Uh*G~2x&*^k=U(@# zw64B?o?Mm;!cp4B7&#_aK`NJ;{1cuWV5dIAkNxX#C%=u29ZWN=!`U7pNAX~g5}45* zZS^-`+)Kv<Jez1|6mt>r`y+(C_Jf<n&gdA89>ts50;6SZ)imDQ<kzwq!+Pz1_#igZ zvz*%zh&)#hz;CB{A&uO$D9As4-Q^#oLjy-RJZu1wGu=*El4ntFzJTrg3a#=DNiRu~ zFH#KVMt=5V$P&x<V6RG8g8AXAxlI=o|LFU#A2dQ<fHCraS|x`@u2fD#-;kPg^!r8G zc@W}xjog@zZx0+e@H@Obp^?AP@>KZk@>Ed%4TFrq;|Q+F0alVr)?c}B^F*Jp^iCw7 z!ybjdWmH6A5vy3i_xNbkYMSE8t0Zc8X*-pWTph+GhubCq#$JsUxKI8gc+^0>D zfa~9C<QTpm7s!v|^eJUAWb953<F*^KgkDfmTa9M8mEXn^OzR0_<nY7;k&Pt;Rj@@u z{r0d`=wrhoD@L2A&?;Ti3ln_>p?E8*TpFBtu8lV+`GCmV`%?ZpzAg9H_Uct;xW{?z ze`w?;jFPk6pKPN26upj9l&X{0`quw0?eY&uFT!>?wmK7$>m09Ue;)&?#rpUUCHzxL z0YT<f<&PnXjGuWIQ)Y9`m*mon4q~0N7SBW6nTwP7;QLSIVKGE@TYvM<`nqj8xi*vj zUE9s~C?avD^*`3gjXBiu0|%bL%ZJC#ZoBKP5;;u)yEkK+D3WLL1CH(rpAgTd8{`g^ zoGTX@HhFqcsA+u>$>TS3Yd8%7X_C5jDj1~CzC<gL*N=odaV2sX#ZgccyT*cK1w|S! zDelOwv1H?+xvz+_!V3+hfQ)>_0xGUWii@iiu@@BChI0Ll{5DqN7?{ZMWRgDX;H<9{ z3e)<u%{Xs7x3O!zIL7>?F)_>ymF;b91nmzsQ5SsMqy$M-d2Bs_Z3T_cbbhzTerwkn zc{7wOW0n}a6^oIHXthz$4Mm)-wR}w&{320HND}+eRw=yKtCKrD!cp9X_Zz+Ie>}sm zwcOD3#{niBC5S62nU^D6@|WnWwJwffr=ouE%orYg|M6<E_`&EXc_s3HmdRmRCyiWp z8`nn02M>_zfxgJbuKST6JbvK7-@u38Yveiu?PdGv-cAQqmhkHoXkN~>-ec&62=aFA zreO96)w(`)3W<B>c_0HGpa=c5AO)*{P6CgtE?Ar8n}OzzN=30H(yF}OnsSLsE^gKH zlI;$0s2oh*jFVB$aspVt$={_KS}!DjpZtydHWqsCO(SxXwz2P3@)=or?8D_DWhV-Z z=lj(nC3K^6G4>wQ&V9SuC=<1iTAcl~uBx#@%@lE-Rjmzu-bdJ{EECdt@djCEmt-_L z`@XZ1FOA4+`cl>J(I)9&TG!6Et%+2AA9D#$EzJEt$Ax)&pkDq}{{y@|y<&71m7g{C z4I10U!15ypI@4vzX}mo8{v#IYU~t-${9m3&4klMwaX@`QyiSTZ66l5GXEpM}u72Ra z(|CDA<P1zd13T;bl>ob^vEvWl^fbTGGsr4Qh3IJ;5Vv?;hLdi{dL6p@UWDsT9tQX& zoX&90GJPMm3i+uo7^on<Fsk8Qw^!1v<0kk|<@a%Db^6vd1d`w1${%j!uZxw;?eOAF z7voeTr*k*~n2C1T=wWtYli$bXq5Mc;9al4Je(I)hCqDvyXS`t@Hu>imHu*o7+J@86 zhrR2%R{1{GjGsGSMB3yrK4^OlbGL-6{tw}C|0D2+{f}avlb^G*{MzSw{QUR-cGHxX zf7rDC8jGzHTPuU#Yvf4LC{oIC@^fS4HTT;C2M#=ocfVxvFE6T!<EB(i>*}9Yv6B)L zb34F4<!K?(mbPqqF5f#f4d6@iefFj%`p)NRG@Z^hCQH6nQbpTp%5^*BKjeQ-{_=zQ zpEgYak*jH(2fgptcVh!PGHT#?jr=gIe`oJpbKHhuAPnamRemTndjA{N1)ag?QL2?2 zr@PK_Hi&6GY|k1XLp{huVh?`)HH|5k>TI{4)po(J1a1&=zZ;5CEl~#_(Z)%Ao30Br z4v=jeA3dzyqf4nK&h!v{{^f-HYk4{UTD~y<1K&SdY_p%O9{Do1e$rU$_k83&d@*}K zHw)+HR$sm3k>|jAB5@GrZa^4)EuWe3q@|DBfU9=_O1MoMLX8_Gyrf(vYJIk%pmw+) zuz4o6f<|g@v^`dcUH&5Yul&mp|MEQlHuJ?^{_GyuK0klSe89i__xG<NbbbE)<6$;= z3SzO_bXuQWbL6nYwgBB{E>xv5nDzmW{6{+EiNr4a>V#;eItq{6H5av;1o?ZMCub+5 zQBxzp^*bg){np-yDnyreYojCGMQb2?4<>KMU*E^@FUG$P^RJ)Azr5o8FIeZs5!>xg z64O&U<abLR{{=VIH0r)7jj>`-KeB2)XUG$YeYkZEIn$=dclTXDjw%5Msn*AM><+m^ z0}Ly{u}y&8dk(Ziw#ZD&oAF;y>v!f40!Q+XZRCh>eBPuf(}Y#)GbhFAk*j<?x8$bk zJm!(t+cl9$?84kL<gtf5O!?dnTYB{6w*1j7r8{kLR0X^FI(W9}>uk==`J<tV_xEw% zY8~H<|BB>)Jb!uOvgVh|Nz;-0K5`srsP%`!Fx%FEbL6?yEs;3fko)#C1!!G9NSb0J zWQGsiB8jYVp+%)+_Low>w_3P+C-fgH`6vG|{<j7C34HFM^(oSkU$|r3_w7YtRGRsY zZpf52<dI(!iNpcx*0%v+VxVwtb(Ujii<e)Z9(vK_pZv$Ja|^&FKW#vmY580bYu(*$ z_sD6zJyUte1FP1riA3U=)oxt1ZfR5Il1L<evv)qfO~X(e=f~gCB2_}jQq;rZ!#H3S zW|ZS@XcD8!fzzT!xmOC6IK!!@qTW|cmG}#GL~ugl|KNYX_BVaJByKt=3@Z7Hw%C5p zZq2rQ`fSI(fr#LIul0L(4pevV8IrdiRjhNILT=<5PnyBjh{yxTgM$9%YBzwKExAQh z9zY%xbR%JH$peP+yN7xp`CW{y-|vpd{j1*SJHtD<hlo5V=r4mDbL917Q?Nzr%_blH zg}ZGi-d=H(m({lFzc*I8dw#a-js5%nlLn#x|8xKG2gCP8G*RtAavUtT5jn>+zG^Y| zmSa>l#c&7_c~B7PHX`yzIFFoIZb80nU#(^-KiVwUBXWi@E0219xq6VQ>6!U*%_Jh} z*@Tqbf8c8+OUjO0f7cD0Oqrf~yi1h&`afv)A32C+clV#W4*Znq?teEqxzC{8|5mC| zJM@1?{~xeXb^P@l>~=7Q<4(0BQz%2QrXnf<z&XYFuC5^>4+^@Kp>;aG6vEItgEkLH zvJs^nhRLQx+;rC>qYP91F(lEFwq%Ioo|+T@`6!Ju=Q|%C*$b-<=BG&8daY&8BbAj$ zz9*0QQd=bo&waiWX|w;7X4kGbv$Ovm8})-++G^O4^Yy=DmsZMlP|_;&e@FjmK8j|i zOjLWIkDpbWt<!%gF`2{KGw9yj0uD9FJ4EC`LAN$X4wfVF(EBtHh}RH}d~0^FG!?1F ze$_{Et}D$YjA>0$<mq&CtayH=dU9M!F_{D8vBZZ5v^FA;^Wk@xRGAdHmg87hxrn{c z%5$eyrNa4}2KY&F#O$^-ZS>#CQ?`vqt%^h)P6lt)eU@YoyiIr4_q&Gv@900REV2I% z{LmEIYn?sWPbuDU4r+3Moul3<tXdBWx}7<4zB?;De&*Ma)+y73=v@jSonozOAa9_N z303P#T@_W1&pszfE@aP8ToxN-i`?PdogglZ5lWgZ6#|OK##N_9qG)^o%4AM2=p17K zDOX(@jbo$gsB+m03i6BgbR(W0=)P_Mxe->aQ(VnbglXjX^Wv>V>!=at$b*8QTNzq! z9Ge1=?^Yr7hS2duLP9h_KANU7ZX-SJ`9aP}EJ`UyWXuqHr+O}>)VkOP@~PBCk}2C- zj@r$S6?0KmDI2<{X)fkT@<G8ljmOo%fsn?eb>0gK>H@hD#pNcbJ<JEm?^X|z^S#;_ z!l@Xk_L_G3h6}vIs`a3t+X6X6DBlh8?6Y!UjVn%$#$c>1lMJ2Nw9trlvlg+5zC{Wp z1adVkGi4KTA<>)*p{L?Q&!dE>+<J`^i5AEe-X+T?p8Cqv4+`qi&#hS@1M<TS$qmQt zVmJQ4I1+78x3^nIwI<s`L>?4$yC8o+mrjsV5S&e7h25@4V<68Y^9>SJk~@S?WS)Ew zy2;2mruoKLK+@#WDu`E*A@~@x<8ue*k#80=0pC3w&beETrXh_wun@?3^P?h7MY?M? z7yT!(q~E=JJJSJOy!F{jb-(0*+>zj|b5CydEA)Sd8$S86O^zQNFv#x$<UArrw~6YM z;?JQ`zI{|$h{%J2ZU^KKX=gVpzOx&@L(`Q&o=hega>{WWrdTMO(!xn6$`wu&Rc<eh zi#0A15xMm%1@yt-H@0%_`i$RE>BdnYBIgEY(PyeTYEP@z%MIjnIoElb3#sShn0+Ep zv4{mg&f6Z;@lZ4S&fenhivCfFhiAS-%Xd)gKV_(_PBC7OnW$>pA0{}5{&)7DO-ms# zKV*<&)q3rx2^dq)$;7ZuOb6p@KZidaksqI*Z?4CbaS7=3^70KixCFbBAMB8^Qi62+ z^ztcOVT3(sFP*M0PW+ZvCr%x8{k2}TicT+{?`r1D3?6&v@#EjEiC-wsuQVC=jmT+( z)|<?c7h*b!<E+X|06Y+0gPJl=lokpZQM4j@+1m<o$JwGROG{`~Xe+~UMCTr*{-O0F z`&I_rEo0Wn8LkB_Ya7pXs>mM4s;4FrnZ5Tc*<VDM?w7y0jd0Yd(ElC!xyX%<F+J2N z@;h{B3b@>i$oWwz?c?t2{wV$n5&2aVx%=IdDEivJjG~vW^i34Kao1I3^mbuyk5Tlk zGF?^Im#7UbqDrfNe}&YOMaAmlD_Go3)w~jP*$>)B%i(bN{)Hd$LumO+h`kuj8YS!3 zww1++kN9*M4%hz<<oJa;=J_|#lRhbm&i7cgPB$U&ymM%s*r_(uQ{$42n5)*T^i<5L zh`DuxysW;@oe`4q<{-xtY+Q+$vRuw9;W=`y%oS*H)C&sgP&J_LKyGyCL+h60wS{f| zQ&W(DjbR&gc)dL$@{=x*uN=ZJ4Ybc0$QKUd=Ii^hb$JV5<NC>vzYF9*`8hr%RL#6S z4ItlNgx%NIv*G(~AYU$*GXwfp`+)p<_<Fg%e&1?kIb1XU_2TbF<izLImU4Xj{G%Yp z(7Gi!$z*nee7=Qn8bIVA$5cARhOM(5Acx8d-i0e2%bxOroJ#%RhNhyZS&Ob^ZJGNN zAWh3bK^@v`zfgTMx_hV(lH0d!K~9l0BQ=4&#da9T5oO4d?RP-_;`Mq9$U$WrbzeFT z6UfgEiS6ZE6n*OVUs`el(&z5_q+bU)C1E>0HP-J{$n?n!!@o4m9oyWhAGE(_!;60Z z{qTiJK&Lg3+sn!O;d&2{pA3f<(XZYOzjS~c`gb6|idL}vg@}9;l7r|s0C^m5iH&7@ zLl~vo9G{D`jPmhZS$T%m0rF8g5gMqUj*W}%2Du;HwDv72tK6In=B1h-Kbnk{p*giY z3ZZ#WS455z$+6h&&Y|w?hKQU^jklgC=ge+k9VHaVbGP3C`2|Kmy&zvWQUm1CO9J_o zy9)x|#~4euBkY^&RTs!n=ECl$XdT%A@;{{oKz`Z*^8T0M!u{+Qv&Dr?JYPP4v6z|R z_!rlU+0s>5F0FZaLSQ~wE{%ip9==0s>*wyWoXsvQ*q85z@0J(+>zN7IuT9);DpND4 zaBVzanIhYWsrBXLFM|AS^!4qA)^Dy>-=0<=KmW8^T>|8L&5`qCQ+9#86xz@6ST#Z3 z*2mZoHk%O1Y1O)SXkErqOme_ij&*M1@(z$^DFb)IaT2>m&L{`oPlQ#hRdZ9BSctRD zOHAw-LQqf}<PPINdG+|&!H%upHKK@|ZTZ4z-drt61<aHD_c)InB=>^clJ*CC=d+qd z6ov8rd5&0UBT^6-CJQ%~ik2+hNkK<k%%UiU?u9D2)>T$Q_YETS30#J{D)=5Huh4VP zH-28dQ?;E~Vtc>DnfrfcTFGzDJ!kIRry`IqWpW)L2dh<J_%OSKi#*zw_JUlx+*<bo zg)d*edyxO7sr9vu9f0(sKxV;npF<(Ol;=W8Ea2fbwP6{pZ7aSirM4MvG%lygaKER< zn#auqhpFjNjpn%=dW}QO%^wHkU*x+x%}y-$&P2a`)uBn(lYyM;S-`f~3-XItLSK{P zu^=ZQyH^TnlKkTGO7!ijw}$dptf^)|-mU1XSHR%c9cjM9B7b9_*(IIibc-9jSEAZh zG{t`NDWC7W7Mug+9O}B#TD5J-g?)VQjdCwXk$c?oOFcbZC%HtrA!^+TNGGI`PqQ3J z?$MUn1i@~xBnM@O>dOYmzZbJV0CM0P8p8Y@no0QElG#thNZ$r|LuG?}Y7+O^+s)Xd z`>3H;BFzELT_FD~yp?t%q3_82=g)+%<#JFKhU=X`U<f>}rfOqps34bl^f`wa<;G&R zLv7Qp{8^f8POSsv97c#*4s-KBX)gA-kRR=j1@fiL@~mudb>Y;9nk#0fg;Z&n4CK-D zAWiZeAP1nYW32QhIKCU?oy(PJ`;8<gnQf4_zFmF0)~R)j{z=EXP@J!xRBteZel_}q zJw^VeyUxMPZ#MD~>8T2g?$<XGV~^%kgKagM@ABiBm)Dl8_nt+&XQ%2T*R|cAJ)=c# zp%_W#u;YG%@wCX3EeJ!ByC5%O>Kh<$2)-u-d7tpTMXgY|UNGhGOU4De^$BwIy_?QU znB$^8gWaTwS29&+3tGAk$g9=ryU(&q1+c4wFf<^C1z)a`z@~`;SHT>Ngy>Y+SmEKM zjmB!7hq>SvAaAdRS)h1kK;G85{or_0>kTFKFx%H}+mv^YC49f?iG1X1n*u!FZIO4H zubVE$Wog#yykmSfd*XlYeQQ-(=qj+hdCS^u@W)QAUq<D+sUQ%pYt};NV(p)zf$}Y) zm|VZ8^g8)<h+en*`r5hKfX7_TdAob>f=>2}Po}pAxtF8JAb-IqlT&|<sR22o+sJ1d z;3})!S+|uoyXdf~^}|U%jp$2|8~FBDATQY<FJu+s--Xlll%x*_`4oR~MN<#*<BA}M zW+pwT8W|GLi0PpAZlMfEKwB9gA58?jw#o~cmp3+gO)PGsLGGOc@~vSe#@shOatNP) z7bFOF1HvtB;rxr{@AOvm7T;H4I7&o?L>4($f>B9w7s#)L*l`%Ybe{ne^LM36)K`(n zkz6!Z9FRA`;3gu?G3jld{l2`pe#1^?Jr_BcJ-W86bnTb3<W0l;c6j>5P3yX=jq*Ao zip4A5WyjWyl=ujCFIQZhRklF+>H5f@Vre%*eEYrQ+ZMSK-p*c|7Wo5%yx1Q~I5|O{ z`jIV`43Db@)=)P3LpjwylJ)Fu-vE8Tk9=vI@Av9~FHEOXnW6VS@}rB7pM?Tlc&wo+ zK`uNNxgZxgf#^Xy%*|xPmD;;Oj&OQS=hQA2joL>8xy%erCKHM5(A&*EjPzoPZu5i| zIcy5q?TA_@96!a-9T<1i>0OC>ofQLn*tt3Qv_%(^0K!|BO|y-><sTHpIEtgIrs;VT zQ=9L#DtRmWCgysi^X1iczh<}fcAdNFHoM*+_lon8uVdXHGqrxAVe7QWH&$T9h9%rs z<~Q5&*J}LGQ|sT&1muz+H(^5e2IL4;i^{(!tA|rTu@HWE2UPC?c|*y4r=!Bve&<1c z1aXl!W+RA>f!it+tUz89&bMp9*ai7K?t!&MZX{hoj<VMxZ_^@|qIdIwxa5y8wGL=o z6G8W|$omfpa(c)m0g(T7^(yj4vo{f4J7*oN=XTXH+Dp+Ro6DU~KGe-CMiIaHFuD53 zpFKHEF>2kOG$)U>z#=<JSw@DlCyO68*i9|xY@Hw%u8aDHz%X$NMXVFkH_N(|6v#^G zy&%T`eZ5V<xFrvATSr;sjUW#~1JIh{9Ew0b$Ib=$K)vgXrW?=r7+Ro_anK%+&r#e4 z$Z@>!kwAWz{n0m?A{rA9QAV>y=#(_rjgOw;@iQ+kuLFepU%1Et^XI2JvmVW@E6DN7 z4|%;Aj_$5d&tH=L2#=o;)c`pbed((~ot;!0rF+@IqL%Uk04+#H?}o~XS}!Qb<&SG! zhM8i5UFPB&RcTQ~)Vg159XisJXpCB)DScsNm&1Vt@;MqgAlE)+TH>MBX-NAZH`nw) zqtNF#?8pVVj=PZU*qp;WoT1^7Kwiv#i7JN@qpn}#Mp2g|!cFLHB9L2tJ^<Z=+{^1A zz1nh1{ZqkioKA<B(LFG|!y-?!_<<LMf#q^bkSoFacor9$u<@<gmlWtIfco)Ev@W$( z;fK9qYcb0~y^@Fv!Elkc4UoempJ`??o0}v+4i|cR9>!SYI;?D=k+{r155nBItT-RY zC^|q}$`>-csdhlFe(_M?zY2CUz1qhCd7sOy53_Z>fm}|9%WM%ho6EamF(JrdQD7eh zyUEAeq?zKLX>8HNtzu`E{g%>)7V{`+o;BOz<J2(cob<nR{aTI<E=6RwV<j3RkJRDU zAKQfKG>+!}TkxDU$v!+HlFkJpiS(iW|B0@jU7Vxx4Fz;gJ$-t@KJsTzXp!4Xw2|qX zdu%LcI1_BBjUIZ5R{Y(&BgoApIO2w;islm9@}(*T0DTY0i%S^;s_Sa&ca4+>`4K?Q zMc&*6VbmnAjign$;MBV8$EIKq3-a=qPm%}o(DcOH&B_Clo&_-JHM+e$mhl~sOZj9p zSV*uNn&8++0l8V52%1POUe2?WU^gw%*YqS@5QaZSu0@V~ay?p0fBVG#q3d4(F%qFk zzOM3Yfeb2$vK>Mv2z!pH12`4f5w7^9tfny|#2(GA-=p8Ze$@X;m{q51O7^Gx9J#T{ zX_1rEM75RMig|P2BAfVq<iQ_?QB@yg3cS$w3&1!!_9AaoP%UqjRBMNQA8J;^fN8$* z6ubDIxe$9C`v@T4{WW7cL9iRvgQ02RedPa!41r!+z+6KKDcYJSrR|EQ5K_AsPS#>T z2fr8)g-p{d7V&@_2jU5H2>X0=&nlh?hL0EVo&5SKP@EvgbL6M_9#gf*<=5gkU~T<u z<!E)=OS`#j-vx57|4`8)Z;wOe*#r*yL4ud299{b@@=O8GznZNkypQ}Jka7yCIGv{t z6GkBFY_XP1J@h!|JL>k0au(Z-yvN6dInPp4zjJJKV$ucqdM%jf?Pn+Z`ZIvs^^wy{ z&K$YzzKNV|P_8Kta<7<0-X4j9ac(@D$wd6S(+2taHKvTfJwNk0ZAJJwKL@kUB_)zQ zem6g;!3KF0+W2xojzW=+jjqffM-bbG*+4mpcy>HJq*;$fQHphE90tYM5WJfhr+)YP zsk1ngBe+C_txm0<D8|iN>+-Y9M~)n7ZLp&?&2tv$$6MrHk6N;_t7uS7or-ooM-G-_ zhA?yHb;?T90F9WM5iDiEOA6G>Ft<^MVpcgUSFVw(nN@ophdD<XCNek&N`Z<*CZ-=6 zXE-?fKrDgm&@>z5e{lV{x-_*BVFyE8agNVP`^a}ht#g*0wQRy7=DF98x5&L7w}M*j z(M%8|m|BOIj~4kF<mtp=Tj``kBAND${h$GQr+ocH7GRm#6pJ?Y$|`19o<@ajVRKS_ zjYW3j5bIIWNKtVobdF7&V$LZ(&6Z%VGbs+4n%}#Arg4Abu>71eSzPB>0>4j`;|g-u zM^0X&V5`b5VxD{NBlq(9$=<o-It@c%n8!Bgg@%|QML{wH#!QgH3?^&<gaj*K0SuV1 z3MA%8EP;h#`%gYj;u3BtMYZI=w|>WQiptkxpE&;m<c%zH*%a{H_$6W6n21=ln<OIS z7}&I~LC!WO;-E|uUJjv+<0;)fox)<T-vKVMap>A%=%NNc1o@Cism_Nu)hHbmn@?dE zt71}^OO|lX#t3-zphE|pCM9*YsWzt5yNhKy83zp}WE`on@1}Nss+|v@x%$?7dTG4B zhHHM;==11~x_(_&%Dc`@;<mI-Yvj1Rg?G76F+J$Djt3jXkR8gKcDY4f*T}1?{>vJ< z%!#P^0ceg&<H8G1Y$eOF<YS;B0FzPB(N0I{J-x`Kcy6MQQ>zjhsswR>dIW&#pCQjR z1Prj$>vzUbZbi?N<s-?aneShU1p@SC$q%sHsMRly6GrO;%lU<XW1ZkFhzG@>+?jQG zyWL`W8$KVl$bq?vNKMt%BCo1K=LflNKMOKJ3;m!FD1n8r$*^j5h+1=CX8Hm<pi7h+ ztq5*`Q^F-OVI-_Zcyt>snz}Nt-*CK(_N;5}{0lX01YknB!Fc3iI>m*lX=Q3_v>I`m zH`i!S=r)@D`h~!~=ZlS$lnE2-rEUl#kh8Q6%*AEUO?h~OZc<8Di@d5T)0v&!FvVxr zoo=@&ciG#!Yzl&Is?6(WQa!x<@GlYT0vrRoCvWbE^kj}-9K|Ik<Z4lT7o(8p139VN zZje!~fB#OCS?q2cgOaD#qi&g}o)BY`18~SqV^T4wYvff`XVCUTQ)a6|_C<YcN~sda z(<-m~$9C@EeJ77Enf${LPI0Mf0=AR?nmpkd?e5cqCrdr})HcU-E1P_t55Zxb4c>x9 zUg`tMZ}QL-L+J*rlU>j{qd3s77I{?_`Y%)Kl2ESIzK-f&4gc09+nGQGd8b(u-kGS` zC_LRmy~OJm#vSJPzm@Z{M<-|Qi#5k37nvJ|8kM}|nuzfy2h}yl8Ra5*P|Lk%O32x* z*opOs@d)yj;~F-&<+&{Y_L%G{uNHY#75Wd(Zrlv}%Px2JDHmX6!JVw5&CS2oRYdO3 zbj3TIT;6k@T~}m?{M84m;=~1BKYOeU{w$DflOI`{xxe6Pbw)e*`F^xv@IH(djAwe# zT)$h{<O2D;{emc-RP=r1f#eH|JYN;3hDmjN+AYuZsup=w)fv=nSmbOnIl19>paySm zN)FP_O>dRs6Gj5kWd<pUxf7ZwcbyxrU^BqY`p#;oMnF9TC0_sR=Qf^a(mU`lnxjM8 zdG9ZGUVV~oe~X`oAH0L(ht(YOAxyWb@4EDL;ZN@f@<R7^yD6g_i=22$*>cP3CAjBg zwaBZg(D^~$y=7M_fm~c~RV@HP6d(hqz$Y2i=%AH{I4K?!Ni$do4I!BV<v56uF-)vd z%V8qNfEhpIRCa~#;;ui|CXA2mowKMJ$8o;5y1jGhY6hR&*LPh&FC0Ia<W2kxS{H5d z>AS+zx>C2wom)@7Za3jH@FulfBe#!3gWHq?{Vj{UxvHwFI!^8HoZV!G6UaQz9>WZu zsKNGB0DfTF0y3(jLrO4I!7FVU0Gy^>N>OU^(2f()tsyyBwu1!kQ6*k~+quE_<GE(N z+kPDVFpOhAUiid%R6BYfN$yAA+-aX|>%q0Vb&=#jF3}tB67D}M_~~aiZVBX~ced2M zJGe$pMr}<EM{R)o?p0M))yW`t5#+|I2%25qQZ<}e*^6tmKtJ9Rwk+TzP*>0hQgS4H z>yNfda~|ahNi273ArJ3O0vejmTw&MmWRC}Koy%HonsMLzpnkl3gFM>K{ouVH(+47N z^$oR0nB+cj{Az+Yzkrp!RqFj`H`i<Axr@3jB5&^>cXnR=Iu`l;tE#H1qvU>Xkz-HT zP2Ma6LD|O6qU&<99JX%mAYI-M$JkClEON9)P?#5Z%|=efB#Dc<eu2CjqWyU$HN!rF zu`j|P56ju_qVeqe5rce7*YCEEUVrzm0C*H%pJ0*SDs^gIZtG%mW`2Wg<IR?D1_SMB zx4lN*UR7099izLuEoV3GJ_~;{*g*z{AF|dV%1Xee`9nbIQ1g5eTB4d3jzY58s9auy z1^lZ)M&OdJUo-1nJM<&SdHm+lLhnzt$lZQF`Y{B*Yx3sVor}>l+J5g@A>Yz&b@(ej zwwKEa*T?mR@P%R{r6|5P#m=m!rTwKv4z4k;$vaS;nc}8tkSy}LNM2QSPG2{HTqKu8 zZhUyM)&w?T7jhA#+B%Rhmu*f8pb=#zxD~nW8ZudZLD!$ub^)_P#v+JxD#)AtK2U7` zPN&HA{?TWD=R(vpyFQS7+{X`OP3`Yr6o2?YQF~pGH+}D~?%lh((w9V`*`l@d`_Cq; zo5<c&M&5GXk+MzP!XmG8>s3|%MsCw0#~x2nN(QyYVH+kvAiWegfJPH)ti?-Xz@%J^ zY05e2hLdFvG*Pr17`>QBf>EQ4Qk=?VKvqR5*FVp!`@U}ti(pWe^N;=U9N+EV?Z^GQ zcbsCO*DnM0Uc5J_cx;o~VocAU#l&_))7$&^8$Uaq29)o^Xqy$szyA0rj(__G$v@ft z-%J1p=;kcVxPQ2xLC$?=Y{qc2T#!eM-?)8Xjoet>Af1JBveZ$UN(AzH16ozpnYM#r zLm2)yN*q_LZ0A6pTI<hp$^lJ#8?;12+{qyrsm$q1DRoDOiXbWpRT?eMOM^8V8IZjS zB`HqXLazTOduPw;L=c5x^>=7K{6L8?Ayb$H1Op-9R+(*VBBZ$MLeiwL5$wd$RN@Z^ zg1xAP*jU)x`g1&IPxkff%o<%aU@r6Cb$7mY&Ma4aJTqr@=_t04lSh8zw?IBKi>4qa z-L{j}YO)d&s^=|V?1qS!CCY?(uum?GIn*^;%`VT4;lzW32v3bI^TteT2YZ=EOM~sM zXtY<V9RGN?Cm?_SrS~!bIpCdE)6i`@yw&Oy99RB0rq)k(Zk<Sucddie{!TOvbIGVi zsFYLL{1C{m-fTrhMKyNFLyx@l#`yw-gY7q!UkOsxyywK*>5N+xfppLo?nPVV19VCb z7()s?10^*z`Gkwq>lzrV3pa;JKA*tz?<dxIXV?)y4vrHVm#h1ei3jqv$;wXMK$!sl ztodz_4|eNAAU6&m7bVHhhuf_O`G;PQKrSS|+k00F@>EZ)b6$hIKfKiykG#77?3(N& zzi^^2gdvWT#3QFu=xj@_8VrX<!G1NAi$@-JphZO;W$zi*$OYppP5|L$;myh?nE6lu z0v>fj&Wd!ZEjU^pAX=qAom4hG<{>N{Ih>V$3&ZFLH5i>7KqvrSoKE8Tiw~0BCT`X8 zDE%iO?=Dw%5_seeuD4rPOqA~O`u9OjY5?+|Yd=~VuC0Rn$)jHH5rh262ZlPOnuFY~ zI<4Cvxj=k>och<#WFL9OxmFIi4pi5T!q9eI&LEGI>rqihnOFzNncZ+I<fjt-#+UtP zm=!*dK{+^x8ZG$6_40UEoAZenN{=zH3<`#p5BDh4{Li2NI(y^;S`%&#@>!a>h2_*B zaan3Njxu)Pvh6GY`D8L#T9^Q);fYsFIFkt9U1lnV)^46;8!?j3G{~)6>_Kj~Zq5tu zXu-FUrIbNFEe6U=XR@DdWUT&Z`^y!Lmp~5xn|1fyJI41To>qSXm)r+A6y&?P9g;(S zzaTjxMENS;BR|zQyIs`#$i)vY54|8>zZFgS>cLe&9=D)HMID9X0`k1Aq+eErGAT#p zHI^T+dkq=&&Prs_i(EwezN9TqXv}qTZ{=?EjoV=YW$L0vjT-3;Pj@b!zuh9VbZ*&Y zzwy+1VzNbQvMD9ECfhi-HI{&C(uFf?4~^4NzU+_01bQ+A*sVo@GLdBr__?8;lp#)~ zX1m~^vUDRx0CJNG$Oq0Ogy>3(S!!rh4DvKfUGcvM>X^G(V61AmlRO{M0g%7zvA(>g z#Pf1m{bldlAA$Tfy|1?R_fI>qPZHzB{xjKr1`6Zgtm3<*z-|Pnqeh)%jXaV(D(YAq z*HP;l9N?WCB)KAwCYqo~14a<aqyhj!S7H=hW6cq?1s-9eq^YK>6qg+;i=|DuA17h^ zxp;o&c&jrUHV3&i&T`(BYur0SAYYpuIq2J6738aN-XDz>$OjLItqEh_&88v9lY*|P zp?VlHTLw8NFK^BKGT%E0K|a`0x6J7?26Z;@rq(w+I5QKF@7Ri!v0}7ztnz$0s(}2t zPJCdO{A2HPV~~&Rkiym_+|B>}pRPw<VEh7s9Pq{gRtK?eNO7sotJVR?Lz2gJ@~Eh0 zJIKSRb$t3v!KOrwMj!A2bOJ6w5{dyIut>R?=uX#YWGNFO&E>rTnATae0@HmffHsD9 z9-g27C8Tv*c;pSH)^}zmaGcVg2Mp(oL5_M4<oRd>kQcpY%xde{MgZ~wmob~2sTfKM zN}rjHOwG?ikf$ao`d`Qp=N`x(6!#@1$al4y<t8**o990R`Rm>zlr{CpTf9b2BoBZ8 zC;Ra;M!8I_hu=H{wRL)*6e)B=oP<YySTS}zD(bMV-MDfP<T>V!HT?p*fEvOQFsGu> z2?p%IE6IAZ(P*Kkz|p5Ns#YV>hu0W(&_eXHnsf2|%<=o(;j$UXK}Er=_{MaxJhPpp ziS<A}ndZ~!7$&55Caz6uL0)veD0;3K5|Gc0OG(Zo0mz-%N*DVU>zZJ<SqXB>V_n+- z<g01Ust388<<#6G=dg8FJNW$<v2G{olIu6Sc@ya1GNRQb3526XGmjjKZ-$AA`nk&Q zksb<m!_>5LZgB=WG^I3#kf^Li2QIKA&=HEmb!2HJ@;>B(8&$3rw<O7;y&4vrW2rw6 z&)*_-ZqwBIsDHiD)Vg@cq{IN^Tjr!)rwnP&$32^l8I34xKUi=hMk%PTO*|lH**W1Y z3<=1&!FEw-9)R4q!pmMPU3FZP&+`{SK)R&6yX#14kp_`&De3M|x<QbTI0b1Aq??mI zx=T{-=xz=U_}$0v@Bf`=cHZxq*?nHSJ5$upkZRE+Ny%kdqr5y(3Vpl+h9kUAid(jl z<hrQWHjnHh&o*wthUqj~A#LyO0YZ5Ve$^hyJta;s0+;p;@SaDeG$$4jqjnkm)$Ycu zL}s|i=hO^|FbX5QqnBBj3W)peD4Uh=KxyeCt&IAf-=d4x#1dwo36yp8K1_69WHHnI znL;97yXRy>o1u3wU|9amK5v>907^?4WD-RIu`Ghd_C75Iu+}+`k=Zx=@cc+)gZa9v zi6X@|`4KOiI(KQgOQm4vFx}!w^_NM_O@YHBTes`T-_&`5<7Q5<da&@8qFmS0?Gnq8 zA$F<Aw{90^k>0B+sn46_$ik{RgBkuXls}y6m-3zZlOmq<#d)c(NjZLNy6S$%E^4uw z6)KK&wj}08WBMCEqGjYRQvi&ZZ*R^#g<Q=B?t=?)=rM}9nFIw))a=pW&O%Ymc!K6e zNveR?)lI<05gL112ysQjsENy)*W($@!A}G8il7NxeY~Gab@eQeddgI`TogY$VMxN1 z=Ea%+oz2IGAu@(mXW1a5j=3YX6AiD_dX;gi$^Fo$EX|vKSNZedKVq+sPNZk_nV-?U z!<b=$6cr}3hf}MEH&YUn6a8jkGwmjZ<kBj?nr;EVWq<Jp%iSYazOG>4TJ&SNgmiF- z0n0Z8wNzMpKQG|Z%5@kOjMtVWvHwV7C_ZP8=c~j{yro!k0Z(FO>e(<eTL3M<&(hAC zU&zi%1oE=~gRVce!ZQGc>f#$32;T|&D;ygqQB_P&*S@qvS_qqc(H`<0NKF{SXnu+k z>~2|dOm59S)z6<Pfc%&L*=F3aEcAsZtrWGRKg^#{{q~xyA)~(GjDk*%_LYy~-vj$@ z>RPb98p$sLa_pDrmX2M|mFY9U?~{%ja*3mVc4wCSB4NOG`fe>UO{F~1e?d0ox@z^z zlkivdYhLSl-s{?(4AW9qD;h6BkHnAzkc8F{LyXFCXW`W-#rvj8@dqj)vQ#bw98bsR zOeheF1<8GrMgl6MWmJF=u)zVN+ZAeC5JZn}K6O_MfT%q8-1a}cmt7TWpZb17Z}9A< zbi4)~Q-z0~RvMWVi@4AL*{??TIX^m-z9UpD)+uDIBy6A=#W%Qli`w43{BDwfY^Chi zHtuthS3lI{bmsCBc91|wG-rZQ&b5z(D(f{_%O}Pw96CIs79fK&znOq)HTEVb@aL~Y zqBG6oqSB0`dVd`$BwfbKOwg$h(n5^ZJ5ox7Q;abnz3WfKYNZtQyfOiuD#;0N&ezt2 z_|P>OWIrR<pGC&h2n<T6Z$z}*I*`)wU)p4TekwE7AD^%5_iB9ex%QRlr_mKU<otO= zu}IUCr}g3VRg`;?z&K@3#2-%t{6dXV{_5|}!ng!|%C`+T!0Q%n1j5q-;b+0e=)8rN zbZ6M>oziJP*nM+X82xbXH76F`u)9Ln8(9<ZUVPvw!l6aXdCg)v+zlNl5b^{SD)FO? zK<vjC&bN=AWg;{=C00+;F22uE0-EwZjjk=I!V{kly;#{%%QH@imnhswV=9TqSG}!o z)<t#ac)J#)ziSnj8}o9DmTBKO;(d(&7*MyKOle8FHDadMzD7p1b9*bnU~M*_WvK1Y zP>4#QO!HmLpoKJ83=ggQX%o)%8@&onDFbH4la=L5TW3vKxmJm<Ga+{HjSWS$Utty5 zKA3pjMZNRWkp@C|cpVlS9h9#kX_soz1x-g3nF6KYFCo&7sp&;-F*GOvTq}oRdp(Yx zd3{c>SmPb+)T(E+jAlFTRFwT9=O>5xBgsT^B+;E6(LKUYab{wLs;E`xzLM#<>c!Ty z$QP<?15wzS+^kkxpIxNG-F}DC_86SYhHTutZtP9uS5|+r_FFAW$iMZd(9{?Ec=>(v zT8Qy8x4@|7Xq5z&+WAP#nF_lZlM}g}j7fCy(y2Ngg~d6a6|9c%4c>W-(KlQIlAks5 z-K+qVYI^&S%<pMOqu6K8UBi!Mn6sz@ZYIBY&w~ag_|5(-+6jlET_=O}(@Z<&*|zTO zXJM65X}sF&oHsOGu0WajFN6*qqj%NZLSgy_^nXH0I~frtW%YZ<w(qa&>i9ZC;C3|y zZcpErGHK?OYU&^+^5@@n!s=8S&X4TRWITh0CC<i4o`>!nl5056L#RXo9Xyiq8fv+j zeSLBC6M7GVo#0}8%thI3%bH7(xtuS>zO+Ho8XzoNBOR;PR<n37Jd_rbpIc$OMC8m7 zw|}5h3YE7rr0$c0s$?@PcP<aOk+$aiRzuowlT1gH-to;iOof?dbsz+JC$^ZY^w?j+ z+kahe|FJXVXlkKqLB-ADaO-wNasg2hsZ{Wr2?ZS<fIw*Z(FOQa=bAAs<f4efN71$g zDO(3boM1_m(q%0vQs@aN)C!~wrWa#m$nEmRLgk;9(Q|xww%U{l<n09PJ({V#jp{x5 zbW^WZyt{&e7{%7b*AKi3ZIGR)bmM`90P~+^r)}ib$gVm%wCA-VVSaEjn#V$&-W!Dh zEhFdUh{cbCboo;Q)szZA4m<0D-dLKAIc5w<P}W2;AFX+TZD(Qv48Lj|#jqxCe#E?{ zD)Uk@NbYfSJpayA)08uJ;$sRXIz-Ett(6wjrgQ$N%VXLsJ%^pn_;A#?RAhOAQY28D z5XKT9XQcA6EuufDa_b~`+g{BgijXR@$%1!K-?adLK#BaL)v$jS3;c6m+fZYtyTa`@ zogG~Qzf*G-10R9B6&e{-PDX2d`SrbXP6OEmAtlAH3$&jib<J=ZkPjVysC<@pO2=}j zY^W#j(moM%6pv{@L3fu){c=XbY+g%Zu$X=7w&KvnnBvi9=4Y?&Q?i7ITM)4!jJ7i* zR5$`rw{QXw2OYrU&Msv2gMt;#OFsx1sr!5B=EqG@!pE2R$FA#@lOE%}KT2QcmguMn zSPuiE0w8nk8kZ~>K53tGeCRrupTROf11ONzWy47$!-`@Gtj+|od~at`qRF7}$v2z* zm;pI`WZggBQKGZUlJ~K?1z~h`d^sN#|9~(xZU&tPUB%B2PzZfRR_<%YJuMQ`QRDFx z+nZTES|o+r^YJnHRR_DL=OwLiO|T9X_+^iGdP{#gJ@QTUJ9bUIsZ}g^4ig?ax{yU4 z2;~l4L9R1n&6_%wxO?@dJPyf{>P?E2@wqiYDl>zM<YT?raZY{A5pvU-%2wY;IeMsX zX?p`@CVKFDbX{FVB*X?1@U24AtLtZi=icv8wmSGEy>6s)At8c?lGhLhv(8$)oA1CD zg6h*A0fc0r-w5=`BrFlExi1fUN^snK5!@gaoAG*rex)F6f*F;iH@pe3wX<SYl^5{) zF211g;&k({VOH7!cG(WQJr}x8AL*l`BWCdZx2J<TAfS0kX)PZ36z3{q0`Bv^Ke8v# zaltpVU*XNpB`H~ji<IaR1g@3o6urqGU(H*Ev_bMd(AIPNJ1Fvcc9MPP5ypCb=>tiy zl3xqPY4v%DnlczrK(8WRQ0hb<WgSueYsKA%f|&<Yab53Zh+r~=B~<X{_|i#6XvJSP z<k?*itb*}rWKTw8T}~h@<4sOb7b?5nDd*Q_Kd-u;2h5*XNTZqZ1$FV!`=#Tg9~eAM z{|pRq>poMJ&>6hKQw=2_<YVhv8LevmaSI1lD|N8~G(6VmBiuBs7pr3qqPW2+N^5(j zrlNc@PP1j2M<WR#+y<${fej)<#ea%axzk}2+zz+cn0UAmDmiCkoG=Q2kotsQl_g!Y zr!4AVqYnyP;#sO2b-S`$(n;;3I60hO0t4bh_=l{L9w0DsaBV8IN_371Ed^<KRQWhI z*@j+PqcWp?kQ_^<%z7rS4gF*wIi$887N$N*WVIn~_q8356_9&7vcJ;Wtmol#;Jf7) zbA8=R>$ZL@^My<oq(*!wqxWTS;wiEjhytT;{qCPNYH}%>JEA}D^iV(w5O^&7;a{ZO zT#E>>2QEmU5L-nE9Prs`j8>miuvD}3!>Iw!S~DX-E|YznZI9~myxc5U$>~}@7E||n zlis)1B0JJ`ee1!1zJUGwX%eznpkmPfAw{{wU&a!_ZK;HC;-{6}#3{!Cy2O?3AWNIA z6QR^oyb1O3SlQbj=c*lKOXr0x_JKJsNq_U?d#(0qP`^2@T$6da7A(9?7?-Zp2l}+N z9mx!&uZA>j-`dn;X$qgzLef-LM;J>*)+{@8ilhUlmY|JY5ig^ygZbOy?uXTQUOip( zbrXijq$lbpE1hEXEqKXISLbuBS0I+8bQ1ywr1jBZ7Tb7^Hm}XE)3_jm4E@b95{<mY zbw;0axeMz<>!y9z*kziJ!p~G_9YxD3sKRgyj6Um>2n-&w)X)^rHXrwag8#H1QWGZf zRp04ZWafBrOzxU$ean7BjPH`=_gL0!9w_Ny1}W||FX@!-k(F<3nbg-3(?KABdAn;u z7nFKV!Rh<zFnK^PhA~XMt#l3<4Iv*-fW~5)D^t9Vwpc>$V()htM-hVv)MvREe9pWG zcS7{fw~T68m-6e^XeO$)wuTH&r12>>d3ZY&x<3{T+xMhy_AI+n%Y9T)AZL<)CDbqi z3^^fNWS^LW4QG3k8n#XkXT?kF@hP7u_c~N|#^#dOPmODuywq(eG~yCHG$LU=LRM{` zjb!uN49HY|aN~Ka4gbKPFpH17npky>kGgeU?E^Qx<Lw+Pu}(>F3;5!lJ_`VN<abI} z{lP&GsFRrk9sd_G$>v;;Ay)}t`r5p(J-J|1#v11Fl`-2Ol^2q&_Og HweR2|!* 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 literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Workflow.png b/web/public/screenshots/light/Workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..a82c9a6a4d04b39653afb3497c0ddcbe912368b7 GIT binary patch literal 22110 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 S)eC+A0000<MNUMnLSTaMwI=%j literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Workflow@2x.png b/web/public/screenshots/light/Workflow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a1a19435bca53e90c5a58d5747ca5297c933f6d GIT binary patch literal 62688 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 N002ovPDHLkV1g{>eUbnG literal 0 HcmV?d00001 diff --git a/web/public/screenshots/light/Workflow@3x.png b/web/public/screenshots/light/Workflow@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..914ce45003eb35bc60ef959705e47133d5a87b11 GIT binary patch literal 147073 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�eFQ0o4AUwEAC8T3LpkX~dl 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�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 literal 0 HcmV?d00001 From 39ec6c8025a2f26087543eaf8eddbc031b11be9b Mon Sep 17 00:00:00 2001 From: Joel <iamjoel007@gmail.com> Date: Fri, 10 Jan 2025 13:10:58 +0800 Subject: [PATCH 14/28] Fix/setting model page crash (#12594) Co-authored-by: JzoNg <jzongcode@gmail.com> --- .../assets/public/llm/Anthropic-dark.svg | 186 +++ .../assets/public/llm/Anthropic-light.svg | 186 +++ .../icons/src/public/llm/AnthropicDark.json | 1046 +++++++++++++++++ .../icons/src/public/llm/AnthropicDark.tsx | 16 + .../icons/src/public/llm/AnthropicLight.json | 1046 +++++++++++++++++ .../icons/src/public/llm/AnthropicLight.tsx | 16 + .../base/icons/src/public/llm/index.ts | 2 + .../model-provider-page/model-icon/index.tsx | 7 +- .../provider-icon/index.tsx | 16 +- web/app/components/plugins/card/card-mock.ts | 160 --- web/hooks/use-i18n.ts | 1 + 11 files changed, 2514 insertions(+), 168 deletions(-) create mode 100644 web/app/components/base/icons/assets/public/llm/Anthropic-dark.svg create mode 100644 web/app/components/base/icons/assets/public/llm/Anthropic-light.svg create mode 100644 web/app/components/base/icons/src/public/llm/AnthropicDark.json create mode 100644 web/app/components/base/icons/src/public/llm/AnthropicDark.tsx create mode 100644 web/app/components/base/icons/src/public/llm/AnthropicLight.json create mode 100644 web/app/components/base/icons/src/public/llm/AnthropicLight.tsx delete mode 100644 web/app/components/plugins/card/card-mock.ts diff --git a/web/app/components/base/icons/assets/public/llm/Anthropic-dark.svg b/web/app/components/base/icons/assets/public/llm/Anthropic-dark.svg new file mode 100644 index 0000000000..57abb737e7 --- /dev/null +++ b/web/app/components/base/icons/assets/public/llm/Anthropic-dark.svg @@ -0,0 +1,186 @@ +<svg width="90" height="10" viewBox="0 0 90 10" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Anthropic" clip-path="url(#clip0_5981_49007)"> +<g id="Clip path group"> +<mask id="mask0_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_2"> +<path id="Vector" d="M89.375 -0.00195312H0V9.99805H89.375V-0.00195312Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask0_5981_49007)"> +<g id="Group"> +<g id="Clip path group_2"> +<mask id="mask1_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_4"> +<path id="Vector_2" d="M0 -0.00390625H89.375V9.99609H0V-0.00390625Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask1_5981_49007)"> +<g id="Group_2"> +<g id="Clip path group_3"> +<mask id="mask2_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_12"> +<path id="Vector_3" d="M0 -0.00585938H89.375V9.99414H0V-0.00585938Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask2_5981_49007)"> +<g id="Group_3"> +<g id="Clip path group_4"> +<mask id="mask3_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_89"> +<path id="Vector_4" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask3_5981_49007)"> +<g id="Group_4"> +<g id="Group_5"> +<g id="Group_6"> +<path id="Vector_5" d="M18.1273 6.92438L13.7773 0.15625H11.4297V9.82501H13.4321V3.05688L17.7821 9.82501H20.1297V0.15625H18.1273V6.92438Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_5"> +<mask id="mask4_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_80"> +<path id="Vector_6" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask4_5981_49007)"> +<g id="Group_7"> +<g id="Group_8"> +<g id="Group_9"> +<path id="Vector_7" d="M21.7969 2.02094H25.0423V9.82501H27.1139V2.02094H30.3594V0.15625H21.7969V2.02094Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_6"> +<mask id="mask5_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_71"> +<path id="Vector_8" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask5_5981_49007)"> +<g id="Group_10"> +<g id="Group_11"> +<g id="Group_12"> +<path id="Vector_9" d="M38.6442 4.00994H34.0871V0.15625H32.0156V9.82501H34.0871V5.87463H38.6442V9.82501H40.7156V0.15625H38.6442V4.00994Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_7"> +<mask id="mask6_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_62"> +<path id="Vector_10" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask6_5981_49007)"> +<g id="Group_13"> +<g id="Group_14"> +<g id="Group_15"> +<path id="Vector_11" d="M45.3376 2.02094H47.893C48.9152 2.02094 49.4539 2.39387 49.4539 3.09831C49.4539 3.80275 48.9152 4.17569 47.893 4.17569H45.3376V2.02094ZM51.5259 3.09831C51.5259 1.27506 50.186 0.15625 47.9897 0.15625H43.2656V9.82501H45.3376V6.04037H47.6443L49.7164 9.82501H52.0094L49.715 5.75211C50.8666 5.30941 51.5259 4.37721 51.5259 3.09831Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_8"> +<mask id="mask7_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_53"> +<path id="Vector_12" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask7_5981_49007)"> +<g id="Group_16"> +<g id="Group_17"> +<g id="Group_18"> +<path id="Vector_13" d="M57.8732 8.05653C56.2438 8.05653 55.2496 6.89631 55.2496 5.00404C55.2496 3.08416 56.2438 1.92394 57.8732 1.92394C59.4887 1.92394 60.4691 3.08416 60.4691 5.00404C60.4691 6.89631 59.4887 8.05653 57.8732 8.05653ZM57.8732 -0.00976562C55.0839 -0.00976562 53.1094 2.06206 53.1094 5.00404C53.1094 7.91841 55.0839 9.99023 57.8732 9.99023C60.6486 9.99023 62.6094 7.91841 62.6094 5.00404C62.6094 2.06206 60.6486 -0.00976562 57.8732 -0.00976562Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_9"> +<mask id="mask8_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_44"> +<path id="Vector_14" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask8_5981_49007)"> +<g id="Group_19"> +<g id="Group_20"> +<g id="Group_21"> +<path id="Vector_15" d="M69.1794 4.45194H66.6233V2.02094H69.1794C70.2019 2.02094 70.7407 2.43532 70.7407 3.23644C70.7407 4.03756 70.2019 4.45194 69.1794 4.45194ZM69.2762 0.15625H64.5508V9.82501H66.6233V6.31662H69.2762C71.473 6.31662 72.8133 5.15637 72.8133 3.23644C72.8133 1.3165 71.473 0.15625 69.2762 0.15625Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_10"> +<mask id="mask9_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_35"> +<path id="Vector_16" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask9_5981_49007)"> +<g id="Group_22"> +<g id="Group_23"> +<g id="Group_24"> +<path id="Vector_17" d="M86.8413 6.57863C86.4823 7.51786 85.7642 8.05653 84.7837 8.05653C83.1542 8.05653 82.16 6.89631 82.16 5.00404C82.16 3.08416 83.1542 1.92394 84.7837 1.92394C85.7642 1.92394 86.4823 2.46261 86.8413 3.40183H89.0369C88.4984 1.33002 86.8827 -0.00976562 84.7837 -0.00976562C81.9942 -0.00976562 80.0195 2.06206 80.0195 5.00404C80.0195 7.91841 81.9942 9.99023 84.7837 9.99023C86.8965 9.99023 88.5122 8.63664 89.0508 6.57863H86.8413Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_11"> +<mask id="mask10_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_26"> +<path id="Vector_18" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask10_5981_49007)"> +<g id="Group_25"> +<g id="Group_26"> +<g id="Group_27"> +<path id="Vector_19" d="M73.6484 0.15625L77.5033 9.82501H79.6172L75.7624 0.15625H73.6484Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_12"> +<mask id="mask11_5981_49007" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_17"> +<path id="Vector_20" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask11_5981_49007)"> +<g id="Group_28"> +<g id="Group_29"> +<g id="Group_30"> +<path id="Vector_21" d="M3.64038 5.99893L4.95938 2.60106L6.27838 5.99893H3.64038ZM3.85422 0.15625L0 9.82501H2.15505L2.9433 7.79456H6.97558L7.76371 9.82501H9.91875L6.06453 0.15625H3.85422Z" fill="black" fill-opacity="0.95"/> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +<defs> +<clipPath id="clip0_5981_49007"> +<rect width="89.375" height="10" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web/app/components/base/icons/assets/public/llm/Anthropic-light.svg b/web/app/components/base/icons/assets/public/llm/Anthropic-light.svg new file mode 100644 index 0000000000..3e587ccc9e --- /dev/null +++ b/web/app/components/base/icons/assets/public/llm/Anthropic-light.svg @@ -0,0 +1,186 @@ +<svg width="90" height="10" viewBox="0 0 90 10" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Anthropic" clip-path="url(#clip0_5981_52010)"> +<g id="Clip path group"> +<mask id="mask0_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_2"> +<path id="Vector" d="M89.375 -0.00195312H0V9.99805H89.375V-0.00195312Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask0_5981_52010)"> +<g id="Group"> +<g id="Clip path group_2"> +<mask id="mask1_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_4"> +<path id="Vector_2" d="M0 -0.00390625H89.375V9.99609H0V-0.00390625Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask1_5981_52010)"> +<g id="Group_2"> +<g id="Clip path group_3"> +<mask id="mask2_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_12"> +<path id="Vector_3" d="M0 -0.00585938H89.375V9.99414H0V-0.00585938Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask2_5981_52010)"> +<g id="Group_3"> +<g id="Clip path group_4"> +<mask id="mask3_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_89"> +<path id="Vector_4" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask3_5981_52010)"> +<g id="Group_4"> +<g id="Group_5"> +<g id="Group_6"> +<path id="Vector_5" d="M18.1273 6.92438L13.7773 0.15625H11.4297V9.82501H13.4321V3.05688L17.7821 9.82501H20.1297V0.15625H18.1273V6.92438Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_5"> +<mask id="mask4_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_80"> +<path id="Vector_6" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask4_5981_52010)"> +<g id="Group_7"> +<g id="Group_8"> +<g id="Group_9"> +<path id="Vector_7" d="M21.7969 2.02094H25.0423V9.82501H27.1139V2.02094H30.3594V0.15625H21.7969V2.02094Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_6"> +<mask id="mask5_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_71"> +<path id="Vector_8" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask5_5981_52010)"> +<g id="Group_10"> +<g id="Group_11"> +<g id="Group_12"> +<path id="Vector_9" d="M38.6442 4.00994H34.0871V0.15625H32.0156V9.82501H34.0871V5.87463H38.6442V9.82501H40.7156V0.15625H38.6442V4.00994Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_7"> +<mask id="mask6_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_62"> +<path id="Vector_10" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask6_5981_52010)"> +<g id="Group_13"> +<g id="Group_14"> +<g id="Group_15"> +<path id="Vector_11" d="M45.3376 2.02094H47.893C48.9152 2.02094 49.4539 2.39387 49.4539 3.09831C49.4539 3.80275 48.9152 4.17569 47.893 4.17569H45.3376V2.02094ZM51.5259 3.09831C51.5259 1.27506 50.186 0.15625 47.9897 0.15625H43.2656V9.82501H45.3376V6.04037H47.6443L49.7164 9.82501H52.0094L49.715 5.75211C50.8666 5.30941 51.5259 4.37721 51.5259 3.09831Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_8"> +<mask id="mask7_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_53"> +<path id="Vector_12" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask7_5981_52010)"> +<g id="Group_16"> +<g id="Group_17"> +<g id="Group_18"> +<path id="Vector_13" d="M57.8732 8.05653C56.2438 8.05653 55.2496 6.89631 55.2496 5.00404C55.2496 3.08416 56.2438 1.92394 57.8732 1.92394C59.4887 1.92394 60.4691 3.08416 60.4691 5.00404C60.4691 6.89631 59.4887 8.05653 57.8732 8.05653ZM57.8732 -0.00976562C55.0839 -0.00976562 53.1094 2.06206 53.1094 5.00404C53.1094 7.91841 55.0839 9.99023 57.8732 9.99023C60.6486 9.99023 62.6094 7.91841 62.6094 5.00404C62.6094 2.06206 60.6486 -0.00976562 57.8732 -0.00976562Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_9"> +<mask id="mask8_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_44"> +<path id="Vector_14" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask8_5981_52010)"> +<g id="Group_19"> +<g id="Group_20"> +<g id="Group_21"> +<path id="Vector_15" d="M69.1794 4.45194H66.6233V2.02094H69.1794C70.2019 2.02094 70.7407 2.43532 70.7407 3.23644C70.7407 4.03756 70.2019 4.45194 69.1794 4.45194ZM69.2762 0.15625H64.5508V9.82501H66.6233V6.31662H69.2762C71.473 6.31662 72.8133 5.15637 72.8133 3.23644C72.8133 1.3165 71.473 0.15625 69.2762 0.15625Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_10"> +<mask id="mask9_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_35"> +<path id="Vector_16" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask9_5981_52010)"> +<g id="Group_22"> +<g id="Group_23"> +<g id="Group_24"> +<path id="Vector_17" d="M86.8413 6.57863C86.4823 7.51786 85.7642 8.05653 84.7837 8.05653C83.1542 8.05653 82.16 6.89631 82.16 5.00404C82.16 3.08416 83.1542 1.92394 84.7837 1.92394C85.7642 1.92394 86.4823 2.46261 86.8413 3.40183H89.0369C88.4984 1.33002 86.8827 -0.00976562 84.7837 -0.00976562C81.9942 -0.00976562 80.0195 2.06206 80.0195 5.00404C80.0195 7.91841 81.9942 9.99023 84.7837 9.99023C86.8965 9.99023 88.5122 8.63664 89.0508 6.57863H86.8413Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_11"> +<mask id="mask10_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_26"> +<path id="Vector_18" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask10_5981_52010)"> +<g id="Group_25"> +<g id="Group_26"> +<g id="Group_27"> +<path id="Vector_19" d="M73.6484 0.15625L77.5033 9.82501H79.6172L75.7624 0.15625H73.6484Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +<g id="Clip path group_12"> +<mask id="mask11_5981_52010" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="-1" width="90" height="11"> +<g id="__lottie_element_17"> +<path id="Vector_20" d="M0 -0.0078125H89.375V9.99219H0V-0.0078125Z" fill="white"/> +</g> +</mask> +<g mask="url(#mask11_5981_52010)"> +<g id="Group_28"> +<g id="Group_29"> +<g id="Group_30"> +<path id="Vector_21" d="M3.64038 5.99893L4.95938 2.60106L6.27838 5.99893H3.64038ZM3.85422 0.15625L0 9.82501H2.15505L2.9433 7.79456H6.97558L7.76371 9.82501H9.91875L6.06453 0.15625H3.85422Z" fill="white" fill-opacity="0.8"/> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +<defs> +<clipPath id="clip0_5981_52010"> +<rect width="89.375" height="10" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web/app/components/base/icons/src/public/llm/AnthropicDark.json b/web/app/components/base/icons/src/public/llm/AnthropicDark.json new file mode 100644 index 0000000000..4f3af3ce79 --- /dev/null +++ b/web/app/components/base/icons/src/public/llm/AnthropicDark.json @@ -0,0 +1,1046 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "90", + "height": "10", + "viewBox": "0 0 90 10", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Anthropic", + "clip-path": "url(#clip0_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask0_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_2" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M89.375 -0.00195312H0V9.99805H89.375V-0.00195312Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask0_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_2" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask1_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_4" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_2", + "d": "M0 -0.00390625H89.375V9.99609H0V-0.00390625Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask1_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_2" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_3" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask2_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_12" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_3", + "d": "M0 -0.00585938H89.375V9.99414H0V-0.00585938Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask2_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_3" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_4" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask3_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_89" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_4", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask3_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_4" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_5" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_6" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_5", + "d": "M18.1273 6.92438L13.7773 0.15625H11.4297V9.82501H13.4321V3.05688L17.7821 9.82501H20.1297V0.15625H18.1273V6.92438Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_5" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask4_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_80" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_6", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask4_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_7" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_8" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_9" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_7", + "d": "M21.7969 2.02094H25.0423V9.82501H27.1139V2.02094H30.3594V0.15625H21.7969V2.02094Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_6" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask5_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_71" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_8", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask5_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_10" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_12" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_9", + "d": "M38.6442 4.00994H34.0871V0.15625H32.0156V9.82501H34.0871V5.87463H38.6442V9.82501H40.7156V0.15625H38.6442V4.00994Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_7" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask6_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_62" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_10", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask6_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_13" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_14" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_15" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_11", + "d": "M45.3376 2.02094H47.893C48.9152 2.02094 49.4539 2.39387 49.4539 3.09831C49.4539 3.80275 48.9152 4.17569 47.893 4.17569H45.3376V2.02094ZM51.5259 3.09831C51.5259 1.27506 50.186 0.15625 47.9897 0.15625H43.2656V9.82501H45.3376V6.04037H47.6443L49.7164 9.82501H52.0094L49.715 5.75211C50.8666 5.30941 51.5259 4.37721 51.5259 3.09831Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_8" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask7_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_53" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_12", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask7_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_16" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_17" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_18" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_13", + "d": "M57.8732 8.05653C56.2438 8.05653 55.2496 6.89631 55.2496 5.00404C55.2496 3.08416 56.2438 1.92394 57.8732 1.92394C59.4887 1.92394 60.4691 3.08416 60.4691 5.00404C60.4691 6.89631 59.4887 8.05653 57.8732 8.05653ZM57.8732 -0.00976562C55.0839 -0.00976562 53.1094 2.06206 53.1094 5.00404C53.1094 7.91841 55.0839 9.99023 57.8732 9.99023C60.6486 9.99023 62.6094 7.91841 62.6094 5.00404C62.6094 2.06206 60.6486 -0.00976562 57.8732 -0.00976562Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_9" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask8_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_44" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_14", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask8_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_19" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_20" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_21" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_15", + "d": "M69.1794 4.45194H66.6233V2.02094H69.1794C70.2019 2.02094 70.7407 2.43532 70.7407 3.23644C70.7407 4.03756 70.2019 4.45194 69.1794 4.45194ZM69.2762 0.15625H64.5508V9.82501H66.6233V6.31662H69.2762C71.473 6.31662 72.8133 5.15637 72.8133 3.23644C72.8133 1.3165 71.473 0.15625 69.2762 0.15625Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_10" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask9_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_35" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_16", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask9_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_22" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_23" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_24" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_17", + "d": "M86.8413 6.57863C86.4823 7.51786 85.7642 8.05653 84.7837 8.05653C83.1542 8.05653 82.16 6.89631 82.16 5.00404C82.16 3.08416 83.1542 1.92394 84.7837 1.92394C85.7642 1.92394 86.4823 2.46261 86.8413 3.40183H89.0369C88.4984 1.33002 86.8827 -0.00976562 84.7837 -0.00976562C81.9942 -0.00976562 80.0195 2.06206 80.0195 5.00404C80.0195 7.91841 81.9942 9.99023 84.7837 9.99023C86.8965 9.99023 88.5122 8.63664 89.0508 6.57863H86.8413Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_11" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask10_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_26" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_18", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask10_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_25" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_26" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_27" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_19", + "d": "M73.6484 0.15625L77.5033 9.82501H79.6172L75.7624 0.15625H73.6484Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_12" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask11_5981_49007", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_17" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_20", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask11_5981_49007)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_28" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_29" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_30" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_21", + "d": "M3.64038 5.99893L4.95938 2.60106L6.27838 5.99893H3.64038ZM3.85422 0.15625L0 9.82501H2.15505L2.9433 7.79456H6.97558L7.76371 9.82501H9.91875L6.06453 0.15625H3.85422Z", + "fill": "black", + "fill-opacity": "0.95" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "defs", + "attributes": {}, + "children": [ + { + "type": "element", + "name": "clipPath", + "attributes": { + "id": "clip0_5981_49007" + }, + "children": [ + { + "type": "element", + "name": "rect", + "attributes": { + "width": "89.375", + "height": "10", + "fill": "white" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "AnthropicDark" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx b/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx new file mode 100644 index 0000000000..d358b0c111 --- /dev/null +++ b/web/app/components/base/icons/src/public/llm/AnthropicDark.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './AnthropicDark.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'AnthropicDark' + +export default Icon diff --git a/web/app/components/base/icons/src/public/llm/AnthropicLight.json b/web/app/components/base/icons/src/public/llm/AnthropicLight.json new file mode 100644 index 0000000000..3e84eb4dd6 --- /dev/null +++ b/web/app/components/base/icons/src/public/llm/AnthropicLight.json @@ -0,0 +1,1046 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "90", + "height": "10", + "viewBox": "0 0 90 10", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Anthropic", + "clip-path": "url(#clip0_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask0_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_2" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M89.375 -0.00195312H0V9.99805H89.375V-0.00195312Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask0_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_2" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask1_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_4" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_2", + "d": "M0 -0.00390625H89.375V9.99609H0V-0.00390625Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask1_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_2" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_3" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask2_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_12" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_3", + "d": "M0 -0.00585938H89.375V9.99414H0V-0.00585938Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask2_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_3" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_4" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask3_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_89" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_4", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask3_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_4" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_5" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_6" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_5", + "d": "M18.1273 6.92438L13.7773 0.15625H11.4297V9.82501H13.4321V3.05688L17.7821 9.82501H20.1297V0.15625H18.1273V6.92438Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_5" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask4_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_80" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_6", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask4_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_7" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_8" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_9" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_7", + "d": "M21.7969 2.02094H25.0423V9.82501H27.1139V2.02094H30.3594V0.15625H21.7969V2.02094Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_6" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask5_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_71" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_8", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask5_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_10" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_12" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_9", + "d": "M38.6442 4.00994H34.0871V0.15625H32.0156V9.82501H34.0871V5.87463H38.6442V9.82501H40.7156V0.15625H38.6442V4.00994Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_7" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask6_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_62" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_10", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask6_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_13" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_14" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_15" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_11", + "d": "M45.3376 2.02094H47.893C48.9152 2.02094 49.4539 2.39387 49.4539 3.09831C49.4539 3.80275 48.9152 4.17569 47.893 4.17569H45.3376V2.02094ZM51.5259 3.09831C51.5259 1.27506 50.186 0.15625 47.9897 0.15625H43.2656V9.82501H45.3376V6.04037H47.6443L49.7164 9.82501H52.0094L49.715 5.75211C50.8666 5.30941 51.5259 4.37721 51.5259 3.09831Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_8" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask7_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_53" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_12", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask7_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_16" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_17" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_18" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_13", + "d": "M57.8732 8.05653C56.2438 8.05653 55.2496 6.89631 55.2496 5.00404C55.2496 3.08416 56.2438 1.92394 57.8732 1.92394C59.4887 1.92394 60.4691 3.08416 60.4691 5.00404C60.4691 6.89631 59.4887 8.05653 57.8732 8.05653ZM57.8732 -0.00976562C55.0839 -0.00976562 53.1094 2.06206 53.1094 5.00404C53.1094 7.91841 55.0839 9.99023 57.8732 9.99023C60.6486 9.99023 62.6094 7.91841 62.6094 5.00404C62.6094 2.06206 60.6486 -0.00976562 57.8732 -0.00976562Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_9" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask8_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_44" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_14", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask8_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_19" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_20" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_21" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_15", + "d": "M69.1794 4.45194H66.6233V2.02094H69.1794C70.2019 2.02094 70.7407 2.43532 70.7407 3.23644C70.7407 4.03756 70.2019 4.45194 69.1794 4.45194ZM69.2762 0.15625H64.5508V9.82501H66.6233V6.31662H69.2762C71.473 6.31662 72.8133 5.15637 72.8133 3.23644C72.8133 1.3165 71.473 0.15625 69.2762 0.15625Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_10" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask9_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_35" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_16", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask9_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_22" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_23" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_24" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_17", + "d": "M86.8413 6.57863C86.4823 7.51786 85.7642 8.05653 84.7837 8.05653C83.1542 8.05653 82.16 6.89631 82.16 5.00404C82.16 3.08416 83.1542 1.92394 84.7837 1.92394C85.7642 1.92394 86.4823 2.46261 86.8413 3.40183H89.0369C88.4984 1.33002 86.8827 -0.00976562 84.7837 -0.00976562C81.9942 -0.00976562 80.0195 2.06206 80.0195 5.00404C80.0195 7.91841 81.9942 9.99023 84.7837 9.99023C86.8965 9.99023 88.5122 8.63664 89.0508 6.57863H86.8413Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_11" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask10_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_26" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_18", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask10_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_25" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_26" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_27" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_19", + "d": "M73.6484 0.15625L77.5033 9.82501H79.6172L75.7624 0.15625H73.6484Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "id": "Clip path group_12" + }, + "children": [ + { + "type": "element", + "name": "mask", + "attributes": { + "id": "mask11_5981_52010", + "style": "mask-type:luminance", + "maskUnits": "userSpaceOnUse", + "x": "0", + "y": "-1", + "width": "90", + "height": "11" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "__lottie_element_17" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_20", + "d": "M0 -0.0078125H89.375V9.99219H0V-0.0078125Z", + "fill": "white" + }, + "children": [] + } + ] + } + ] + }, + { + "type": "element", + "name": "g", + "attributes": { + "mask": "url(#mask11_5981_52010)" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_28" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_29" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "Group_30" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector_21", + "d": "M3.64038 5.99893L4.95938 2.60106L6.27838 5.99893H3.64038ZM3.85422 0.15625L0 9.82501H2.15505L2.9433 7.79456H6.97558L7.76371 9.82501H9.91875L6.06453 0.15625H3.85422Z", + "fill": "white", + "fill-opacity": "0.8" + }, + "children": [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "element", + "name": "defs", + "attributes": {}, + "children": [ + { + "type": "element", + "name": "clipPath", + "attributes": { + "id": "clip0_5981_52010" + }, + "children": [ + { + "type": "element", + "name": "rect", + "attributes": { + "width": "89.375", + "height": "10", + "fill": "white" + }, + "children": [] + } + ] + } + ] + } + ] + }, + "name": "AnthropicLight" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx b/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx new file mode 100644 index 0000000000..34df60f28c --- /dev/null +++ b/web/app/components/base/icons/src/public/llm/AnthropicLight.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './AnthropicLight.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>(( + props, + ref, +) => <IconBase {...props} ref={ref} data={data as IconData} />) + +Icon.displayName = 'AnthropicLight' + +export default Icon diff --git a/web/app/components/base/icons/src/public/llm/index.ts b/web/app/components/base/icons/src/public/llm/index.ts index 3545049795..cc9b531ebf 100644 --- a/web/app/components/base/icons/src/public/llm/index.ts +++ b/web/app/components/base/icons/src/public/llm/index.ts @@ -1,3 +1,5 @@ +export { default as AnthropicDark } from './AnthropicDark' +export { default as AnthropicLight } from './AnthropicLight' export { default as AnthropicText } from './AnthropicText' export { default as Anthropic } from './Anthropic' export { default as AzureOpenaiServiceText } from './AzureOpenaiServiceText' diff --git a/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx index 0576672a4f..9fa12825fc 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-icon/index.tsx @@ -7,6 +7,7 @@ import { useLanguage } from '../hooks' import { Group } from '@/app/components/base/icons/src/vender/other' import { OpenaiBlue, OpenaiViolet } from '@/app/components/base/icons/src/public/llm' import cn from '@/utils/classnames' +import { renderI18nObject } from '@/hooks/use-i18n' type ModelIconProps = { provider?: Model | ModelProvider @@ -22,16 +23,16 @@ const ModelIcon: FC<ModelIconProps> = ({ }) => { const language = useLanguage() if (provider?.provider.includes('openai') && modelName?.includes('gpt-4o')) - return <div className='flex items-center justify-center'><OpenaiBlue className={cn('w-5 h-5', className)}/></div> + return <div className='flex items-center justify-center'><OpenaiBlue className={cn('w-5 h-5', className)} /></div> if (provider?.provider.includes('openai') && modelName?.startsWith('gpt-4')) - return <div className='flex items-center justify-center'><OpenaiViolet className={cn('w-5 h-5', className)}/></div> + return <div className='flex items-center justify-center'><OpenaiViolet className={cn('w-5 h-5', className)} /></div> if (provider?.icon_small) { return ( <div className={`flex items-center justify-center w-5 h-5 ${isDeprecated ? 'opacity-50' : ''}`}> <img alt='model-icon' - src={`${provider.icon_small[language] || provider.icon_small.en_US}`} + src={renderI18nObject(provider.icon_small, language)} className={cn('w-4.5 h-4.5', className)} /> </div> diff --git a/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx b/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx index 25105b1193..e669b4a38b 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-icon/index.tsx @@ -1,7 +1,11 @@ import type { FC } from 'react' import type { ModelProvider } from '../declarations' import { useLanguage } from '../hooks' -import { AnthropicText, Openai } from '@/app/components/base/icons/src/vender/other' +import { useAppContext } from '@/context/app-context' +import { Openai } from '@/app/components/base/icons/src/vender/other' +import { AnthropicDark, AnthropicLight } from '@/app/components/base/icons/src/public/llm' +import { renderI18nObject } from '@/hooks/use-i18n' +import { Theme } from '@/types/app' import cn from '@/utils/classnames' type ProviderIconProps = { @@ -12,12 +16,14 @@ const ProviderIcon: FC<ProviderIconProps> = ({ provider, className, }) => { + const { theme } = useAppContext() const language = useLanguage() if (provider.provider === 'langgenius/anthropic/anthropic') { return ( - <div className='mb-2'> - <AnthropicText className='w-auto h-6 text-text-inverted-dimmed' /> + <div className='mb-2 py-[7px]'> + {theme === Theme.dark && <AnthropicLight className='w-[90px] h-2.5' />} + {theme === Theme.light && <AnthropicDark className='w-[90px] h-2.5' />} </div> ) } @@ -34,11 +40,11 @@ const ProviderIcon: FC<ProviderIconProps> = ({ <div className={cn('inline-flex items-center gap-2', className)}> <img alt='provider-icon' - src={`${provider.icon_small[language] || provider.icon_small.en_US}`} + src={renderI18nObject(provider.icon_small, language)} className='w-6 h-6' /> <div className='system-md-semibold text-text-primary'> - {provider.label[language] || provider.label.en_US} + {renderI18nObject(provider.label, language)} </div> </div> ) diff --git a/web/app/components/plugins/card/card-mock.ts b/web/app/components/plugins/card/card-mock.ts deleted file mode 100644 index 201a7bc65d..0000000000 --- a/web/app/components/plugins/card/card-mock.ts +++ /dev/null @@ -1,160 +0,0 @@ -import type { PluginDeclaration } from '../types' -import { PluginType } from '../types' - -export const toolNeko: PluginDeclaration = { - plugin_unique_identifier: 'xxxxxx', - version: '0.0.1', - author: 'langgenius', - name: 'neko', - description: { - en_US: 'Neko is a cute cat.', - zh_Hans: '这是一只可爱的小猫。', - pt_BR: 'Neko is a cute cat.', - ja_JP: 'Neko is a cute cat.', - }, - icon: '241e5209ecc8b5ce6b7a29a8e50388e9c75b89c3047c6ecd8e552f26de758883.svg', - label: { - en_US: 'Neko', - zh_Hans: 'Neko', - pt_BR: 'Neko', - ja_JP: 'Neko', - }, - category: 'extension' as any, - created_at: '2024-07-12T08:03:44.658609Z', - resource: { - memory: 1048576, - permission: { - tool: { - enabled: true, - }, - model: { - enabled: true, - llm: true, - text_embedding: false, - rerank: false, - tts: false, - speech2text: false, - moderation: false, - }, - node: null, - endpoint: { - enabled: true, - }, - storage: { - enabled: true, - size: 1048576, - }, - }, - }, - plugins: { - tools: null, - models: null, - endpoints: [ - 'provider/neko.yaml', - ], - }, - tags: [], - verified: false, - tool: null, - model: null, - endpoint: null, -} - -export const toolNotion = { - type: PluginType.tool, - org: 'Notion', - name: 'notion page search', - version: '1.2.0', - latest_version: '1.3.0', - icon: 'https://via.placeholder.com/150', - label: { - 'en-US': 'Notion Page Search', - 'zh-Hans': 'Notion 页面搜索', - }, - brief: { - 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', - 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', - }, -} - -export const toolNotionManifest: PluginDeclaration = { - version: '1.2.0', - author: 'Notion', - icon: 'https://via.placeholder.com/150', - name: 'notion page search', - category: PluginType.tool, - label: { - 'en-US': 'Notion Page Search', - 'zh-Hans': 'Notion 页面搜索', - }, - description: { - 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', - 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', - }, - created_at: '2022-01-01', - resource: {}, - plugins: {}, - verified: true, - endpoint: { - settings: [], - endpoints: [], - }, - tool: { - } as any, - model: {}, -} - -export const extensionDallE = { - type: PluginType.extension, - org: 'OpenAI', - name: 'DALL-E', - version: '1.1.0', - latest_version: '1.2.0', - install_count: 1234, - icon: 'https://via.placeholder.com/150', - label: { - 'en-US': 'DALL-E', - 'zh-Hans': 'DALL-E', - }, - brief: { - 'en-US': 'Description: A simple plugin to use OpenAI DALL-E model.', - 'zh-Hans': '一个使用 OpenAI DALL-E 模型的简单插件。', - }, -} - -export const modelGPT4 = { - type: PluginType.model, - org: 'OpenAI', - name: 'GPT-4', - version: '1.0.0', - latest_version: '1.0.0', - install_count: 99999, - icon: 'https://via.placeholder.com/150', - label: { - 'en-US': 'GPT-4', - 'zh-Hans': 'GPT-4', - }, - brief: { - 'en-US': 'Description: A simple plugin to use OpenAI GPT-4 model.', - 'zh-Hans': '一个使用 OpenAI GPT-4 模型的简单插件。', - }, -} - -export const customTool = { - type: PluginType.tool, - name: 'notion page search', - version: '1.2.0', - latest_version: '1.3.0', - icon: { - content: '🕵️', - background: '#FEF7C3', - }, - label: { - 'en-US': 'Notion Page Search', - 'zh-Hans': 'Notion 页面搜索', - }, - brief: { - 'en-US': 'Description: Search Notion pages and open visited ones faster. No admin access required.More and more info...More and more info...More and more info...', - 'zh-Hans': '搜索 Notion 页面并更快地打开已访问的页面。无需管理员访问权限。More and more info...More and more info...More and more info...', - }, -} diff --git a/web/hooks/use-i18n.ts b/web/hooks/use-i18n.ts index 261293c86d..d95ef0d114 100644 --- a/web/hooks/use-i18n.ts +++ b/web/hooks/use-i18n.ts @@ -1,6 +1,7 @@ import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' export const renderI18nObject = (obj: Record<string, string>, language: string) => { + if (!obj) return '' if (obj?.[language]) return obj[language] if (obj?.en_US) return obj.en_US return Object.values(obj)[0] From 71976f91922484b360f2061ac589e572b9402e7e Mon Sep 17 00:00:00 2001 From: zxhlyh <jasonapring2015@outlook.com> Date: Fri, 10 Jan 2025 14:03:00 +0800 Subject: [PATCH 15/28] fix: marketplace serach bundle (#12581) --- web/app/components/plugins/marketplace/hooks.ts | 2 +- web/app/components/plugins/marketplace/utils.ts | 3 +++ web/app/components/plugins/types.ts | 1 + web/service/use-plugins.ts | 3 ++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/web/app/components/plugins/marketplace/hooks.ts b/web/app/components/plugins/marketplace/hooks.ts index 8f811d1b3e..83a6709a47 100644 --- a/web/app/components/plugins/marketplace/hooks.ts +++ b/web/app/components/plugins/marketplace/hooks.ts @@ -72,7 +72,7 @@ export const useMarketplacePlugins = () => { const handleUpdatePlugins = useCallback((pluginsSearchParams: PluginsSearchParams) => { mutateAsync(pluginsSearchParams).then((res) => { const currentPage = pluginsSearchParams.page || 1 - const resPlugins = res.data.plugins + const resPlugins = res.data.bundles || res.data.plugins if (currentPage > 1) { setPrevPlugins(prevPlugins => [...(prevPlugins || []), ...resPlugins.map((plugin) => { return getFormattedPlugin(plugin) diff --git a/web/app/components/plugins/marketplace/utils.ts b/web/app/components/plugins/marketplace/utils.ts index 78d4437681..0c00a98d6d 100644 --- a/web/app/components/plugins/marketplace/utils.ts +++ b/web/app/components/plugins/marketplace/utils.ts @@ -110,6 +110,9 @@ export const getMarketplaceListCondition = (pluginType: string) => { if (pluginType === PluginType.extension) return 'category=endpoint' + if (pluginType === 'bundle') + return 'type=bundle' + return '' } diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 15da9991a6..e9f7884257 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -320,6 +320,7 @@ export type UninstallPluginResponse = { export type PluginsFromMarketplaceResponse = { plugins: Plugin[] + bundles?: Plugin[] total: number } export type PluginsFromMarketplaceByInfoResponse = { diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts index 66e55c6431..1673b5fff8 100644 --- a/web/service/use-plugins.ts +++ b/web/service/use-plugins.ts @@ -305,7 +305,8 @@ export const useMutationPluginsFromMarketplace = () => { page = 1, pageSize = 40, } = pluginsSearchParams - return postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/search/basic', { + const pluginOrBundle = type === 'bundle' ? 'bundles' : 'plugins' + return postMarketplace<{ data: PluginsFromMarketplaceResponse }>(`/${pluginOrBundle}/search/basic`, { body: { page, page_size: pageSize, From a5e24ff6d30130a8a9e0e654ab02e8f56227f89e Mon Sep 17 00:00:00 2001 From: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:47:24 +0800 Subject: [PATCH 16/28] fix: update language change handling in I18n component (#12596) ok --- web/app/components/i18n.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/app/components/i18n.tsx b/web/app/components/i18n.tsx index 7fe1df23e0..f04f8d6cbe 100644 --- a/web/app/components/i18n.tsx +++ b/web/app/components/i18n.tsx @@ -2,7 +2,6 @@ import type { FC } from 'react' import React, { useEffect } from 'react' -import { changeLanguage } from '@/i18n/i18next-config' import I18NContext from '@/context/i18n' import type { Locale } from '@/i18n' import { setLocaleOnClient } from '@/i18n' @@ -16,7 +15,7 @@ const I18n: FC<II18nProps> = ({ children, }) => { useEffect(() => { - changeLanguage(locale) + setLocaleOnClient(locale, false) }, [locale]) return ( From f69220ca96ca501ac6adb572b5854d6febdb8c91 Mon Sep 17 00:00:00 2001 From: kurokobo <kuro664@gmail.com> Date: Fri, 10 Jan 2025 16:42:32 +0900 Subject: [PATCH 17/28] fix: add location directive for /explore (#12572) --- docker/nginx/conf.d/default.conf.template | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/nginx/conf.d/default.conf.template b/docker/nginx/conf.d/default.conf.template index bf86c70735..7cef848127 100644 --- a/docker/nginx/conf.d/default.conf.template +++ b/docker/nginx/conf.d/default.conf.template @@ -24,6 +24,11 @@ server { include proxy.conf; } + location /explore { + proxy_pass http://web:3000; + include proxy.conf; + } + location /e { proxy_pass http://plugin_daemon:5002; include proxy.conf; From 04dade2f9b487fa7d6b6403dc54a55f9506de1e9 Mon Sep 17 00:00:00 2001 From: Hiroshi Fujita <fujita-h@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:46:10 +0900 Subject: [PATCH 18/28] fix: update fetchReleases to use owner and repo from meta (#12590) --- web/app/components/plugins/plugin-item/action.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/app/components/plugins/plugin-item/action.tsx b/web/app/components/plugins/plugin-item/action.tsx index 1bc34c9928..bc646609eb 100644 --- a/web/app/components/plugins/plugin-item/action.tsx +++ b/web/app/components/plugins/plugin-item/action.tsx @@ -54,7 +54,9 @@ const Action: FC<Props> = ({ const invalidateInstalledPluginList = useInvalidateInstalledPluginList() const handleFetchNewVersion = async () => { - const fetchedReleases = await fetchReleases(author, pluginName) + const owner = meta!.repo.split('/')[0] || author + const repo = meta!.repo.split('/')[1] || pluginName + const fetchedReleases = await fetchReleases(owner, repo) if (fetchedReleases.length === 0) return const { needUpdate, toastProps } = checkForUpdates(fetchedReleases, meta!.version) Toast.notify(toastProps) From c03adcb1542a006ea9417f1036e2fa8a184b58fb Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:40:39 +0800 Subject: [PATCH 19/28] Fix: style checks and unittests (#12603) --- api/core/helper/ssrf_proxy.py | 9 ++-- .../datasource/vdb/lindorm/lindorm_vector.py | 44 +++++++------------ .../question_classifier_node.py | 33 +++++--------- api/pytest.ini | 6 +++ .../test_http_request_executor.py | 6 +-- .../http_request/test_http_request_node.py | 11 +---- 6 files changed, 38 insertions(+), 71 deletions(-) diff --git a/api/core/helper/ssrf_proxy.py b/api/core/helper/ssrf_proxy.py index c7a834a6b9..2e422cf444 100644 --- a/api/core/helper/ssrf_proxy.py +++ b/api/core/helper/ssrf_proxy.py @@ -60,20 +60,17 @@ def make_request(method, url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs): if response.status_code not in STATUS_FORCELIST: return response else: - logging.warning( - f"Received status code {response.status_code} for URL {url} which is in the force list") + logging.warning(f"Received status code {response.status_code} for URL {url} which is in the force list") except httpx.RequestError as e: - logging.warning(f"Request to URL {url} failed on attempt { - retries + 1}: {e}") + logging.warning(f"Request to URL {url} failed on attempt {retries + 1}: {e}") if max_retries == 0: raise retries += 1 if retries <= max_retries: time.sleep(BACKOFF_FACTOR * (2 ** (retries - 1))) - raise MaxRetriesExceededError( - f"Reached maximum retries ({max_retries}) for URL {url}") + raise MaxRetriesExceededError(f"Reached maximum retries ({max_retries}) for URL {url}") def get(url, max_retries=SSRF_DEFAULT_MAX_RETRIES, **kwargs): diff --git a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py index 3b3e47578a..3fa0ce16d3 100644 --- a/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py +++ b/api/core/rag/datasource/vdb/lindorm/lindorm_vector.py @@ -17,8 +17,7 @@ from extensions.ext_redis import redis_client from models.dataset import Dataset logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.INFO, - format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") logging.getLogger("lindorm").setLevel(logging.WARN) ROUTING_FIELD = "routing_field" @@ -135,8 +134,7 @@ class LindormVectorStore(BaseVector): self._client.delete(index=self._collection_name, id=id, params=params) self.refresh() else: - logger.warning( - f"DELETE BY ID: ID {id} does not exist in the index.") + logger.warning(f"DELETE BY ID: ID {id} does not exist in the index.") def delete(self) -> None: if self._using_ugc: @@ -147,8 +145,7 @@ class LindormVectorStore(BaseVector): self.refresh() else: if self._client.indices.exists(index=self._collection_name): - self._client.indices.delete( - index=self._collection_name, params={"timeout": 60}) + self._client.indices.delete(index=self._collection_name, params={"timeout": 60}) logger.info("Delete index success") else: logger.warning(f"Index '{self._collection_name}' does not exist. No deletion performed.") @@ -171,14 +168,13 @@ class LindormVectorStore(BaseVector): raise ValueError("All elements in query_vector should be floats") top_k = kwargs.get("top_k", 10) - query = default_vector_search_query( - query_vector=query_vector, k=top_k, **kwargs) + query = default_vector_search_query(query_vector=query_vector, k=top_k, **kwargs) try: params = {} if self._using_ugc: params["routing"] = self._routing response = self._client.search(index=self._collection_name, body=query, params=params) - except Exception as e: + except Exception: logger.exception(f"Error executing vector search, query: {query}") raise @@ -224,8 +220,7 @@ class LindormVectorStore(BaseVector): routing=routing, routing_field=self._routing_field, ) - response = self._client.search( - index=self._collection_name, body=full_text_query) + response = self._client.search(index=self._collection_name, body=full_text_query) docs = [] for hit in response["hits"]["hits"]: docs.append( @@ -243,8 +238,7 @@ class LindormVectorStore(BaseVector): with redis_client.lock(lock_name, timeout=20): collection_exist_cache_key = f"vector_indexing_{self._collection_name}" if redis_client.get(collection_exist_cache_key): - logger.info( - f"Collection {self._collection_name} already exists.") + logger.info(f"Collection {self._collection_name} already exists.") return if self._client.indices.exists(index=self._collection_name): logger.info(f"{self._collection_name.lower()} already exists.") @@ -264,13 +258,10 @@ class LindormVectorStore(BaseVector): hnsw_ef_construction = kwargs.pop("hnsw_ef_construction", 500) ivfpq_m = kwargs.pop("ivfpq_m", dimension) nlist = kwargs.pop("nlist", 1000) - centroids_use_hnsw = kwargs.pop( - "centroids_use_hnsw", True if nlist >= 5000 else False) + centroids_use_hnsw = kwargs.pop("centroids_use_hnsw", True if nlist >= 5000 else False) centroids_hnsw_m = kwargs.pop("centroids_hnsw_m", 24) - centroids_hnsw_ef_construct = kwargs.pop( - "centroids_hnsw_ef_construct", 500) - centroids_hnsw_ef_search = kwargs.pop( - "centroids_hnsw_ef_search", 100) + centroids_hnsw_ef_construct = kwargs.pop("centroids_hnsw_ef_construct", 500) + centroids_hnsw_ef_search = kwargs.pop("centroids_hnsw_ef_search", 100) mapping = default_text_mapping( dimension, method_name, @@ -290,8 +281,7 @@ class LindormVectorStore(BaseVector): using_ugc=self._using_ugc, **kwargs, ) - self._client.indices.create( - index=self._collection_name.lower(), body=mapping) + self._client.indices.create(index=self._collection_name.lower(), body=mapping) redis_client.set(collection_exist_cache_key, 1, ex=3600) # logger.info(f"create index success: {self._collection_name}") @@ -396,8 +386,7 @@ def default_text_search_query( # build complex search_query when either of must/must_not/should/filter is specified if must: if not isinstance(must, list): - raise RuntimeError( - f"unexpected [must] clause with {type(filters)}") + raise RuntimeError(f"unexpected [must] clause with {type(filters)}") if query_clause not in must: must.append(query_clause) else: @@ -407,22 +396,19 @@ def default_text_search_query( if must_not: if not isinstance(must_not, list): - raise RuntimeError( - f"unexpected [must_not] clause with {type(filters)}") + raise RuntimeError(f"unexpected [must_not] clause with {type(filters)}") boolean_query["must_not"] = must_not if should: if not isinstance(should, list): - raise RuntimeError( - f"unexpected [should] clause with {type(filters)}") + raise RuntimeError(f"unexpected [should] clause with {type(filters)}") boolean_query["should"] = should if minimum_should_match != 0: boolean_query["minimum_should_match"] = minimum_should_match if filters: if not isinstance(filters, list): - raise RuntimeError( - f"unexpected [filter] clause with {type(filters)}") + raise RuntimeError(f"unexpected [filter] clause with {type(filters)}") boolean_query["filter"] = filters search_query = {"size": k, "query": {"bool": boolean_query}} diff --git a/api/core/workflow/nodes/question_classifier/question_classifier_node.py b/api/core/workflow/nodes/question_classifier/question_classifier_node.py index 9aa43f58d5..0ec44eefac 100644 --- a/api/core/workflow/nodes/question_classifier/question_classifier_node.py +++ b/api/core/workflow/nodes/question_classifier/question_classifier_node.py @@ -44,13 +44,11 @@ class QuestionClassifierNode(LLMNode): variable_pool = self.graph_runtime_state.variable_pool # extract variables - variable = variable_pool.get( - node_data.query_variable_selector) if node_data.query_variable_selector else None + variable = variable_pool.get(node_data.query_variable_selector) if node_data.query_variable_selector else None query = variable.value if variable else None variables = {"query": query} # fetch model config - model_instance, model_config = self._fetch_model_config( - node_data.model) + model_instance, model_config = self._fetch_model_config(node_data.model) # fetch memory memory = self._fetch_memory( node_data_memory=node_data.memory, @@ -58,8 +56,7 @@ class QuestionClassifierNode(LLMNode): ) # fetch instruction node_data.instruction = node_data.instruction or "" - node_data.instruction = variable_pool.convert_template( - node_data.instruction).text + node_data.instruction = variable_pool.convert_template(node_data.instruction).text files = ( self._fetch_files( @@ -181,15 +178,12 @@ class QuestionClassifierNode(LLMNode): variable_mapping = {"query": node_data.query_variable_selector} variable_selectors = [] if node_data.instruction: - variable_template_parser = VariableTemplateParser( - template=node_data.instruction) - variable_selectors.extend( - variable_template_parser.extract_variable_selectors()) + variable_template_parser = VariableTemplateParser(template=node_data.instruction) + variable_selectors.extend(variable_template_parser.extract_variable_selectors()) for variable_selector in variable_selectors: variable_mapping[variable_selector.variable] = variable_selector.value_selector - variable_mapping = {node_id + "." + key: value for key, - value in variable_mapping.items()} + variable_mapping = {node_id + "." + key: value for key, value in variable_mapping.items()} return variable_mapping @@ -210,8 +204,7 @@ class QuestionClassifierNode(LLMNode): context: Optional[str], ) -> int: prompt_transform = AdvancedPromptTransform(with_variable_tmpl=True) - prompt_template = self._get_prompt_template( - node_data, query, None, 2000) + prompt_template = self._get_prompt_template(node_data, query, None, 2000) prompt_messages = prompt_transform.get_prompt( prompt_template=prompt_template, inputs={}, @@ -224,15 +217,13 @@ class QuestionClassifierNode(LLMNode): ) rest_tokens = 2000 - model_context_tokens = model_config.model_schema.model_properties.get( - ModelPropertyKey.CONTEXT_SIZE) + model_context_tokens = model_config.model_schema.model_properties.get(ModelPropertyKey.CONTEXT_SIZE) if model_context_tokens: model_instance = ModelInstance( provider_model_bundle=model_config.provider_model_bundle, model=model_config.model ) - curr_message_tokens = model_instance.get_llm_num_tokens( - prompt_messages) + curr_message_tokens = model_instance.get_llm_num_tokens(prompt_messages) max_tokens = 0 for parameter_rule in model_config.model_schema.parameter_rules: @@ -273,8 +264,7 @@ class QuestionClassifierNode(LLMNode): prompt_messages: list[LLMNodeChatModelMessage] = [] if model_mode == ModelMode.CHAT: system_prompt_messages = LLMNodeChatModelMessage( - role=PromptMessageRole.SYSTEM, text=QUESTION_CLASSIFIER_SYSTEM_PROMPT.format( - histories=memory_str) + role=PromptMessageRole.SYSTEM, text=QUESTION_CLASSIFIER_SYSTEM_PROMPT.format(histories=memory_str) ) prompt_messages.append(system_prompt_messages) user_prompt_message_1 = LLMNodeChatModelMessage( @@ -315,5 +305,4 @@ class QuestionClassifierNode(LLMNode): ) else: - raise InvalidModelTypeError( - f"Model mode {model_mode} not support.") + raise InvalidModelTypeError(f"Model mode {model_mode} not support.") diff --git a/api/pytest.ini b/api/pytest.ini index 993da4c9a7..b08cca5240 100644 --- a/api/pytest.ini +++ b/api/pytest.ini @@ -7,6 +7,12 @@ env = CODE_EXECUTION_API_KEY = dify-sandbox CODE_EXECUTION_ENDPOINT = http://127.0.0.1:8194 CODE_MAX_STRING_LENGTH = 80000 + PLUGIN_API_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi + PLUGIN_DAEMON_URL=http://127.0.0.1:5002 + PLUGIN_MAX_PACKAGE_SIZE=15728640 + INNER_API_KEY_FOR_PLUGIN=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1 + MARKETPLACE_ENABLED=true + MARKETPLACE_API_URL=https://marketplace.dify.ai FIRECRAWL_API_KEY = fc- FIREWORKS_API_KEY = fw_aaaaaaaaaaaaaaaaaaaa GOOGLE_API_KEY = abcdefghijklmnopqrstuvwxyz diff --git a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py index 285384ee6e..58b910e17b 100644 --- a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py +++ b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_executor.py @@ -68,8 +68,7 @@ def test_executor_with_json_body_and_object_variable(): system_variables={}, user_inputs={}, ) - variable_pool.add(["pre_node_id", "object"], { - "name": "John Doe", "age": 30, "email": "john@example.com"}) + variable_pool.add(["pre_node_id", "object"], {"name": "John Doe", "age": 30, "email": "john@example.com"}) # Prepare the node data node_data = HttpRequestNodeData( @@ -124,8 +123,7 @@ def test_executor_with_json_body_and_nested_object_variable(): system_variables={}, user_inputs={}, ) - variable_pool.add(["pre_node_id", "object"], { - "name": "John Doe", "age": 30, "email": "john@example.com"}) + variable_pool.add(["pre_node_id", "object"], {"name": "John Doe", "age": 30, "email": "john@example.com"}) # Prepare the node data node_data = HttpRequestNodeData( diff --git a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py index 1375d835d3..97bacada74 100644 --- a/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/http_request/test_http_request_node.py @@ -18,14 +18,6 @@ from models.enums import UserFrom from models.workflow import WorkflowNodeExecutionStatus, WorkflowType -def test_plain_text_to_dict(): - assert _plain_text_to_dict("aa\n cc:") == {"aa": "", "cc": ""} - assert _plain_text_to_dict("aa:bb\n cc:dd") == {"aa": "bb", "cc": "dd"} - assert _plain_text_to_dict("aa:bb\n cc:dd\n") == {"aa": "bb", "cc": "dd"} - assert _plain_text_to_dict("aa:bb\n\n cc : dd\n\n") == { - "aa": "bb", "cc": "dd"} - - def test_http_request_node_binary_file(monkeypatch): data = HttpRequestNodeData( title="test", @@ -191,8 +183,7 @@ def test_http_request_node_form_with_file(monkeypatch): def attr_checker(*args, **kwargs): assert kwargs["data"] == {"name": "test"} - assert kwargs["files"] == { - "file": (None, b"test", "application/octet-stream")} + assert kwargs["files"] == {"file": (None, b"test", "application/octet-stream")} return httpx.Response(200, content=b"") monkeypatch.setattr( From 4cbd511cd70a971766749e38b1ead3cebdfd4ff9 Mon Sep 17 00:00:00 2001 From: Joel <iamjoel007@gmail.com> Date: Fri, 10 Jan 2025 16:55:16 +0800 Subject: [PATCH 20/28] fix: ci use pnpm error (#12597) --- .github/workflows/style.yml | 8 +++++++- web/package.json | 9 +++++---- web/pnpm-lock.yaml | 11 +++++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 54372506e1..9956d7c22c 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -66,6 +66,12 @@ jobs: uses: tj-actions/changed-files@v45 with: files: web/** + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + run_install: false - name: Setup NodeJS uses: actions/setup-node@v4 @@ -81,7 +87,7 @@ jobs: - name: Web style check if: steps.changed-files.outputs.any_changed == 'true' - run: pnpm run lint + run: echo "${{ steps.changed-files.outputs.all_changed_files }}" | sed 's|web/||g' | xargs pnpm eslint # wait for next lint support eslint v9 superlinter: name: SuperLinter diff --git a/web/package.json b/web/package.json index 7b5006254c..d5020f92e7 100644 --- a/web/package.json +++ b/web/package.json @@ -9,7 +9,7 @@ "dev": "NODE_OPTIONS='--inspect' next dev", "build": "next build", "start": "cp -r .next/static .next/standalone/.next/static && cp -r public .next/standalone/public && cross-env PORT=$npm_config_port HOSTNAME=$npm_config_host node .next/standalone/server.js", - "lint": "next lint", + "lint": "pnpm eslint", "fix": "next lint --fix", "eslint-fix": "eslint --fix", "prepare": "cd ../ && node -e \"if (process.env.NODE_ENV !== 'production'){process.exit(1)} \" || husky ./web/.husky", @@ -27,6 +27,7 @@ "@babel/runtime": "^7.22.3", "@dagrejs/dagre": "^1.1.4", "@emoji-mart/data": "^1.2.1", + "@eslint/compat": "^1.2.4", "@floating-ui/react": "^0.26.25", "@formatjs/intl-localematcher": "^0.5.6", "@headlessui/react": "^1.7.13", @@ -86,14 +87,14 @@ "react-error-boundary": "^4.1.2", "react-headless-pagination": "^1.1.6", "react-hook-form": "^7.53.1", + "react-hotkeys-hook": "^4.6.1", "react-i18next": "^15.1.0", "react-infinite-scroll-component": "^6.1.0", "react-markdown": "^9.0.1", "react-multi-email": "^1.0.25", "react-papaparse": "^4.4.0", - "react-slider": "^2.0.6", - "react-hotkeys-hook": "^4.6.1", "react-pdf-highlighter": "^8.0.0-rc.0", + "react-slider": "^2.0.6", "react-sortablejs": "^6.1.4", "react-syntax-highlighter": "^15.6.1", "react-tooltip": "5.8.3", @@ -194,4 +195,4 @@ "eslint --fix" ] } -} +} \ No newline at end of file diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index e857736357..0243ab2c56 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -22,6 +22,9 @@ importers: '@emoji-mart/data': specifier: ^1.2.1 version: 1.2.1 + '@eslint/compat': + specifier: ^1.2.4 + version: 1.2.4(eslint@9.13.0(jiti@1.21.6)) '@floating-ui/react': specifier: ^0.26.25 version: 0.26.27(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1425,8 +1428,8 @@ packages: '@eslint-react/var@1.15.0': resolution: {integrity: sha512-/QycKnbgZRygM/lhHtUFQrvvrswdOyaXfVxwtIFVEYoPHP9q7NaUn0mrBu4VWkXQC9zPk1nWQeC3rZMUxzretg==} - '@eslint/compat@1.2.1': - resolution: {integrity: sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==} + '@eslint/compat@1.2.4': + resolution: {integrity: sha512-S8ZdQj/N69YAtuqFt7653jwcvuUj131+6qGLUyDqfDg1OIoBQ66OCuXC473YQfO2AaxITTutiRQiDwoo7ZLYyg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^9.10.0 @@ -9526,7 +9529,7 @@ snapshots: - supports-color - typescript - '@eslint/compat@1.2.1(eslint@9.13.0(jiti@1.21.6))': + '@eslint/compat@1.2.4(eslint@9.13.0(jiti@1.21.6))': optionalDependencies: eslint: 9.13.0(jiti@1.21.6) @@ -13140,7 +13143,7 @@ snapshots: eslint-config-flat-gitignore@0.3.0(eslint@9.13.0(jiti@1.21.6)): dependencies: - '@eslint/compat': 1.2.1(eslint@9.13.0(jiti@1.21.6)) + '@eslint/compat': 1.2.4(eslint@9.13.0(jiti@1.21.6)) eslint: 9.13.0(jiti@1.21.6) find-up-simple: 1.0.0 From ac336ff35988d42c43d14a15922f78535b7fa82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=9E=E6=B3=95=E6=93=8D=E4=BD=9C?= <hjlarry@163.com> Date: Fri, 10 Jan 2025 17:17:13 +0800 Subject: [PATCH 21/28] fix(1.0): add missing environment variable (#12599) --- api/.env.example | 3 ++- dev/pytest/pytest_config_tests.py | 12 ++++++++++++ docker/docker-compose-template.yaml | 10 +++------- docker/docker-compose.yaml | 12 ++++-------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/api/.env.example b/api/.env.example index c0962f06d6..06e1c51043 100644 --- a/api/.env.example +++ b/api/.env.example @@ -422,8 +422,9 @@ POSITION_PROVIDER_INCLUDES= POSITION_PROVIDER_EXCLUDES= # Plugin configuration -PLUGIN_API_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1 +PLUGIN_API_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi PLUGIN_API_URL=http://127.0.0.1:5002 +PLUGIN_DAEMON_URL=http://127.0.0.1:5002 PLUGIN_REMOTE_INSTALL_PORT=5003 PLUGIN_REMOTE_INSTALL_HOST=localhost PLUGIN_MAX_PACKAGE_SIZE=15728640 diff --git a/dev/pytest/pytest_config_tests.py b/dev/pytest/pytest_config_tests.py index 08adc9ebe9..11e98bb58b 100644 --- a/dev/pytest/pytest_config_tests.py +++ b/dev/pytest/pytest_config_tests.py @@ -10,6 +10,8 @@ BASE_API_AND_DOCKER_CONFIG_SET_DIFF = { "HTTP_REQUEST_MAX_CONNECT_TIMEOUT", "HTTP_REQUEST_MAX_READ_TIMEOUT", "HTTP_REQUEST_MAX_WRITE_TIMEOUT", + "INNER_API_KEY", + "INNER_API_KEY_FOR_PLUGIN", "KEYWORD_DATA_SOURCE_TYPE", "LOGIN_LOCKOUT_DURATION", "LOG_FORMAT", @@ -18,6 +20,10 @@ BASE_API_AND_DOCKER_CONFIG_SET_DIFF = { "OCI_ENDPOINT", "OCI_REGION", "OCI_SECRET_KEY", + "PLUGIN_API_KEY", + "PLUGIN_API_URL", + "PLUGIN_REMOTE_INSTALL_HOST", + "PLUGIN_REMOTE_INSTALL_PORT", "REDIS_DB", "RESEND_API_URL", "RESPECT_XFORWARD_HEADERS_ENABLED", @@ -40,6 +46,8 @@ BASE_API_AND_DOCKER_COMPOSE_CONFIG_SET_DIFF = { "HTTP_REQUEST_MAX_CONNECT_TIMEOUT", "HTTP_REQUEST_MAX_READ_TIMEOUT", "HTTP_REQUEST_MAX_WRITE_TIMEOUT", + "INNER_API_KEY", + "INNER_API_KEY_FOR_PLUGIN", "KEYWORD_DATA_SOURCE_TYPE", "LOGIN_LOCKOUT_DURATION", "LOG_FORMAT", @@ -58,6 +66,10 @@ BASE_API_AND_DOCKER_COMPOSE_CONFIG_SET_DIFF = { "PGVECTO_RS_PASSWORD", "PGVECTO_RS_PORT", "PGVECTO_RS_USER", + "PLUGIN_API_KEY", + "PLUGIN_API_URL", + "PLUGIN_REMOTE_INSTALL_HOST", + "PLUGIN_REMOTE_INSTALL_PORT", "RESPECT_XFORWARD_HEADERS_ENABLED", "SCARF_NO_ANALYTICS", "SSRF_DEFAULT_CONNECT_TIME_OUT", diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 9736372c76..8e52046510 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -14,14 +14,10 @@ services: SENTRY_DSN: ${API_SENTRY_DSN:-} SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} - PLUGIN_API_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi} - PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002} PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true} MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} - PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003} - PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost} ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}} depends_on: - db @@ -151,9 +147,9 @@ services: MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false} DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001} - DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} - PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0} - PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003} + DIFY_INNER_API_KEY: ${INNER_API_KEY_FOR_PLUGIN:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} + PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_REMOTE_INSTALL_HOST:-0.0.0.0} + PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_REMOTE_INSTALL_PORT:-5003} PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd} ports: - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 152df41c55..d9c393e193 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -389,7 +389,7 @@ x-shared-env: &shared-api-worker-env CREATE_TIDB_SERVICE_JOB_ENABLED: ${CREATE_TIDB_SERVICE_JOB_ENABLED:-false} MAX_SUBMIT_COUNT: ${MAX_SUBMIT_COUNT:-100} TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-10} - DB_PLUGIN_DATABASE: ${DB_PLUGIN_DATABASE:-dify-plugin} + DB_PLUGIN_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin} EXPOSE_PLUGIN_DAEMON_PORT: ${EXPOSE_PLUGIN_DAEMON_PORT:-5002} PLUGIN_DAEMON_PORT: ${PLUGIN_DAEMON_PORT:-5002} PLUGIN_DAEMON_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi} @@ -421,14 +421,10 @@ services: SENTRY_DSN: ${API_SENTRY_DSN:-} SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} - PLUGIN_API_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi} - PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002} PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true} MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai} - PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003} - PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost} ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}} depends_on: - db @@ -558,9 +554,9 @@ services: MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800} PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false} DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001} - DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} - PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0} - PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003} + DIFY_INNER_API_KEY: ${INNER_API_KEY_FOR_PLUGIN:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1} + PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_REMOTE_INSTALL_HOST:-0.0.0.0} + PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_REMOTE_INSTALL_PORT:-5003} PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd} ports: - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" From c08b4518740e0566cdb0cacad0053a4d9f3502a3 Mon Sep 17 00:00:00 2001 From: zxhlyh <jasonapring2015@outlook.com> Date: Fri, 10 Jan 2025 17:31:09 +0800 Subject: [PATCH 22/28] fix: marketplace page list style (#12613) --- .../components/plugins/marketplace/intersection-line/index.tsx | 2 +- web/app/components/plugins/marketplace/list/list-wrapper.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/components/plugins/marketplace/intersection-line/index.tsx b/web/app/components/plugins/marketplace/intersection-line/index.tsx index 6f8e4b02ab..94f592410a 100644 --- a/web/app/components/plugins/marketplace/intersection-line/index.tsx +++ b/web/app/components/plugins/marketplace/intersection-line/index.tsx @@ -14,7 +14,7 @@ const IntersectionLine = ({ useScrollIntersection(ref, intersectionContainerId) return ( - <div ref={ref} className='mb-4 h-[1px] bg-transparent'></div> + <div ref={ref} className='shrink-0 mb-4 h-[1px] bg-transparent'></div> ) } diff --git a/web/app/components/plugins/marketplace/list/list-wrapper.tsx b/web/app/components/plugins/marketplace/list/list-wrapper.tsx index 2dc83ee831..761adee5f8 100644 --- a/web/app/components/plugins/marketplace/list/list-wrapper.tsx +++ b/web/app/components/plugins/marketplace/list/list-wrapper.tsx @@ -37,7 +37,7 @@ const ListWrapper = ({ }, [handleQueryPlugins, marketplaceCollections, marketplaceCollectionsFromClient, isSuccessCollections]) return ( - <div className='relative flex flex-col grow h-0 px-12 py-2 bg-background-default-subtle'> + <div className='relative flex flex-col grow px-12 py-2 bg-background-default-subtle'> { plugins && ( <div className='flex items-center mb-4 pt-3'> From d56079a549ff4bb1ed1811f3078a8845566275cb Mon Sep 17 00:00:00 2001 From: zxhlyh <jasonapring2015@outlook.com> Date: Fri, 10 Jan 2025 18:15:58 +0800 Subject: [PATCH 23/28] fix: marketplace card i18n (#12623) --- web/app/components/plugins/card/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/app/components/plugins/card/index.tsx b/web/app/components/plugins/card/index.tsx index accd57c965..871f5cb62f 100644 --- a/web/app/components/plugins/card/index.tsx +++ b/web/app/components/plugins/card/index.tsx @@ -13,6 +13,7 @@ import { useGetLanguage } from '@/context/i18n' import { getLanguage } from '@/i18n/language' import { useSingleCategories } from '../hooks' import { renderI18nObject } from '@/hooks/use-i18n' +import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' export type Props = { className?: string @@ -43,7 +44,8 @@ const Card = ({ }: Props) => { const defaultLocale = useGetLanguage() const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale - const { categoriesMap } = useSingleCategories() + const { t } = useMixedTranslation(localeFromProps) + const { categoriesMap } = useSingleCategories(t) const { category, type, name, org, label, brief, icon, verified } = payload const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent-strategy'].includes(type) const cornerMark = isBundle ? categoriesMap.bundle?.label : categoriesMap[category]?.label From cb8debee3efe347c943f6b83a2939fc21485f474 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:46:59 +0800 Subject: [PATCH 24/28] Plugins/fix backend ci errors (#12615) --- .../__base/large_language_model.py | 40 ++- .../time/tools/timezone_conversion.py | 2 +- .../providers/webscraper/webscraper.py | 3 + .../model_runtime/__mock/plugin_daemon.py | 44 ++++ .../model_runtime/__mock/plugin_model.py | 249 ++++++++++++++++++ .../workflow/nodes/__mock/model.py | 50 ++++ .../workflow/nodes/test_llm.py | 93 ++----- .../nodes/test_parameter_extractor.py | 132 +++------- .../workflow/nodes/test_tool.py | 60 ++--- 9 files changed, 480 insertions(+), 193 deletions(-) create mode 100644 api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py create mode 100644 api/tests/integration_tests/model_runtime/__mock/plugin_model.py create mode 100644 api/tests/integration_tests/workflow/nodes/__mock/model.py diff --git a/api/core/model_runtime/model_providers/__base/large_language_model.py b/api/core/model_runtime/model_providers/__base/large_language_model.py index e833322f27..7f8de7cbab 100644 --- a/api/core/model_runtime/model_providers/__base/large_language_model.py +++ b/api/core/model_runtime/model_providers/__base/large_language_model.py @@ -107,11 +107,46 @@ class LargeLanguageModel(AIModel): content_list = [] usage = LLMUsage.empty_usage() system_fingerprint = None + tools_calls: list[AssistantPromptMessage.ToolCall] = [] + + def increase_tool_call(new_tool_calls: list[AssistantPromptMessage.ToolCall]): + def get_tool_call(tool_name: str): + if not tool_name: + return tools_calls[-1] + + tool_call = next( + (tool_call for tool_call in tools_calls if tool_call.function.name == tool_name), None + ) + if tool_call is None: + tool_call = AssistantPromptMessage.ToolCall( + id="", + type="", + function=AssistantPromptMessage.ToolCall.ToolCallFunction(name=tool_name, arguments=""), + ) + tools_calls.append(tool_call) + + return tool_call + + for new_tool_call in new_tool_calls: + # get tool call + tool_call = get_tool_call(new_tool_call.function.name) + # update tool call + if new_tool_call.id: + tool_call.id = new_tool_call.id + if new_tool_call.type: + tool_call.type = new_tool_call.type + if new_tool_call.function.name: + tool_call.function.name = new_tool_call.function.name + if new_tool_call.function.arguments: + tool_call.function.arguments += new_tool_call.function.arguments + for chunk in result: if isinstance(chunk.delta.message.content, str): content += chunk.delta.message.content elif isinstance(chunk.delta.message.content, list): content_list.extend(chunk.delta.message.content) + if chunk.delta.message.tool_calls: + increase_tool_call(chunk.delta.message.tool_calls) usage = chunk.delta.usage or LLMUsage.empty_usage() system_fingerprint = chunk.system_fingerprint @@ -120,7 +155,10 @@ class LargeLanguageModel(AIModel): result = LLMResult( model=model, prompt_messages=prompt_messages, - message=AssistantPromptMessage(content=content or content_list), + message=AssistantPromptMessage( + content=content or content_list, + tool_calls=tools_calls, + ), usage=usage, system_fingerprint=system_fingerprint, ) diff --git a/api/core/tools/builtin_tool/providers/time/tools/timezone_conversion.py b/api/core/tools/builtin_tool/providers/time/tools/timezone_conversion.py index 796c38b697..f9b776b3b9 100644 --- a/api/core/tools/builtin_tool/providers/time/tools/timezone_conversion.py +++ b/api/core/tools/builtin_tool/providers/time/tools/timezone_conversion.py @@ -48,6 +48,6 @@ class TimezoneConversionTool(BuiltinTool): datetime_with_tz = input_timezone.localize(local_time) # timezone convert converted_datetime = datetime_with_tz.astimezone(output_timezone) - return converted_datetime.strftime(format=time_format) + return converted_datetime.strftime(format=time_format) # type: ignore except Exception as e: raise ToolInvokeError(str(e)) diff --git a/api/core/tools/builtin_tool/providers/webscraper/webscraper.py b/api/core/tools/builtin_tool/providers/webscraper/webscraper.py index bf2199518e..52c8370e0d 100644 --- a/api/core/tools/builtin_tool/providers/webscraper/webscraper.py +++ b/api/core/tools/builtin_tool/providers/webscraper/webscraper.py @@ -5,4 +5,7 @@ from core.tools.builtin_tool.provider import BuiltinToolProviderController class WebscraperProvider(BuiltinToolProviderController): def _validate_credentials(self, user_id: str, credentials: dict[str, Any]) -> None: + """ + Validate credentials + """ pass diff --git a/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py b/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py new file mode 100644 index 0000000000..6dfc01ab4c --- /dev/null +++ b/api/tests/integration_tests/model_runtime/__mock/plugin_daemon.py @@ -0,0 +1,44 @@ +import os +from collections.abc import Callable + +import pytest + +# import monkeypatch +from _pytest.monkeypatch import MonkeyPatch + +from core.plugin.manager.model import PluginModelManager +from tests.integration_tests.model_runtime.__mock.plugin_model import MockModelClass + + +def mock_plugin_daemon( + monkeypatch: MonkeyPatch, +) -> Callable[[], None]: + """ + mock openai module + + :param monkeypatch: pytest monkeypatch fixture + :return: unpatch function + """ + + def unpatch() -> None: + monkeypatch.undo() + + monkeypatch.setattr(PluginModelManager, "invoke_llm", MockModelClass.invoke_llm) + monkeypatch.setattr(PluginModelManager, "fetch_model_providers", MockModelClass.fetch_model_providers) + monkeypatch.setattr(PluginModelManager, "get_model_schema", MockModelClass.get_model_schema) + + return unpatch + + +MOCK = os.getenv("MOCK_SWITCH", "false").lower() == "true" + + +@pytest.fixture +def setup_model_mock(monkeypatch): + if MOCK: + unpatch = mock_plugin_daemon(monkeypatch) + + yield + + if MOCK: + unpatch() diff --git a/api/tests/integration_tests/model_runtime/__mock/plugin_model.py b/api/tests/integration_tests/model_runtime/__mock/plugin_model.py new file mode 100644 index 0000000000..50913662e2 --- /dev/null +++ b/api/tests/integration_tests/model_runtime/__mock/plugin_model.py @@ -0,0 +1,249 @@ +import datetime +import uuid +from collections.abc import Generator, Sequence +from decimal import Decimal +from json import dumps + +# import monkeypatch +from typing import Optional + +from core.model_runtime.entities.common_entities import I18nObject +from core.model_runtime.entities.llm_entities import LLMMode, LLMResult, LLMResultChunk, LLMResultChunkDelta, LLMUsage +from core.model_runtime.entities.message_entities import AssistantPromptMessage, PromptMessage, PromptMessageTool +from core.model_runtime.entities.model_entities import ( + AIModelEntity, + FetchFrom, + ModelFeature, + ModelPropertyKey, + ModelType, +) +from core.model_runtime.entities.provider_entities import ConfigurateMethod, ProviderEntity +from core.plugin.entities.plugin_daemon import PluginModelProviderEntity +from core.plugin.manager.model import PluginModelManager + + +class MockModelClass(PluginModelManager): + def fetch_model_providers(self, tenant_id: str) -> Sequence[PluginModelProviderEntity]: + """ + Fetch model providers for the given tenant. + """ + return [ + PluginModelProviderEntity( + id=uuid.uuid4().hex, + created_at=datetime.datetime.now(), + updated_at=datetime.datetime.now(), + provider="openai", + tenant_id=tenant_id, + plugin_unique_identifier="langgenius/openai/openai", + plugin_id="langgenius/openai", + declaration=ProviderEntity( + provider="openai", + label=I18nObject( + en_US="OpenAI", + zh_Hans="OpenAI", + ), + description=I18nObject( + en_US="OpenAI", + zh_Hans="OpenAI", + ), + icon_small=I18nObject( + en_US="https://example.com/icon_small.png", + zh_Hans="https://example.com/icon_small.png", + ), + icon_large=I18nObject( + en_US="https://example.com/icon_large.png", + zh_Hans="https://example.com/icon_large.png", + ), + supported_model_types=[ModelType.LLM], + configurate_methods=[ConfigurateMethod.PREDEFINED_MODEL], + models=[ + AIModelEntity( + model="gpt-3.5-turbo", + label=I18nObject( + en_US="gpt-3.5-turbo", + zh_Hans="gpt-3.5-turbo", + ), + model_type=ModelType.LLM, + fetch_from=FetchFrom.PREDEFINED_MODEL, + model_properties={}, + features=[ModelFeature.TOOL_CALL, ModelFeature.MULTI_TOOL_CALL], + ), + AIModelEntity( + model="gpt-3.5-turbo-instruct", + label=I18nObject( + en_US="gpt-3.5-turbo-instruct", + zh_Hans="gpt-3.5-turbo-instruct", + ), + model_type=ModelType.LLM, + fetch_from=FetchFrom.PREDEFINED_MODEL, + model_properties={ + ModelPropertyKey.MODE: LLMMode.COMPLETION, + }, + features=[], + ), + ], + ), + ) + ] + + def get_model_schema( + self, + tenant_id: str, + user_id: str, + plugin_id: str, + provider: str, + model_type: str, + model: str, + credentials: dict, + ) -> AIModelEntity | None: + """ + Get model schema + """ + return AIModelEntity( + model=model, + label=I18nObject( + en_US="OpenAI", + zh_Hans="OpenAI", + ), + model_type=ModelType(model_type), + fetch_from=FetchFrom.PREDEFINED_MODEL, + model_properties={}, + features=[ModelFeature.TOOL_CALL, ModelFeature.MULTI_TOOL_CALL] if model == "gpt-3.5-turbo" else [], + ) + + @staticmethod + def generate_function_call( + tools: Optional[list[PromptMessageTool]], + ) -> Optional[AssistantPromptMessage.ToolCall]: + if not tools or len(tools) == 0: + return None + function: PromptMessageTool = tools[0] + function_name = function.name + function_parameters = function.parameters + function_parameters_type = function_parameters["type"] + if function_parameters_type != "object": + return None + function_parameters_properties = function_parameters["properties"] + function_parameters_required = function_parameters["required"] + parameters = {} + for parameter_name, parameter in function_parameters_properties.items(): + if parameter_name not in function_parameters_required: + continue + parameter_type = parameter["type"] + if parameter_type == "string": + if "enum" in parameter: + if len(parameter["enum"]) == 0: + continue + parameters[parameter_name] = parameter["enum"][0] + else: + parameters[parameter_name] = "kawaii" + elif parameter_type == "integer": + parameters[parameter_name] = 114514 + elif parameter_type == "number": + parameters[parameter_name] = 1919810.0 + elif parameter_type == "boolean": + parameters[parameter_name] = True + + return AssistantPromptMessage.ToolCall( + id=str(uuid.uuid4()), + type="function", + function=AssistantPromptMessage.ToolCall.ToolCallFunction( + name=function_name, + arguments=dumps(parameters), + ), + ) + + @staticmethod + def mocked_chat_create_sync( + model: str, + prompt_messages: list[PromptMessage], + tools: Optional[list[PromptMessageTool]] = None, + ) -> LLMResult: + tool_call = MockModelClass.generate_function_call(tools=tools) + + return LLMResult( + id=str(uuid.uuid4()), + model=model, + prompt_messages=prompt_messages, + message=AssistantPromptMessage(content="elaina", tool_calls=[tool_call] if tool_call else []), + usage=LLMUsage( + prompt_tokens=2, + completion_tokens=1, + total_tokens=3, + prompt_unit_price=Decimal(0.0001), + completion_unit_price=Decimal(0.0002), + prompt_price_unit=Decimal(1), + prompt_price=Decimal(0.0001), + completion_price_unit=Decimal(1), + completion_price=Decimal(0.0002), + total_price=Decimal(0.0003), + currency="USD", + latency=0.001, + ), + ) + + @staticmethod + def mocked_chat_create_stream( + model: str, + prompt_messages: list[PromptMessage], + tools: Optional[list[PromptMessageTool]] = None, + ) -> Generator[LLMResultChunk, None, None]: + tool_call = MockModelClass.generate_function_call(tools=tools) + + full_text = "Hello, world!\n\n```python\nprint('Hello, world!')\n```" + for i in range(0, len(full_text) + 1): + if i == len(full_text): + yield LLMResultChunk( + model=model, + prompt_messages=prompt_messages, + delta=LLMResultChunkDelta( + index=0, + message=AssistantPromptMessage( + content="", + tool_calls=[tool_call] if tool_call else [], + ), + ), + ) + else: + yield LLMResultChunk( + model=model, + prompt_messages=prompt_messages, + delta=LLMResultChunkDelta( + index=0, + message=AssistantPromptMessage( + content=full_text[i], + tool_calls=[tool_call] if tool_call else [], + ), + usage=LLMUsage( + prompt_tokens=2, + completion_tokens=17, + total_tokens=19, + prompt_unit_price=Decimal(0.0001), + completion_unit_price=Decimal(0.0002), + prompt_price_unit=Decimal(1), + prompt_price=Decimal(0.0001), + completion_price_unit=Decimal(1), + completion_price=Decimal(0.0002), + total_price=Decimal(0.0003), + currency="USD", + latency=0.001, + ), + ), + ) + + def invoke_llm( + self: PluginModelManager, + *, + tenant_id: str, + user_id: str, + plugin_id: str, + provider: str, + model: str, + credentials: dict, + prompt_messages: list[PromptMessage], + model_parameters: Optional[dict] = None, + tools: Optional[list[PromptMessageTool]] = None, + stop: Optional[list[str]] = None, + stream: bool = True, + ): + return MockModelClass.mocked_chat_create_stream(model=model, prompt_messages=prompt_messages, tools=tools) diff --git a/api/tests/integration_tests/workflow/nodes/__mock/model.py b/api/tests/integration_tests/workflow/nodes/__mock/model.py new file mode 100644 index 0000000000..7c48d84d69 --- /dev/null +++ b/api/tests/integration_tests/workflow/nodes/__mock/model.py @@ -0,0 +1,50 @@ +from unittest.mock import MagicMock + +from core.app.entities.app_invoke_entities import ModelConfigWithCredentialsEntity +from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle +from core.entities.provider_entities import CustomConfiguration, CustomProviderConfiguration, SystemConfiguration +from core.model_manager import ModelInstance +from core.model_runtime.entities.model_entities import ModelType +from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory +from models.provider import ProviderType + + +def get_mocked_fetch_model_config( + provider: str, + model: str, + mode: str, + credentials: dict, +): + model_provider_factory = ModelProviderFactory(tenant_id="test_tenant") + model_type_instance = model_provider_factory.get_model_type_instance(provider, ModelType.LLM) + provider_model_bundle = ProviderModelBundle( + configuration=ProviderConfiguration( + tenant_id="1", + provider=model_provider_factory.get_provider_schema(provider), + preferred_provider_type=ProviderType.CUSTOM, + using_provider_type=ProviderType.CUSTOM, + system_configuration=SystemConfiguration(enabled=False), + custom_configuration=CustomConfiguration(provider=CustomProviderConfiguration(credentials=credentials)), + model_settings=[], + ), + model_type_instance=model_type_instance, + ) + model_instance = ModelInstance(provider_model_bundle=provider_model_bundle, model=model) + model_schema = model_provider_factory.get_model_schema( + provider=provider, + model_type=model_type_instance.model_type, + model=model, + credentials=credentials, + ) + assert model_schema is not None + model_config = ModelConfigWithCredentialsEntity( + model=model, + provider=provider, + mode=mode, + credentials=credentials, + parameters={}, + model_schema=model_schema, + provider_model_bundle=provider_model_bundle, + ) + + return MagicMock(return_value=(model_instance, model_config)) diff --git a/api/tests/integration_tests/workflow/nodes/test_llm.py b/api/tests/integration_tests/workflow/nodes/test_llm.py index ca271d5362..22354df196 100644 --- a/api/tests/integration_tests/workflow/nodes/test_llm.py +++ b/api/tests/integration_tests/workflow/nodes/test_llm.py @@ -7,12 +7,7 @@ from unittest.mock import MagicMock import pytest -from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity -from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle -from core.entities.provider_entities import CustomConfiguration, CustomProviderConfiguration, SystemConfiguration -from core.model_manager import ModelInstance -from core.model_runtime.entities.model_entities import ModelType -from core.model_runtime.model_providers import ModelProviderFactory +from core.app.entities.app_invoke_entities import InvokeFrom from core.workflow.entities.variable_pool import VariablePool from core.workflow.enums import SystemVariableKey from core.workflow.graph_engine.entities.graph import Graph @@ -22,11 +17,11 @@ from core.workflow.nodes.event import RunCompletedEvent from core.workflow.nodes.llm.node import LLMNode from extensions.ext_database import db from models.enums import UserFrom -from models.provider import ProviderType from models.workflow import WorkflowNodeExecutionStatus, WorkflowType +from tests.integration_tests.workflow.nodes.__mock.model import get_mocked_fetch_model_config """FOR MOCK FIXTURES, DO NOT REMOVE""" -from tests.integration_tests.model_runtime.__mock.openai import setup_openai_mock +from tests.integration_tests.model_runtime.__mock.plugin_daemon import setup_model_mock from tests.integration_tests.workflow.nodes.__mock.code_executor import setup_code_executor_mock @@ -81,15 +76,19 @@ def init_llm_node(config: dict) -> LLMNode: return node -@pytest.mark.parametrize("setup_openai_mock", [["chat"]], indirect=True) -def test_execute_llm(setup_openai_mock): +def test_execute_llm(setup_model_mock): node = init_llm_node( config={ "id": "llm", "data": { "title": "123", "type": "llm", - "model": {"provider": "openai", "name": "gpt-3.5-turbo", "mode": "chat", "completion_params": {}}, + "model": { + "provider": "langgenius/openai/openai", + "name": "gpt-3.5-turbo", + "mode": "chat", + "completion_params": {}, + }, "prompt_template": [ {"role": "system", "text": "you are a helpful assistant.\ntoday's weather is {{#abc.output#}}."}, {"role": "user", "text": "{{#sys.query#}}"}, @@ -103,37 +102,15 @@ def test_execute_llm(setup_openai_mock): credentials = {"openai_api_key": os.environ.get("OPENAI_API_KEY")} - provider_instance = ModelProviderFactory().get_provider_instance("openai") - model_type_instance = provider_instance.get_model_instance(ModelType.LLM) - provider_model_bundle = ProviderModelBundle( - configuration=ProviderConfiguration( - tenant_id="1", - provider=provider_instance.get_provider_schema(), - preferred_provider_type=ProviderType.CUSTOM, - using_provider_type=ProviderType.CUSTOM, - system_configuration=SystemConfiguration(enabled=False), - custom_configuration=CustomConfiguration(provider=CustomProviderConfiguration(credentials=credentials)), - model_settings=[], - ), - model_type_instance=model_type_instance, - ) - model_instance = ModelInstance(provider_model_bundle=provider_model_bundle, model="gpt-3.5-turbo") - model_schema = model_type_instance.get_model_schema("gpt-3.5-turbo") - assert model_schema is not None - model_config = ModelConfigWithCredentialsEntity( - model="gpt-3.5-turbo", - provider="openai", - mode="chat", - credentials=credentials, - parameters={}, - model_schema=model_schema, - provider_model_bundle=provider_model_bundle, - ) - # Mock db.session.close() db.session.close = MagicMock() - node._fetch_model_config = MagicMock(return_value=(model_instance, model_config)) + node._fetch_model_config = get_mocked_fetch_model_config( + provider="langgenius/openai/openai", + model="gpt-3.5-turbo", + mode="chat", + credentials=credentials, + ) # execute node result = node._run() @@ -149,8 +126,7 @@ def test_execute_llm(setup_openai_mock): @pytest.mark.parametrize("setup_code_executor_mock", [["none"]], indirect=True) -@pytest.mark.parametrize("setup_openai_mock", [["chat"]], indirect=True) -def test_execute_llm_with_jinja2(setup_code_executor_mock, setup_openai_mock): +def test_execute_llm_with_jinja2(setup_code_executor_mock, setup_model_mock): """ Test execute LLM node with jinja2 """ @@ -190,38 +166,15 @@ def test_execute_llm_with_jinja2(setup_code_executor_mock, setup_openai_mock): credentials = {"openai_api_key": os.environ.get("OPENAI_API_KEY")} - provider_instance = ModelProviderFactory().get_provider_instance("openai") - model_type_instance = provider_instance.get_model_instance(ModelType.LLM) - provider_model_bundle = ProviderModelBundle( - configuration=ProviderConfiguration( - tenant_id="1", - provider=provider_instance.get_provider_schema(), - preferred_provider_type=ProviderType.CUSTOM, - using_provider_type=ProviderType.CUSTOM, - system_configuration=SystemConfiguration(enabled=False), - custom_configuration=CustomConfiguration(provider=CustomProviderConfiguration(credentials=credentials)), - model_settings=[], - ), - model_type_instance=model_type_instance, - ) - - model_instance = ModelInstance(provider_model_bundle=provider_model_bundle, model="gpt-3.5-turbo") - model_schema = model_type_instance.get_model_schema("gpt-3.5-turbo") - assert model_schema is not None - model_config = ModelConfigWithCredentialsEntity( - model="gpt-3.5-turbo", - provider="openai", - mode="chat", - credentials=credentials, - parameters={}, - model_schema=model_schema, - provider_model_bundle=provider_model_bundle, - ) - # Mock db.session.close() db.session.close = MagicMock() - node._fetch_model_config = MagicMock(return_value=(model_instance, model_config)) + node._fetch_model_config = get_mocked_fetch_model_config( + provider="langgenius/openai/openai", + model="gpt-3.5-turbo", + mode="chat", + credentials=credentials, + ) # execute node result = node._run() diff --git a/api/tests/integration_tests/workflow/nodes/test_parameter_extractor.py b/api/tests/integration_tests/workflow/nodes/test_parameter_extractor.py index 39aaafd981..ca055f5cc5 100644 --- a/api/tests/integration_tests/workflow/nodes/test_parameter_extractor.py +++ b/api/tests/integration_tests/workflow/nodes/test_parameter_extractor.py @@ -4,14 +4,7 @@ import uuid from typing import Optional from unittest.mock import MagicMock -import pytest - -from core.app.entities.app_invoke_entities import InvokeFrom, ModelConfigWithCredentialsEntity -from core.entities.provider_configuration import ProviderConfiguration, ProviderModelBundle -from core.entities.provider_entities import CustomConfiguration, CustomProviderConfiguration, SystemConfiguration -from core.model_manager import ModelInstance -from core.model_runtime.entities.model_entities import ModelType -from core.model_runtime.model_providers.model_provider_factory import ModelProviderFactory +from core.app.entities.app_invoke_entities import InvokeFrom from core.workflow.entities.variable_pool import VariablePool from core.workflow.enums import SystemVariableKey from core.workflow.graph_engine.entities.graph import Graph @@ -20,53 +13,11 @@ from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntime from core.workflow.nodes.parameter_extractor.parameter_extractor_node import ParameterExtractorNode from extensions.ext_database import db from models.enums import UserFrom -from models.provider import ProviderType +from tests.integration_tests.workflow.nodes.__mock.model import get_mocked_fetch_model_config """FOR MOCK FIXTURES, DO NOT REMOVE""" from models.workflow import WorkflowNodeExecutionStatus, WorkflowType -from tests.integration_tests.model_runtime.__mock.anthropic import setup_anthropic_mock -from tests.integration_tests.model_runtime.__mock.openai import setup_openai_mock - - -def get_mocked_fetch_model_config( - provider: str, - model: str, - mode: str, - credentials: dict, -): - model_provider_factory = ModelProviderFactory(tenant_id="test_tenant") - model_type_instance = model_provider_factory.get_model_type_instance(provider, ModelType.LLM) - provider_model_bundle = ProviderModelBundle( - configuration=ProviderConfiguration( - tenant_id="1", - provider=model_provider_factory.get_provider_schema(provider), - preferred_provider_type=ProviderType.CUSTOM, - using_provider_type=ProviderType.CUSTOM, - system_configuration=SystemConfiguration(enabled=False), - custom_configuration=CustomConfiguration(provider=CustomProviderConfiguration(credentials=credentials)), - model_settings=[], - ), - model_type_instance=model_type_instance, - ) - model_instance = ModelInstance(provider_model_bundle=provider_model_bundle, model=model) - model_schema = model_provider_factory.get_model_schema( - provider=provider, - model_type=model_type_instance.model_type, - model=model, - credentials=credentials, - ) - assert model_schema is not None - model_config = ModelConfigWithCredentialsEntity( - model=model, - provider=provider, - mode=mode, - credentials=credentials, - parameters={}, - model_schema=model_schema, - provider_model_bundle=provider_model_bundle, - ) - - return MagicMock(return_value=(model_instance, model_config)) +from tests.integration_tests.model_runtime.__mock.plugin_daemon import setup_model_mock def get_mocked_fetch_memory(memory_text: str): @@ -133,8 +84,7 @@ def init_parameter_extractor_node(config: dict): ) -@pytest.mark.parametrize("setup_openai_mock", [["chat"]], indirect=True) -def test_function_calling_parameter_extractor(setup_openai_mock): +def test_function_calling_parameter_extractor(setup_model_mock): """ Test function calling for parameter extractor. """ @@ -144,7 +94,12 @@ def test_function_calling_parameter_extractor(setup_openai_mock): "data": { "title": "123", "type": "parameter-extractor", - "model": {"provider": "openai", "name": "gpt-3.5-turbo", "mode": "chat", "completion_params": {}}, + "model": { + "provider": "langgenius/openai/openai", + "name": "gpt-3.5-turbo", + "mode": "chat", + "completion_params": {}, + }, "query": ["sys", "query"], "parameters": [{"name": "location", "type": "string", "description": "location", "required": True}], "instruction": "", @@ -155,25 +110,13 @@ def test_function_calling_parameter_extractor(setup_openai_mock): ) node._fetch_model_config = get_mocked_fetch_model_config( - provider="openai", + provider="langgenius/openai/openai", model="gpt-3.5-turbo", mode="chat", credentials={"openai_api_key": os.environ.get("OPENAI_API_KEY")}, ) db.session.close = MagicMock() - # construct variable pool - pool = VariablePool( - system_variables={ - SystemVariableKey.QUERY: "what's the weather in SF", - SystemVariableKey.FILES: [], - SystemVariableKey.CONVERSATION_ID: "abababa", - SystemVariableKey.USER_ID: "aaa", - }, - user_inputs={}, - environment_variables=[], - ) - result = node._run() assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED @@ -182,8 +125,7 @@ def test_function_calling_parameter_extractor(setup_openai_mock): assert result.outputs.get("__reason") == None -@pytest.mark.parametrize("setup_openai_mock", [["chat"]], indirect=True) -def test_instructions(setup_openai_mock): +def test_instructions(setup_model_mock): """ Test chat parameter extractor. """ @@ -193,7 +135,12 @@ def test_instructions(setup_openai_mock): "data": { "title": "123", "type": "parameter-extractor", - "model": {"provider": "openai", "name": "gpt-3.5-turbo", "mode": "chat", "completion_params": {}}, + "model": { + "provider": "langgenius/openai/openai", + "name": "gpt-3.5-turbo", + "mode": "chat", + "completion_params": {}, + }, "query": ["sys", "query"], "parameters": [{"name": "location", "type": "string", "description": "location", "required": True}], "reasoning_mode": "function_call", @@ -204,7 +151,7 @@ def test_instructions(setup_openai_mock): ) node._fetch_model_config = get_mocked_fetch_model_config( - provider="openai", + provider="langgenius/openai/openai", model="gpt-3.5-turbo", mode="chat", credentials={"openai_api_key": os.environ.get("OPENAI_API_KEY")}, @@ -228,8 +175,7 @@ def test_instructions(setup_openai_mock): assert "what's the weather in SF" in prompt.get("text") -@pytest.mark.parametrize("setup_anthropic_mock", [["none"]], indirect=True) -def test_chat_parameter_extractor(setup_anthropic_mock): +def test_chat_parameter_extractor(setup_model_mock): """ Test chat parameter extractor. """ @@ -239,7 +185,12 @@ def test_chat_parameter_extractor(setup_anthropic_mock): "data": { "title": "123", "type": "parameter-extractor", - "model": {"provider": "anthropic", "name": "claude-2", "mode": "chat", "completion_params": {}}, + "model": { + "provider": "langgenius/openai/openai", + "name": "gpt-3.5-turbo", + "mode": "chat", + "completion_params": {}, + }, "query": ["sys", "query"], "parameters": [{"name": "location", "type": "string", "description": "location", "required": True}], "reasoning_mode": "prompt", @@ -250,10 +201,10 @@ def test_chat_parameter_extractor(setup_anthropic_mock): ) node._fetch_model_config = get_mocked_fetch_model_config( - provider="anthropic", - model="claude-2", + provider="langgenius/openai/openai", + model="gpt-3.5-turbo", mode="chat", - credentials={"anthropic_api_key": os.environ.get("ANTHROPIC_API_KEY")}, + credentials={"openai_api_key": os.environ.get("OPENAI_API_KEY")}, ) db.session.close = MagicMock() @@ -275,8 +226,7 @@ def test_chat_parameter_extractor(setup_anthropic_mock): assert '<structure>\n{"type": "object"' in prompt.get("text") -@pytest.mark.parametrize("setup_openai_mock", [["completion"]], indirect=True) -def test_completion_parameter_extractor(setup_openai_mock): +def test_completion_parameter_extractor(setup_model_mock): """ Test completion parameter extractor. """ @@ -287,7 +237,7 @@ def test_completion_parameter_extractor(setup_openai_mock): "title": "123", "type": "parameter-extractor", "model": { - "provider": "openai", + "provider": "langgenius/openai/openai", "name": "gpt-3.5-turbo-instruct", "mode": "completion", "completion_params": {}, @@ -302,7 +252,7 @@ def test_completion_parameter_extractor(setup_openai_mock): ) node._fetch_model_config = get_mocked_fetch_model_config( - provider="openai", + provider="langgenius/openai/openai", model="gpt-3.5-turbo-instruct", mode="completion", credentials={"openai_api_key": os.environ.get("OPENAI_API_KEY")}, @@ -335,7 +285,7 @@ def test_extract_json_response(): "title": "123", "type": "parameter-extractor", "model": { - "provider": "openai", + "provider": "langgenius/openai/openai", "name": "gpt-3.5-turbo-instruct", "mode": "completion", "completion_params": {}, @@ -361,8 +311,7 @@ def test_extract_json_response(): assert result["location"] == "kawaii" -@pytest.mark.parametrize("setup_anthropic_mock", [["none"]], indirect=True) -def test_chat_parameter_extractor_with_memory(setup_anthropic_mock): +def test_chat_parameter_extractor_with_memory(setup_model_mock): """ Test chat parameter extractor with memory. """ @@ -372,7 +321,12 @@ def test_chat_parameter_extractor_with_memory(setup_anthropic_mock): "data": { "title": "123", "type": "parameter-extractor", - "model": {"provider": "anthropic", "name": "claude-2", "mode": "chat", "completion_params": {}}, + "model": { + "provider": "langgenius/openai/openai", + "name": "gpt-3.5-turbo", + "mode": "chat", + "completion_params": {}, + }, "query": ["sys", "query"], "parameters": [{"name": "location", "type": "string", "description": "location", "required": True}], "reasoning_mode": "prompt", @@ -383,10 +337,10 @@ def test_chat_parameter_extractor_with_memory(setup_anthropic_mock): ) node._fetch_model_config = get_mocked_fetch_model_config( - provider="anthropic", - model="claude-2", + provider="langgenius/openai/openai", + model="gpt-3.5-turbo", mode="chat", - credentials={"anthropic_api_key": os.environ.get("ANTHROPIC_API_KEY")}, + credentials={"openai_api_key": os.environ.get("OPENAI_API_KEY")}, ) node._fetch_memory = get_mocked_fetch_memory("customized memory") db.session.close = MagicMock() diff --git a/api/tests/integration_tests/workflow/nodes/test_tool.py b/api/tests/integration_tests/workflow/nodes/test_tool.py index 4068e796b7..5a569a5983 100644 --- a/api/tests/integration_tests/workflow/nodes/test_tool.py +++ b/api/tests/integration_tests/workflow/nodes/test_tool.py @@ -1,13 +1,15 @@ import time import uuid +from unittest.mock import MagicMock from core.app.entities.app_invoke_entities import InvokeFrom -from core.workflow.entities.node_entities import NodeRunResult +from core.tools.utils.configuration import ToolParameterConfigurationManager from core.workflow.entities.variable_pool import VariablePool from core.workflow.enums import SystemVariableKey from core.workflow.graph_engine.entities.graph import Graph from core.workflow.graph_engine.entities.graph_init_params import GraphInitParams from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntimeState +from core.workflow.nodes.event.event import RunCompletedEvent from core.workflow.nodes.tool.tool_node import ToolNode from models.enums import UserFrom from models.workflow import WorkflowNodeExecutionStatus, WorkflowType @@ -63,31 +65,28 @@ def test_tool_variable_invoke(): "data": { "title": "a", "desc": "a", - "provider_id": "maths", + "provider_id": "time", "provider_type": "builtin", - "provider_name": "maths", - "tool_name": "eval_expression", - "tool_label": "eval_expression", + "provider_name": "time", + "tool_name": "current_time", + "tool_label": "current_time", "tool_configurations": {}, - "tool_parameters": { - "expression": { - "type": "variable", - "value": ["1", "123", "args1"], - } - }, + "tool_parameters": {}, }, } ) + ToolParameterConfigurationManager.decrypt_tool_parameters = MagicMock(return_value={"format": "%Y-%m-%d %H:%M:%S"}) + node.graph_runtime_state.variable_pool.add(["1", "123", "args1"], "1+1") # execute node result = node._run() - assert isinstance(result, NodeRunResult) - assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED - assert result.outputs is not None - assert "2" in result.outputs["text"] - assert result.outputs["files"] == [] + for item in result: + if isinstance(item, RunCompletedEvent): + assert item.run_result.status == WorkflowNodeExecutionStatus.SUCCEEDED + assert item.run_result.outputs is not None + assert item.run_result.outputs.get("text") is not None def test_tool_mixed_invoke(): @@ -97,28 +96,25 @@ def test_tool_mixed_invoke(): "data": { "title": "a", "desc": "a", - "provider_id": "maths", + "provider_id": "time", "provider_type": "builtin", - "provider_name": "maths", - "tool_name": "eval_expression", - "tool_label": "eval_expression", - "tool_configurations": {}, - "tool_parameters": { - "expression": { - "type": "mixed", - "value": "{{#1.args1#}}", - } + "provider_name": "time", + "tool_name": "current_time", + "tool_label": "current_time", + "tool_configurations": { + "format": "%Y-%m-%d %H:%M:%S", }, + "tool_parameters": {}, }, } ) - node.graph_runtime_state.variable_pool.add(["1", "args1"], "1+1") + ToolParameterConfigurationManager.decrypt_tool_parameters = MagicMock(return_value={"format": "%Y-%m-%d %H:%M:%S"}) # execute node result = node._run() - assert isinstance(result, NodeRunResult) - assert result.status == WorkflowNodeExecutionStatus.SUCCEEDED - assert result.outputs is not None - assert "2" in result.outputs["text"] - assert result.outputs["files"] == [] + for item in result: + if isinstance(item, RunCompletedEvent): + assert item.run_result.status == WorkflowNodeExecutionStatus.SUCCEEDED + assert item.run_result.outputs is not None + assert item.run_result.outputs.get("text") is not None From 51947575c22b7645ae94803ca5524a72c4c5fe33 Mon Sep 17 00:00:00 2001 From: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Date: Fri, 10 Jan 2025 20:37:33 +0800 Subject: [PATCH 25/28] feat: add skip signature verification (#12627) --- .github/workflows/style.yml | 2 +- docker/.env.example | 1 + docker/docker-compose-template.yaml | 1 + docker/docker-compose.middleware.yaml | 1 + docker/docker-compose.yaml | 9 ++++----- docker/middleware.env.example | 2 ++ 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 9956d7c22c..c35d4c3e4b 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -66,7 +66,7 @@ jobs: uses: tj-actions/changed-files@v45 with: files: web/** - + - name: Install pnpm uses: pnpm/action-setup@v4 with: diff --git a/docker/.env.example b/docker/.env.example index 80508fbf72..02e80db9ac 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -958,3 +958,4 @@ ENDPOINT_URL_TEMPLATE=http://localhost/e/{hook_id} MARKETPLACE_ENABLED=true MARKETPLACE_API_URL=https://marketplace-plugin.dify.dev +FORCE_VERIFYING_SIGNATURE=true diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index 8e52046510..cc1f55a6af 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -151,6 +151,7 @@ services: PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_REMOTE_INSTALL_HOST:-0.0.0.0} PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_REMOTE_INSTALL_PORT:-5003} PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd} + FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true} ports: - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" volumes: diff --git a/docker/docker-compose.middleware.yaml b/docker/docker-compose.middleware.yaml index 8a20fff150..01879c4238 100644 --- a/docker/docker-compose.middleware.yaml +++ b/docker/docker-compose.middleware.yaml @@ -87,6 +87,7 @@ services: PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0} PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003} PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd} + FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true} ports: - "${EXPOSE_PLUGIN_DAEMON_PORT:-5002}:${PLUGIN_DAEMON_PORT:-5002}" - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index d9c393e193..b5c8a0b9fb 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -5,9 +5,9 @@ # ================================================================== x-shared-env: &shared-api-worker-env - CONSOLE_API_URL: ${CONSOLE_API_URL:-} - CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-} - SERVICE_API_URL: ${SERVICE_API_URL:-} + CONSOLE_API_URL: ${CONSOLE_API_URL:-http://localhost} + CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-http://localhost} + SERVICE_API_URL: ${SERVICE_API_URL:-http://localhost} APP_API_URL: ${APP_API_URL:-} APP_WEB_URL: ${APP_WEB_URL:-} FILES_URL: ${FILES_URL:-} @@ -416,8 +416,6 @@ services: <<: *shared-api-worker-env # Startup mode, 'api' starts the API server. MODE: api - CONSOLE_API_URL: ${CONSOLE_API_URL:-http://localhost:5001} - CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-http://localhost:3000} SENTRY_DSN: ${API_SENTRY_DSN:-} SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} @@ -558,6 +556,7 @@ services: PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_REMOTE_INSTALL_HOST:-0.0.0.0} PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_REMOTE_INSTALL_PORT:-5003} PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd} + FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true} ports: - "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}" volumes: diff --git a/docker/middleware.env.example b/docker/middleware.env.example index 357a60fe13..558ad46428 100644 --- a/docker/middleware.env.example +++ b/docker/middleware.env.example @@ -113,3 +113,5 @@ PLUGIN_DIFY_INNER_API_URL=http://api:5001 MARKETPLACE_ENABLED=true MARKETPLACE_API_URL=https://marketplace-plugin.dify.dev + +FORCE_VERIFYING_SIGNATURE=true \ No newline at end of file From f0a3c14adb2a632e0bcac36ceeae189e435e9a79 Mon Sep 17 00:00:00 2001 From: zxhlyh <jasonapring2015@outlook.com> Date: Mon, 13 Jan 2025 10:59:34 +0800 Subject: [PATCH 26/28] fix: plugins task (#12662) --- .../plugins/marketplace/description/index.tsx | 28 +++++++++++++++++-- web/service/use-plugins.ts | 18 +++++------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/web/app/components/plugins/marketplace/description/index.tsx b/web/app/components/plugins/marketplace/description/index.tsx index 337f456e6d..3e500155cf 100644 --- a/web/app/components/plugins/marketplace/description/index.tsx +++ b/web/app/components/plugins/marketplace/description/index.tsx @@ -12,6 +12,7 @@ const Description = async ({ const localeDefault = getLocaleOnServer() const { t } = await translate(localeFromProps || localeDefault, 'plugin') const { t: tCommon } = await translate(localeFromProps || localeDefault, 'common') + const isZhHans = localeFromProps === 'zh-Hans' return ( <> @@ -19,7 +20,22 @@ const Description = async ({ {t('marketplace.empower')} </h1> <h2 className='shrink-0 flex justify-center items-center text-center body-md-regular text-text-tertiary'> - {t('marketplace.discover')} + { + isZhHans && ( + <> + <span className='mr-1'>{tCommon('operation.in')}</span> + {t('marketplace.difyMarketplace')} + {t('marketplace.discover')} + </> + ) + } + { + !isZhHans && ( + <> + {t('marketplace.discover')} + </> + ) + } <span className="relative ml-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> <span className='relative z-[2] lowercase'>{t('category.models')}</span> </span> @@ -39,8 +55,14 @@ const Description = async ({ <span className="relative ml-1 mr-1 body-md-medium text-text-secondary after:content-[''] after:absolute after:left-0 after:bottom-[1.5px] after:w-full after:h-2 after:bg-text-text-selected z-[1]"> <span className='relative z-[2] lowercase'>{t('category.bundles')}</span> </span> - <span className='mr-1'>{tCommon('operation.in')}</span> - {t('marketplace.difyMarketplace')} + { + !isZhHans && ( + <> + <span className='mr-1'>{tCommon('operation.in')}</span> + {t('marketplace.difyMarketplace')} + </> + ) + } </h2> </> ) diff --git a/web/service/use-plugins.ts b/web/service/use-plugins.ts index 1673b5fff8..3feb66df8d 100644 --- a/web/service/use-plugins.ts +++ b/web/service/use-plugins.ts @@ -1,4 +1,4 @@ -import { useCallback, useState } from 'react' +import { useCallback } from 'react' import type { DebugInfo as DebugInfoTypes, Dependency, @@ -356,7 +356,6 @@ export const useFetchPluginsInMarketPlaceByInfo = (infos: Record<string, any>[]) const usePluginTaskListKey = [NAME_SPACE, 'pluginTaskList'] export const usePluginTaskList = () => { - const [enabled, setEnabled] = useState(true) const { data, isFetched, @@ -364,20 +363,17 @@ export const usePluginTaskList = () => { ...rest } = useQuery({ queryKey: usePluginTaskListKey, - queryFn: async () => { - const currentData = await get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100') - const taskDone = currentData.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed) - + queryFn: () => get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100'), + refetchInterval: (lastQuery) => { + const lastData = lastQuery.state.data + const taskDone = lastData?.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed) if (taskDone) - setEnabled(false) + return false - return currentData + return 5000 }, - refetchInterval: 5000, - enabled, }) const handleRefetch = useCallback(() => { - setEnabled(true) refetch() }, [refetch]) From 98b139c680fb3b1a1623cf2ca980d3bfcf3c25d4 Mon Sep 17 00:00:00 2001 From: Novice <857526207@qq.com> Date: Mon, 13 Jan 2025 13:04:05 +0800 Subject: [PATCH 27/28] feat: add agent strategy on node start (#12667) Co-authored-by: Novice Lee <novicelee@NoviPro.local> --- api/core/app/apps/workflow_app_runner.py | 1 + api/core/app/entities/queue_entities.py | 3 +- api/core/app/entities/task_entities.py | 2 + .../task_pipeline/workflow_cycle_manage.py | 1 + api/core/workflow/entities/node_entities.py | 5 +++ .../workflow/graph_engine/entities/event.py | 5 ++- .../workflow/graph_engine/graph_engine.py | 13 ++++++- api/core/workflow/nodes/agent/agent_node.py | 38 ++++++++++++------- 8 files changed, 51 insertions(+), 17 deletions(-) diff --git a/api/core/app/apps/workflow_app_runner.py b/api/core/app/apps/workflow_app_runner.py index 2d0bc95524..6d3b8a996b 100644 --- a/api/core/app/apps/workflow_app_runner.py +++ b/api/core/app/apps/workflow_app_runner.py @@ -241,6 +241,7 @@ class WorkflowBasedAppRunner(AppRunner): predecessor_node_id=event.predecessor_node_id, in_iteration_id=event.in_iteration_id, parallel_mode_run_id=event.parallel_mode_run_id, + agent_strategy=event.agent_strategy, ) ) elif isinstance(event, NodeRunSucceededEvent): diff --git a/api/core/app/entities/queue_entities.py b/api/core/app/entities/queue_entities.py index 334e2abf87..f1cc3ac221 100644 --- a/api/core/app/entities/queue_entities.py +++ b/api/core/app/entities/queue_entities.py @@ -6,7 +6,7 @@ from typing import Any, Optional from pydantic import BaseModel from core.model_runtime.entities.llm_entities import LLMResult, LLMResultChunk -from core.workflow.entities.node_entities import NodeRunMetadataKey +from core.workflow.entities.node_entities import AgentNodeStrategyInit, NodeRunMetadataKey from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntimeState from core.workflow.nodes import NodeType from core.workflow.nodes.base import BaseNodeData @@ -281,6 +281,7 @@ class QueueNodeStartedEvent(AppQueueEvent): start_at: datetime parallel_mode_run_id: Optional[str] = None """iteratoin run in parallel mode run id""" + agent_strategy: Optional[AgentNodeStrategyInit] = None class QueueNodeSucceededEvent(AppQueueEvent): diff --git a/api/core/app/entities/task_entities.py b/api/core/app/entities/task_entities.py index b5b909a3e9..e64bd416e0 100644 --- a/api/core/app/entities/task_entities.py +++ b/api/core/app/entities/task_entities.py @@ -6,6 +6,7 @@ from pydantic import BaseModel, ConfigDict from core.model_runtime.entities.llm_entities import LLMResult from core.model_runtime.utils.encoders import jsonable_encoder +from core.workflow.entities.node_entities import AgentNodeStrategyInit from models.workflow import WorkflowNodeExecutionStatus @@ -248,6 +249,7 @@ class NodeStartStreamResponse(StreamResponse): parent_parallel_start_node_id: Optional[str] = None iteration_id: Optional[str] = None parallel_run_id: Optional[str] = None + agent_strategy: Optional[AgentNodeStrategyInit] = None event: StreamEvent = StreamEvent.NODE_STARTED workflow_run_id: str diff --git a/api/core/app/task_pipeline/workflow_cycle_manage.py b/api/core/app/task_pipeline/workflow_cycle_manage.py index 31df7d2d86..0fff343eb9 100644 --- a/api/core/app/task_pipeline/workflow_cycle_manage.py +++ b/api/core/app/task_pipeline/workflow_cycle_manage.py @@ -541,6 +541,7 @@ class WorkflowCycleManage: parent_parallel_start_node_id=event.parent_parallel_start_node_id, iteration_id=event.in_iteration_id, parallel_run_id=event.parallel_mode_run_id, + agent_strategy=event.agent_strategy, ), ) diff --git a/api/core/workflow/entities/node_entities.py b/api/core/workflow/entities/node_entities.py index ed26889614..27c0e6702a 100644 --- a/api/core/workflow/entities/node_entities.py +++ b/api/core/workflow/entities/node_entities.py @@ -49,3 +49,8 @@ class NodeRunResult(BaseModel): # single step node run retry retry_index: int = 0 + + +class AgentNodeStrategyInit(BaseModel): + name: str + icon: str | None = None diff --git a/api/core/workflow/graph_engine/entities/event.py b/api/core/workflow/graph_engine/entities/event.py index 9d3a3f8f9f..3130bb25da 100644 --- a/api/core/workflow/graph_engine/entities/event.py +++ b/api/core/workflow/graph_engine/entities/event.py @@ -4,6 +4,7 @@ from typing import Any, Optional from pydantic import BaseModel, Field +from core.workflow.entities.node_entities import AgentNodeStrategyInit from core.workflow.graph_engine.entities.runtime_route_state import RouteNodeState from core.workflow.nodes import NodeType from core.workflow.nodes.base import BaseNodeData @@ -66,8 +67,10 @@ class BaseNodeEvent(GraphEngineEvent): class NodeRunStartedEvent(BaseNodeEvent): predecessor_node_id: Optional[str] = None - parallel_mode_run_id: Optional[str] = None """predecessor node id""" + parallel_mode_run_id: Optional[str] = None + """iteration node parallel mode run id""" + agent_strategy: Optional[AgentNodeStrategyInit] = None class NodeRunStreamChunkEvent(BaseNodeEvent): diff --git a/api/core/workflow/graph_engine/graph_engine.py b/api/core/workflow/graph_engine/graph_engine.py index 463525b9f4..a05cc30cab 100644 --- a/api/core/workflow/graph_engine/graph_engine.py +++ b/api/core/workflow/graph_engine/graph_engine.py @@ -14,7 +14,7 @@ from flask import Flask, current_app from configs import dify_config from core.app.apps.base_app_queue_manager import GenerateTaskStoppedError from core.app.entities.app_invoke_entities import InvokeFrom -from core.workflow.entities.node_entities import NodeRunMetadataKey, NodeRunResult +from core.workflow.entities.node_entities import AgentNodeStrategyInit, NodeRunMetadataKey, NodeRunResult from core.workflow.entities.variable_pool import VariablePool, VariableValue from core.workflow.graph_engine.condition_handlers.condition_manager import ConditionManager from core.workflow.graph_engine.entities.event import ( @@ -40,6 +40,8 @@ from core.workflow.graph_engine.entities.graph_init_params import GraphInitParam from core.workflow.graph_engine.entities.graph_runtime_state import GraphRuntimeState from core.workflow.graph_engine.entities.runtime_route_state import RouteNodeState from core.workflow.nodes import NodeType +from core.workflow.nodes.agent.agent_node import AgentNode +from core.workflow.nodes.agent.entities import AgentNodeData from core.workflow.nodes.answer.answer_stream_processor import AnswerStreamProcessor from core.workflow.nodes.answer.base_stream_processor import StreamProcessor from core.workflow.nodes.base import BaseNode @@ -606,6 +608,14 @@ class GraphEngine: Run node """ # trigger node run start event + agent_strategy = ( + AgentNodeStrategyInit( + name=cast(AgentNodeData, node_instance.node_data).agent_strategy_name, + icon=cast(AgentNode, node_instance).agent_strategy_icon, + ) + if node_instance.node_type == NodeType.AGENT + else None + ) yield NodeRunStartedEvent( id=node_instance.id, node_id=node_instance.node_id, @@ -617,6 +627,7 @@ class GraphEngine: parallel_start_node_id=parallel_start_node_id, parent_parallel_id=parent_parallel_id, parent_parallel_start_node_id=parent_parallel_start_node_id, + agent_strategy=agent_strategy, ) db.session.close() diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py index 8c29ce5176..db84624961 100644 --- a/api/core/workflow/nodes/agent/agent_node.py +++ b/api/core/workflow/nodes/agent/agent_node.py @@ -90,18 +90,11 @@ class AgentNode(ToolNode): try: # convert tool messages - manager = PluginInstallationManager() - plugins = manager.list_plugins(self.tenant_id) - current_plugin = next( - plugin - for plugin in plugins - if f"{plugin.plugin_id}/{plugin.name}" - == cast(AgentNodeData, self.node_data).agent_strategy_provider_name - ) + yield from self._transform_message( message_stream, { - "icon": current_plugin.declaration.icon, + "icon": self.agent_strategy_icon, "agent_strategy": cast(AgentNodeData, self.node_data).agent_strategy_name, }, parameters_for_log, @@ -229,16 +222,33 @@ class AgentNode(ToolNode): result: dict[str, Any] = {} for parameter_name in node_data.agent_parameters: input = node_data.agent_parameters[parameter_name] - if input.type == "mixed": - assert isinstance(input.value, str) - selectors = VariableTemplateParser(input.value).extract_variable_selectors() + if input.type in ["mixed", "constant"]: + selectors = VariableTemplateParser(str(input.value)).extract_variable_selectors() for selector in selectors: result[selector.variable] = selector.value_selector elif input.type == "variable": result[parameter_name] = input.value - elif input.type == "constant": - pass result = {node_id + "." + key: value for key, value in result.items()} return result + + @property + def agent_strategy_icon(self) -> str | None: + """ + Get agent strategy icon + :return: + """ + manager = PluginInstallationManager() + plugins = manager.list_plugins(self.tenant_id) + try: + current_plugin = next( + plugin + for plugin in plugins + if f"{plugin.plugin_id}/{plugin.name}" + == cast(AgentNodeData, self.node_data).agent_strategy_provider_name + ) + icon = current_plugin.declaration.icon + except StopIteration: + icon = None + return icon From 0a6b4d01d79e0240b53cbfa5b318020ce098921f Mon Sep 17 00:00:00 2001 From: Joel <iamjoel007@gmail.com> Date: Tue, 14 Jan 2025 10:28:41 +0800 Subject: [PATCH 28/28] fix: save tool not add type (#12712) --- .../plugins/plugin-detail-panel/tool-selector/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx index 1be8498788..8e9966e8b8 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx @@ -111,6 +111,7 @@ const ToolSelector: FC<Props> = ({ const paramValues = addDefaultValue(tool.params, toolParametersToFormSchemas(tool.paramSchemas.filter(param => param.form !== 'llm') as any)) const toolValue = { provider_name: tool.provider_id, + type: tool.provider_type, tool_name: tool.tool_name, parameters: paramValues, enabled: tool.is_team_authorization,