diff --git a/AGENTS.md b/AGENTS.md index 4fb546042..bc016a26e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -87,11 +87,22 @@ Config keys to verify in `data/config.yaml` / `src/langbot/templates/config.yaml - When changing Service API routes or capabilities used by `lbctl`, check compatibility with the separate `langbot-cli` repository. - New schema changes use Alembic under `src/langbot/pkg/persistence/alembic/versions/`. LangBot 4.x does not support upgrading 3.x databases. - New platform behavior belongs in platform adapters only for platform translation; pipeline/business logic belongs in `pkg/pipeline/` or services. -- User-facing strings must support i18n (`en_US`, `zh_Hans`; include `ja_JP` where the repo already does). +- User-facing strings must support i18n; follow the backend language rules below for server-generated content. - Code comments and docstrings must be English. - Keep compatibility and security in mind; LangBot is used in both self-hosted/community and toB deployments. - Commit message format: `(): `. +## Backend Message Language + +- LangBot-owned business errors, runtime notices, and default messages sent to users must use the owning Workspace's message language. Keep this independent of each member's WebUI language; an unset Workspace language defaults to `en_US`. +- Reuse `src/langbot/pkg/i18n/` and the existing `message_language` entry in `WorkspaceMetadata`. Use `t()` with stable English templates and named parameters; add matching keys and placeholders to all eight catalogs: `en_US`, `zh_Hans`, `zh_Hant`, `ja_JP`, `es_ES`, `ru_RU`, `th_TH`, and `vi_VN`. Avoid new translation frameworks or duplicate language settings. +- Resolve language from a trusted Workspace or bot execution context, and isolate it across concurrent requests, tasks, and adapter callbacks. Browser language hints may supply account-only or unauthenticated response language, but must not override a resolved Workspace or authorize tenant selection. Reading/changing the setting requires `workspace.view` / `workspace.update`. +- Pipeline notices should be configurable in Pipeline output settings through `pipeline_notice()`. Blank overrides inherit the Workspace translation. Preserve user-authored text literally except for documented placeholders, and retain existing visibility switches. Do not rewrite historical messages or custom text when the language changes. +- China-only adapters and configuration/field validation diagnostics do not require localization. An adapter also serving international users is not exempt merely because it supports a Chinese platform. +- Preserve raw provider/plugin diagnostics, tracebacks, protocol values, and machine-readable error/status codes. Translate LangBot's own category or explanation around them; do not translate arbitrary errors with substring replacement. Plugin-authored messages remain the plugin's localization responsibility. +- Keep changes small and maintainable. Reuse existing persistence and response boundaries; delete obsolete fields only after verifying they have no remaining readers, including compatibility paths. +- When changing language behavior, verify catalog/placeholder parity, Workspace isolation and permissions, and Pipeline inheritance/custom overrides. Update affected configuration snapshots and API/MCP documentation. Implementation details and focused test locations: [Backend message language](docs/architecture/backend-i18n.md). + ## Runtime Pitfalls - Local stdio Plugin Runtime disconnects do not auto-reconnect; restart LangBot if that path breaks. diff --git a/docs/architecture/backend-i18n.md b/docs/architecture/backend-i18n.md new file mode 100644 index 000000000..bf5a4ba35 --- /dev/null +++ b/docs/architecture/backend-i18n.md @@ -0,0 +1,68 @@ +# Backend message language + +Workspace settings expose one **Workspace language**, independent of each member's +WebUI language. It selects LangBot-owned API business errors, model error prefixes, +Pipeline default notices and international platform replies. Supported locales are +`en_US`, `zh_Hans`, `zh_Hant`, `ja_JP`, `es_ES`, `ru_RU`, `th_TH` and `vi_VN`. +Workspaces without a setting default to English. Existing custom messages and +historical records are not rewritten. + +## Storage and boundaries + +`pkg/i18n/workspace.py` stores `message_language` in existing `WorkspaceMetadata`; +no database migration or instance-wide configuration is needed. Reads and writes +use tenant-scoped units of work. GET/PUT `/api/v1/workspaces/current/language` +require `workspace.view` / `workspace.update`; matching MCP tools are +`get_workspace_message_language` and `set_workspace_message_language`. + +An authenticated Workspace takes precedence over the browser's +`X-LangBot-Language` header. The header supplies presentation language only for +account-only or unauthenticated responses and never selects a tenant. HTTP, MCP, +Pipeline and adapter boundaries set a ContextVar so concurrent Workspaces do not +share a language. Adapter SDK thread callbacks use their owning bot's cached +Workspace language, never the calling request's language. + +The per-application cache holds at most 256 Workspaces for 30 seconds. Local +writes update the cache immediately; other processes refresh at the next async +message/request boundary after expiry. A running operation keeps its selected +language. Synchronous SDK callbacks use the most recently loaded value. + +## Pipeline overrides + +The output `misc` section accepts these optional string settings: + +| Setting | Default purpose | Placeholder | +| --- | --- | --- | +| `failure-hint` | Request/runner execution failure | none | +| `rate-limit-hint` | Rate limit reached | none | +| `content-filter-hint` | Message rejected by content filter | none | +| `content-filter-error-hint` | Content check failed | none | +| `tool-call-hint` | Tool call notification | `{tools}` | +| `runner-not-found-hint` | Configured runner missing | `{runner}` | +| `runner-not-authorized-hint` | Runner authorization failure | none | +| `runner-unavailable-hint` | Runner temporarily unavailable | none | + +Blank values inherit the Workspace translation. Custom text is emitted literally +with only the documented placeholder replaced. The previous shipped +`failure-hint` value `Request failed.` also inherits language; this avoids a data +migration. Existing output switches (including tool-call visibility and exception +handling) retain their behavior. + +## Adding messages + +Use `pkg.i18n.t()` with a stable English template and named parameters. Add the +same key and placeholders to all eight JSON catalogs. The catalog parity test +checks completeness and formatting. `pipeline_notice()` handles configurable +notices. Exact aliases at the API response boundary cover legacy business wording; +do not add substring replacement of arbitrary error text. + +China-only adapters, field validation diagnostics, raw provider/plugin errors, +tracebacks, protocol values and machine-readable status codes are outside this +translation layer. Their values remain useful for diagnostics and interoperability. +Model errors translate LangBot's category/prefix while retaining upstream detail. +Plugin-authored content must use the plugin's own localization. System prompts and +user-authored content are not translated. + +Locale JSON files are included in Python package data. Focused coverage lives in +`tests/unit_tests/test_backend_i18n.py`, the Workspace HTTP integration tests and +`web/tests/e2e/workspace-language.spec.ts`. diff --git a/docs/architecture/cloud-plan-revisions.md b/docs/architecture/cloud-plan-revisions.md new file mode 100644 index 000000000..2cc7d3c37 --- /dev/null +++ b/docs/architecture/cloud-plan-revisions.md @@ -0,0 +1,37 @@ +## Cloud plan comparison + +`EntitlementSnapshot.plan_revision` and `monthly_bonus_credits` are optional +signed display metadata. The Space adapter opts into these fields with +`plan_metadata=2`. `/api/v1/workspaces/current` exposes them as `current_plan`, +alongside the snapshot's effective limits and feature switches. The existing +Workspace permission check and entitlement resolver remain authoritative. +Admission and quotas do not use plan names or display metadata. + +The comparison dialog shows the purchased revision even when the catalog has +no matching plan. It compares resource limits, retention, credits, platform +restrictions and feature switches; identical benefits use one column even if +the revision changed. Missing signed metadata is an explicit unavailable state. +Purchase links for existing paid plans go to Space subscription management, +where permissions, cancellation and revision eligibility are checked again. + +This adds display information to an existing authenticated response, not an +agent operation. There is no new MCP operation or billing mutation in Core. +Roll out the matching Core snapshot model before the updated Space adapter. + +Verification: + +```sh +uv run pytest tests/unit_tests/cloud/test_entitlements.py tests/integration/api/test_workspaces.py -q +cd web +node --test tests/unit/cloud-plans.test.mjs tests/unit/plan-revisions.test.mjs +pnpm build +node tests/revisions/verify.mjs +``` + +The browser runner expects sibling `space` and `core` checkouts and uses isolated +fixtures and mocked catalog responses. It never authenticates to real Space or +initiates a real payment, and shuts down its own servers after the tests. + +Purchased benefits are a card in the existing horizontally scrollable plan card area, immediately before the matching latest plan. There is no separate revision comparison panel, and historical prices are not inferred from the latest catalog. + +Customer presentation uses subscription dates and “Latest quotas for this plan”, never revision numbers. Unrelated plans and current latest subscriptions have no comparison markers. Core reuses its normal Benefits card content without diff rows or highlighting. Internal entitlement feature keys are not rendered as product benefits. The optional signed subscription_started_at is the current subscription period start, returned only for a matching entitlement revision; it is not snapshot issuance time. Requests with plan_metadata=1 retain their previous response shape. diff --git a/pyproject.toml b/pyproject.toml index fef399ca5..3e2c0d4d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,7 +129,7 @@ requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools] -package-data = { "langbot" = ["templates/**", "pkg/provider/modelmgr/requesters/*", "pkg/platform/sources/*", "pkg/platform/adapters/**", "web/dist/**", "pkg/persistence/alembic/**"] } +package-data = { "langbot" = ["templates/**", "pkg/i18n/locales/*.json", "pkg/provider/modelmgr/requesters/*", "pkg/platform/sources/*", "pkg/platform/adapters/**", "web/dist/**", "pkg/persistence/alembic/**"] } [dependency-groups] dev = [ diff --git a/skills/skills/langbot-mcp-ops/SKILL.md b/skills/skills/langbot-mcp-ops/SKILL.md index ebe12cb47..ae73d104c 100644 --- a/skills/skills/langbot-mcp-ops/SKILL.md +++ b/skills/skills/langbot-mcp-ops/SKILL.md @@ -212,6 +212,18 @@ Monitoring record filters accept `mode` (`all`, `real`, `debug`) and execution, not the individual model/tool call outcome. Calls without a recorded execution link are excluded when an execution filter is active. +### Workspace message language + +`get_workspace_message_language` reads the current Workspace's backend language +(`workspace.view`). `set_workspace_message_language(language)` requires +`workspace.update`; supported values are `en_US`, `zh_Hans`, `zh_Hant`, `ja_JP`, +`es_ES`, `ru_RU`, `th_TH`, `vi_VN`. HTTP equivalents are GET/PUT +`/api/v1/workspaces/current/language` (PUT body: `{"language":"ja_JP"}`). +The API key's Workspace remains authoritative. The setting controls new backend +messages and default bot notices, independently of personal UI language. +Pipeline `output.misc` hint fields override defaults; empty values inherit this +setting. Existing custom text and historical logs are not rewritten. + ### Workspace default LLM model `get_starred_model` reads the Workspace-wide favorite. `set_starred_model` @@ -227,6 +239,10 @@ are not rewritten. Embedding and rerank models are not eligible. Use `reset_session_context(bot_id, session_id)` only when a user asks to start a session afresh. It requires `resource.manage`, preserves monitoring records, and refuses sessions with active tasks. It clears conversation runner state and excludes earlier transcript entries from subsequent model context. Files and long-term memory are not removed. +## Cloud plan platform restrictions + +Bot creation and enabling use the same Workspace entitlement policy as HTTP. A disabled platform is rejected even through MCP or plugin calls; do not retry using an Omni or legacy alias to bypass the restriction. The Workspace-scoped HTTP adapter catalog omits disabled platforms. + ## LLM request diagnostics `get_monitoring_records(kind="llm_calls")` includes nullable `details` on each call. diff --git a/src/langbot/pkg/api/http/controller/group.py b/src/langbot/pkg/api/http/controller/group.py index bb9fcc048..6cafbdc8c 100644 --- a/src/langbot/pkg/api/http/controller/group.py +++ b/src/langbot/pkg/api/http/controller/group.py @@ -17,6 +17,8 @@ from ....workspace.errors import WorkspaceNotFoundError from ....cloud.entitlements import EntitlementUnavailableError from ....core.errors import TaskCapacityError from ....provider.modelmgr.codex_errors import CodexProviderError +from ....i18n import DEFAULT_LANGUAGE, language, language_scope, t, error_text +from ....i18n.workspace import get_workspace_language from ..authz import ( AuthenticationDeniedError, AuthorizationError, @@ -137,7 +139,7 @@ class RouterGroup(abc.ABC): # receive RequestContext or enforce Workspace permissions. self._inject_handler_context(f, kwargs, user_email, None, account) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) elif auth_type == AuthType.USER_TOKEN: # get token from Authorization header @@ -160,7 +162,7 @@ class RouterGroup(abc.ABC): require_permission(request_context, permission) self._inject_handler_context(f, kwargs, user_email, request_context) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) elif auth_type == AuthType.API_KEY: # get API key from Authorization header or X-API-Key header @@ -179,7 +181,7 @@ class RouterGroup(abc.ABC): require_permission(request_context, permission) self._inject_handler_context(f, kwargs, None, request_context) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) elif auth_type == AuthType.USER_TOKEN_OR_API_KEY: token = quart.request.headers.get('Authorization', '').replace('Bearer ', '') @@ -193,7 +195,7 @@ class RouterGroup(abc.ABC): require_permission(request_context, permission) self._inject_handler_context(f, kwargs, None, request_context) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) # Try API key first (check X-API-Key header) elif api_key := quart.request.headers.get('X-API-Key', ''): # API key authentication @@ -203,7 +205,7 @@ class RouterGroup(abc.ABC): require_permission(request_context, permission) self._inject_handler_context(f, kwargs, None, request_context) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) else: # Try user token authentication (Authorization header) if not token: @@ -223,7 +225,7 @@ class RouterGroup(abc.ABC): # Authentication succeeded and authorization was # evaluated. Do not reinterpret a denied user token # as an API key, which would mask the stable 403/404. - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) except Exception: # If user token fails, maybe it's an API key in Authorization header try: @@ -232,10 +234,12 @@ class RouterGroup(abc.ABC): require_permission(request_context, permission) self._inject_handler_context(f, kwargs, None, request_context) except Exception as e: - return self._auth_error_response(e) + return await self._localized_auth_error_response(e) observed_at = time.monotonic() try: + if request_context is not None: + language.set(await get_workspace_language(self.ap, request_context.workspace_uuid)) if request_context is not None: with bounded_executor.blocking_work_scope(request_context.workspace_uuid): persistence_mgr = getattr( @@ -292,6 +296,8 @@ class RouterGroup(abc.ABC): ) if isinstance(e, CodexProviderError): return self.http_status(e.status_code, e.error_code, str(e)) + if isinstance(e, EntitlementUnavailableError): + return self.http_status(403, 'entitlement_unavailable', str(e)) if isinstance(e, AuthorizationError): return self.http_status(e.status_code, e.error_code, str(e)) if isinstance(e, WorkspaceNotFoundError): @@ -319,7 +325,11 @@ class RouterGroup(abc.ABC): ) return self.internal_error_response(request_id) - new_f = handler_error + async def new_f(*args, **kwargs): + # Reset even on errors; child tasks inherit this request's locale. + with language_scope(quart.request.headers.get('X-LangBot-Language', DEFAULT_LANGUAGE)): + return await handler_error(*args, **kwargs) + # Quart/Flask requires a unique endpoint name even when the same URL # intentionally has separate handlers for different HTTP methods. # Include the method set so CRUD routes can declare distinct @@ -687,6 +697,14 @@ class RouterGroup(abc.ABC): 'Invalid authentication credentials', ) + async def _localized_auth_error_response(self, error: Exception): + # A resolved context is trusted even when its permissions deny this + # operation. Never look up a language using the unverified selector. + context = getattr(quart.g, 'request_context', None) + if context is not None: + language.set(await get_workspace_language(self.ap, context.workspace_uuid)) + return self._auth_error_response(error) + def request_id(self) -> str: """Return one stable request ID for authentication, logs, and errors.""" @@ -707,7 +725,7 @@ class RouterGroup(abc.ABC): response = quart.jsonify( { 'code': 'internal_error', - 'msg': 'Internal server error', + 'msg': t('Internal server error'), 'request_id': resolved_request_id, } ) @@ -729,7 +747,7 @@ class RouterGroup(abc.ABC): return quart.jsonify( { 'code': code, - 'msg': msg, + 'msg': error_text(code, msg), } ) diff --git a/src/langbot/pkg/api/http/controller/groups/agent_debug_stream.py b/src/langbot/pkg/api/http/controller/groups/agent_debug_stream.py index bf3fc03bd..700eab509 100644 --- a/src/langbot/pkg/api/http/controller/groups/agent_debug_stream.py +++ b/src/langbot/pkg/api/http/controller/groups/agent_debug_stream.py @@ -2,6 +2,8 @@ from __future__ import annotations +from .....i18n import t + import asyncio import contextlib import json @@ -45,20 +47,20 @@ def debug_stream_response(service, context, agent_uuid: str, payload: dict) -> q if isinstance(exc, RunnerExecutionError): code, message = exc.error_code or 'runner_execution_failed', exc.message elif isinstance(exc, RunnerNotFoundError): - code, message = 'runner_not_found', 'The configured Agent runner is unavailable' + code, message = 'runner_not_found', t('Agent runner temporarily unavailable. Please try again.') elif isinstance(exc, RunnerNotAuthorizedError): - code, message = 'runner_not_authorized', 'The configured Agent runner is not authorized' + code, message = 'runner_not_authorized', t('Agent runner not authorized for this pipeline.') elif isinstance(exc, RunnerProtocolError): - code, message = 'runner_protocol_error', 'The Agent runner returned an invalid response' + code, message = 'runner_protocol_error', t('The Agent runner returned an invalid response.') elif isinstance(exc, ValueError): code, message = 'invalid_request', str(exc) elif isinstance(exc, RunnerError): - code, message = 'runner_error', 'The Agent runner could not complete this test' + code, message = 'runner_error', t('Agent runner execution failed.') else: logger = getattr(application, 'logger', None) if logger is not None: logger.exception('Agent debug stream execution failed') - code, message = 'runner_error', 'The Agent debug execution failed' + code, message = 'runner_error', t('Agent runner execution failed.') await queue.put({'kind': 'error', 'code': code, 'msg': message}) task = asyncio.create_task(execute()) diff --git a/src/langbot/pkg/api/http/controller/groups/pipelines/embed.py b/src/langbot/pkg/api/http/controller/groups/pipelines/embed.py index 88deea8e6..9f32a63d3 100644 --- a/src/langbot/pkg/api/http/controller/groups/pipelines/embed.py +++ b/src/langbot/pkg/api/http/controller/groups/pipelines/embed.py @@ -21,6 +21,8 @@ import httpx import quart from ... import group +from ......i18n import language, t +from ......i18n.workspace import get_workspace_language from ......utils import httpclient, paths from ......platform.sources.websocket_manager import WebSocketScope, is_valid_session_id, ws_connection_manager from .websocket_chat import create_scoped_duplex_tasks, wait_for_duplex_tasks @@ -73,6 +75,7 @@ class EmbedRouterGroup(group.RouterGroup): bot = await self.ap.platform_mgr.resolve_public_bot(bot_uuid) pipeline_uuid = bot.get_pipeline_target_for_event_type('message.received') if bot is not None else None if bot is not None and bot.bot_entity.adapter == 'web_page_bot' and bot.bot_entity.enable and pipeline_uuid: + language.set(await get_workspace_language(self.ap, bot.execution_context.workspace_uuid)) return bot, pipeline_uuid return None, None @@ -284,7 +287,7 @@ class EmbedRouterGroup(group.RouterGroup): return self.http_status(404, -1, 'WebSocket adapter not found') websocket_adapter.reset_session(pipeline_uuid, session_type, session_id) - return self.success(data={'message': 'Session reset successfully'}) + return self.success(data={'message': t('Session reset successfully')}) except Exception as e: logger.error(f'Failed to reset embed session: {e}', exc_info=True) @@ -338,7 +341,9 @@ class EmbedRouterGroup(group.RouterGroup): runtime_bot, pipeline_uuid = await self._resolve_bot(bot_uuid) if runtime_bot is None: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Bot not found or not available'})) + await quart.websocket.send( + json.dumps({'type': 'error', 'message': t('Bot not found or not available')}) + ) return session_type = quart.websocket.args.get('session_type', 'person') @@ -357,13 +362,15 @@ class EmbedRouterGroup(group.RouterGroup): await self._authenticate_websocket(runtime_bot) await self._assert_execution_active(runtime_bot) except Exception: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Unauthorized'})) + await quart.websocket.send(json.dumps({'type': 'error', 'message': t('Unauthorized')})) return try: proxy_bot = await self.ap.platform_mgr.get_websocket_proxy_bot(runtime_bot.execution_context) websocket_adapter = proxy_bot.adapter if not websocket_adapter: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'WebSocket adapter not found'})) + await quart.websocket.send( + json.dumps({'type': 'error', 'message': t('WebSocket adapter not found')}) + ) return connection = await ws_connection_manager.add_connection( @@ -428,7 +435,7 @@ class EmbedRouterGroup(group.RouterGroup): except Exception as e: logger.error(f'Embed WebSocket connection error: {e}', exc_info=True) try: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Internal server error'})) + await quart.websocket.send(json.dumps({'type': 'error', 'message': t('Internal server error')})) except Exception: pass @@ -451,7 +458,7 @@ class EmbedRouterGroup(group.RouterGroup): try: current_bot = await self._resolve_connected_bot(owner_bot, pipeline_uuid) except Exception: - await connection.send_queue.put({'type': 'error', 'message': 'Bot is unavailable'}) + await connection.send_queue.put({'type': 'error', 'message': t('Bot is unavailable')}) break await websocket_adapter.handle_websocket_message(connection, data, owner_bot=current_bot) elif message_type == 'disconnect': @@ -460,7 +467,7 @@ class EmbedRouterGroup(group.RouterGroup): pass except json.JSONDecodeError: - await connection.send_queue.put({'type': 'error', 'message': 'Invalid JSON format'}) + await connection.send_queue.put({'type': 'error', 'message': t('Invalid JSON format')}) except Exception as e: logger.error(f'Embed receive error: {e}', exc_info=True) diff --git a/src/langbot/pkg/api/http/controller/groups/pipelines/websocket_chat.py b/src/langbot/pkg/api/http/controller/groups/pipelines/websocket_chat.py index 16406de90..649293e10 100644 --- a/src/langbot/pkg/api/http/controller/groups/pipelines/websocket_chat.py +++ b/src/langbot/pkg/api/http/controller/groups/pipelines/websocket_chat.py @@ -2,6 +2,9 @@ from __future__ import annotations +from ......i18n import language, t +from ......i18n.workspace import get_workspace_language + import asyncio import datetime import json @@ -217,8 +220,9 @@ class WebSocketChatRouterGroup(group.RouterGroup): try: request_context, token = await self._authenticate_websocket() except Exception: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Unauthorized'})) + await quart.websocket.send(json.dumps({'type': 'error', 'message': t('Unauthorized')})) return + language.set(await get_workspace_language(self.ap, request_context.workspace_uuid)) session_type = quart.websocket.args.get('session_type', 'person') if session_type not in ['person', 'group']: await quart.websocket.send( @@ -229,7 +233,7 @@ class WebSocketChatRouterGroup(group.RouterGroup): try: websocket_adapter = await self._get_scoped_adapter(request_context, pipeline_uuid) if websocket_adapter is None: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Pipeline not found'})) + await quart.websocket.send(json.dumps({'type': 'error', 'message': t('Pipeline not found')})) return connection = await ws_connection_manager.add_connection( @@ -294,7 +298,7 @@ class WebSocketChatRouterGroup(group.RouterGroup): except Exception: logger.error('Dashboard WebSocket connection error', exc_info=True) try: - await quart.websocket.send(json.dumps({'type': 'error', 'message': 'Internal server error'})) + await quart.websocket.send(json.dumps({'type': 'error', 'message': t('Internal server error')})) except Exception: pass @@ -419,7 +423,7 @@ class WebSocketChatRouterGroup(group.RouterGroup): try: request_context = await self._revalidate_websocket_authorization(request_context, token) except Exception: - await connection.send_queue.put({'type': 'error', 'message': 'Unauthorized'}) + await connection.send_queue.put({'type': 'error', 'message': t('Unauthorized')}) break await websocket_adapter.handle_websocket_message(connection, data) elif message_type == 'disconnect': @@ -427,7 +431,7 @@ class WebSocketChatRouterGroup(group.RouterGroup): else: logger.warning(f'Unknown WebSocket message type: {message_type}') except json.JSONDecodeError: - await connection.send_queue.put({'type': 'error', 'message': 'Invalid JSON format'}) + await connection.send_queue.put({'type': 'error', 'message': t('Invalid JSON format')}) except Exception: logger.error('Dashboard WebSocket receive error', exc_info=True) diff --git a/src/langbot/pkg/api/http/controller/groups/platform/adapters.py b/src/langbot/pkg/api/http/controller/groups/platform/adapters.py index 4715ceb95..d740221f1 100644 --- a/src/langbot/pkg/api/http/controller/groups/platform/adapters.py +++ b/src/langbot/pkg/api/http/controller/groups/platform/adapters.py @@ -1,3 +1,5 @@ +from langbot.pkg.i18n import t, DEFAULT_LANGUAGE +from langbot.pkg.i18n.workspace import get_workspace_language import asyncio import dataclasses import mimetypes @@ -6,6 +8,7 @@ import quart from langbot.pkg.api.http.authz import Permission from langbot.pkg.api.http.context import RequestContext +from langbot.pkg.cloud.plan_policy import workspace_entitlement, platform_feature_names, require_workspace_platform from langbot.pkg.core.errors import TaskCapacityError from langbot.pkg.utils import httpclient, importutil @@ -213,16 +216,20 @@ class AdaptersRouterGroup(group.RouterGroup): @self.route('/slack/setup/callback', methods=['GET'], auth_type=group.AuthType.NONE) async def slack_callback(): + session = slack_setup.sessions.get(quart.request.args.get('state', '')) + locale = DEFAULT_LANGUAGE + if session is not None: + locale = await get_workspace_language(self.ap, session['context'].workspace_uuid) try: await slack_setup.finish( quart.request.args.get('state', ''), quart.request.args.get('code', ''), quart.request.args.get('error'), ) - message = 'Slack authorization completed. Return to LangBot to finish setup. / Slack 授权完成,请返回 LangBot 完成配置。' + message = t('Slack authorization completed. Return to LangBot to finish setup.', locale=locale) status = 200 except SlackSetupError: - message = 'Slack authorization failed or expired. Return to LangBot for details. / Slack 授权失败或已过期,请返回 LangBot 查看详情。' + message = t('Slack authorization failed or expired. Return to LangBot for details.', locale=locale) status = 400 return quart.Response( message, @@ -232,11 +239,20 @@ class AdaptersRouterGroup(group.RouterGroup): ) @self.route('', methods=['GET']) - async def _() -> str: - return self.success(data={'adapters': self.ap.platform_mgr.get_available_adapters_info()}) + async def _(request_context: RequestContext) -> str: + snapshot = await workspace_entitlement(self.ap, request_context.workspace_uuid) + adapters = self.ap.platform_mgr.get_available_adapters_info() + if snapshot is not None: + adapters = [ + a + for a in adapters + if not any(snapshot.features.get(f) is False for f in platform_feature_names(a['name'])) + ] + return self.success(data={'adapters': adapters}) @self.route('/', methods=['GET']) - async def _(adapter_name: str) -> str: + async def _(adapter_name: str, request_context: RequestContext) -> str: + await require_workspace_platform(self.ap, request_context.workspace_uuid, adapter_name) adapter_info = self.ap.platform_mgr.get_available_adapter_info_by_name(adapter_name) if adapter_info is None: diff --git a/src/langbot/pkg/api/http/controller/groups/plugins.py b/src/langbot/pkg/api/http/controller/groups/plugins.py index 950a8954d..28024ca5d 100644 --- a/src/langbot/pkg/api/http/controller/groups/plugins.py +++ b/src/langbot/pkg/api/http/controller/groups/plugins.py @@ -1,5 +1,7 @@ from __future__ import annotations +from .....i18n import t + import asyncio import base64 import collections.abc @@ -296,14 +298,20 @@ class PluginsRouterGroup(group.RouterGroup): async def _check_extensions_limit(self, request_context: RequestContext) -> str | None: """Check if extensions limit is reached. Returns error response if limit exceeded, None otherwise.""" await self.ap.plugin_connector.require_workspace_context(request_context) - limitation = self.ap.instance_config.data.get('system', {}).get('limitation', {}) + from ...service.workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, request_context.workspace_uuid) max_extensions = limitation.get('max_extensions', -1) if max_extensions >= 0: plugins = await self.ap.plugin_connector.list_plugins() mcp_servers = await self.ap.mcp_service.get_mcp_servers(request_context) total_extensions = len(plugins) + len(mcp_servers) if total_extensions >= max_extensions: - return self.http_status(400, -1, f'Maximum number of extensions ({max_extensions}) reached') + return self.http_status( + 400, + -1, + t('Maximum number of {resource} ({limit}) reached', resource=t('extensions'), limit=max_extensions), + ) return None @staticmethod diff --git a/src/langbot/pkg/api/http/controller/groups/workspaces.py b/src/langbot/pkg/api/http/controller/groups/workspaces.py index 7873e9f17..4f653a2e3 100644 --- a/src/langbot/pkg/api/http/controller/groups/workspaces.py +++ b/src/langbot/pkg/api/http/controller/groups/workspaces.py @@ -14,6 +14,8 @@ from .....workspace.errors import WorkspaceNotFoundError from .....workspace.invitation_delivery import InvitationDeliveryService from .....operation_trace import service as settings_service from .. import group +from .....i18n import SUPPORTED_LANGUAGES +from .....i18n.workspace import get_workspace_language, set_workspace_language def _workspace_payload(workspace: Workspace) -> dict[str, typing.Any]: @@ -74,6 +76,34 @@ class WorkspacesRouterGroup(group.RouterGroup): return await operation() async def initialize(self) -> None: + @self.route( + '/current/language', + methods=['GET'], + auth_type=group.AuthType.USER_TOKEN_OR_API_KEY, + permission=Permission.WORKSPACE_VIEW, + ) + async def get_language(request_context: RequestContext): + return self.success( + data={ + 'language': await get_workspace_language(self.ap, request_context.workspace_uuid, refresh=True), + 'supported_languages': list(SUPPORTED_LANGUAGES), + } + ) + + @self.route( + '/current/language', + methods=['PUT'], + auth_type=group.AuthType.USER_TOKEN_OR_API_KEY, + permission=Permission.WORKSPACE_UPDATE, + ) + async def update_language(request_context: RequestContext): + body = await quart.request.get_json() + locale = body.get('language') if isinstance(body, dict) else None + if locale not in SUPPORTED_LANGUAGES: + return self.http_status(400, 'invalid_language', 'Unsupported Workspace language') + locale = await set_workspace_language(self.ap, request_context.workspace_uuid, locale) + return self.success(data={'language': locale}) + @self.route('/bootstrap', methods=['GET'], auth_type=group.AuthType.ACCOUNT_TOKEN) async def _(account) -> typing.Any: """List the active Workspaces available to an authenticated Account. @@ -129,6 +159,8 @@ class WorkspacesRouterGroup(group.RouterGroup): membership = quart.g.workspace_membership workspace = await self.ap.workspace_service.get_workspace(request_context.workspace_uuid) plan_name: str | None = None + limitation = None + current_plan = None resolver = getattr(self.ap, 'entitlement_resolver', None) if workspace.source == WorkspaceSource.CLOUD_PROJECTION.value and resolver is not None: entitlement = await resolver.resolve( @@ -136,6 +168,18 @@ class WorkspacesRouterGroup(group.RouterGroup): minimum_revision=request_context.entitlement_revision, ) plan_name = entitlement.plan_name + if entitlement.plan_revision is not None and entitlement.monthly_bonus_credits is not None: + current_plan = { + 'name': entitlement.plan_name, + 'subscription_started_at': entitlement.subscription_started_at, + 'revision': entitlement.plan_revision, + 'monthly_bonus_credits': entitlement.monthly_bonus_credits, + 'limits': entitlement.limits, + 'entitlement_features': entitlement.features, + } + from ...service.workspace_limits import LIMIT_KEYS + + limitation = {key: entitlement.limit(value) for key, value in LIMIT_KEYS.items()} if request_context.principal.principal_type == PrincipalType.SUPPORT_ADMIN: return self.success( data={ @@ -154,6 +198,8 @@ class WorkspacesRouterGroup(group.RouterGroup): 'permissions': sorted(request_context.workspace.permissions), 'placement_generation': request_context.placement_generation, 'plan_name': plan_name, + 'current_plan': current_plan, + 'limitation': limitation, } ) account = await self.ap.user_service.get_user_by_uuid(request_context.account_uuid) @@ -170,6 +216,8 @@ class WorkspacesRouterGroup(group.RouterGroup): 'permissions': sorted(request_context.workspace.permissions), 'placement_generation': request_context.placement_generation, 'plan_name': plan_name, + 'current_plan': current_plan, + 'limitation': limitation, } ) diff --git a/src/langbot/pkg/api/http/service/agent.py b/src/langbot/pkg/api/http/service/agent.py index 394c3b3dd..c0f0b34bf 100644 --- a/src/langbot/pkg/api/http/service/agent.py +++ b/src/langbot/pkg/api/http/service/agent.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + from contextlib import aclosing import datetime @@ -432,7 +434,7 @@ class AgentService: pipeline_uuid = await self.ap.pipeline_service.create_pipeline( context, { - 'name': agent_data.get('name') or 'New Pipeline', + 'name': agent_data.get('name') or t('New Pipeline'), 'description': agent_data.get('description') or '', 'emoji': agent_data.get('emoji') or '⚙️', 'config': {}, @@ -461,7 +463,7 @@ class AgentService: values = { 'workspace_uuid': workspace_uuid, 'uuid': new_uuid, - 'name': agent_data.get('name') or 'New Agent', + 'name': agent_data.get('name') or t('New Agent'), 'description': agent_data.get('description') or '', 'emoji': agent_data.get('emoji') or ('🧩' if kind == AGENT_KIND_EVENT_PROCESSOR else '🤖'), 'kind': kind, diff --git a/src/langbot/pkg/api/http/service/bot.py b/src/langbot/pkg/api/http/service/bot.py index 59ab6fe58..766adbc87 100644 --- a/src/langbot/pkg/api/http/service/bot.py +++ b/src/langbot/pkg/api/http/service/bot.py @@ -16,6 +16,7 @@ from .tenant import TenantContext, require_workspace_uuid, scope_statement from ....utils import httpclient from ....platform.sources import http_bot_signing from ....platform.adapter_names import canonical_adapter_name +from ....cloud.plan_policy import require_workspace_platform from ....agent.runner.errors import RunnerNotFoundError @@ -685,7 +686,9 @@ class BotService: """Create bot""" workspace_uuid = require_workspace_uuid(context) # Check limitation - limitation = self.ap.instance_config.data.get('system', {}).get('limitation', {}) + from .workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, workspace_uuid) max_bots = limitation.get('max_bots', -1) if max_bots >= 0: existing_bots = await self.get_bots(context) @@ -694,6 +697,7 @@ class BotService: # TODO: 检查配置信息格式 bot_data = await self._prepare_bot_data(context, bot_data, include_uuid=True) + await require_workspace_platform(self.ap, workspace_uuid, bot_data['adapter']) bot_data['uuid'] = str(uuid.uuid4()) bot_data['workspace_uuid'] = workspace_uuid bot_data.setdefault('event_bindings', []) @@ -716,6 +720,9 @@ class BotService: workspace_uuid = require_workspace_uuid(context) update_data = await self._prepare_bot_data(context, bot_data, include_uuid=False) update_data.pop('workspace_uuid', None) + if 'adapter' in update_data or update_data.get('enable'): + current = await self.get_bot(context, bot_uuid, include_secret=True) + await require_workspace_platform(self.ap, workspace_uuid, update_data.get('adapter', current['adapter'])) result = await self.ap.persistence_mgr.execute_async( scope_statement( diff --git a/src/langbot/pkg/api/http/service/knowledge.py b/src/langbot/pkg/api/http/service/knowledge.py index 654bf2f17..e85d16fd8 100644 --- a/src/langbot/pkg/api/http/service/knowledge.py +++ b/src/langbot/pkg/api/http/service/knowledge.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + import sqlalchemy from ....api.http.authz import WorkspaceRequiredError @@ -56,14 +58,20 @@ class KnowledgeService: require_workspace_uuid(context) # In new architecture, we delegate entirely to RAGManager which uses plugins. # Legacy internal KB creation is removed. - limitation = ( - getattr(getattr(self.ap, 'instance_config', None), 'data', {}).get('system', {}).get('limitation', {}) - ) + from .workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, require_workspace_uuid(context)) max_knowledge_bases = limitation.get('max_knowledge_bases', -1) if max_knowledge_bases >= 0: knowledge_bases = await self.ap.rag_mgr.get_all_knowledge_base_details(context) if len(knowledge_bases) >= max_knowledge_bases: - raise ValueError(f'Maximum number of knowledge bases ({max_knowledge_bases}) reached') + raise ValueError( + t( + 'Maximum number of {resource} ({limit}) reached', + resource=t('knowledge bases'), + limit=max_knowledge_bases, + ) + ) knowledge_engine_plugin_id = kb_data.get('knowledge_engine_plugin_id') if not knowledge_engine_plugin_id: diff --git a/src/langbot/pkg/api/http/service/mcp.py b/src/langbot/pkg/api/http/service/mcp.py index 67e8e14ae..3e5eb7339 100644 --- a/src/langbot/pkg/api/http/service/mcp.py +++ b/src/langbot/pkg/api/http/service/mcp.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + import copy import re import uuid @@ -212,7 +214,9 @@ class MCPService: # stdio MCP even though Box Runtime itself remains available. require_stdio_mcp_enabled(self.ap, server_data) - limitation = self.ap.instance_config.data.get('system', {}).get('limitation', {}) + from .workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, workspace_uuid) max_extensions = limitation.get('max_extensions', -1) if max_extensions >= 0: mcp_count_result = await self.ap.persistence_mgr.execute_async( @@ -226,7 +230,9 @@ class MCPService: .where(persistence_plugin.PluginSetting.workspace_uuid == workspace_uuid) ) if (mcp_count_result.scalar() or 0) + (plugin_count_result.scalar() or 0) >= max_extensions: - raise ValueError(f'Maximum number of extensions ({max_extensions}) reached') + raise ValueError( + t('Maximum number of {resource} ({limit}) reached', resource=t('extensions'), limit=max_extensions) + ) payload = dict(server_data) payload.pop('workspace_uuid', None) @@ -244,7 +250,7 @@ class MCPService: ) ) if existing_result.first() is not None: - raise ValueError(f'MCP server already exists: {server_name}') + raise ValueError(t('MCP server already exists: {name}', name=server_name)) await self.ap.persistence_mgr.execute_async(sqlalchemy.insert(persistence_mcp.MCPServer).values(payload)) created = await self._get_mcp_server_by_uuid_raw(execution_context, payload['uuid']) @@ -330,7 +336,7 @@ class MCPService: raise ValueError('MCP server name is required') duplicate = await self._get_mcp_server_by_name_raw(execution_context, payload['name']) if duplicate is not None and duplicate['uuid'] != server_uuid: - raise ValueError(f'MCP server already exists: {payload["name"]}') + raise ValueError(t('MCP server already exists: {name}', name=payload['name'])) effective_server = {**old_server, **payload} # Existing disabled rows remain readable/deletable. Switching away diff --git a/src/langbot/pkg/api/http/service/model.py b/src/langbot/pkg/api/http/service/model.py index 601d79d30..bfd20bfaa 100644 --- a/src/langbot/pkg/api/http/service/model.py +++ b/src/langbot/pkg/api/http/service/model.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + import uuid import sqlalchemy @@ -146,7 +148,13 @@ async def _validate_provider_supports( if not support_type: return if model_type not in support_type: - raise ValueError(f'Provider requester "{requester_name}" does not support {model_type} models') + raise ValueError( + t( + 'Provider {provider} does not support {model_type} models', + provider=requester_name, + model_type=model_type, + ) + ) async def _require_workspace_provider( diff --git a/src/langbot/pkg/api/http/service/monitoring.py b/src/langbot/pkg/api/http/service/monitoring.py index f9f924ebc..335d334c6 100644 --- a/src/langbot/pkg/api/http/service/monitoring.py +++ b/src/langbot/pkg/api/http/service/monitoring.py @@ -260,6 +260,9 @@ class MonitoringService(ExecutionDetailsMixin): A dict mapping table name to the number of deleted rows. """ workspace_uuid = self._require_write_context(context) + from ....cloud.plan_policy import workspace_history_retention_days + + retention_days = await workspace_history_retention_days(self.ap, workspace_uuid, retention_days) if retention_days < 1: raise ValueError('retention_days must be >= 1') if batch_size < 1: @@ -1690,9 +1693,14 @@ class MonitoringService(ExecutionDetailsMixin): workspace = require_workspace_uuid(context) active = await self.get_executions(context, statuses=['running', 'queued'], limit=100, include_summary=False) + # Execution timestamps are stored as UTC without a timezone. asyncpg + # rejects aware datetimes for these columns, even though SQLite accepts them. + recent_start = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) - datetime.timedelta( + seconds=30 + ) recent = await self.get_executions( context, - start_time=datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=30), + start_time=recent_start, limit=100, include_summary=False, ) diff --git a/src/langbot/pkg/api/http/service/pipeline.py b/src/langbot/pkg/api/http/service/pipeline.py index bdd24f3d7..22a1c86c0 100644 --- a/src/langbot/pkg/api/http/service/pipeline.py +++ b/src/langbot/pkg/api/http/service/pipeline.py @@ -173,7 +173,9 @@ class PipelineService: if 'config' in pipeline_data: RunnerConfigResolver.validate_pipeline_config(pipeline_data['config']) # Check limitation - limitation = self.ap.instance_config.data.get('system', {}).get('limitation', {}) + from .workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, workspace_uuid) max_pipelines = limitation.get('max_pipelines', -1) if max_pipelines >= 0: existing_pipelines = await self.get_pipelines(context) @@ -290,7 +292,9 @@ class PipelineService: """Copy a pipeline with all its configurations""" workspace_uuid = require_workspace_uuid(context) # Check limitation - limitation = self.ap.instance_config.data.get('system', {}).get('limitation', {}) + from .workspace_limits import workspace_limits + + limitation = await workspace_limits(self.ap, workspace_uuid) max_pipelines = limitation.get('max_pipelines', -1) if max_pipelines >= 0: existing_pipelines = await self.get_pipelines(context) diff --git a/src/langbot/pkg/api/http/service/user.py b/src/langbot/pkg/api/http/service/user.py index 5cd5766d0..60926178f 100644 --- a/src/langbot/pkg/api/http/service/user.py +++ b/src/langbot/pkg/api/http/service/user.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + import sqlalchemy import argon2 import jwt @@ -423,12 +425,12 @@ class UserService: user_obj = await self.get_user_by_email(user_email) if user_obj is None: - raise ValueError('用户不存在') + raise ValueError(t('Resource not found')) self._require_active_account(user_obj) # Check if this user has a local password set if not user_obj.password: - raise ValueError('请使用 LangBot 账号登录') + raise ValueError(t('Please sign in with your LangBot Account')) await self._verify_password(user_obj.password, password) diff --git a/src/langbot/pkg/api/http/service/workspace_limits.py b/src/langbot/pkg/api/http/service/workspace_limits.py new file mode 100644 index 000000000..dc41a2a2b --- /dev/null +++ b/src/langbot/pkg/api/http/service/workspace_limits.py @@ -0,0 +1,20 @@ +"""Resolve resource limits at the Workspace service boundary.""" + +from ....cloud.entitlements import EntitlementUnavailableError + +LIMIT_KEYS = { + 'max_bots': 'bots.max', + 'max_pipelines': 'pipelines.max', + 'max_extensions': 'plugins.max', + 'max_knowledge_bases': 'knowledge_bases.max', +} + + +async def workspace_limits(ap, workspace_uuid: str, *, minimum_revision: int = 0) -> dict[str, int]: + if getattr(getattr(ap, 'deployment', None), 'mode', None) != 'cloud': + return dict(ap.instance_config.data.get('system', {}).get('limitation', {})) + resolver = getattr(ap, 'entitlement_resolver', None) + if resolver is None: + raise EntitlementUnavailableError('Workspace entitlement resolver is unavailable') + snapshot = await resolver.resolve(workspace_uuid, minimum_revision=minimum_revision) + return {config_key: snapshot.limit(limit_key) for config_key, limit_key in LIMIT_KEYS.items()} diff --git a/src/langbot/pkg/api/mcp/server.py b/src/langbot/pkg/api/mcp/server.py index ae1686229..d7ad628d6 100644 --- a/src/langbot/pkg/api/mcp/server.py +++ b/src/langbot/pkg/api/mcp/server.py @@ -19,11 +19,14 @@ from __future__ import annotations import json import typing +import functools from mcp.server.fastmcp import FastMCP from ..http.authz import Permission, require_permission from .context import get_request_context +from ...i18n import language_scope +from ...i18n.workspace import get_workspace_language, set_workspace_language if typing.TYPE_CHECKING: from ...core import app as app_module @@ -78,6 +81,20 @@ class LangBotMCPServer: ap = self.ap mcp = self + @mcp.tool(description='Get the Workspace language used for backend messages and default bot replies.') + async def get_workspace_message_language() -> str: + context = _authorized(Permission.WORKSPACE_VIEW) + return _dump({'language': await get_workspace_language(ap, context.workspace_uuid, refresh=True)}) + + @mcp.tool( + description='Set the Workspace message language. Requires workspace.update; does not change personal UI language.' + ) + async def set_workspace_message_language( + language: typing.Literal['en_US', 'zh_Hans', 'zh_Hant', 'ja_JP', 'es_ES', 'ru_RU', 'th_TH', 'vi_VN'], + ) -> str: + context = _authorized(Permission.WORKSPACE_UPDATE) + return _dump({'language': await set_workspace_language(ap, context.workspace_uuid, language)}) + # ----- System (read-only) -------------------------------------- # @mcp.tool(description='Get basic LangBot system/runtime information (version, edition).') async def get_system_info() -> str: @@ -330,7 +347,7 @@ class LangBotMCPServer: @mcp.tool( description=( - 'Create a bot. `bot_data` is a JSON object matching the LangBot ' + 'Create a bot. Cloud Workspace platform restrictions also apply to this tool. `bot_data` is a JSON object matching the LangBot ' 'POST /api/v1/platform/bots body (e.g. name, adapter, config). ' 'Use event_bindings for exclusive Agent/Pipeline routes; plugin_processors is an array ' 'of {processor_uuid, enabled} subscriptions that automatically match Runner-declared events. ' @@ -577,7 +594,12 @@ class LangBotMCPServer: """Register a tool boundary before its authorization and service call.""" def register(fn): - observed = fn + @functools.wraps(fn) + async def observed(*args, **kwargs): + context = get_request_context() + with language_scope(await get_workspace_language(self.ap, context.workspace_uuid)): + return await fn(*args, **kwargs) + return self.mcp.tool(**options)(observed) return register diff --git a/src/langbot/pkg/cloud/entitlements.py b/src/langbot/pkg/cloud/entitlements.py index d6d34afd5..7787f7ae1 100644 --- a/src/langbot/pkg/cloud/entitlements.py +++ b/src/langbot/pkg/cloud/entitlements.py @@ -55,6 +55,10 @@ class EntitlementSnapshot(pydantic.BaseModel): # must continue to use generic ``features`` and ``limits`` exclusively. plan_name: str | None = pydantic.Field(default=None, min_length=1, max_length=128) + subscription_started_at: int | None = pydantic.Field(default=None, ge=0) + plan_revision: int | None = pydantic.Field(default=None, ge=1) + monthly_bonus_credits: int | None = pydantic.Field(default=None, ge=0) + @pydantic.field_validator('features') @classmethod def _validate_feature_names(cls, value: dict[str, bool]) -> dict[str, bool]: diff --git a/src/langbot/pkg/cloud/plan_policy.py b/src/langbot/pkg/cloud/plan_policy.py new file mode 100644 index 000000000..dc64b32f5 --- /dev/null +++ b/src/langbot/pkg/cloud/plan_policy.py @@ -0,0 +1,42 @@ +"""Workspace plan policies evaluated from trusted entitlement projections.""" + +from .entitlements import EntitlementFeatureUnavailableError, EntitlementUnavailableError +from ..platform.adapter_names import canonical_adapter_name + + +def platform_feature_names(adapter: str) -> set[str]: + canonical = canonical_adapter_name(adapter) + names = {adapter, canonical} + if adapter.lower() == 'line': + names.update({'line', 'LINE'}) + if canonical.endswith('-omni'): + names.add(canonical[:-5]) + names.add(canonical[:-5] + '-eba') + return {'platform.' + name for name in names} + + +async def workspace_entitlement(ap, workspace_uuid: str): + if getattr(getattr(ap, 'deployment', None), 'mode', None) != 'cloud': + return None + resolver = getattr(ap, 'entitlement_resolver', None) + if resolver is None: + raise EntitlementUnavailableError('Workspace entitlement resolver is unavailable') + return await resolver.resolve(workspace_uuid) + + +async def require_workspace_platform(ap, workspace_uuid: str, adapter: str) -> None: + snapshot = await workspace_entitlement(ap, workspace_uuid) + if snapshot is None: + return + for feature in platform_feature_names(adapter): + if snapshot.features.get(feature) is False: + raise EntitlementFeatureUnavailableError(feature, entitlement_revision=snapshot.entitlement_revision) + + +async def workspace_history_retention_days(ap, workspace_uuid: str, fallback: int = 30) -> int: + snapshot = await workspace_entitlement(ap, workspace_uuid) + if snapshot is None: + return fallback + # Old signed snapshots inherit the existing 30-day policy. Never interpret + # missing entitlement data as an unlimited retention policy. + return max(1, snapshot.limits.get('chat_history.retention_days', 30)) diff --git a/src/langbot/pkg/core/app.py b/src/langbot/pkg/core/app.py index 41aefe6f5..78c567da5 100644 --- a/src/langbot/pkg/core/app.py +++ b/src/langbot/pkg/core/app.py @@ -427,7 +427,10 @@ class Application: monitoring_cfg = self.instance_config.data.get('monitoring', {}) auto_cleanup_cfg = monitoring_cfg.get('auto_cleanup', {}) - monitoring_enabled = auto_cleanup_cfg.get('enabled', True) + monitoring_enabled = ( + auto_cleanup_cfg.get('enabled', True) + or getattr(getattr(self, 'deployment', None), 'mode', None) == 'cloud' + ) retention_days = self._get_positive_int_config( auto_cleanup_cfg.get('retention_days', 30), default=30, diff --git a/src/langbot/pkg/core/taskmgr.py b/src/langbot/pkg/core/taskmgr.py index 6c5df7b81..b3ae3d1c7 100644 --- a/src/langbot/pkg/core/taskmgr.py +++ b/src/langbot/pkg/core/taskmgr.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ..i18n import t + import asyncio import json import typing @@ -202,7 +204,7 @@ class TaskWrapper: """Return the stable task projection exposed to API-key callers.""" if self.task.cancelled(): status = 'cancelled' - error = {'type': 'task_cancelled', 'message': 'Task was cancelled'} + error = {'type': 'task_cancelled', 'message': t('Task was cancelled')} result = None elif not self.task.done(): status = 'running' @@ -212,7 +214,7 @@ class TaskWrapper: exception = self.assume_exception() if exception is not None: status = 'failed' - error = {'type': 'task_failed', 'message': 'Task execution failed'} + error = {'type': 'task_failed', 'message': t('Task execution failed')} result = None else: status = 'succeeded' diff --git a/src/langbot/pkg/i18n/__init__.py b/src/langbot/pkg/i18n/__init__.py new file mode 100644 index 000000000..113b4f909 --- /dev/null +++ b/src/langbot/pkg/i18n/__init__.py @@ -0,0 +1,197 @@ +"""Small, dependency-free catalog for LangBot-owned runtime messages. + +English message templates are the stable catalog IDs. Diagnostic text from +providers, plugins and validators is deliberately not translated. +""" + +from __future__ import annotations + +import contextlib +import contextvars +import json +from pathlib import Path + +DEFAULT_LANGUAGE = 'en_US' +SUPPORTED_LANGUAGES = ('en_US', 'zh_Hans', 'zh_Hant', 'ja_JP', 'es_ES', 'ru_RU', 'th_TH', 'vi_VN') +language = contextvars.ContextVar('langbot_message_language', default=DEFAULT_LANGUAGE) +_catalogs = { + locale: json.loads((Path(__file__).parent / 'locales' / f'{locale}.json').read_text(encoding='utf-8')) + for locale in SUPPORTED_LANGUAGES +} + +# Normalize existing API wording at the response boundary. Only exact owned +# messages are matched; validators and third-party diagnostics pass through. +_ALIASES = { + **{ + name: 'Resource not found' + for name in ( + 'bot not found', + 'model not found', + 'provider not found', + 'plugin not found', + 'Server not found', + 'Skill not found', + 'Pipeline not found', + 'pipeline not found', + 'knowledge base not found', + 'Knowledge base not found', + 'User not found', + 'Account not found', + 'agent not found', + 'API key not found', + 'Message not found', + 'Task not found', + 'Passkey not found', + 'Webhook not found', + 'Bot not found or not available', + 'Bot is unavailable', + 'WebSocket adapter not found', + 'adapter not found', + 'requester not found', + 'icon not found', + 'Session not found', + ) + }, + 'Unauthorized': 'Invalid authentication credentials', + 'No valid user token provided': 'Invalid authentication credentials', + 'No valid API key provided': 'Invalid authentication credentials', + 'Invalid username or password': 'Invalid authentication credentials', + 'Invalid TOTP code': 'Invalid TOTP or recovery code', + 'Too many attempts, try again later': 'Too many requests. Please try again later.', + 'The configured Agent runner is unavailable': 'Agent runner temporarily unavailable. Please try again.', + 'The configured Agent runner is not authorized': 'Agent runner not authorized for this pipeline.', + 'The Agent runner could not complete this test': 'Agent runner execution failed.', + 'Forbidden': 'Permission denied', + 'Member removal permission is required': 'Permission denied', + 'The Agent runner returned an invalid response': 'The Agent runner returned an invalid response.', + 'Invalid or expired state': 'Authorization failed. Please try signing in again.', + 'Space OAuth Workspace binding mismatch': 'Authorization failed. Please try signing in again.', + 'Space OAuth response is missing the Cloud Workspace binding': 'Authorization failed. Please try signing in again.', + 'Space launch requires Cloud mode': 'This feature is unavailable in this Workspace.', + 'An Account is required': 'Please sign in with your LangBot Account', + 'ChatGPT authorization requires an authorized workspace user': 'Permission denied', + 'ChatGPT authorization is busy. Please retry shortly.': 'Server is busy. Please try again later.', + 'ChatGPT authorization network error. Please retry.': 'Connection failed', + 'ChatGPT credential storage failed. Please retry.': 'Failed to save ChatGPT credentials. Please retry.', + 'ChatGPT Codex response was not completed': 'ChatGPT Codex response failed or was incomplete. Please retry.', + 'ChatGPT Codex stream ended before completion. Please retry.': 'ChatGPT Codex response failed or was incomplete. Please retry.', + 'Not permitted': 'Permission denied', + 'Unauthorized or session expired': 'Invalid authentication credentials', + 'TOTP is not enabled for that Account': 'TOTP is not enabled for this Account', + 'No pending TOTP enrolment for this Account': 'TOTP is not enabled for this Account', + 'Too many active credential exchanges': 'Server is busy. Please try again later.', + 'Timeout waiting for QR code': 'Request timed out', + 'Model availability is unavailable': 'This feature is unavailable in this Workspace.', + 'Survey not available': 'This feature is unavailable in this Workspace.', + **{ + message: 'Submission failed. Please try again.' + for message in ( + 'Failed to submit response', + 'Failed to submit feedback', + 'Failed to dismiss', + ) + }, + **{ + message: 'File size exceeds the limit.' + for message in ( + 'Image size exceeds 10MB limit.', + 'file size exceeds 10MB limit', + 'attachment too large', + ) + }, + **{ + message: 'Authorization failed. Please try signing in again.' + for message in ( + 'Space launch failed', + 'Space OAuth failed', + 'LangBot Account binding failed', + 'Failed to get access token from Space', + 'ChatGPT returned an incomplete authorization. Please sign in again.', + 'ChatGPT authorization was cancelled or replaced. Please retry.', + 'ChatGPT returned an invalid authorization response', + 'ChatGPT returned an invalid device code', + 'ChatGPT returned an invalid device code expiry', + 'ChatGPT device authorization failed. Please start again.', + 'ChatGPT returned an incomplete device authorization', + 'ChatGPT token exchange failed. Please start sign-in again.', + ) + }, +} + + +def normalize_language(value: str | None) -> str: + value = (value or '').replace('-', '_') + aliases = { + 'zh_CN': 'zh_Hans', + 'zh_TW': 'zh_Hant', + 'en': 'en_US', + 'ja': 'ja_JP', + 'es': 'es_ES', + 'ru': 'ru_RU', + 'th': 'th_TH', + 'vi': 'vi_VN', + } + value = aliases.get(value, value) + return value if value in SUPPORTED_LANGUAGES else DEFAULT_LANGUAGE + + +@contextlib.contextmanager +def language_scope(locale: str): + token = language.set(normalize_language(locale)) + try: + yield + finally: + language.reset(token) + + +def t(message: str, *, locale: str | None = None, **params) -> str: + selected = normalize_language(locale or language.get()) + # Preserve established English diagnostic wording and resource names. + # Aliases only share translations; they do not rewrite the source language. + key = _ALIASES.get(message, message) + text = message if selected == DEFAULT_LANGUAGE else _catalogs[selected].get(key, message) + return text.format(**params) if params else text + + +def error_text(code: int | str, message: str) -> str: + """Stable business codes take precedence over variable diagnostic wording.""" + if language.get() == DEFAULT_LANGUAGE: + return message + messages = { + 'permission_denied': 'Permission denied', + 'resource_not_found': 'Resource not found', + 'membership_not_found': 'Resource not found', + 'invalid_authentication': 'Invalid authentication credentials', + 'task_capacity_exceeded': 'Server is busy. Please try again later.', + 'blocking_work_capacity_exceeded': 'Server is busy. Please try again later.', + 'edition_limit': 'This feature is unavailable in this Workspace.', + 'entitlement_unavailable': 'This feature is unavailable in this Workspace.', + 'last_owner_required': 'The Workspace must retain an owner.', + 'already_a_member': 'This user is already a member.', + 'invitation_email_mismatch': 'The invitation email does not match your Account', + 'totp_invalid_code': 'Invalid TOTP or recovery code', + 'totp_challenge_invalid': 'Invalid TOTP or recovery code', + 'totp_already_enrolled': 'TOTP is already enabled for this Account', + 'totp_not_enrolled': 'TOTP is not enabled for this Account', + } + if code in ('invitation_invalid', 'invitation_expired', 'invitation_revoked', 'invitation_used'): + return t('Invalid or expired invitation') + return t(messages.get(code, message)) + + +def pipeline_notice(query, name: str, default: str, **params) -> str: + """Empty overrides inherit the Workspace language; user text stays literal. + + Only documented placeholders are substituted, so arbitrary braces in custom + messages cannot cause a formatting exception. + """ + config = query.pipeline_config.get('output', {}).get('misc', {}) + custom = config.get(name) + # This was the shipped default before language inheritance existed. + if name == 'failure-hint' and custom == 'Request failed.': + custom = None + if not isinstance(custom, str) or not custom.strip(): + return t(default, **params) + for key, value in params.items(): + custom = custom.replace('{' + key + '}', str(value)) + return custom diff --git a/src/langbot/pkg/i18n/adapters.py b/src/langbot/pkg/i18n/adapters.py new file mode 100644 index 000000000..899b57a19 --- /dev/null +++ b/src/langbot/pkg/i18n/adapters.py @@ -0,0 +1,31 @@ +"""Language boundaries for adapter-owned replies outside the Pipeline.""" + +import functools + +from . import DEFAULT_LANGUAGE, language_scope, t +from .workspace import _cache, get_workspace_language + + +def _owner(adapter): + logger = getattr(adapter, 'logger', None) + context = getattr(logger, 'execution_context', None) + workspace_uuid = getattr(context, 'workspace_uuid', None) + return getattr(logger, 'ap', None), workspace_uuid if isinstance(workspace_uuid, str) else None + + +def adapter_t(adapter, message: str, **params) -> str: + """Synchronous SDK callbacks use the bot's own cached language, never a peer's.""" + ap, workspace_uuid = _owner(adapter) + cached = _cache(ap).get(workspace_uuid) if ap is not None and workspace_uuid else None + return t(message, locale=cached[0] if cached else DEFAULT_LANGUAGE, **params) + + +def localized_adapter(method): + @functools.wraps(method) + async def wrapped(self, *args, **kwargs): + ap, workspace_uuid = _owner(self) + locale = await get_workspace_language(ap, workspace_uuid) if ap is not None else DEFAULT_LANGUAGE + with language_scope(locale): + return await method(self, *args, **kwargs) + + return wrapped diff --git a/src/langbot/pkg/i18n/locales/en_US.json b/src/langbot/pkg/i18n/locales/en_US.json new file mode 100644 index 000000000..dd07ff255 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/en_US.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "Request failed.", + "Too many requests. Please try again later.": "Too many requests. Please try again later.", + "Your message contains inappropriate content. Please revise it.": "Your message contains inappropriate content. Please revise it.", + "Content checking failed. Please contact the administrator.": "Content checking failed. Please contact the administrator.", + "Calling {tools}...": "Calling {tools}...", + "Agent runner not found: {runner}": "Agent runner not found: {runner}", + "Agent runner not authorized for this pipeline.": "Agent runner not authorized for this pipeline.", + "Agent runner temporarily unavailable. Please try again.": "Agent runner temporarily unavailable. Please try again.", + "Agent runner execution failed.": "Agent runner execution failed.", + "The Agent runner returned an invalid response.": "The Agent runner returned an invalid response.", + "Model request failed": "Model request failed", + "Context length exceeded": "Context length exceeded", + "Invalid request parameters": "Invalid request parameters", + "Invalid API key": "Invalid API key", + "Invalid model or endpoint": "Invalid model or endpoint", + "Rate limit exceeded or insufficient balance": "Rate limit exceeded or insufficient balance", + "Request timed out": "Request timed out", + "Connection failed": "Connection failed", + "API error": "API error", + "Unknown error": "Unknown error", + "Internal server error": "Internal server error", + "Resource not found": "Resource not found", + "Permission denied": "Permission denied", + "Invalid authentication credentials": "Invalid authentication credentials", + "MCP runtime failed": "MCP runtime failed", + "Task execution failed": "Task execution failed", + "Task was cancelled": "Task was cancelled", + "Maximum number of {resource} ({limit}) reached": "Maximum number of {resource} ({limit}) reached", + "extensions": "extensions", + "knowledge bases": "knowledge bases", + "MCP server already exists: {name}": "MCP server already exists: {name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models is managed by Cloud and cannot be modified", + "Please sign in with your LangBot Account": "Please sign in with your LangBot Account", + "Current password is incorrect": "Current password is incorrect", + "Invalid TOTP or recovery code": "Invalid TOTP or recovery code", + "No local password set, please set a password first": "No local password set, please set a password first", + "This LangBot Account is already bound to another user": "This LangBot Account is already bound to another user", + "Invalid recovery key": "Invalid recovery key", + "Done": "Done", + "Thank you for your feedback": "Thank you for your feedback", + "Failed to process feedback": "Failed to process feedback", + "Helpful": "Helpful", + "Not helpful": "Not helpful", + "Select an option": "Select an option", + "Enter a value": "Enter a value", + "Submit": "Submit", + "Submitted": "Submitted", + "Thinking": "Thinking", + "AI-generated": "AI-generated", + "AI-generated content. Refer to the cited sources for details.": "AI-generated content. Refer to the cited sources for details.", + "No bridges configured.": "No bridges configured.", + "Signing in to all bridges again...": "Signing in to all bridges again...", + "Bridge status:": "Bridge status:", + "Signed in ✓": "Signed in ✓", + "Not signed in ✗": "Not signed in ✗", + "None": "None", + "Bridge {bridge}: skipped (login command or DM room missing).": "Bridge {bridge}: skipped (login command or DM room missing).", + "Bridge {bridge}: sending {command}...": "Bridge {bridge}: sending {command}...", + "Bridge {bridge}: sign-out failed.": "Bridge {bridge}: sign-out failed.", + "Bridge {bridge}: sign-in started.": "Bridge {bridge}: sign-in started.", + "Slack authorization completed. Return to LangBot to finish setup.": "Slack authorization completed. Return to LangBot to finish setup.", + "Slack authorization failed or expired. Return to LangBot for details.": "Slack authorization failed or expired. Return to LangBot for details.", + "TOTP is already enabled for this Account": "TOTP is already enabled for this Account", + "TOTP is not enabled for this Account": "TOTP is not enabled for this Account", + "Invalid or expired passkey challenge": "Invalid or expired passkey challenge", + "Passkey credential not recognized": "Passkey credential not recognized", + "Account is disabled": "Account is disabled", + "Modifying login info is disabled": "Modifying login info is disabled", + "Invalid GitHub repository URL": "Invalid GitHub repository URL", + "Server is busy. Please try again later.": "Server is busy. Please try again later.", + "This feature is unavailable in this Workspace.": "This feature is unavailable in this Workspace.", + "The Workspace must retain an owner.": "The Workspace must retain an owner.", + "Invalid or expired invitation": "Invalid or expired invitation", + "This user is already a member.": "This user is already a member.", + "Voice connection failed": "Voice connection failed", + "User is not in the voice channel": "User is not in the voice channel", + "Voice service is unavailable": "Voice service is unavailable", + "Submission failed. Please try again.": "Submission failed. Please try again.", + "File size exceeds the limit.": "File size exceeds the limit.", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "File size exceeds 10MB limit. Please split large files into smaller parts.", + "Authorization failed. Please try signing in again.": "Authorization failed. Please try signing in again.", + "Bind the LangBot Account with the same email as this local Account": "Bind the LangBot Account with the same email as this local Account", + "Only local accounts can bind to Space": "Only local accounts can bind to Space", + "System already initialized": "System already initialized", + "System not initialized": "System not initialized", + "Password login is disabled on LangBot Cloud": "Password login is disabled on LangBot Cloud", + "This edition supports one Workspace per instance": "This edition supports one Workspace per instance", + "Cloud Workspaces are created by the SaaS control plane": "Cloud Workspaces are created by the SaaS control plane", + "Login with your LangBot Account to accept this invitation": "Login with your LangBot Account to accept this invitation", + "RAG migration is not needed": "RAG migration is not needed", + "New Agent": "New Agent", + "New Pipeline": "New Pipeline", + "Provider {provider} does not support {model_type} models": "Provider {provider} does not support {model_type} models", + "Invalid JSON format": "Invalid JSON format", + "ChatGPT sign-in required. Open this provider and sign in again.": "ChatGPT sign-in required. Open this provider and sign in again.", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT denied this request. Check subscription and workspace permissions.", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT rejected the model or request. Check the selected model and request settings.", + "ChatGPT Codex upstream request failed. Please retry later.": "ChatGPT Codex upstream request failed. Please retry later.", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "ChatGPT subscription usage limit reached. Please retry later or check your plan.", + "ChatGPT Codex response failed or was incomplete. Please retry.": "ChatGPT Codex response failed or was incomplete. Please retry.", + "ChatGPT token refresh temporarily failed. Please retry.": "ChatGPT token refresh temporarily failed. Please retry.", + "A second factor is required": "A second factor is required", + "Sign in or provide registration details to accept this invitation": "Sign in or provide registration details to accept this invitation", + "Sign out before creating the invited local Account": "Sign out before creating the invited local Account", + "Turnstile verification failed": "Turnstile verification failed", + "The invitation email does not match your Account": "The invitation email does not match your Account", + "Failed to save ChatGPT credentials. Please retry.": "Failed to save ChatGPT credentials. Please retry.", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.", + "Option {number}": "Option {number}", + "Confirmation needed": "Confirmation needed", + "Session reset successfully": "Session reset successfully" +} diff --git a/src/langbot/pkg/i18n/locales/es_ES.json b/src/langbot/pkg/i18n/locales/es_ES.json new file mode 100644 index 000000000..116aa09a8 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/es_ES.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "La solicitud ha fallado.", + "Too many requests. Please try again later.": "Demasiadas solicitudes. Inténtalo más tarde.", + "Your message contains inappropriate content. Please revise it.": "Tu mensaje contiene contenido inapropiado. Modifícalo.", + "Content checking failed. Please contact the administrator.": "No se pudo verificar el contenido. Contacta con el administrador.", + "Calling {tools}...": "Llamando a {tools}…", + "Agent runner not found: {runner}": "No se encontró el ejecutor del agente: {runner}", + "Agent runner not authorized for this pipeline.": "Este flujo no tiene autorización para usar el ejecutor del agente.", + "Agent runner temporarily unavailable. Please try again.": "El ejecutor del agente no está disponible temporalmente. Reinténtalo.", + "Agent runner execution failed.": "La ejecución del agente ha fallado.", + "The Agent runner returned an invalid response.": "El ejecutor del agente devolvió una respuesta no válida.", + "Model request failed": "Error en la solicitud al modelo", + "Context length exceeded": "Se superó el límite de contexto", + "Invalid request parameters": "Parámetros de solicitud no válidos", + "Invalid API key": "Clave API no válida", + "Invalid model or endpoint": "Modelo o endpoint no válido", + "Rate limit exceeded or insufficient balance": "Límite de solicitudes excedido o saldo insuficiente", + "Request timed out": "La solicitud agotó el tiempo de espera", + "Connection failed": "Error de conexión", + "API error": "Error de API", + "Unknown error": "Error desconocido", + "Internal server error": "Error interno del servidor", + "Resource not found": "Recurso no encontrado", + "Permission denied": "No tienes permiso para realizar esta acción", + "Invalid authentication credentials": "Error de autenticación. Vuelve a iniciar sesión", + "MCP runtime failed": "Error de ejecución de MCP", + "Task execution failed": "La tarea ha fallado", + "Task was cancelled": "La tarea se ha cancelado", + "Maximum number of {resource} ({limit}) reached": "Se alcanzó el máximo de {resource} ({limit})", + "extensions": "extensiones", + "knowledge bases": "bases de conocimiento", + "MCP server already exists: {name}": "El servidor MCP ya existe: {name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models está gestionado por Cloud y no se puede modificar", + "Please sign in with your LangBot Account": "Inicia sesión con tu cuenta de LangBot", + "Current password is incorrect": "La contraseña actual es incorrecta", + "Invalid TOTP or recovery code": "Código TOTP o de recuperación no válido", + "No local password set, please set a password first": "No hay contraseña local. Configura una primero", + "This LangBot Account is already bound to another user": "Esta cuenta de LangBot ya está vinculada a otro usuario", + "Invalid recovery key": "Clave de recuperación no válida", + "Done": "Hecho", + "Thank you for your feedback": "Gracias por tus comentarios", + "Failed to process feedback": "No se pudieron procesar los comentarios", + "Helpful": "Útil", + "Not helpful": "No es útil", + "Select an option": "Selecciona una opción", + "Enter a value": "Introduce un valor", + "Submit": "Enviar", + "Submitted": "Enviado", + "Thinking": "Razonamiento", + "AI-generated": "Generado por IA", + "AI-generated content. Refer to the cited sources for details.": "Contenido generado por IA. Consulta las fuentes citadas para más detalles.", + "No bridges configured.": "No hay puentes configurados.", + "Signing in to all bridges again...": "Iniciando sesión de nuevo en todos los puentes…", + "Bridge status:": "Estado de los puentes:", + "Signed in ✓": "Sesión iniciada ✓", + "Not signed in ✗": "Sin sesión ✗", + "None": "Ninguno", + "Bridge {bridge}: skipped (login command or DM room missing).": "Puente {bridge}: omitido (falta comando de inicio de sesión o sala DM).", + "Bridge {bridge}: sending {command}...": "Puente {bridge}: enviando {command}…", + "Bridge {bridge}: sign-out failed.": "Puente {bridge}: no se pudo cerrar sesión.", + "Bridge {bridge}: sign-in started.": "Puente {bridge}: inicio de sesión en curso.", + "Slack authorization completed. Return to LangBot to finish setup.": "Autorización de Slack completada. Vuelve a LangBot para terminar la configuración.", + "Slack authorization failed or expired. Return to LangBot for details.": "La autorización de Slack falló o caducó. Consulta los detalles en LangBot.", + "TOTP is already enabled for this Account": "Esta cuenta ya tiene TOTP activado", + "TOTP is not enabled for this Account": "Esta cuenta no tiene TOTP activado", + "Invalid or expired passkey challenge": "El desafío de clave de acceso no es válido o ha caducado", + "Passkey credential not recognized": "No se reconoce la clave de acceso", + "Account is disabled": "La cuenta está desactivada", + "Modifying login info is disabled": "No se permite modificar los datos de inicio de sesión", + "Invalid GitHub repository URL": "URL del repositorio GitHub no válida", + "Server is busy. Please try again later.": "El servidor está ocupado. Inténtalo más tarde.", + "This feature is unavailable in this Workspace.": "Esta función no está disponible en este espacio de trabajo.", + "The Workspace must retain an owner.": "El espacio de trabajo debe conservar un propietario.", + "Invalid or expired invitation": "Invitación no válida o caducada", + "This user is already a member.": "Este usuario ya es miembro.", + "Voice connection failed": "Error de conexión de voz", + "User is not in the voice channel": "El usuario no está en el canal de voz", + "Voice service is unavailable": "El servicio de voz no está disponible", + "Submission failed. Please try again.": "El envío ha fallado. Reinténtalo.", + "File size exceeds the limit.": "El archivo supera el tamaño permitido.", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "El archivo supera los 10 MB. Divídelo en partes más pequeñas.", + "Authorization failed. Please try signing in again.": "La autorización ha fallado. Vuelve a iniciar sesión.", + "Bind the LangBot Account with the same email as this local Account": "Vincula una cuenta de LangBot con el mismo correo que esta cuenta local", + "Only local accounts can bind to Space": "Solo las cuentas locales pueden vincularse a Space", + "System already initialized": "El sistema ya está inicializado", + "System not initialized": "El sistema no está inicializado", + "Password login is disabled on LangBot Cloud": "El acceso con contraseña está desactivado en LangBot Cloud", + "This edition supports one Workspace per instance": "Esta edición admite un espacio de trabajo por instancia", + "Cloud Workspaces are created by the SaaS control plane": "Los espacios de trabajo Cloud se crean desde el panel SaaS", + "Login with your LangBot Account to accept this invitation": "Inicia sesión con tu cuenta de LangBot para aceptar la invitación", + "RAG migration is not needed": "No es necesaria la migración de RAG", + "New Agent": "Nuevo agente", + "New Pipeline": "Nuevo flujo", + "Provider {provider} does not support {model_type} models": "El proveedor {provider} no admite modelos {model_type}", + "Invalid JSON format": "Formato JSON no válido", + "ChatGPT sign-in required. Open this provider and sign in again.": "Debes iniciar sesión en ChatGPT. Abre este proveedor y vuelve a iniciar sesión.", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "ChatGPT limitó la solicitud por frecuencia o uso. Inténtalo más tarde o revisa tu plan.", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT rechazó la solicitud. Revisa la suscripción y los permisos del espacio de trabajo.", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT rechazó el modelo o la solicitud. Revisa el modelo seleccionado y la configuración.", + "ChatGPT Codex upstream request failed. Please retry later.": "Falló la solicitud a ChatGPT Codex. Inténtalo más tarde.", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "Se alcanzó el límite de uso de tu suscripción de ChatGPT. Inténtalo más tarde o revisa tu plan.", + "ChatGPT Codex response failed or was incomplete. Please retry.": "La respuesta de ChatGPT Codex falló o está incompleta. Inténtalo de nuevo.", + "ChatGPT token refresh temporarily failed. Please retry.": "No se pudo renovar el token de ChatGPT temporalmente. Inténtalo de nuevo.", + "A second factor is required": "Se requiere un segundo factor de autenticación", + "Sign in or provide registration details to accept this invitation": "Inicia sesión o proporciona los datos de registro para aceptar esta invitación", + "Sign out before creating the invited local Account": "Cierra sesión antes de crear la cuenta local invitada", + "Turnstile verification failed": "La verificación de Turnstile falló. Inténtalo de nuevo", + "The invitation email does not match your Account": "El correo de la invitación no coincide con tu cuenta", + "Failed to save ChatGPT credentials. Please retry.": "No se pudieron guardar las credenciales de ChatGPT. Inténtalo de nuevo.", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "No se pudo iniciar el acceso por dispositivo. Activa el inicio de sesión con código de dispositivo en la configuración de ChatGPT.", + "Option {number}": "Opción {number}", + "Confirmation needed": "Se requiere confirmación", + "Session reset successfully": "Sesión restablecida" +} diff --git a/src/langbot/pkg/i18n/locales/ja_JP.json b/src/langbot/pkg/i18n/locales/ja_JP.json new file mode 100644 index 000000000..292bb1b56 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/ja_JP.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "リクエストに失敗しました。", + "Too many requests. Please try again later.": "リクエストが多すぎます。しばらくしてから再試行してください。", + "Your message contains inappropriate content. Please revise it.": "不適切な内容が含まれています。メッセージを修正してください。", + "Content checking failed. Please contact the administrator.": "コンテンツの確認に失敗しました。管理者にお問い合わせください。", + "Calling {tools}...": "{tools} を呼び出しています…", + "Agent runner not found: {runner}": "Agent ランナーが見つかりません:{runner}", + "Agent runner not authorized for this pipeline.": "このパイプラインには Agent ランナーの使用権限がありません。", + "Agent runner temporarily unavailable. Please try again.": "Agent ランナーは一時的に利用できません。再試行してください。", + "Agent runner execution failed.": "Agent の実行に失敗しました。", + "The Agent runner returned an invalid response.": "Agent ランナーが無効な応答を返しました。", + "Model request failed": "モデルへのリクエストに失敗しました", + "Context length exceeded": "コンテキスト長の上限を超えました", + "Invalid request parameters": "リクエストのパラメータが無効です", + "Invalid API key": "API キーが無効です", + "Invalid model or endpoint": "モデルまたはエンドポイントが無効です", + "Rate limit exceeded or insufficient balance": "リクエスト制限を超えたか、残高が不足しています", + "Request timed out": "リクエストがタイムアウトしました", + "Connection failed": "接続に失敗しました", + "API error": "API エラー", + "Unknown error": "不明なエラー", + "Internal server error": "サーバー内部エラー", + "Resource not found": "リソースが見つかりません", + "Permission denied": "この操作の権限がありません", + "Invalid authentication credentials": "認証に失敗しました。再度ログインしてください", + "MCP runtime failed": "MCP の実行に失敗しました", + "Task execution failed": "タスクの実行に失敗しました", + "Task was cancelled": "タスクがキャンセルされました", + "Maximum number of {resource} ({limit}) reached": "{resource}の上限数({limit})に達しました", + "extensions": "拡張機能", + "knowledge bases": "ナレッジベース", + "MCP server already exists: {name}": "MCP サーバーは既に存在します:{name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models はクラウドで管理されているため変更できません", + "Please sign in with your LangBot Account": "LangBot アカウントでログインしてください", + "Current password is incorrect": "現在のパスワードが正しくありません", + "Invalid TOTP or recovery code": "認証コードまたはリカバリーコードが無効です", + "No local password set, please set a password first": "ローカルパスワードが未設定です。先に設定してください", + "This LangBot Account is already bound to another user": "この LangBot アカウントは別のユーザーに連携されています", + "Invalid recovery key": "リカバリーキーが無効です", + "Done": "完了しました", + "Thank you for your feedback": "フィードバックありがとうございます", + "Failed to process feedback": "フィードバックの処理に失敗しました", + "Helpful": "役に立った", + "Not helpful": "役に立たなかった", + "Select an option": "選択してください", + "Enter a value": "入力してください", + "Submit": "送信", + "Submitted": "送信済み", + "Thinking": "思考過程", + "AI-generated": "AI による生成コンテンツ", + "AI-generated content. Refer to the cited sources for details.": "AI が生成した内容です。詳細は引用元を参照してください。", + "No bridges configured.": "ブリッジが設定されていません。", + "Signing in to all bridges again...": "すべてのブリッジに再ログインしています…", + "Bridge status:": "ブリッジの状態:", + "Signed in ✓": "ログイン済み ✓", + "Not signed in ✗": "未ログイン ✗", + "None": "なし", + "Bridge {bridge}: skipped (login command or DM room missing).": "ブリッジ {bridge}:スキップしました(ログインコマンドまたは DM ルームがありません)。", + "Bridge {bridge}: sending {command}...": "ブリッジ {bridge}:{command} を送信中…", + "Bridge {bridge}: sign-out failed.": "ブリッジ {bridge}:ログアウトに失敗しました。", + "Bridge {bridge}: sign-in started.": "ブリッジ {bridge}:ログインを開始しました。", + "Slack authorization completed. Return to LangBot to finish setup.": "Slack の認証が完了しました。LangBot に戻って設定を完了してください。", + "Slack authorization failed or expired. Return to LangBot for details.": "Slack の認証に失敗したか期限切れです。詳細は LangBot で確認してください。", + "TOTP is already enabled for this Account": "このアカウントでは二段階認証が有効です", + "TOTP is not enabled for this Account": "このアカウントでは二段階認証が無効です", + "Invalid or expired passkey challenge": "パスキーの認証要求が無効または期限切れです", + "Passkey credential not recognized": "このパスキーは認識できません", + "Account is disabled": "アカウントは無効です", + "Modifying login info is disabled": "ログイン情報の変更は無効です", + "Invalid GitHub repository URL": "GitHub リポジトリの URL が無効です", + "Server is busy. Please try again later.": "サーバーが混雑しています。後で再試行してください。", + "This feature is unavailable in this Workspace.": "このワークスペースではこの機能を利用できません。", + "The Workspace must retain an owner.": "ワークスペースにはオーナーが必要です。", + "Invalid or expired invitation": "招待が無効または期限切れです", + "This user is already a member.": "このユーザーは既にメンバーです。", + "Voice connection failed": "音声接続に失敗しました", + "User is not in the voice channel": "ユーザーは音声チャンネルに参加していません", + "Voice service is unavailable": "音声サービスを利用できません", + "Submission failed. Please try again.": "送信に失敗しました。再試行してください。", + "File size exceeds the limit.": "ファイルサイズが上限を超えています。", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "ファイルが 10MB を超えています。分割してアップロードしてください。", + "Authorization failed. Please try signing in again.": "認証に失敗しました。再度ログインしてください。", + "Bind the LangBot Account with the same email as this local Account": "このローカルアカウントと同じメールアドレスの LangBot アカウントを連携してください", + "Only local accounts can bind to Space": "Space と連携できるのはローカルアカウントのみです", + "System already initialized": "システムは初期化済みです", + "System not initialized": "システムが初期化されていません", + "Password login is disabled on LangBot Cloud": "LangBot Cloud ではパスワードログインは無効です", + "This edition supports one Workspace per instance": "このエディションではインスタンスごとにワークスペースは1つです", + "Cloud Workspaces are created by the SaaS control plane": "クラウドのワークスペースは SaaS 管理画面で作成します", + "Login with your LangBot Account to accept this invitation": "招待を承諾するには LangBot アカウントでログインしてください", + "RAG migration is not needed": "RAG の移行は不要です", + "New Agent": "新しい Agent", + "New Pipeline": "新しいパイプライン", + "Provider {provider} does not support {model_type} models": "プロバイダー {provider} は {model_type} モデルに対応していません", + "Invalid JSON format": "JSON 形式が無効です", + "ChatGPT sign-in required. Open this provider and sign in again.": "ChatGPT へのログインが必要です。このプロバイダーを開いて再ログインしてください。", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "ChatGPT のリクエストが制限されました(頻度または使用量)。後で再試行するか、プランを確認してください。", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT がリクエストを拒否しました。サブスクリプションとワークスペースの権限を確認してください。", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT がモデルまたはリクエストを拒否しました。選択したモデルとリクエスト設定を確認してください。", + "ChatGPT Codex upstream request failed. Please retry later.": "ChatGPT Codex の上流リクエストに失敗しました。後で再試行してください。", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "ChatGPT のサブスクリプション使用量が上限に達しました。後で再試行するか、プランを確認してください。", + "ChatGPT Codex response failed or was incomplete. Please retry.": "ChatGPT Codex の応答に失敗したか、応答が不完全です。再試行してください。", + "ChatGPT token refresh temporarily failed. Please retry.": "ChatGPT トークンの更新に一時的に失敗しました。再試行してください。", + "A second factor is required": "二要素認証が必要です", + "Sign in or provide registration details to accept this invitation": "招待を承諾するにはログインするか、登録情報を入力してください", + "Sign out before creating the invited local Account": "招待されたローカルアカウントを作成する前にログアウトしてください", + "Turnstile verification failed": "人間確認に失敗しました。再試行してください", + "The invitation email does not match your Account": "招待のメールアドレスがアカウントと一致しません", + "Failed to save ChatGPT credentials. Please retry.": "ChatGPT 認証情報の保存に失敗しました。再試行してください。", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "ChatGPT のデバイスログインを開始できません。ChatGPT の設定でデバイスコードログインを有効にしてください。", + "Option {number}": "選択肢 {number}", + "Confirmation needed": "確認が必要です", + "Session reset successfully": "セッションをリセットしました" +} diff --git a/src/langbot/pkg/i18n/locales/ru_RU.json b/src/langbot/pkg/i18n/locales/ru_RU.json new file mode 100644 index 000000000..ed9529018 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/ru_RU.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "Запрос не выполнен.", + "Too many requests. Please try again later.": "Слишком много запросов. Повторите позже.", + "Your message contains inappropriate content. Please revise it.": "Сообщение содержит недопустимый контент. Измените его.", + "Content checking failed. Please contact the administrator.": "Ошибка проверки содержимого. Обратитесь к администратору.", + "Calling {tools}...": "Вызов {tools}…", + "Agent runner not found: {runner}": "Исполнитель агента не найден: {runner}", + "Agent runner not authorized for this pipeline.": "У конвейера нет разрешения на использование исполнителя агента.", + "Agent runner temporarily unavailable. Please try again.": "Исполнитель агента временно недоступен. Повторите попытку.", + "Agent runner execution failed.": "Ошибка выполнения агента.", + "The Agent runner returned an invalid response.": "Исполнитель агента вернул некорректный ответ.", + "Model request failed": "Ошибка запроса к модели", + "Context length exceeded": "Превышена длина контекста", + "Invalid request parameters": "Некорректные параметры запроса", + "Invalid API key": "Недействительный API-ключ", + "Invalid model or endpoint": "Некорректная модель или адрес API", + "Rate limit exceeded or insufficient balance": "Превышен лимит запросов или недостаточно средств", + "Request timed out": "Время ожидания запроса истекло", + "Connection failed": "Ошибка подключения", + "API error": "Ошибка API", + "Unknown error": "Неизвестная ошибка", + "Internal server error": "Внутренняя ошибка сервера", + "Resource not found": "Ресурс не найден", + "Permission denied": "Нет разрешения на это действие", + "Invalid authentication credentials": "Ошибка аутентификации. Войдите снова", + "MCP runtime failed": "Ошибка выполнения MCP", + "Task execution failed": "Ошибка выполнения задачи", + "Task was cancelled": "Задача отменена", + "Maximum number of {resource} ({limit}) reached": "Достигнуто максимальное число {resource} ({limit})", + "extensions": "расширений", + "knowledge bases": "баз знаний", + "MCP server already exists: {name}": "Сервер MCP уже существует: {name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models управляется облаком и не может быть изменён", + "Please sign in with your LangBot Account": "Войдите с учётной записью LangBot", + "Current password is incorrect": "Текущий пароль неверен", + "Invalid TOTP or recovery code": "Неверный код TOTP или восстановления", + "No local password set, please set a password first": "Локальный пароль не задан. Сначала задайте пароль", + "This LangBot Account is already bound to another user": "Эта учётная запись LangBot уже связана с другим пользователем", + "Invalid recovery key": "Недействительный ключ восстановления", + "Done": "Готово", + "Thank you for your feedback": "Спасибо за отзыв", + "Failed to process feedback": "Не удалось обработать отзыв", + "Helpful": "Полезно", + "Not helpful": "Не полезно", + "Select an option": "Выберите вариант", + "Enter a value": "Введите значение", + "Submit": "Отправить", + "Submitted": "Отправлено", + "Thinking": "Ход рассуждений", + "AI-generated": "Создано ИИ", + "AI-generated content. Refer to the cited sources for details.": "Контент создан ИИ. Подробности смотрите в указанных источниках.", + "No bridges configured.": "Мосты не настроены.", + "Signing in to all bridges again...": "Повторный вход во все мосты…", + "Bridge status:": "Состояние мостов:", + "Signed in ✓": "Вход выполнен ✓", + "Not signed in ✗": "Вход не выполнен ✗", + "None": "Нет", + "Bridge {bridge}: skipped (login command or DM room missing).": "Мост {bridge}: пропущен (нет команды входа или комнаты DM).", + "Bridge {bridge}: sending {command}...": "Мост {bridge}: отправка {command}…", + "Bridge {bridge}: sign-out failed.": "Мост {bridge}: ошибка выхода.", + "Bridge {bridge}: sign-in started.": "Мост {bridge}: вход начат.", + "Slack authorization completed. Return to LangBot to finish setup.": "Авторизация Slack завершена. Вернитесь в LangBot для завершения настройки.", + "Slack authorization failed or expired. Return to LangBot for details.": "Авторизация Slack не удалась или истекла. Подробности в LangBot.", + "TOTP is already enabled for this Account": "Для этой учётной записи TOTP уже включён", + "TOTP is not enabled for this Account": "Для этой учётной записи TOTP не включён", + "Invalid or expired passkey challenge": "Запрос проверки ключа доступа недействителен или истёк", + "Passkey credential not recognized": "Ключ доступа не распознан", + "Account is disabled": "Учётная запись отключена", + "Modifying login info is disabled": "Изменение данных входа отключено", + "Invalid GitHub repository URL": "Некорректный URL репозитория GitHub", + "Server is busy. Please try again later.": "Сервер занят. Повторите позже.", + "This feature is unavailable in this Workspace.": "Эта функция недоступна в данном рабочем пространстве.", + "The Workspace must retain an owner.": "У рабочего пространства должен остаться владелец.", + "Invalid or expired invitation": "Приглашение недействительно или истекло", + "This user is already a member.": "Этот пользователь уже является участником.", + "Voice connection failed": "Ошибка голосового соединения", + "User is not in the voice channel": "Пользователь не в голосовом канале", + "Voice service is unavailable": "Голосовая служба недоступна", + "Submission failed. Please try again.": "Не удалось отправить. Повторите попытку.", + "File size exceeds the limit.": "Размер файла превышает ограничение.", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "Размер файла превышает 10 МБ. Разделите его на части.", + "Authorization failed. Please try signing in again.": "Авторизация не удалась. Войдите снова.", + "Bind the LangBot Account with the same email as this local Account": "Свяжите учётную запись LangBot с тем же адресом почты, что и локальная", + "Only local accounts can bind to Space": "К Space можно привязать только локальные учётные записи", + "System already initialized": "Система уже инициализирована", + "System not initialized": "Система не инициализирована", + "Password login is disabled on LangBot Cloud": "В LangBot Cloud вход по паролю отключён", + "This edition supports one Workspace per instance": "Эта редакция поддерживает одно рабочее пространство на экземпляр", + "Cloud Workspaces are created by the SaaS control plane": "Облачные рабочие пространства создаются в панели SaaS", + "Login with your LangBot Account to accept this invitation": "Войдите в LangBot, чтобы принять приглашение", + "RAG migration is not needed": "Миграция RAG не требуется", + "New Agent": "Новый агент", + "New Pipeline": "Новый конвейер", + "Provider {provider} does not support {model_type} models": "Провайдер {provider} не поддерживает модели {model_type}", + "Invalid JSON format": "Некорректный формат JSON", + "ChatGPT sign-in required. Open this provider and sign in again.": "Требуется вход в ChatGPT. Откройте этого провайдера и войдите снова.", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "Запрос ChatGPT ограничен по частоте или использованию. Повторите позже или проверьте тариф.", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT отклонил запрос. Проверьте подписку и права рабочего пространства.", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT отклонил модель или запрос. Проверьте выбранную модель и настройки запроса.", + "ChatGPT Codex upstream request failed. Please retry later.": "Ошибка запроса к ChatGPT Codex. Повторите позже.", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "Достигнут лимит использования подписки ChatGPT. Повторите позже или проверьте тариф.", + "ChatGPT Codex response failed or was incomplete. Please retry.": "Ошибка или неполный ответ ChatGPT Codex. Повторите запрос.", + "ChatGPT token refresh temporarily failed. Please retry.": "Временная ошибка обновления токена ChatGPT. Повторите попытку.", + "A second factor is required": "Требуется второй фактор аутентификации", + "Sign in or provide registration details to accept this invitation": "Войдите или укажите данные регистрации, чтобы принять приглашение", + "Sign out before creating the invited local Account": "Выйдите перед созданием приглашённой локальной учётной записи", + "Turnstile verification failed": "Проверка Turnstile не пройдена. Повторите попытку", + "The invitation email does not match your Account": "Адрес приглашения не совпадает с вашей учётной записью", + "Failed to save ChatGPT credentials. Please retry.": "Не удалось сохранить учётные данные ChatGPT. Повторите попытку.", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "Не удалось начать вход с устройства. Включите вход по коду устройства в настройках ChatGPT.", + "Option {number}": "Вариант {number}", + "Confirmation needed": "Требуется подтверждение", + "Session reset successfully": "Сессия сброшена" +} diff --git a/src/langbot/pkg/i18n/locales/th_TH.json b/src/langbot/pkg/i18n/locales/th_TH.json new file mode 100644 index 000000000..ff40282cd --- /dev/null +++ b/src/langbot/pkg/i18n/locales/th_TH.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "คำขอล้มเหลว", + "Too many requests. Please try again later.": "มีคำขอมากเกินไป โปรดลองอีกครั้งภายหลัง", + "Your message contains inappropriate content. Please revise it.": "ข้อความมีเนื้อหาไม่เหมาะสม โปรดแก้ไข", + "Content checking failed. Please contact the administrator.": "ตรวจสอบเนื้อหาไม่สำเร็จ โปรดติดต่อผู้ดูแลระบบ", + "Calling {tools}...": "กำลังเรียกใช้ {tools}…", + "Agent runner not found: {runner}": "ไม่พบตัวรัน Agent: {runner}", + "Agent runner not authorized for this pipeline.": "ไปป์ไลน์นี้ไม่ได้รับอนุญาตให้ใช้ตัวรัน Agent", + "Agent runner temporarily unavailable. Please try again.": "ตัวรัน Agent ไม่พร้อมใช้งานชั่วคราว โปรดลองอีกครั้ง", + "Agent runner execution failed.": "การทำงานของ Agent ล้มเหลว", + "The Agent runner returned an invalid response.": "ตัวรัน Agent ส่งการตอบกลับที่ไม่ถูกต้อง", + "Model request failed": "คำขอไปยังโมเดลล้มเหลว", + "Context length exceeded": "ความยาวบริบทเกินขีดจำกัด", + "Invalid request parameters": "พารามิเตอร์คำขอไม่ถูกต้อง", + "Invalid API key": "คีย์ API ไม่ถูกต้อง", + "Invalid model or endpoint": "โมเดลหรือจุดเชื่อมต่อไม่ถูกต้อง", + "Rate limit exceeded or insufficient balance": "เกินขีดจำกัดคำขอหรือยอดเงินไม่เพียงพอ", + "Request timed out": "คำขอหมดเวลา", + "Connection failed": "การเชื่อมต่อล้มเหลว", + "API error": "ข้อผิดพลาด API", + "Unknown error": "ข้อผิดพลาดที่ไม่ทราบสาเหตุ", + "Internal server error": "ข้อผิดพลาดภายในเซิร์ฟเวอร์", + "Resource not found": "ไม่พบทรัพยากร", + "Permission denied": "ไม่มีสิทธิ์ดำเนินการนี้", + "Invalid authentication credentials": "ยืนยันตัวตนไม่สำเร็จ โปรดเข้าสู่ระบบอีกครั้ง", + "MCP runtime failed": "การทำงานของ MCP ล้มเหลว", + "Task execution failed": "การทำงานของงานล้มเหลว", + "Task was cancelled": "งานถูกยกเลิกแล้ว", + "Maximum number of {resource} ({limit}) reached": "ถึงจำนวนสูงสุดของ{resource} ({limit}) แล้ว", + "extensions": "ส่วนขยาย", + "knowledge bases": "ฐานความรู้", + "MCP server already exists: {name}": "มีเซิร์ฟเวอร์ MCP อยู่แล้ว: {name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models จัดการโดย Cloud และไม่สามารถแก้ไขได้", + "Please sign in with your LangBot Account": "โปรดเข้าสู่ระบบด้วยบัญชี LangBot", + "Current password is incorrect": "รหัสผ่านปัจจุบันไม่ถูกต้อง", + "Invalid TOTP or recovery code": "รหัส TOTP หรือรหัสกู้คืนไม่ถูกต้อง", + "No local password set, please set a password first": "ยังไม่ได้ตั้งรหัสผ่านในระบบ โปรดตั้งรหัสผ่านก่อน", + "This LangBot Account is already bound to another user": "บัญชี LangBot นี้เชื่อมโยงกับผู้ใช้อื่นแล้ว", + "Invalid recovery key": "คีย์กู้คืนไม่ถูกต้อง", + "Done": "เสร็จแล้ว", + "Thank you for your feedback": "ขอบคุณสำหรับความคิดเห็น", + "Failed to process feedback": "ประมวลผลความคิดเห็นไม่สำเร็จ", + "Helpful": "มีประโยชน์", + "Not helpful": "ไม่มีประโยชน์", + "Select an option": "โปรดเลือก", + "Enter a value": "โปรดป้อนค่า", + "Submit": "ส่ง", + "Submitted": "ส่งแล้ว", + "Thinking": "กระบวนการคิด", + "AI-generated": "สร้างโดย AI", + "AI-generated content. Refer to the cited sources for details.": "เนื้อหาสร้างโดย AI ดูรายละเอียดจากแหล่งอ้างอิง", + "No bridges configured.": "ยังไม่ได้ตั้งค่าบริดจ์", + "Signing in to all bridges again...": "กำลังเข้าสู่ระบบบริดจ์ทั้งหมดอีกครั้ง…", + "Bridge status:": "สถานะบริดจ์:", + "Signed in ✓": "เข้าสู่ระบบแล้ว ✓", + "Not signed in ✗": "ยังไม่ได้เข้าสู่ระบบ ✗", + "None": "ไม่มี", + "Bridge {bridge}: skipped (login command or DM room missing).": "บริดจ์ {bridge}: ข้ามแล้ว (ไม่มีคำสั่งเข้าสู่ระบบหรือห้อง DM)", + "Bridge {bridge}: sending {command}...": "บริดจ์ {bridge}: กำลังส่ง {command}…", + "Bridge {bridge}: sign-out failed.": "บริดจ์ {bridge}: ออกจากระบบไม่สำเร็จ", + "Bridge {bridge}: sign-in started.": "บริดจ์ {bridge}: เริ่มเข้าสู่ระบบแล้ว", + "Slack authorization completed. Return to LangBot to finish setup.": "อนุญาต Slack สำเร็จแล้ว กลับไปที่ LangBot เพื่อดำเนินการตั้งค่าให้เสร็จ", + "Slack authorization failed or expired. Return to LangBot for details.": "อนุญาต Slack ไม่สำเร็จหรือหมดอายุ ดูรายละเอียดใน LangBot", + "TOTP is already enabled for this Account": "บัญชีนี้เปิดใช้ TOTP แล้ว", + "TOTP is not enabled for this Account": "บัญชีนี้ยังไม่ได้เปิดใช้ TOTP", + "Invalid or expired passkey challenge": "คำขอยืนยัน Passkey ไม่ถูกต้องหรือหมดอายุ", + "Passkey credential not recognized": "ไม่รู้จัก Passkey นี้", + "Account is disabled": "บัญชีถูกปิดใช้งาน", + "Modifying login info is disabled": "ไม่อนุญาตให้แก้ไขข้อมูลเข้าสู่ระบบ", + "Invalid GitHub repository URL": "URL ที่เก็บ GitHub ไม่ถูกต้อง", + "Server is busy. Please try again later.": "เซิร์ฟเวอร์ไม่ว่าง โปรดลองอีกครั้งภายหลัง", + "This feature is unavailable in this Workspace.": "พื้นที่ทำงานนี้ไม่สามารถใช้ฟีเจอร์นี้ได้", + "The Workspace must retain an owner.": "พื้นที่ทำงานต้องมีเจ้าของอย่างน้อยหนึ่งคน", + "Invalid or expired invitation": "คำเชิญไม่ถูกต้องหรือหมดอายุ", + "This user is already a member.": "ผู้ใช้นี้เป็นสมาชิกอยู่แล้ว", + "Voice connection failed": "การเชื่อมต่อเสียงล้มเหลว", + "User is not in the voice channel": "ผู้ใช้ไม่ได้อยู่ในช่องเสียง", + "Voice service is unavailable": "บริการเสียงไม่พร้อมใช้งาน", + "Submission failed. Please try again.": "ส่งไม่สำเร็จ โปรดลองอีกครั้ง", + "File size exceeds the limit.": "ขนาดไฟล์เกินขีดจำกัด", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "ไฟล์ใหญ่กว่า 10MB โปรดแบ่งเป็นไฟล์ย่อย", + "Authorization failed. Please try signing in again.": "การอนุญาตล้มเหลว โปรดเข้าสู่ระบบอีกครั้ง", + "Bind the LangBot Account with the same email as this local Account": "เชื่อมโยงบัญชี LangBot ที่ใช้อีเมลเดียวกับบัญชีในระบบนี้", + "Only local accounts can bind to Space": "เฉพาะบัญชีในระบบเท่านั้นที่เชื่อมโยงกับ Space ได้", + "System already initialized": "ระบบเริ่มต้นแล้ว", + "System not initialized": "ระบบยังไม่ได้เริ่มต้น", + "Password login is disabled on LangBot Cloud": "LangBot Cloud ปิดการเข้าสู่ระบบด้วยรหัสผ่าน", + "This edition supports one Workspace per instance": "รุ่นนี้รองรับพื้นที่ทำงานหนึ่งแห่งต่ออินสแตนซ์", + "Cloud Workspaces are created by the SaaS control plane": "พื้นที่ทำงาน Cloud สร้างจากแผงควบคุม SaaS", + "Login with your LangBot Account to accept this invitation": "เข้าสู่ระบบด้วยบัญชี LangBot เพื่อรับคำเชิญ", + "RAG migration is not needed": "ไม่จำเป็นต้องย้าย RAG", + "New Agent": "Agent ใหม่", + "New Pipeline": "ไปป์ไลน์ใหม่", + "Provider {provider} does not support {model_type} models": "ผู้ให้บริการ {provider} ไม่รองรับโมเดล {model_type}", + "Invalid JSON format": "รูปแบบ JSON ไม่ถูกต้อง", + "ChatGPT sign-in required. Open this provider and sign in again.": "ต้องเข้าสู่ระบบ ChatGPT โปรดเปิดผู้ให้บริการนี้แล้วเข้าสู่ระบบอีกครั้ง", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "คำขอ ChatGPT ถูกจำกัดตามความถี่หรือปริมาณการใช้งาน โปรดลองภายหลังหรือตรวจสอบแผนของคุณ", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT ปฏิเสธคำขอ โปรดตรวจสอบการสมัครสมาชิกและสิทธิ์ของพื้นที่ทำงาน", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT ปฏิเสธโมเดลหรือคำขอ โปรดตรวจสอบโมเดลและการตั้งค่าคำขอ", + "ChatGPT Codex upstream request failed. Please retry later.": "คำขอไปยัง ChatGPT Codex ล้มเหลว โปรดลองอีกครั้งภายหลัง", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "การใช้งานสมาชิก ChatGPT ถึงขีดจำกัดแล้ว โปรดลองภายหลังหรือตรวจสอบแผนของคุณ", + "ChatGPT Codex response failed or was incomplete. Please retry.": "การตอบกลับของ ChatGPT Codex ล้มเหลวหรือไม่ครบถ้วน โปรดลองอีกครั้ง", + "ChatGPT token refresh temporarily failed. Please retry.": "ไม่สามารถรีเฟรชโทเค็น ChatGPT ได้ชั่วคราว โปรดลองอีกครั้ง", + "A second factor is required": "ต้องยืนยันตัวตนสองขั้นตอน", + "Sign in or provide registration details to accept this invitation": "เข้าสู่ระบบหรือกรอกข้อมูลลงทะเบียนเพื่อยอมรับคำเชิญนี้", + "Sign out before creating the invited local Account": "ออกจากระบบก่อนสร้างบัญชีภายในที่ได้รับเชิญ", + "Turnstile verification failed": "การยืนยัน Turnstile ล้มเหลว โปรดลองอีกครั้ง", + "The invitation email does not match your Account": "อีเมลคำเชิญไม่ตรงกับบัญชีของคุณ", + "Failed to save ChatGPT credentials. Please retry.": "บันทึกข้อมูลรับรอง ChatGPT ไม่สำเร็จ โปรดลองอีกครั้ง", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "ไม่สามารถเริ่มเข้าสู่ระบบด้วยอุปกรณ์ได้ โปรดเปิดการเข้าสู่ระบบด้วยรหัสอุปกรณ์ในการตั้งค่า ChatGPT", + "Option {number}": "ตัวเลือก {number}", + "Confirmation needed": "ต้องยืนยัน", + "Session reset successfully": "รีเซ็ตเซสชันแล้ว" +} diff --git a/src/langbot/pkg/i18n/locales/vi_VN.json b/src/langbot/pkg/i18n/locales/vi_VN.json new file mode 100644 index 000000000..39b3110a8 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/vi_VN.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "Yêu cầu thất bại.", + "Too many requests. Please try again later.": "Quá nhiều yêu cầu. Vui lòng thử lại sau.", + "Your message contains inappropriate content. Please revise it.": "Tin nhắn chứa nội dung không phù hợp. Vui lòng chỉnh sửa.", + "Content checking failed. Please contact the administrator.": "Kiểm tra nội dung thất bại. Vui lòng liên hệ quản trị viên.", + "Calling {tools}...": "Đang gọi {tools}…", + "Agent runner not found: {runner}": "Không tìm thấy trình chạy Agent: {runner}", + "Agent runner not authorized for this pipeline.": "Pipeline này không được phép sử dụng trình chạy Agent.", + "Agent runner temporarily unavailable. Please try again.": "Trình chạy Agent tạm thời không khả dụng. Vui lòng thử lại.", + "Agent runner execution failed.": "Thực thi Agent thất bại.", + "The Agent runner returned an invalid response.": "Trình chạy Agent trả về phản hồi không hợp lệ.", + "Model request failed": "Yêu cầu đến mô hình thất bại", + "Context length exceeded": "Đã vượt quá độ dài ngữ cảnh", + "Invalid request parameters": "Tham số yêu cầu không hợp lệ", + "Invalid API key": "Khóa API không hợp lệ", + "Invalid model or endpoint": "Mô hình hoặc địa chỉ API không hợp lệ", + "Rate limit exceeded or insufficient balance": "Vượt giới hạn yêu cầu hoặc số dư không đủ", + "Request timed out": "Yêu cầu đã hết thời gian chờ", + "Connection failed": "Kết nối thất bại", + "API error": "Lỗi API", + "Unknown error": "Lỗi không xác định", + "Internal server error": "Lỗi máy chủ nội bộ", + "Resource not found": "Không tìm thấy tài nguyên", + "Permission denied": "Bạn không có quyền thực hiện thao tác này", + "Invalid authentication credentials": "Xác thực thất bại. Vui lòng đăng nhập lại", + "MCP runtime failed": "Thực thi MCP thất bại", + "Task execution failed": "Thực thi tác vụ thất bại", + "Task was cancelled": "Tác vụ đã bị hủy", + "Maximum number of {resource} ({limit}) reached": "Đã đạt số lượng tối đa của {resource} ({limit})", + "extensions": "tiện ích mở rộng", + "knowledge bases": "cơ sở tri thức", + "MCP server already exists: {name}": "Máy chủ MCP đã tồn tại: {name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models được quản lý bởi Cloud và không thể chỉnh sửa", + "Please sign in with your LangBot Account": "Vui lòng đăng nhập bằng tài khoản LangBot", + "Current password is incorrect": "Mật khẩu hiện tại không đúng", + "Invalid TOTP or recovery code": "Mã TOTP hoặc mã khôi phục không hợp lệ", + "No local password set, please set a password first": "Chưa có mật khẩu cục bộ. Vui lòng đặt mật khẩu trước", + "This LangBot Account is already bound to another user": "Tài khoản LangBot này đã được liên kết với người dùng khác", + "Invalid recovery key": "Khóa khôi phục không hợp lệ", + "Done": "Hoàn tất", + "Thank you for your feedback": "Cảm ơn bạn đã phản hồi", + "Failed to process feedback": "Không thể xử lý phản hồi", + "Helpful": "Hữu ích", + "Not helpful": "Không hữu ích", + "Select an option": "Chọn một mục", + "Enter a value": "Nhập giá trị", + "Submit": "Gửi", + "Submitted": "Đã gửi", + "Thinking": "Quá trình suy nghĩ", + "AI-generated": "Được tạo bởi AI", + "AI-generated content. Refer to the cited sources for details.": "Nội dung do AI tạo. Xem nguồn trích dẫn để biết chi tiết.", + "No bridges configured.": "Chưa cấu hình cầu nối nào.", + "Signing in to all bridges again...": "Đang đăng nhập lại vào tất cả cầu nối…", + "Bridge status:": "Trạng thái cầu nối:", + "Signed in ✓": "Đã đăng nhập ✓", + "Not signed in ✗": "Chưa đăng nhập ✗", + "None": "Không có", + "Bridge {bridge}: skipped (login command or DM room missing).": "Cầu nối {bridge}: đã bỏ qua (thiếu lệnh đăng nhập hoặc phòng DM).", + "Bridge {bridge}: sending {command}...": "Cầu nối {bridge}: đang gửi {command}…", + "Bridge {bridge}: sign-out failed.": "Cầu nối {bridge}: đăng xuất thất bại.", + "Bridge {bridge}: sign-in started.": "Cầu nối {bridge}: đã bắt đầu đăng nhập.", + "Slack authorization completed. Return to LangBot to finish setup.": "Đã cấp quyền Slack. Quay lại LangBot để hoàn tất thiết lập.", + "Slack authorization failed or expired. Return to LangBot for details.": "Cấp quyền Slack thất bại hoặc đã hết hạn. Xem chi tiết trong LangBot.", + "TOTP is already enabled for this Account": "Tài khoản này đã bật TOTP", + "TOTP is not enabled for this Account": "Tài khoản này chưa bật TOTP", + "Invalid or expired passkey challenge": "Yêu cầu xác minh passkey không hợp lệ hoặc đã hết hạn", + "Passkey credential not recognized": "Không nhận diện được passkey", + "Account is disabled": "Tài khoản đã bị vô hiệu hóa", + "Modifying login info is disabled": "Không được phép sửa thông tin đăng nhập", + "Invalid GitHub repository URL": "URL kho GitHub không hợp lệ", + "Server is busy. Please try again later.": "Máy chủ đang bận. Vui lòng thử lại sau.", + "This feature is unavailable in this Workspace.": "Tính năng này không khả dụng trong không gian làm việc này.", + "The Workspace must retain an owner.": "Không gian làm việc phải có ít nhất một chủ sở hữu.", + "Invalid or expired invitation": "Lời mời không hợp lệ hoặc đã hết hạn", + "This user is already a member.": "Người dùng này đã là thành viên.", + "Voice connection failed": "Kết nối thoại thất bại", + "User is not in the voice channel": "Người dùng không ở trong kênh thoại", + "Voice service is unavailable": "Dịch vụ thoại không khả dụng", + "Submission failed. Please try again.": "Gửi thất bại. Vui lòng thử lại.", + "File size exceeds the limit.": "Kích thước tệp vượt quá giới hạn.", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "Tệp vượt quá 10MB. Vui lòng chia thành các phần nhỏ hơn.", + "Authorization failed. Please try signing in again.": "Cấp quyền thất bại. Vui lòng đăng nhập lại.", + "Bind the LangBot Account with the same email as this local Account": "Liên kết tài khoản LangBot có cùng email với tài khoản cục bộ này", + "Only local accounts can bind to Space": "Chỉ tài khoản cục bộ mới có thể liên kết với Space", + "System already initialized": "Hệ thống đã được khởi tạo", + "System not initialized": "Hệ thống chưa được khởi tạo", + "Password login is disabled on LangBot Cloud": "LangBot Cloud không cho phép đăng nhập bằng mật khẩu", + "This edition supports one Workspace per instance": "Phiên bản này hỗ trợ một không gian làm việc cho mỗi phiên bản triển khai", + "Cloud Workspaces are created by the SaaS control plane": "Không gian làm việc Cloud được tạo từ bảng điều khiển SaaS", + "Login with your LangBot Account to accept this invitation": "Đăng nhập bằng tài khoản LangBot để chấp nhận lời mời", + "RAG migration is not needed": "Không cần di chuyển RAG", + "New Agent": "Agent mới", + "New Pipeline": "Pipeline mới", + "Provider {provider} does not support {model_type} models": "Nhà cung cấp {provider} không hỗ trợ mô hình {model_type}", + "Invalid JSON format": "Định dạng JSON không hợp lệ", + "ChatGPT sign-in required. Open this provider and sign in again.": "Cần đăng nhập ChatGPT. Mở nhà cung cấp này và đăng nhập lại.", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "Yêu cầu ChatGPT bị giới hạn tần suất hoặc mức sử dụng. Hãy thử lại sau hoặc kiểm tra gói của bạn.", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT đã từ chối yêu cầu. Kiểm tra gói đăng ký và quyền của không gian làm việc.", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT đã từ chối mô hình hoặc yêu cầu. Kiểm tra mô hình đã chọn và cài đặt yêu cầu.", + "ChatGPT Codex upstream request failed. Please retry later.": "Yêu cầu tới ChatGPT Codex thất bại. Vui lòng thử lại sau.", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "Đã đạt giới hạn sử dụng gói ChatGPT. Hãy thử lại sau hoặc kiểm tra gói của bạn.", + "ChatGPT Codex response failed or was incomplete. Please retry.": "Phản hồi ChatGPT Codex thất bại hoặc chưa hoàn tất. Vui lòng thử lại.", + "ChatGPT token refresh temporarily failed. Please retry.": "Tạm thời không thể làm mới token ChatGPT. Vui lòng thử lại.", + "A second factor is required": "Cần xác thực hai yếu tố", + "Sign in or provide registration details to accept this invitation": "Đăng nhập hoặc cung cấp thông tin đăng ký để chấp nhận lời mời", + "Sign out before creating the invited local Account": "Đăng xuất trước khi tạo tài khoản cục bộ được mời", + "Turnstile verification failed": "Xác minh Turnstile thất bại. Vui lòng thử lại.", + "The invitation email does not match your Account": "Email trong lời mời không khớp với tài khoản của bạn", + "Failed to save ChatGPT credentials. Please retry.": "Không thể lưu thông tin xác thực ChatGPT. Vui lòng thử lại.", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "Không thể bắt đầu đăng nhập thiết bị ChatGPT. Hãy bật đăng nhập bằng mã thiết bị trong cài đặt ChatGPT.", + "Option {number}": "Lựa chọn {number}", + "Confirmation needed": "Cần xác nhận", + "Session reset successfully": "Đã đặt lại phiên" +} diff --git a/src/langbot/pkg/i18n/locales/zh_Hans.json b/src/langbot/pkg/i18n/locales/zh_Hans.json new file mode 100644 index 000000000..29a12e840 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/zh_Hans.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "请求失败。", + "Too many requests. Please try again later.": "请求过于频繁,请稍后重试。", + "Your message contains inappropriate content. Please revise it.": "消息中存在不合适的内容,请修改。", + "Content checking failed. Please contact the administrator.": "内容检查失败,请联系管理员。", + "Calling {tools}...": "正在调用 {tools}…", + "Agent runner not found: {runner}": "找不到 Agent 运行器:{runner}", + "Agent runner not authorized for this pipeline.": "此流水线未获授权使用该 Agent 运行器。", + "Agent runner temporarily unavailable. Please try again.": "Agent 运行器暂时不可用,请重试。", + "Agent runner execution failed.": "Agent 执行失败。", + "The Agent runner returned an invalid response.": "Agent 运行器返回了无效响应。", + "Model request failed": "模型请求失败", + "Context length exceeded": "上下文长度超限", + "Invalid request parameters": "请求参数错误", + "Invalid API key": "API 密钥无效", + "Invalid model or endpoint": "模型或接口地址无效", + "Rate limit exceeded or insufficient balance": "请求过于频繁或余额不足", + "Request timed out": "请求超时", + "Connection failed": "连接失败", + "API error": "API 错误", + "Unknown error": "未知错误", + "Internal server error": "服务器内部错误", + "Resource not found": "资源不存在", + "Permission denied": "没有执行此操作的权限", + "Invalid authentication credentials": "身份验证失败,请重新登录", + "MCP runtime failed": "MCP 运行失败", + "Task execution failed": "任务执行失败", + "Task was cancelled": "任务已取消", + "Maximum number of {resource} ({limit}) reached": "{resource}数量已达到上限({limit})", + "extensions": "扩展", + "knowledge bases": "知识库", + "MCP server already exists: {name}": "MCP 服务器已存在:{name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models 由云端管理,无法修改", + "Please sign in with your LangBot Account": "请使用 LangBot 账号登录", + "Current password is incorrect": "当前密码不正确", + "Invalid TOTP or recovery code": "验证码或恢复码无效", + "No local password set, please set a password first": "尚未设置本地密码,请先设置密码", + "This LangBot Account is already bound to another user": "此 LangBot 账号已绑定其他用户", + "Invalid recovery key": "恢复密钥无效", + "Done": "操作成功", + "Thank you for your feedback": "感谢您的反馈", + "Failed to process feedback": "反馈处理失败", + "Helpful": "有帮助", + "Not helpful": "无帮助", + "Select an option": "请选择", + "Enter a value": "请输入", + "Submit": "提交", + "Submitted": "已提交", + "Thinking": "思考过程", + "AI-generated": "内容由 AI 生成", + "AI-generated content. Refer to the cited sources for details.": "内容由 AI 生成,详情请参考引用来源。", + "No bridges configured.": "没有配置任何桥。", + "Signing in to all bridges again...": "正在重新登录所有桥…", + "Bridge status:": "桥状态:", + "Signed in ✓": "已登录 ✓", + "Not signed in ✗": "未登录 ✗", + "None": "无", + "Bridge {bridge}: skipped (login command or DM room missing).": "桥 {bridge}:已跳过(缺少登录命令或私聊房间)。", + "Bridge {bridge}: sending {command}...": "桥 {bridge}:正在发送 {command}…", + "Bridge {bridge}: sign-out failed.": "桥 {bridge}:退出登录失败。", + "Bridge {bridge}: sign-in started.": "桥 {bridge}:已开始登录。", + "Slack authorization completed. Return to LangBot to finish setup.": "Slack 授权完成,请返回 LangBot 完成配置。", + "Slack authorization failed or expired. Return to LangBot for details.": "Slack 授权失败或已过期,请返回 LangBot 查看详情。", + "TOTP is already enabled for this Account": "此账号已启用两步验证", + "TOTP is not enabled for this Account": "此账号尚未启用两步验证", + "Invalid or expired passkey challenge": "通行密钥验证请求无效或已过期", + "Passkey credential not recognized": "无法识别此通行密钥", + "Account is disabled": "账号已停用", + "Modifying login info is disabled": "不允许修改登录信息", + "Invalid GitHub repository URL": "GitHub 仓库地址无效", + "Server is busy. Please try again later.": "服务器繁忙,请稍后重试。", + "This feature is unavailable in this Workspace.": "此工作区无法使用该功能。", + "The Workspace must retain an owner.": "工作区必须保留一位所有者。", + "Invalid or expired invitation": "邀请无效或已过期", + "This user is already a member.": "此用户已是工作区成员。", + "Voice connection failed": "语音连接失败", + "User is not in the voice channel": "用户不在语音频道中", + "Voice service is unavailable": "语音服务不可用", + "Submission failed. Please try again.": "提交失败,请重试。", + "File size exceeds the limit.": "文件大小超过限制。", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "文件大小超过 10MB,请拆分后上传。", + "Authorization failed. Please try signing in again.": "授权失败,请重新登录。", + "Bind the LangBot Account with the same email as this local Account": "请绑定与此本地账号邮箱相同的 LangBot 账号", + "Only local accounts can bind to Space": "只有本地账号可以绑定 Space", + "System already initialized": "系统已初始化", + "System not initialized": "系统尚未初始化", + "Password login is disabled on LangBot Cloud": "LangBot Cloud 不支持密码登录", + "This edition supports one Workspace per instance": "此版本每个实例仅支持一个工作区", + "Cloud Workspaces are created by the SaaS control plane": "云工作区由 SaaS 控制台创建", + "Login with your LangBot Account to accept this invitation": "请登录 LangBot 账号以接受邀请", + "RAG migration is not needed": "无需迁移知识库", + "New Agent": "新 Agent", + "New Pipeline": "新流水线", + "Provider {provider} does not support {model_type} models": "提供商 {provider} 不支持 {model_type} 模型", + "Invalid JSON format": "JSON 格式无效", + "ChatGPT sign-in required. Open this provider and sign in again.": "需要登录 ChatGPT。请打开此提供商并重新登录。", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "ChatGPT 请求受限(请求频率或用量限制)。请稍后重试或检查套餐。", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT 拒绝了此请求。请检查订阅和工作区权限。", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT 拒绝了模型或请求。请检查所选模型和请求设置。", + "ChatGPT Codex upstream request failed. Please retry later.": "ChatGPT Codex 上游请求失败,请稍后重试。", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "ChatGPT 订阅用量已达上限。请稍后重试或检查套餐。", + "ChatGPT Codex response failed or was incomplete. Please retry.": "ChatGPT Codex 响应失败或不完整,请重试。", + "ChatGPT token refresh temporarily failed. Please retry.": "ChatGPT 令牌暂时刷新失败,请重试。", + "A second factor is required": "需要二次验证", + "Sign in or provide registration details to accept this invitation": "请登录或填写注册信息以接受此邀请", + "Sign out before creating the invited local Account": "请先退出登录,再创建受邀本地账号", + "Turnstile verification failed": "人机验证失败,请重试", + "The invitation email does not match your Account": "邀请邮箱与您的账号不匹配", + "Failed to save ChatGPT credentials. Please retry.": "保存 ChatGPT 凭据失败,请重试。", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "无法启动 ChatGPT 设备登录。请在 ChatGPT 设置中启用设备代码登录。", + "Option {number}": "选项 {number}", + "Confirmation needed": "需要确认", + "Session reset successfully": "会话已重置" +} diff --git a/src/langbot/pkg/i18n/locales/zh_Hant.json b/src/langbot/pkg/i18n/locales/zh_Hant.json new file mode 100644 index 000000000..15f5e90c3 --- /dev/null +++ b/src/langbot/pkg/i18n/locales/zh_Hant.json @@ -0,0 +1,114 @@ +{ + "Request failed.": "請求失敗。", + "Too many requests. Please try again later.": "請求過於頻繁,請稍後重試。", + "Your message contains inappropriate content. Please revise it.": "訊息中存在不適當的內容,請修改。", + "Content checking failed. Please contact the administrator.": "內容檢查失敗,請聯絡管理員。", + "Calling {tools}...": "正在呼叫 {tools}…", + "Agent runner not found: {runner}": "找不到 Agent 執行器:{runner}", + "Agent runner not authorized for this pipeline.": "此流水線未獲授權使用該 Agent 執行器。", + "Agent runner temporarily unavailable. Please try again.": "Agent 執行器暫時無法使用,請重試。", + "Agent runner execution failed.": "Agent 執行失敗。", + "The Agent runner returned an invalid response.": "Agent 執行器傳回了無效回應。", + "Model request failed": "模型請求失敗", + "Context length exceeded": "上下文長度超出限制", + "Invalid request parameters": "請求參數錯誤", + "Invalid API key": "API 金鑰無效", + "Invalid model or endpoint": "模型或介面位址無效", + "Rate limit exceeded or insufficient balance": "請求過於頻繁或餘額不足", + "Request timed out": "請求逾時", + "Connection failed": "連線失敗", + "API error": "API 錯誤", + "Unknown error": "未知錯誤", + "Internal server error": "伺服器內部錯誤", + "Resource not found": "資源不存在", + "Permission denied": "沒有執行此操作的權限", + "Invalid authentication credentials": "身分驗證失敗,請重新登入", + "MCP runtime failed": "MCP 執行失敗", + "Task execution failed": "任務執行失敗", + "Task was cancelled": "任務已取消", + "Maximum number of {resource} ({limit}) reached": "{resource}數量已達上限({limit})", + "extensions": "擴充功能", + "knowledge bases": "知識庫", + "MCP server already exists: {name}": "MCP 伺服器已存在:{name}", + "LangBot Models is managed by Cloud and cannot be modified": "LangBot Models 由雲端管理,無法修改", + "Please sign in with your LangBot Account": "請使用 LangBot 帳號登入", + "Current password is incorrect": "目前密碼不正確", + "Invalid TOTP or recovery code": "驗證碼或復原碼無效", + "No local password set, please set a password first": "尚未設定本機密碼,請先設定密碼", + "This LangBot Account is already bound to another user": "此 LangBot 帳號已綁定其他使用者", + "Invalid recovery key": "復原金鑰無效", + "Done": "操作成功", + "Thank you for your feedback": "感謝您的回饋", + "Failed to process feedback": "回饋處理失敗", + "Helpful": "有幫助", + "Not helpful": "沒有幫助", + "Select an option": "請選擇", + "Enter a value": "請輸入", + "Submit": "提交", + "Submitted": "已提交", + "Thinking": "思考過程", + "AI-generated": "內容由 AI 產生", + "AI-generated content. Refer to the cited sources for details.": "內容由 AI 產生,詳情請參考引用來源。", + "No bridges configured.": "尚未設定任何橋接。", + "Signing in to all bridges again...": "正在重新登入所有橋接…", + "Bridge status:": "橋接狀態:", + "Signed in ✓": "已登入 ✓", + "Not signed in ✗": "未登入 ✗", + "None": "無", + "Bridge {bridge}: skipped (login command or DM room missing).": "橋接 {bridge}:已略過(缺少登入命令或私訊房間)。", + "Bridge {bridge}: sending {command}...": "橋接 {bridge}:正在傳送 {command}…", + "Bridge {bridge}: sign-out failed.": "橋接 {bridge}:登出失敗。", + "Bridge {bridge}: sign-in started.": "橋接 {bridge}:已開始登入。", + "Slack authorization completed. Return to LangBot to finish setup.": "Slack 授權完成,請返回 LangBot 完成設定。", + "Slack authorization failed or expired. Return to LangBot for details.": "Slack 授權失敗或已過期,請返回 LangBot 查看詳情。", + "TOTP is already enabled for this Account": "此帳號已啟用兩步驗證", + "TOTP is not enabled for this Account": "此帳號尚未啟用兩步驗證", + "Invalid or expired passkey challenge": "通行金鑰驗證請求無效或已過期", + "Passkey credential not recognized": "無法識別此通行金鑰", + "Account is disabled": "帳號已停用", + "Modifying login info is disabled": "不允許修改登入資訊", + "Invalid GitHub repository URL": "GitHub 儲存庫網址無效", + "Server is busy. Please try again later.": "伺服器忙碌中,請稍後重試。", + "This feature is unavailable in this Workspace.": "此工作區無法使用該功能。", + "The Workspace must retain an owner.": "工作區必須保留一位擁有者。", + "Invalid or expired invitation": "邀請無效或已過期", + "This user is already a member.": "此使用者已是工作區成員。", + "Voice connection failed": "語音連線失敗", + "User is not in the voice channel": "使用者不在語音頻道中", + "Voice service is unavailable": "語音服務無法使用", + "Submission failed. Please try again.": "提交失敗,請重試。", + "File size exceeds the limit.": "檔案大小超過限制。", + "File size exceeds 10MB limit. Please split large files into smaller parts.": "檔案大小超過 10MB,請分割後上傳。", + "Authorization failed. Please try signing in again.": "授權失敗,請重新登入。", + "Bind the LangBot Account with the same email as this local Account": "請綁定與此本機帳號電子郵件相同的 LangBot 帳號", + "Only local accounts can bind to Space": "只有本機帳號可以綁定 Space", + "System already initialized": "系統已初始化", + "System not initialized": "系統尚未初始化", + "Password login is disabled on LangBot Cloud": "LangBot Cloud 不支援密碼登入", + "This edition supports one Workspace per instance": "此版本每個執行個體僅支援一個工作區", + "Cloud Workspaces are created by the SaaS control plane": "雲端工作區由 SaaS 控制台建立", + "Login with your LangBot Account to accept this invitation": "請登入 LangBot 帳號以接受邀請", + "RAG migration is not needed": "無需遷移知識庫", + "New Agent": "新 Agent", + "New Pipeline": "新流水線", + "Provider {provider} does not support {model_type} models": "提供商 {provider} 不支援 {model_type} 模型", + "Invalid JSON format": "JSON 格式無效", + "ChatGPT sign-in required. Open this provider and sign in again.": "需要登入 ChatGPT。請開啟此供應商並重新登入。", + "ChatGPT request was limited (rate limit or usage restriction). Please retry later or check your plan.": "ChatGPT 請求受限(請求頻率或用量限制)。請稍後重試或檢查方案。", + "ChatGPT denied this request. Check subscription and workspace permissions.": "ChatGPT 拒絕了此請求。請檢查訂閱和工作區權限。", + "ChatGPT rejected the model or request. Check the selected model and request settings.": "ChatGPT 拒絕了模型或請求。請檢查所選模型和請求設定。", + "ChatGPT Codex upstream request failed. Please retry later.": "ChatGPT Codex 上游請求失敗,請稍後重試。", + "ChatGPT subscription usage limit reached. Please retry later or check your plan.": "ChatGPT 訂閱用量已達上限。請稍後重試或檢查方案。", + "ChatGPT Codex response failed or was incomplete. Please retry.": "ChatGPT Codex 回應失敗或不完整,請重試。", + "ChatGPT token refresh temporarily failed. Please retry.": "ChatGPT 權杖暫時更新失敗,請重試。", + "A second factor is required": "需要雙重驗證", + "Sign in or provide registration details to accept this invitation": "請登入或填寫註冊資料以接受此邀請", + "Sign out before creating the invited local Account": "請先登出,再建立受邀本機帳號", + "Turnstile verification failed": "人機驗證失敗,請重試", + "The invitation email does not match your Account": "邀請信箱與您的帳號不符", + "Failed to save ChatGPT credentials. Please retry.": "儲存 ChatGPT 憑證失敗,請重試。", + "Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.": "無法啟動 ChatGPT 裝置登入。請在 ChatGPT 設定中啟用裝置代碼登入。", + "Option {number}": "選項 {number}", + "Confirmation needed": "需要確認", + "Session reset successfully": "對話已重設" +} diff --git a/src/langbot/pkg/i18n/workspace.py b/src/langbot/pkg/i18n/workspace.py new file mode 100644 index 000000000..0527b818b --- /dev/null +++ b/src/langbot/pkg/i18n/workspace.py @@ -0,0 +1,71 @@ +"""Workspace-owned message language, stored in the existing tenant metadata.""" + +from __future__ import annotations + +import time +from collections import OrderedDict + +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import insert as pg_insert +from sqlalchemy.dialects.sqlite import insert as sqlite_insert + +from ..entity.persistence.metadata import WorkspaceMetadata +from . import DEFAULT_LANGUAGE, SUPPORTED_LANGUAGES, normalize_language + +LANGUAGE_KEY = 'message_language' +_CACHE_TTL = 30 +_CACHE_SIZE = 256 + + +def _cache(ap) -> OrderedDict: + cache = getattr(ap, '_message_language_cache', None) + if cache is None: + cache = OrderedDict() + ap._message_language_cache = cache + return cache + + +async def get_workspace_language(ap, workspace_uuid: str, *, refresh: bool = False) -> str: + if not workspace_uuid: + return DEFAULT_LANGUAGE + cache = _cache(ap) + cached = cache.get(workspace_uuid) + if not refresh and cached and cached[1] > time.monotonic(): + return cached[0] + manager = getattr(ap, 'persistence_mgr', None) + if manager is None or not callable(getattr(manager, 'tenant_uow', None)): + return DEFAULT_LANGUAGE + async with manager.tenant_uow(workspace_uuid) as uow: + result = await uow.execute( + sa.select(WorkspaceMetadata.value).where( + WorkspaceMetadata.workspace_uuid == workspace_uuid, + WorkspaceMetadata.key == LANGUAGE_KEY, + ) + ) + locale = normalize_language(result.scalar_one_or_none()) + cache[workspace_uuid] = (locale, time.monotonic() + _CACHE_TTL) + cache.move_to_end(workspace_uuid) + while len(cache) > _CACHE_SIZE: + cache.popitem(last=False) + return locale + + +async def set_workspace_language(ap, workspace_uuid: str, locale: str) -> str: + if locale not in SUPPORTED_LANGUAGES: + raise ValueError('Unsupported Workspace language') + async with ap.persistence_mgr.tenant_uow(workspace_uuid) as uow: + dialect = ap.persistence_mgr.get_db_engine().dialect.name + insert = pg_insert if dialect == 'postgresql' else sqlite_insert + statement = insert(WorkspaceMetadata).values(workspace_uuid=workspace_uuid, key=LANGUAGE_KEY, value=locale) + await uow.execute( + statement.on_conflict_do_update( + index_elements=['workspace_uuid', 'key'], + set_={'value': locale}, + ) + ) + # Synchronous platform callbacks may run in SDK threads. Publish the new + # value only after commit, so they see changes without restarting a bot. + _cache(ap)[workspace_uuid] = (locale, time.monotonic() + _CACHE_TTL) + while len(_cache(ap)) > _CACHE_SIZE: + _cache(ap).popitem(last=False) + return locale diff --git a/src/langbot/pkg/pipeline/cntfilter/filters/baiduexamine.py b/src/langbot/pkg/pipeline/cntfilter/filters/baiduexamine.py index 8c74150b0..444fd4798 100644 --- a/src/langbot/pkg/pipeline/cntfilter/filters/baiduexamine.py +++ b/src/langbot/pkg/pipeline/cntfilter/filters/baiduexamine.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import pipeline_notice + from .. import entities from .. import filter as filter_model import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query @@ -58,6 +60,10 @@ class BaiduCloudExamine(filter_model.ContentFilter): return entities.FilterResult( level=entities.ResultLevel.BLOCK, replacement=message, - user_notice='消息中存在不合适的内容, 请修改', + user_notice=pipeline_notice( + query, + 'content-filter-hint', + 'Your message contains inappropriate content. Please revise it.', + ), console_notice=f'百度云判定结果:{conclusion}', ) diff --git a/src/langbot/pkg/pipeline/cntfilter/filters/banwords.py b/src/langbot/pkg/pipeline/cntfilter/filters/banwords.py index bfd8ca772..32a3a5f30 100644 --- a/src/langbot/pkg/pipeline/cntfilter/filters/banwords.py +++ b/src/langbot/pkg/pipeline/cntfilter/filters/banwords.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import pipeline_notice + from .. import filter as filter_model from .. import entities import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query @@ -35,13 +37,19 @@ class BanWordFilter(filter_model.ContentFilter): return entities.FilterResult( level=entities.ResultLevel.BLOCK, replacement='', - user_notice='内容检查规则执行失败,请联系管理员', + user_notice=pipeline_notice( + query, 'content-filter-error-hint', 'Content checking failed. Please contact the administrator.' + ), console_notice=f'Sensitive-word regex rejected: {exc}', ) return entities.FilterResult( level=entities.ResultLevel.MASKED if found else entities.ResultLevel.PASS, replacement=current, - user_notice='消息中存在不合适的内容, 请修改' if found else '', + user_notice=pipeline_notice( + query, 'content-filter-hint', 'Your message contains inappropriate content. Please revise it.' + ) + if found + else '', console_notice='', ) diff --git a/src/langbot/pkg/pipeline/pipelinemgr.py b/src/langbot/pkg/pipeline/pipelinemgr.py index e15be688f..fc7aaaf31 100644 --- a/src/langbot/pkg/pipeline/pipelinemgr.py +++ b/src/langbot/pkg/pipeline/pipelinemgr.py @@ -20,6 +20,8 @@ from ..api.http.context import ExecutionContext, PrincipalContext, PrincipalType from ..workspace.errors import WorkspaceError, WorkspaceInvariantError from .config_coercion import coerce_pipeline_config from .pool import get_query_execution_context +from ..i18n import language_scope +from ..i18n.workspace import get_workspace_language from ..agent.runner.config_resolver import RunnerConfigResolver from .extension_preferences import normalize_extension_preferences @@ -414,6 +416,11 @@ class RuntimePipeline: return event_type[:160] or 'message.received' async def process_query(self, query: pipeline_query.Query): + workspace_uuid = getattr(query, 'workspace_uuid', None) or getattr(self, 'workspace_uuid', '') + with language_scope(await get_workspace_language(self.ap, workspace_uuid)): + return await self._process_query_with_language(query) + + async def _process_query_with_language(self, query: pipeline_query.Query): from ..telemetry import trace as trace_mod from ..telemetry.execution import ingress from ..telemetry.execution import record as record_execution diff --git a/src/langbot/pkg/pipeline/process/handlers/chat.py b/src/langbot/pkg/pipeline/process/handlers/chat.py index 1bc6143b9..5226d56b0 100644 --- a/src/langbot/pkg/pipeline/process/handlers/chat.py +++ b/src/langbot/pkg/pipeline/process/handlers/chat.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import pipeline_notice + import uuid import typing import traceback @@ -238,14 +240,20 @@ class ChatMessageHandler(handler.MessageHandler): # Handle specific runner errors with appropriate messages if isinstance(e, RunnerNotFoundError): - user_notice = f'Agent runner not found: {e.runner_id}' + user_notice = pipeline_notice( + query, 'runner-not-found-hint', 'Agent runner not found: {runner}', runner=e.runner_id + ) elif isinstance(e, RunnerNotAuthorizedError): - user_notice = 'Agent runner not authorized for this pipeline' + user_notice = pipeline_notice( + query, 'runner-not-authorized-hint', 'Agent runner not authorized for this pipeline.' + ) elif isinstance(e, RunnerExecutionError): if e.retryable: - user_notice = 'Agent runner temporarily unavailable. Please try again.' + user_notice = pipeline_notice( + query, 'runner-unavailable-hint', 'Agent runner temporarily unavailable. Please try again.' + ) else: - user_notice = 'Agent runner execution failed.' + user_notice = pipeline_notice(query, 'failure-hint', 'Agent runner execution failed.') else: # Use existing exception handling exception_handling = query.pipeline_config['output']['misc'].get('exception-handling', 'show-hint') @@ -253,7 +261,7 @@ class ChatMessageHandler(handler.MessageHandler): if exception_handling == 'show-error': user_notice = f'{e}' elif exception_handling == 'show-hint': - user_notice = query.pipeline_config['output']['misc'].get('failure-hint', 'Request failed.') + user_notice = pipeline_notice(query, 'failure-hint', 'Request failed.') else: # hide user_notice = None diff --git a/src/langbot/pkg/pipeline/ratelimit/ratelimit.py b/src/langbot/pkg/pipeline/ratelimit/ratelimit.py index cab62b8d5..8ee1bb639 100644 --- a/src/langbot/pkg/pipeline/ratelimit/ratelimit.py +++ b/src/langbot/pkg/pipeline/ratelimit/ratelimit.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ...i18n import pipeline_notice + import typing from .. import entities, stage @@ -62,7 +64,7 @@ class RateLimit(stage.PipelineStage): result_type=entities.ResultType.INTERRUPT, new_query=query, console_notice=f'根据限速规则忽略 {query.launcher_type.value}:{query.launcher_id} 消息', - user_notice='请求数超过限速器设定值,已丢弃本消息。', + user_notice=pipeline_notice(query, 'rate-limit-hint', 'Too many requests. Please try again later.'), ) elif stage_inst_name == 'ReleaseRateLimitOccupancy': await self.algo.release_access( diff --git a/src/langbot/pkg/pipeline/wrapper/wrapper.py b/src/langbot/pkg/pipeline/wrapper/wrapper.py index 9ea275e1d..2dcda3a05 100644 --- a/src/langbot/pkg/pipeline/wrapper/wrapper.py +++ b/src/langbot/pkg/pipeline/wrapper/wrapper.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ...i18n import pipeline_notice + import typing from .. import entities @@ -175,7 +177,9 @@ class ResponseWrapper(stage.PipelineStage): if result.tool_calls is not None and len(result.tool_calls) > 0: # 有函数调用 function_names = [tc.function.name for tc in result.tool_calls] - reply_text = f'Call {".".join(function_names)}...' + reply_text = pipeline_notice( + query, 'tool-call-hint', 'Calling {tools}...', tools=', '.join(function_names) + ) # Only surface the tool-call notice when the pipeline option # is enabled. Emitting it unconditionally would become the diff --git a/src/langbot/pkg/platform/adapters/lark/adapter.py b/src/langbot/pkg/platform/adapters/lark/adapter.py index df820ae74..aa04ae8a7 100644 --- a/src/langbot/pkg/platform/adapters/lark/adapter.py +++ b/src/langbot/pkg/platform/adapters/lark/adapter.py @@ -1,5 +1,7 @@ from __future__ import annotations +from langbot.pkg.i18n.adapters import adapter_t, localized_adapter + from langbot.pkg.platform.sources.lark import ( LarkAdapter as LegacyLarkAdapter, NonBlockingLarkWSClient, @@ -347,6 +349,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte self.request_tenant_access_token(tenant_key) return self.tenant_access_tokens.get(tenant_key, {}).get('token') + @localized_adapter async def send_message( self, target_type: str, @@ -380,6 +383,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte message_id=message_ids[-1] if message_ids else '', raw={'message_ids': message_ids} ) + @localized_adapter async def reply_message( self, message_source: platform_events.MessageEvent, @@ -538,6 +542,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte raise RuntimeError(f'Lark card update failed: {response.code} {response.msg}') self.closed_streaming_cards.add(card_id) + @localized_adapter async def reply_message_chunk( self, message_source: platform_events.MessageEvent, @@ -592,6 +597,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte self.card_last_update_dict.pop(card_id, None) self.closed_streaming_cards.discard(card_id) + @localized_adapter async def call_platform_api(self, action: str, params: dict = {}) -> dict: if action == 'interaction.request': return await send_interaction(self, params) @@ -632,6 +638,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte return f'{event.group.id}_{thread_id}' return None + @localized_adapter async def handle_unified_webhook(self, bot_uuid: str, path: str, request): try: data = await request.json @@ -668,7 +675,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte feedback_event = self._feedback_event_from_webhook(data) if feedback_event and platform_events.FeedbackEvent in self.listeners: await self.listeners[platform_events.FeedbackEvent](feedback_event, self) - return {'toast': {'type': 'success', 'content': '感谢您的反馈'}} + return {'toast': {'type': 'success', 'content': adapter_t(self, 'Thank you for your feedback')}} await self._dispatch_eba_event(LarkEventConverter.platform_specific(data, event_type, data)) return {'code': 200, 'message': 'ok'} except Exception: @@ -689,6 +696,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte def _webhook_header(self, data: dict): return type('LarkWebhookHeader', (), data.get('header', {}))() + @localized_adapter async def run_async(self): self.event_loop = asyncio.get_running_loop() if self.config.get('app_type', 'self') != 'isv': @@ -892,12 +900,13 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte self._submit_coro(self.listeners[platform_events.FeedbackEvent](feedback_event, self)) from lark_oapi.event.callback.model.p2_card_action_trigger import P2CardActionTriggerResponse - return P2CardActionTriggerResponse({'toast': {'type': 'success', 'content': '感谢您的反馈'}}) + return P2CardActionTriggerResponse( + {'toast': {'type': 'success', 'content': adapter_t(self, 'Thank you for your feedback')}} + ) - @staticmethod - def _interaction_action_response(event: platform_events.PlatformSpecificEvent) -> dict[str, typing.Any]: + def _interaction_action_response(self, event: platform_events.PlatformSpecificEvent) -> dict[str, typing.Any]: response: dict[str, typing.Any] = { - 'toast': {'type': 'success', 'content': 'Submitted / 已提交'}, + 'toast': {'type': 'success', 'content': adapter_t(self, 'Submitted')}, } if not event.data.get('cardkit'): response['card'] = { @@ -907,7 +916,7 @@ class LarkAdapter(LarkAPIMixin, abstract_platform_adapter.AbstractPlatformAdapte 'elements': [ { 'tag': 'div', - 'text': {'tag': 'lark_md', 'content': '**Submitted / 已提交**'}, + 'text': {'tag': 'lark_md', 'content': '**' + adapter_t(self, 'Submitted') + '**'}, } ], }, diff --git a/src/langbot/pkg/platform/adapters/lark/interaction.py b/src/langbot/pkg/platform/adapters/lark/interaction.py index 9c9873125..8896f6316 100644 --- a/src/langbot/pkg/platform/adapters/lark/interaction.py +++ b/src/langbot/pkg/platform/adapters/lark/interaction.py @@ -2,6 +2,8 @@ from __future__ import annotations +from langbot.pkg.i18n import t + import json import time import typing @@ -61,8 +63,7 @@ def _field_form_elements( component_name = 'lbi_field_0' label = str(field.get('label') or field_id) placeholder = str( - field.get('placeholder') - or ('Select an option / 请选择' if field_type == 'select' else 'Enter a value / 请输入') + field.get('placeholder') or (t('Select an option') if field_type == 'select' else t('Enter a value')) ) required = bool(field.get('required')) if field_type == 'select': @@ -122,7 +123,7 @@ def _field_form_elements( submit_button = { 'tag': 'button', 'name': 'lbi_submit', - 'text': {'tag': 'plain_text', 'content': 'Submit / 提交'}, + 'text': {'tag': 'plain_text', 'content': t('Submit')}, 'type': 'primary', 'width': 'fill', 'form_action_type': 'submit', diff --git a/src/langbot/pkg/platform/adapters/lark/stream_card.py b/src/langbot/pkg/platform/adapters/lark/stream_card.py index 332400a82..cd5adbd56 100644 --- a/src/langbot/pkg/platform/adapters/lark/stream_card.py +++ b/src/langbot/pkg/platform/adapters/lark/stream_card.py @@ -2,6 +2,8 @@ import re +from langbot.pkg.i18n import t + def split_content(content: str) -> tuple[str, str]: reasoning, answer = [], [] @@ -28,7 +30,7 @@ def streaming_text(content: str) -> str: if len(reasoning) > 360: preview = '…' + preview quote = '> ' + preview.replace('\n', '\n> ') - return '**思考过程 / Thinking**\n\n' + quote + ('\n\n---\n\n' + answer if answer else '') + return '**' + t('Thinking') + '**\n\n' + quote + ('\n\n---\n\n' + answer if answer else '') def build_card(content: str = '', *, streaming: bool = False, finished: bool = True) -> dict: @@ -42,7 +44,7 @@ def build_card(content: str = '', *, streaming: bool = False, finished: bool = T { 'tag': 'collapsible_panel', 'expanded': not finished, - 'header': {'title': {'tag': 'plain_text', 'content': '思考过程 / Thinking'}}, + 'header': {'title': {'tag': 'plain_text', 'content': t('Thinking')}}, 'elements': [{'tag': 'markdown', 'content': reasoning}], } ) @@ -58,9 +60,7 @@ def build_card(content: str = '', *, streaming: bool = False, finished: bool = T 'width': 'weighted', 'weight': 1, 'vertical_align': 'center', - 'elements': [ - {'tag': 'markdown', 'content': '内容由 AI 生成 / AI-generated', 'text_size': 'notation'} - ], + 'elements': [{'tag': 'markdown', 'content': t('AI-generated'), 'text_size': 'notation'}], }, { 'tag': 'column', diff --git a/src/langbot/pkg/platform/botmgr.py b/src/langbot/pkg/platform/botmgr.py index dfb99d292..bb3beb0e8 100644 --- a/src/langbot/pkg/platform/botmgr.py +++ b/src/langbot/pkg/platform/botmgr.py @@ -1,5 +1,10 @@ from __future__ import annotations +from ..cloud.plan_policy import require_workspace_platform + +from ..i18n import language_scope +from ..i18n.workspace import get_workspace_language + import asyncio import contextlib import dataclasses @@ -114,6 +119,7 @@ class RuntimeBot: async def assert_execution_active(self) -> None: """Fail closed when this long-lived adapter belongs to a stale placement.""" + await require_workspace_platform(self.ap, self.workspace_uuid, self.bot_entity.adapter) await self.ap.workspace_service.get_execution_binding( self.workspace_uuid, expected_generation=self.placement_generation, @@ -916,6 +922,7 @@ class RuntimeBot: from ..telemetry import trace as trace_mod from ..telemetry.execution import ingress + await self.assert_execution_active() event.bot_uuid = self.bot_entity.uuid execution_id = self._platform_event_execution_id(event) if getattr(event, 'adapter_name', None) == 'wecomcs-omni': @@ -1713,21 +1720,22 @@ class RuntimeBot: def tenant_scoped_listener(listener): @functools.wraps(listener) async def wrapped(*args, **kwargs): - tenant_scope = getattr(self.ap.persistence_mgr, 'tenant_scope', None) - cloud_runtime = ( - getattr( - getattr(self.ap.persistence_mgr, 'mode', None), - 'value', - None, + with language_scope(await get_workspace_language(self.ap, self.workspace_uuid)): + tenant_scope = getattr(self.ap.persistence_mgr, 'tenant_scope', None) + cloud_runtime = ( + getattr( + getattr(self.ap.persistence_mgr, 'mode', None), + 'value', + None, + ) + == 'cloud_runtime' ) - == 'cloud_runtime' - ) - if cloud_runtime: - if not callable(tenant_scope): - raise RuntimeError('Cloud platform callbacks require a tenant scope') - async with tenant_scope(self.workspace_uuid): - return await listener(*args, **kwargs) - return await listener(*args, **kwargs) + if cloud_runtime: + if not callable(tenant_scope): + raise RuntimeError('Cloud platform callbacks require a tenant scope') + async with tenant_scope(self.workspace_uuid): + return await listener(*args, **kwargs) + return await listener(*args, **kwargs) return wrapped @@ -2312,6 +2320,7 @@ class PlatformManager: bot_entity = persistence_bot.Bot(**bot_entity) execution_context = self._normalize_execution_context(context, bot_uuid=bot_entity.uuid) + await require_workspace_platform(self.ap, execution_context.workspace_uuid, bot_entity.adapter) if bot_entity.workspace_uuid != execution_context.workspace_uuid: raise WorkspaceRequiredError('Bot entity Workspace does not match its runtime context') if not _binding_validated: @@ -2401,6 +2410,7 @@ class PlatformManager: ) if bot is None or bot.placement_generation != execution_context.placement_generation: return None + await require_workspace_platform(self.ap, execution_context.workspace_uuid, bot.bot_entity.adapter) return bot async def resolve_public_bot(self, route_key: str) -> RuntimeBot | None: diff --git a/src/langbot/pkg/platform/sources/discord.py b/src/langbot/pkg/platform/sources/discord.py index e7119e391..1d9a29234 100644 --- a/src/langbot/pkg/platform/sources/discord.py +++ b/src/langbot/pkg/platform/sources/discord.py @@ -1,5 +1,8 @@ from __future__ import annotations +from langbot.pkg.i18n import t +from langbot.pkg.i18n.adapters import adapter_t, localized_adapter + import discord from discord import ui as discord_ui @@ -219,11 +222,13 @@ class VoiceConnectionManager: # 获取服务器和频道对象 guild = self.bot.get_guild(guild_id) if not guild: - raise VoiceConnectionError(f'无法找到服务器 {guild_id}', 'GUILD_NOT_FOUND', guild_id) + raise VoiceConnectionError(t('Resource not found') + f': {guild_id}', 'GUILD_NOT_FOUND', guild_id) channel = guild.get_channel(channel_id) if not channel or not isinstance(channel, discord.VoiceChannel): - raise VoiceConnectionError(f'无法找到语音频道 {channel_id}', 'CHANNEL_NOT_FOUND', guild_id) + raise VoiceConnectionError( + t('Resource not found') + f': {channel_id}', 'CHANNEL_NOT_FOUND', guild_id + ) # 验证用户是否在语音频道中(如果提供了用户ID) if user_id: @@ -258,12 +263,14 @@ class VoiceConnectionManager: return voice_client except discord.ClientException as e: - raise VoiceNetworkError(f'Discord 客户端错误: {str(e)}') + raise VoiceNetworkError(t('Voice connection failed') + f': {e}') except discord.opus.OpusNotLoaded as e: - raise VoiceConnectionError(f'Opus 编码器未加载: {str(e)}', 'OPUS_NOT_LOADED', guild_id) + raise VoiceConnectionError( + t('Voice service is unavailable') + f': Opus: {e}', 'OPUS_NOT_LOADED', guild_id + ) except Exception as e: await self.logger.error(f'连接语音频道时发生未知错误: {str(e)}') - raise VoiceConnectionError(f'连接失败: {str(e)}', 'UNKNOWN_ERROR', guild_id) + raise VoiceConnectionError(t('Voice connection failed') + f': {e}', 'UNKNOWN_ERROR', guild_id) async def leave_voice_channel(self, guild_id: int) -> bool: """ @@ -494,11 +501,13 @@ class VoiceConnectionManager: """ member = guild.get_member(user_id) if not member: - raise VoicePermissionError(f'无法找到用户 {user_id}', ['member_not_found'], user_id, channel.id) + raise VoicePermissionError( + t('Resource not found') + f': {user_id}', ['member_not_found'], user_id, channel.id + ) if not member.voice or member.voice.channel != channel: raise VoicePermissionError( - f'用户 {member.display_name} 不在语音频道 {channel.name} 中', + t('User is not in the voice channel') + f': {member.display_name}, {channel.name}', ['user_not_in_channel'], user_id, channel.id, @@ -528,7 +537,7 @@ class VoiceConnectionManager: if missing_permissions: raise VoicePermissionError( - f'机器人在频道 {channel.name} 中缺少权限: {", ".join(missing_permissions)}', + t('Permission denied') + f': {channel.name}: {", ".join(missing_permissions)}', missing_permissions, channel_id=channel.id, ) @@ -843,7 +852,7 @@ class DiscordFormView(discord_ui.View): # silently — most Dify forms have ≤10 actions in practice. for idx, action in enumerate(actions[:25]): action_id = str(action.get('id') or '') - label = str(action.get('title') or action_id or f'Option {idx + 1}') + label = str(action.get('title') or action_id or adapter_t(adapter, 'Option {number}', number=idx + 1)) style = self._STYLE_MAP.get( str(action.get('button_style') or '').lower(), discord.ButtonStyle.secondary, @@ -966,6 +975,7 @@ class DiscordAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): self._pending_forms.pop(next(iter(self._pending_forms)), None) # Voice functionality methods + @localized_adapter async def join_voice_channel(self, guild_id: int, channel_id: int, user_id: int = None) -> discord.VoiceClient: """ 加入语音频道 @@ -990,7 +1000,7 @@ class DiscordAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): VoiceConnectionError: 其他连接错误 """ if not self.voice_manager: - raise VoiceConnectionError('语音管理器未初始化', 'MANAGER_NOT_READY') + raise VoiceConnectionError(t('Voice service is unavailable'), 'MANAGER_NOT_READY') return await self.voice_manager.join_voice_channel(guild_id, channel_id, user_id) @@ -1358,7 +1368,7 @@ class DiscordAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): ) return - node_title = str(form_data.get('node_title') or 'Confirmation needed') + node_title = str(form_data.get('node_title') or adapter_t(self, 'Confirmation needed')) form_content = str(form_data.get('form_content') or '').strip() # Two paths: diff --git a/src/langbot/pkg/platform/sources/lark.py b/src/langbot/pkg/platform/sources/lark.py index b4c4dc827..c6c2c9455 100644 --- a/src/langbot/pkg/platform/sources/lark.py +++ b/src/langbot/pkg/platform/sources/lark.py @@ -1,5 +1,7 @@ from __future__ import annotations +from langbot.pkg.i18n.adapters import adapter_t, localized_adapter + import lark_oapi from lark_oapi.api.im.v1 import CreateImageRequest, CreateImageRequestBody, CreateFileRequest, CreateFileRequestBody import traceback @@ -1240,7 +1242,9 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): from lark_oapi.event.callback.model.p2_card_action_trigger import P2CardActionTriggerResponse - return P2CardActionTriggerResponse({'toast': {'type': 'success', 'content': '操作成功'}}) + return P2CardActionTriggerResponse( + {'toast': {'type': 'success', 'content': adapter_t(self, 'Done')}} + ) if action_value == '有帮助': feedback_type = 1 @@ -1249,7 +1253,9 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): else: from lark_oapi.event.callback.model.p2_card_action_trigger import P2CardActionTriggerResponse - return P2CardActionTriggerResponse({'toast': {'type': 'success', 'content': '操作成功'}}) + return P2CardActionTriggerResponse( + {'toast': {'type': 'success', 'content': adapter_t(self, 'Done')}} + ) operator = getattr(event.event, 'operator', None) context = getattr(event.event, 'context', None) @@ -1286,13 +1292,17 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): from lark_oapi.event.callback.model.p2_card_action_trigger import P2CardActionTriggerResponse - return P2CardActionTriggerResponse({'toast': {'type': 'success', 'content': '感谢您的反馈'}}) + return P2CardActionTriggerResponse( + {'toast': {'type': 'success', 'content': adapter_t(self, 'Thank you for your feedback')}} + ) except Exception: traceback.print_exc() schedule_on_app_loop(self.logger.error(f'Error in lark card action callback: {traceback.format_exc()}')) from lark_oapi.event.callback.model.p2_card_action_trigger import P2CardActionTriggerResponse - return P2CardActionTriggerResponse({'toast': {'type': 'error', 'content': '反馈处理失败'}}) + return P2CardActionTriggerResponse( + {'toast': {'type': 'error', 'content': adapter_t(self, 'Failed to process feedback')}} + ) event_handler = ( lark_oapi.EventDispatcherHandler.builder('', '') @@ -1545,6 +1555,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): return True return False + @localized_adapter async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain): text_elements, media_items = await self.message_converter.yiri2target(message, self.api_client) @@ -1809,7 +1820,11 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'elements': [ { 'tag': 'markdown', - 'content': '以上内容由 AI 生成,仅供参考。更多详细、准确信息可点击引用链接查看', + 'content': '' + + adapter_t( + self, 'AI-generated content. Refer to the cited sources for details.' + ) + + '', 'text_align': 'left', 'text_size': 'notation', 'margin': '4px 0px 0px 0px', @@ -1840,7 +1855,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'width': 'fill', 'size': 'medium', 'icon': {'tag': 'standard_icon', 'token': 'thumbsup_outlined'}, - 'hover_tips': {'tag': 'plain_text', 'content': '有帮助'}, + 'hover_tips': {'tag': 'plain_text', 'content': adapter_t(self, 'Helpful')}, 'behaviors': [{'type': 'callback', 'value': {'feedback': '有帮助'}}], 'margin': '0px 0px 0px 0px', } @@ -1864,7 +1879,10 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'width': 'default', 'size': 'medium', 'icon': {'tag': 'standard_icon', 'token': 'thumbdown_outlined'}, - 'hover_tips': {'tag': 'plain_text', 'content': '无帮助'}, + 'hover_tips': { + 'tag': 'plain_text', + 'content': adapter_t(self, 'Not helpful'), + }, 'behaviors': [{'type': 'callback', 'value': {'feedback': '无帮助'}}], 'margin': '0px 0px 0px 0px', } @@ -2064,6 +2082,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): ) return new_card_id + @localized_adapter async def reply_message( self, message_source: platform_events.MessageEvent, @@ -2174,6 +2193,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): f'client.im.v1.message.reply ({media["msg_type"]}) failed, code: {response.code}, msg: {response.msg}, log_id: {response.get_log_id()}, resp: \n{json.dumps(json.loads(response.raw.content), indent=4, ensure_ascii=False)}' ) + @localized_adapter async def reply_message_chunk( self, message_source: platform_events.MessageEvent, @@ -2491,7 +2511,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'tag': 'select_static', 'name': component_name, 'label': {'tag': 'plain_text', 'content': field_name}, - 'placeholder': {'tag': 'plain_text', 'content': '请选择'}, + 'placeholder': {'tag': 'plain_text', 'content': adapter_t(self, 'Select an option')}, 'options': [ { 'text': {'tag': 'plain_text', 'content': option}, @@ -2525,7 +2545,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'tag': 'input', 'name': component_name, 'label': {'tag': 'plain_text', 'content': field_name}, - 'placeholder': {'tag': 'plain_text', 'content': '请输入'}, + 'placeholder': {'tag': 'plain_text', 'content': adapter_t(self, 'Enter a value')}, 'default_value': _dify_default_value(field), 'width': 'fill', 'required': False, @@ -2820,7 +2840,11 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'elements': [ { 'tag': 'markdown', - 'content': '以上内容由 AI 生成,仅供参考。更多详细、准确信息可点击引用链接查看', + 'content': '' + + adapter_t( + self, 'AI-generated content. Refer to the cited sources for details.' + ) + + '', 'text_align': 'left', 'text_size': 'notation', 'margin': '4px 0px 0px 0px', @@ -2855,7 +2879,10 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'width': 'fill', 'size': 'medium', 'icon': {'tag': 'standard_icon', 'token': 'thumbsup_outlined'}, - 'hover_tips': {'tag': 'plain_text', 'content': '有帮助'}, + 'hover_tips': { + 'tag': 'plain_text', + 'content': adapter_t(self, 'Helpful'), + }, 'behaviors': [{'type': 'callback', 'value': {'feedback': '有帮助'}}], 'margin': '0px 0px 0px 0px', } @@ -2879,7 +2906,10 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): 'width': 'default', 'size': 'medium', 'icon': {'tag': 'standard_icon', 'token': 'thumbdown_outlined'}, - 'hover_tips': {'tag': 'plain_text', 'content': '无帮助'}, + 'hover_tips': { + 'tag': 'plain_text', + 'content': adapter_t(self, 'Not helpful'), + }, 'behaviors': [{'type': 'callback', 'value': {'feedback': '无帮助'}}], 'margin': '0px 0px 0px 0px', } @@ -2973,6 +3003,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): else: return data['type'] + @localized_adapter async def handle_unified_webhook(self, bot_uuid: str, path: str, request): """处理统一 webhook 请求。 Args: @@ -3132,14 +3163,14 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): }, ) - return {'toast': {'type': 'success', 'content': '操作成功'}} + return {'toast': {'type': 'success', 'content': adapter_t(self, 'Done')}} if action_value == '有帮助': feedback_type = 1 elif action_value == '无帮助': feedback_type = 2 else: - return {'toast': {'type': 'success', 'content': '操作成功'}} + return {'toast': {'type': 'success', 'content': adapter_t(self, 'Done')}} user_id = operator.get('open_id') or operator.get('user_id') open_chat_id = context_data.get('open_chat_id') @@ -3171,10 +3202,10 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): if platform_events.FeedbackEvent in self.listeners: await self.listeners[platform_events.FeedbackEvent](feedback_event, self) - return {'toast': {'type': 'success', 'content': '感谢您的反馈'}} + return {'toast': {'type': 'success', 'content': adapter_t(self, 'Thank you for your feedback')}} except Exception: await self.logger.error(f'Error in lark card action callback: {traceback.format_exc()}') - return {'toast': {'type': 'error', 'content': '反馈处理失败'}} + return {'toast': {'type': 'error', 'content': adapter_t(self, 'Failed to process feedback')}} elif 'im.chat.member.bot.added_v1' == type: try: @@ -3227,6 +3258,7 @@ class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): await self.logger.error(f'Error in lark callback: {traceback.format_exc()}') return {'code': 500, 'message': 'error'} + @localized_adapter async def run_async(self): enable_webhook = self.config['enable-webhook'] diff --git a/src/langbot/pkg/platform/sources/matrix.py b/src/langbot/pkg/platform/sources/matrix.py index f0a9822e3..3fc311392 100644 --- a/src/langbot/pkg/platform/sources/matrix.py +++ b/src/langbot/pkg/platform/sources/matrix.py @@ -1,5 +1,8 @@ from __future__ import annotations +from langbot.pkg.i18n import t +from langbot.pkg.i18n.adapters import localized_adapter + import typing import asyncio import traceback @@ -666,25 +669,26 @@ class MatrixAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): except Exception: await self.logger.error(f'[{bridge.user_id}] Bridge status check fatal error: {traceback.format_exc()}') + @localized_adapter async def _handle_relogin_command(self, room_id: str): """Handle !relogin command: logout then re-login all bridges.""" if not self._bridges: await self.client.room_send( room_id=room_id, message_type='m.room.message', - content={'msgtype': 'm.text', 'body': '没有配置任何桥。'}, + content={'msgtype': 'm.text', 'body': t('No bridges configured.')}, ) return - lines = ['开始重新登录所有桥...'] + lines = [t('Signing in to all bridges again...')] for bridge in self._bridges: if not bridge.login_command or not bridge.dm_room_id: - lines.append(f'[{bridge.user_id}] 跳过(未配置登录命令或无DM房间)') + lines.append(t('Bridge {bridge}: skipped (login command or DM room missing).', bridge=bridge.user_id)) continue # Use configured logout command, fallback to deriving from login command logout_cmd = bridge.logout_command or bridge.login_command.replace('login', 'logout') - lines.append(f'[{bridge.user_id}] 发送 "{logout_cmd}"...') + lines.append(t('Bridge {bridge}: sending {command}...', bridge=bridge.user_id, command=logout_cmd)) # Cancel existing tasks if bridge.login_task and not bridge.login_task.done(): @@ -700,14 +704,14 @@ class MatrixAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): content={'msgtype': 'm.text', 'body': logout_cmd}, ) except Exception as e: - lines.append(f'[{bridge.user_id}] logout 发送失败: {e}') + lines.append(t('Bridge {bridge}: sign-out failed.', bridge=bridge.user_id) + f' {e}') await asyncio.sleep(2) # Reset state and restart login bridge.logged_in = False self._restart_bridge_login(bridge) - lines.append(f'[{bridge.user_id}] 已触发重新登录') + lines.append(t('Bridge {bridge}: sign-in started.', bridge=bridge.user_id)) await self.client.room_send( room_id=room_id, @@ -715,20 +719,21 @@ class MatrixAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter): content={'msgtype': 'm.text', 'body': '\n'.join(lines)}, ) + @localized_adapter async def _handle_status_command(self, room_id: str): """Handle !status command: show bridge states.""" if not self._bridges: await self.client.room_send( room_id=room_id, message_type='m.room.message', - content={'msgtype': 'm.text', 'body': '没有配置任何桥。'}, + content={'msgtype': 'm.text', 'body': t('No bridges configured.')}, ) return - lines = ['桥状态:'] + lines = [t('Bridge status:')] for bridge in self._bridges: - status = '已登录 ✓' if bridge.logged_in else '未登录 ✗' - dm = bridge.dm_room_id or '无' + status = t('Signed in ✓') if bridge.logged_in else t('Not signed in ✗') + dm = bridge.dm_room_id or t('None') lines.append(f'• {bridge.user_id}: {status} (DM: {dm})') await self.client.room_send( room_id=room_id, diff --git a/src/langbot/pkg/provider/modelmgr/codex_auth.py b/src/langbot/pkg/provider/modelmgr/codex_auth.py index 571a67b40..1f6b618ec 100644 --- a/src/langbot/pkg/provider/modelmgr/codex_auth.py +++ b/src/langbot/pkg/provider/modelmgr/codex_auth.py @@ -23,6 +23,7 @@ from ...api.http.context import PrincipalType, RequestContext from ...api.http.authz import Permission, has_permission from ...api.http.service.tenant import require_workspace_uuid from ...workspace.errors import WorkspaceNotFoundError +from ...i18n import t REQUESTER = 'openai-codex' BASE_URL = 'https://chatgpt.com/backend-api/codex' @@ -77,7 +78,7 @@ def _tokens(data: dict, previous: dict | None = None) -> dict: or not math.isfinite(expires_at) or expires_at <= time.time() ): - raise ValueError('ChatGPT returned an incomplete authorization. Please sign in again.') + raise ValueError(t('ChatGPT returned an incomplete authorization. Please sign in again.')) return { 'access_token': access, 'refresh_token': refresh, @@ -99,7 +100,7 @@ class CodexAuth: try: return await self.ap.persistence_mgr.execute_async(statement) except Exception: - raise ValueError('ChatGPT credential storage failed. Please retry.') from None + raise ValueError(t('ChatGPT credential storage failed. Please retry.')) from None async def _read(self, workspace: str, provider: str) -> dict | None: result = await self._execute(sa.select(CodexCredential).where(*self._where(workspace, provider))) @@ -107,7 +108,7 @@ class CodexAuth: row = result.first() return dict(row._mapping) if row is not None else None except Exception: - raise ValueError('ChatGPT credential storage failed. Please retry.') from None + raise ValueError(t('ChatGPT credential storage failed. Please retry.')) from None async def _provider(self, context, provider: str, *, user: bool = False) -> str: workspace = require_workspace_uuid(context) @@ -117,7 +118,7 @@ class CodexAuth: or not context.account_uuid or not has_permission(context, Permission.PROVIDER_SECRET_MANAGE) ): - raise ValueError('ChatGPT authorization requires an authorized workspace user') + raise ValueError(t('ChatGPT authorization requires an authorized workspace user')) result = await self._execute( sa.select(ModelProvider.requester).where( ModelProvider.workspace_uuid == workspace, ModelProvider.uuid == provider @@ -147,9 +148,9 @@ class CodexAuth: if result.rowcount == 1: break if await self._read(workspace, provider) is None: - raise ValueError(LOGIN_REQUIRED) + raise ValueError(t(LOGIN_REQUIRED)) if time.monotonic() >= deadline: - raise ValueError('ChatGPT authorization is busy. Please retry shortly.') + raise ValueError(t('ChatGPT authorization is busy. Please retry shortly.')) await asyncio.sleep(0.1) try: yield owner @@ -171,7 +172,7 @@ class CodexAuth: .values(payload=payload, version=CodexCredential.version + 1) ) if result.rowcount != 1: - raise ValueError('ChatGPT authorization was cancelled or replaced. Please retry.') + raise ValueError(t('ChatGPT authorization was cancelled or replaced. Please retry.')) async def _post(self, path: str, *, data=None, json_body=None) -> httpx.Response: try: @@ -186,7 +187,7 @@ class CodexAuth: 25, ) except (httpx.HTTPError, TimeoutError): - raise ValueError('ChatGPT authorization network error. Please retry.') from None + raise ValueError(t('ChatGPT authorization network error. Please retry.')) from None @staticmethod def _json(response: httpx.Response) -> dict: @@ -196,7 +197,7 @@ class CodexAuth: raise ValueError return value except ValueError: - raise ValueError('ChatGPT returned an invalid authorization response') from None + raise ValueError(t('ChatGPT returned an invalid authorization response')) from None async def status(self, context, provider: str) -> dict: workspace = await self._provider(context, provider, user=True) @@ -215,7 +216,9 @@ class CodexAuth: async with self._lease(workspace, provider) as owner: response = await self._post('/api/accounts/deviceauth/usercode', json_body={'client_id': CLIENT_ID}) if response.status_code != 200: - raise ValueError('Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.') + raise ValueError( + t('Unable to start ChatGPT device login. Enable device code login in ChatGPT settings.') + ) data = self._json(response) try: code = data.get('user_code') or data['usercode'] @@ -224,7 +227,7 @@ class CodexAuth: if not isinstance(code, str) or not isinstance(device, str) or not code or not device: raise ValueError except (KeyError, ValueError, TypeError): - raise ValueError('ChatGPT returned an invalid device code') from None + raise ValueError(t('ChatGPT returned an invalid device code')) from None now = time.time() try: expiry = data.get('expires_at') @@ -241,7 +244,7 @@ class CodexAuth: raise ValueError expires_at = min(now + 900, expires_at) except (ValueError, TypeError): - raise ValueError('ChatGPT returned an invalid device code expiry') from None + raise ValueError(t('ChatGPT returned an invalid device code expiry')) from None pending = { 'authorization_id': secrets.token_urlsafe(32), 'user_code': code, @@ -306,12 +309,12 @@ class CodexAuth: if response.status_code != 200: payload.pop('pending', None) await self._save(workspace, provider, owner, payload) - raise ValueError('ChatGPT device authorization failed. Please start again.') + raise ValueError(t('ChatGPT device authorization failed. Please start again.')) data = self._json(response) if not data.get('authorization_code') or not data.get('code_verifier'): payload.pop('pending', None) await self._save(workspace, provider, owner, payload) - raise ValueError('ChatGPT returned an incomplete device authorization') + raise ValueError(t('ChatGPT returned an incomplete device authorization')) # Keep an attempt tombstone so cancel can preempt exchange, but never replay a code. pending['consumed'] = True await self._save(workspace, provider, owner, payload) @@ -326,7 +329,7 @@ class CodexAuth: }, ) if response.status_code != 200: - raise ValueError('ChatGPT token exchange failed. Please start sign-in again.') + raise ValueError(t('ChatGPT token exchange failed. Please start sign-in again.')) tokens = _tokens(self._json(response)) await self._save( workspace, @@ -384,7 +387,7 @@ class CodexAuth: payload = row['payload'] if row else {} tokens = payload.get('tokens') if not tokens or payload.get('invalid'): - raise ValueError(LOGIN_REQUIRED) + raise ValueError(t(LOGIN_REQUIRED)) if tokens['expires_at'] > time.time() + 120 and tokens['access_token'] != rejected_token: return tokens async with self._lease(workspace, provider, refresh=True) as owner: @@ -392,7 +395,7 @@ class CodexAuth: payload = dict(row['payload']) tokens = payload.get('tokens') if not tokens or payload.get('invalid'): - raise ValueError(LOGIN_REQUIRED) + raise ValueError(t(LOGIN_REQUIRED)) if tokens['expires_at'] > time.time() + 120 and tokens['access_token'] != rejected_token: return tokens response = await self._post( @@ -411,9 +414,9 @@ class CodexAuth: payload.pop('tokens', None) payload.pop('completed', None) await self._save(workspace, provider, owner, payload) - raise ValueError(LOGIN_REQUIRED) + raise ValueError(t(LOGIN_REQUIRED)) if response.status_code != 200: - raise ValueError('ChatGPT token refresh temporarily failed. Please retry.') + raise ValueError(t('ChatGPT token refresh temporarily failed. Please retry.')) refreshed = _tokens(self._json(response), tokens) payload['tokens'] = refreshed await self._save(workspace, provider, owner, payload) diff --git a/src/langbot/pkg/provider/modelmgr/codex_errors.py b/src/langbot/pkg/provider/modelmgr/codex_errors.py index da32d531e..78141afb7 100644 --- a/src/langbot/pkg/provider/modelmgr/codex_errors.py +++ b/src/langbot/pkg/provider/modelmgr/codex_errors.py @@ -1,5 +1,6 @@ """Explicitly safe Codex failures; never construct messages from upstream bodies.""" +from ...i18n import t from .errors import RequesterError @@ -7,7 +8,7 @@ class CodexProviderError(ValueError): """A known provider failure safe to expose at the HTTP boundary.""" def __init__(self, message: str, status_code: int = 502, error_code: str = 'codex_upstream_failure'): - ValueError.__init__(self, message) + ValueError.__init__(self, t(message)) self.code = error_code self.retryable = status_code in (500, 502, 503, 504) self.retry_after = None diff --git a/src/langbot/pkg/provider/modelmgr/errors.py b/src/langbot/pkg/provider/modelmgr/errors.py index fda01de86..6df4c297b 100644 --- a/src/langbot/pkg/provider/modelmgr/errors.py +++ b/src/langbot/pkg/provider/modelmgr/errors.py @@ -1,3 +1,6 @@ +from ...i18n import t + + class RequesterError(Exception): """Base class for all Requester errors.""" @@ -12,7 +15,7 @@ class RequesterError(Exception): request_id: str | None = None, phase: str | None = None, ): - super().__init__('模型请求失败: ' + message) + super().__init__(t('Model request failed') + ': ' + message) self.code = code self.status_code = status_code self.retryable = retryable diff --git a/src/langbot/pkg/provider/modelmgr/requesters/litellmchat.py b/src/langbot/pkg/provider/modelmgr/requesters/litellmchat.py index dfaaf44bf..300fb7551 100644 --- a/src/langbot/pkg/provider/modelmgr/requesters/litellmchat.py +++ b/src/langbot/pkg/provider/modelmgr/requesters/litellmchat.py @@ -2,6 +2,8 @@ from __future__ import annotations +from ....i18n import t + import typing import copy import time @@ -1196,13 +1198,13 @@ class LiteLLMRequester(requester.ProviderAPIRequester): raise e metadata = error_metadata(e) mappings = ( - (litellm.ContextWindowExceededError, 'context_length', '上下文长度超限', False), - (litellm.AuthenticationError, 'authentication', 'API key 无效', False), - (litellm.NotFoundError, 'not_found', '模型或路径无效', False), - (litellm.RateLimitError, 'rate_limit', '请求过于频繁或余额不足', True), - (litellm.Timeout, 'timeout', '请求超时', True), - (litellm.APIConnectionError, 'connection', '连接错误', True), - (litellm.BadRequestError, 'bad_request', '请求参数错误', False), + (litellm.ContextWindowExceededError, 'context_length', t('Context length exceeded'), False), + (litellm.AuthenticationError, 'authentication', t('Invalid API key'), False), + (litellm.NotFoundError, 'not_found', t('Invalid model or endpoint'), False), + (litellm.RateLimitError, 'rate_limit', t('Rate limit exceeded or insufficient balance'), True), + (litellm.Timeout, 'timeout', t('Request timed out'), True), + (litellm.APIConnectionError, 'connection', t('Connection failed'), True), + (litellm.BadRequestError, 'bad_request', t('Invalid request parameters'), False), ) for exception_type, code, message, retryable in mappings: if isinstance(e, exception_type): @@ -1215,7 +1217,7 @@ class LiteLLMRequester(requester.ProviderAPIRequester): raise errors.RequesterError(message, code=code, retryable=retryable, **metadata) from e status = metadata['status_code'] raise errors.RequesterError( - 'API 错误' if isinstance(e, litellm.APIError) else '未知错误', + t('API error') if isinstance(e, litellm.APIError) else t('Unknown error'), code='upstream_error', retryable=status in (408, 409, 429, 500, 502, 503, 504), **metadata, @@ -1814,9 +1816,9 @@ class LiteLLMRequester(requester.ProviderAPIRequester): body = await httpclient.response_text(e.response) except Exception: pass - raise errors.RequesterError(f'rerank 请求失败 (HTTP {e.response.status_code}): {body or str(e)}') + raise errors.RequesterError(t('API error') + f' (HTTP {e.response.status_code}): {body or str(e)}') except httpx.HTTPError as e: - raise errors.RequesterError(f'rerank 连接错误: {str(e)}') + raise errors.RequesterError(t('Connection failed') + f': {e}') raw_results = data.get('results', []) if isinstance(data, dict) else [] results = [] diff --git a/src/langbot/pkg/provider/tools/loaders/mcp.py b/src/langbot/pkg/provider/tools/loaders/mcp.py index 7b5a83afd..3cb8b8cf5 100644 --- a/src/langbot/pkg/provider/tools/loaders/mcp.py +++ b/src/langbot/pkg/provider/tools/loaders/mcp.py @@ -1,5 +1,7 @@ from __future__ import annotations +from ....i18n import t + import dataclasses import enum import json @@ -1490,7 +1492,7 @@ class RuntimeMCPSession: # Raw transport exceptions may echo command arguments, headers, or # environment values. Detailed diagnostics belong in AUDIT_VIEW # logs; resource-list responses expose only a stable status. - 'error_message': 'MCP runtime failed' if self.error_message else None, + 'error_message': t('MCP runtime failed') if self.error_message else None, 'error_code': self._public_error_code if self.error_message else None, 'error_phase': self.error_phase.value if self.error_phase else None, 'retry_count': self.retry_count, diff --git a/src/langbot/pkg/utils/inflight.py b/src/langbot/pkg/utils/inflight.py index 6a0f1a0e0..8d6b8c0b4 100644 --- a/src/langbot/pkg/utils/inflight.py +++ b/src/langbot/pkg/utils/inflight.py @@ -7,9 +7,13 @@ No payloads or subscriptions survive the final viewer disconnecting. import asyncio import contextlib +import logging import time +logger = logging.getLogger(__name__) + + class InflightHub: def __init__(self): self.channels = {} @@ -75,6 +79,8 @@ class InflightHub: snapshot = await loader() frame = {'kind': 'snapshot', 'data': snapshot} except Exception: + if previous is None or previous['kind'] != 'unavailable': + logger.exception('Failed to load in-flight monitoring snapshot') frame = {'kind': 'unavailable'} # Heartbeats are sent separately; unchanged snapshots generate no traffic. if frame != previous: diff --git a/src/langbot/templates/default-pipeline-config.json b/src/langbot/templates/default-pipeline-config.json index 23666ab03..b692c3e0e 100644 --- a/src/langbot/templates/default-pipeline-config.json +++ b/src/langbot/templates/default-pipeline-config.json @@ -55,7 +55,7 @@ }, "misc": { "exception-handling": "show-hint", - "failure-hint": "Request failed.", + "failure-hint": "", "at-sender": true, "quote-origin": true, "track-function-calls": false, diff --git a/src/langbot/templates/embed/widget.js b/src/langbot/templates/embed/widget.js index 63d00f737..6cd9643a4 100644 --- a/src/langbot/templates/embed/widget.js +++ b/src/langbot/templates/embed/widget.js @@ -535,18 +535,15 @@ return; } - var protocol = CONFIG.baseUrl.indexOf("https") === 0 ? "wss:" : "ws:"; - var host = CONFIG.baseUrl.replace(/^https?:\/\//, ""); - var url = - protocol + - "//" + - host + - "/api/v1/embed/" + - CONFIG.botUuid + - "/ws/connect?session_type=" + - CONFIG.sessionType + - "&session_id=" + - encodeURIComponent(state.sessionId); + var endpoint = new URL(CONFIG.baseUrl || "/", window.location.href); + endpoint.protocol = endpoint.protocol === "https:" || endpoint.protocol === "wss:" ? "wss:" : "ws:"; + endpoint.pathname = endpoint.pathname.replace(/\/$/, "") + + "/api/v1/embed/" + encodeURIComponent(CONFIG.botUuid) + "/ws/connect"; + endpoint.search = ""; + endpoint.hash = ""; + endpoint.searchParams.set("session_type", CONFIG.sessionType); + endpoint.searchParams.set("session_id", state.sessionId); + var url = endpoint.toString(); try { state.ws = new WebSocket(url); diff --git a/src/langbot/templates/metadata/pipeline/output.yaml b/src/langbot/templates/metadata/pipeline/output.yaml index d5e0fae07..d3acfc693 100644 --- a/src/langbot/templates/metadata/pipeline/output.yaml +++ b/src/langbot/templates/metadata/pipeline/output.yaml @@ -106,11 +106,81 @@ stages: en_US: Failure Hint Text zh_Hans: 失败提示文本 description: - en_US: The text to display when a request fails. Only effective when Exception Handling Strategy is set to "Show Failure Hint" - zh_Hans: 请求失败时显示的提示文本,仅在异常处理策略设置为"仅文字提示"时生效 + en_US: Leave empty to use the Workspace language. Used for request and runner execution failures; custom text is not translated. + zh_Hans: 留空时使用工作区语言的默认提示。用于请求和运行器执行失败;自定义文本不会自动翻译。 type: string required: false - default: 'Request failed.' + default: '' + - name: rate-limit-hint + label: + en_US: Rate Limit Hint + zh_Hans: 限速提示 + description: + en_US: "Leave empty to use the Workspace language." + zh_Hans: "留空时使用工作区语言的默认提示。" + type: string + required: false + default: '' + - name: content-filter-hint + label: + en_US: Content Filter Hint + zh_Hans: 内容过滤提示 + description: + en_US: "Leave empty to use the Workspace language." + zh_Hans: "留空时使用工作区语言的默认提示。" + type: string + required: false + default: '' + - name: content-filter-error-hint + label: + en_US: Content Check Failure Hint + zh_Hans: 内容检查失败提示 + description: + en_US: "Leave empty to use the Workspace language." + zh_Hans: "留空时使用工作区语言的默认提示。" + type: string + required: false + default: '' + - name: tool-call-hint + label: + en_US: Tool Call Hint + zh_Hans: 工具调用提示 + description: + en_US: "Leave empty to use the Workspace language. Use {tools} for tool names. Requires Track Function Calls." + zh_Hans: "留空时使用工作区语言的默认提示。 可用 {tools} 插入工具名称,需开启跟踪函数调用。" + type: string + required: false + default: '' + - name: runner-not-found-hint + label: + en_US: Runner Missing Hint + zh_Hans: 运行器不存在提示 + description: + en_US: "Leave empty to use the Workspace language. Use {runner} for the runner ID." + zh_Hans: "留空时使用工作区语言的默认提示。 可用 {runner} 插入运行器 ID。" + type: string + required: false + default: '' + - name: runner-not-authorized-hint + label: + en_US: Runner Authorization Hint + zh_Hans: 运行器未授权提示 + description: + en_US: "Leave empty to use the Workspace language." + zh_Hans: "留空时使用工作区语言的默认提示。" + type: string + required: false + default: '' + - name: runner-unavailable-hint + label: + en_US: Runner Unavailable Hint + zh_Hans: 运行器不可用提示 + description: + en_US: "Leave empty to use the Workspace language." + zh_Hans: "留空时使用工作区语言的默认提示。" + type: string + required: false + default: '' - name: at-sender label: en_US: At Sender diff --git a/tests/integration/api/test_box_security.py b/tests/integration/api/test_box_security.py index 0a40f230a..a0409d908 100644 --- a/tests/integration/api/test_box_security.py +++ b/tests/integration/api/test_box_security.py @@ -35,6 +35,7 @@ async def box_security_api(): 'owner-token': SimpleNamespace(uuid='owner-account', user='owner@example.com'), } application = Mock() + application._message_language_cache = None application.deployment = SimpleNamespace(multi_workspace_enabled=False) application.persistence_mgr = SimpleNamespace(tenant_uow=None) application.user_service.get_authenticated_account = AsyncMock(side_effect=lambda token: accounts[token]) diff --git a/tests/integration/api/test_plugins_security.py b/tests/integration/api/test_plugins_security.py index 52442e371..2f773595a 100644 --- a/tests/integration/api/test_plugins_security.py +++ b/tests/integration/api/test_plugins_security.py @@ -88,6 +88,7 @@ async def plugin_security_api(plugin_module): } application = Mock() + application._message_language_cache = None application.deployment = SimpleNamespace(multi_workspace_enabled=False) application.user_service.get_authenticated_account = AsyncMock(side_effect=lambda token: accounts[token]) application.workspace_collaboration_service.resolve_account_workspace = AsyncMock( diff --git a/tests/integration/api/test_providers.py b/tests/integration/api/test_providers.py index df72d9084..bedd1d871 100644 --- a/tests/integration/api/test_providers.py +++ b/tests/integration/api/test_providers.py @@ -329,7 +329,7 @@ class TestModelEndpoints: assert response.status_code == 400 data = await response.get_json() assert data['code'] == 'model_test_failed' - assert data['msg'] == '模型请求失败: API key invalid' + assert data['msg'] == 'Model request failed: API key invalid' @pytest.mark.usefixtures('mock_circular_import_chain') diff --git a/tests/integration/api/test_skills_entitlements.py b/tests/integration/api/test_skills_entitlements.py index baafe1f18..af4f21722 100644 --- a/tests/integration/api/test_skills_entitlements.py +++ b/tests/integration/api/test_skills_entitlements.py @@ -27,6 +27,7 @@ async def skills_api(): execution=SimpleNamespace(instance_uuid='instance-a', placement_generation=1), ) application = Mock() + application._message_language_cache = None application.deployment = SimpleNamespace(multi_workspace_enabled=False) application.persistence_mgr = SimpleNamespace(tenant_uow=None) application.user_service.get_authenticated_account = AsyncMock(return_value=account) @@ -76,4 +77,6 @@ async def test_list_skills_does_not_hide_other_entitlement_failures(skills_api): }, ) - assert response.status_code == 500 + assert response.status_code == 403 + payload = await response.get_json() + assert payload['code'] == 'entitlement_unavailable' diff --git a/tests/integration/api/test_support_admin_launch.py b/tests/integration/api/test_support_admin_launch.py index e71cb4374..dd578794f 100644 --- a/tests/integration/api/test_support_admin_launch.py +++ b/tests/integration/api/test_support_admin_launch.py @@ -24,6 +24,7 @@ from langbot.pkg.api.http.controller.groups.user import UserRouterGroup from langbot.pkg.cloud.launch import SpaceLaunchError, SpaceLaunchService from langbot.pkg.cloud.support_admin import SupportAdminSessionService from langbot.pkg.entity.persistence.base import Base +from langbot.pkg.entity.persistence.metadata import WorkspaceMetadata from langbot.pkg.entity.persistence.support_admin import SupportAdminTemporarySession from langbot.pkg.entity.persistence.user import User from langbot.pkg.entity.persistence.workspace import ( @@ -124,6 +125,9 @@ class _TenantUow: self._transaction = await self.session.begin() return self + async def execute(self, statement): + return await self.session.execute(statement) + async def __aexit__(self, exc_type, exc, traceback): try: if exc_type is None: @@ -173,6 +177,7 @@ async def support_admin_api(tmp_path): tables=[ User.__table__, Workspace.__table__, + WorkspaceMetadata.__table__, WorkspaceExecutionState.__table__, WorkspaceMembership.__table__, SupportAdminTemporarySession.__table__, diff --git a/tests/integration/api/test_totp_workspace_scope.py b/tests/integration/api/test_totp_workspace_scope.py index 460dcbbb2..4f822062b 100644 --- a/tests/integration/api/test_totp_workspace_scope.py +++ b/tests/integration/api/test_totp_workspace_scope.py @@ -46,6 +46,7 @@ async def _resolve(account_uuid: str, _workspace_uuid: str | None) -> SimpleName async def totp_admin_api(): accounts = {'member-token': SimpleNamespace(uuid=MEMBER_UUID, user='member@example.com')} application = Mock() + application._message_language_cache = None application.deployment = SimpleNamespace(multi_workspace_enabled=False) application.instance_config.data = {'system': {'allow_modify_login_info': True}} application.persistence_mgr = SimpleNamespace(tenant_uow=None) diff --git a/tests/integration/api/test_user_space_oauth.py b/tests/integration/api/test_user_space_oauth.py index af2bab140..ad49c83a6 100644 --- a/tests/integration/api/test_user_space_oauth.py +++ b/tests/integration/api/test_user_space_oauth.py @@ -27,6 +27,7 @@ async def space_oauth_api(): execution=SimpleNamespace(instance_uuid='instance-a', placement_generation=1), ) application = Mock() + application._message_language_cache = None application.deployment = SimpleNamespace(multi_workspace_enabled=False, mode='oss') application.directory_projection_service = None application.persistence_mgr = None diff --git a/tests/integration/api/test_workspaces.py b/tests/integration/api/test_workspaces.py index a561cd44c..dd2baf961 100644 --- a/tests/integration/api/test_workspaces.py +++ b/tests/integration/api/test_workspaces.py @@ -824,6 +824,10 @@ async def test_cloud_projection_is_selected_explicitly_and_collaboration_runs_in not_before=1, expires_at=4102444800, plan_name='free', + plan_revision=3, + monthly_bonus_credits=12, + subscription_started_at=1720000000, + limits={'bots.max': 2, 'pipelines.max': 3, 'plugins.max': 4, 'knowledge_bases.max': 5}, ) application.entitlement_resolver = PlanResolver() @@ -843,6 +847,11 @@ async def test_cloud_projection_is_selected_explicitly_and_collaboration_runs_in assert current['workspace']['source'] == 'cloud_projection' assert current['placement_generation'] == 12 assert current['plan_name'] == 'free' + assert current['limitation']['max_bots'] == 2 + assert current['current_plan']['subscription_started_at'] == 1720000000 + assert current['current_plan']['revision'] == 3 + assert current['current_plan']['monthly_bonus_credits'] == 12 + assert current['current_plan']['limits']['bots.max'] == 2 create_workspace = await client.post( '/api/v1/workspaces', @@ -926,3 +935,64 @@ async def test_account_bootstrap_does_not_disclose_non_member_workspaces(workspa ) assert current.status_code == 404 assert (await current.get_json())['code'] == 'resource_not_found' + + +async def test_workspace_language_persists_and_controls_api_errors(workspace_api): + from langbot.pkg.i18n.workspace import get_workspace_language, set_workspace_language + + application, client, engine, owner_token = workspace_api + current = await client.get('/api/v1/workspaces/current', headers=_auth(owner_token)) + current = (await current.get_json())['data'] + workspace_uuid = current['workspace']['uuid'] + owner_uuid = current['membership']['account_uuid'] + headers = {**_auth(owner_token, workspace_uuid), 'X-LangBot-Language': 'ja-JP'} + initial = await client.get('/api/v1/workspaces/current/language', headers=headers) + assert (await initial.get_json())['data']['language'] == 'en_US' + + updated = await client.put('/api/v1/workspaces/current/language', headers=headers, json={'language': 'zh_Hans'}) + assert updated.status_code == 200 + assert await get_workspace_language(application, workspace_uuid) == 'zh_Hans' + restarted = SimpleNamespace(persistence_mgr=application.persistence_mgr) + assert await get_workspace_language(restarted, workspace_uuid) == 'zh_Hans' + + invalid = await client.put('/api/v1/workspaces/current/language', headers=headers, json={'language': '../bad'}) + assert invalid.status_code == 400 + assert await get_workspace_language(application, workspace_uuid, refresh=True) == 'zh_Hans' + + # A second Workspace has independent persisted metadata and cache entries. + async with engine.begin() as connection: + await connection.execute( + sqlalchemy.insert(Workspace).values( + uuid='language-other', + instance_uuid='instance-workspace-api', + name='Other', + slug='language-other', + source='cloud_projection', + type='team', + ) + ) + await set_workspace_language(application, 'language-other', 'es_ES') + assert await get_workspace_language(application, 'language-other') == 'es_ES' + assert await get_workspace_language(application, workspace_uuid) == 'zh_Hans' + + # Read-only members can inspect the setting but cannot modify it. The + # verified Workspace setting wins over the browser language hint. + async with engine.begin() as connection: + await connection.execute( + sqlalchemy.update(WorkspaceMembership) + .where( + WorkspaceMembership.workspace_uuid == workspace_uuid, + WorkspaceMembership.account_uuid == owner_uuid, + ) + .values(role='viewer') + ) + denied = await client.put('/api/v1/workspaces/current/language', headers=headers, json={'language': 'ja_JP'}) + assert denied.status_code == 403 + assert (await denied.get_json())['msg'] == '没有执行此操作的权限' + visible = await client.get('/api/v1/workspaces/current/language', headers=headers) + assert visible.status_code == 200 + assert (await visible.get_json())['data']['language'] == 'zh_Hans' + + # An untrusted selector never causes us to read another tenant's language. + unauthorized = await client.get('/api/v1/workspaces/current/language', headers=_auth(owner_token, 'language-other')) + assert unauthorized.status_code in (403, 404) diff --git a/tests/integration/persistence/test_monitoring_postgres.py b/tests/integration/persistence/test_monitoring_postgres.py index ebfee7a7e..d46ff2107 100644 --- a/tests/integration/persistence/test_monitoring_postgres.py +++ b/tests/integration/persistence/test_monitoring_postgres.py @@ -7,6 +7,7 @@ no existing tables are dropped. Without that URL these tests are skipped. from __future__ import annotations +import datetime import logging import os import uuid @@ -19,6 +20,7 @@ from sqlalchemy.ext.asyncio import create_async_engine from langbot.pkg.api.http.context import ExecutionContext from langbot.pkg.api.http.service.monitoring import MonitoringService +from langbot.pkg.entity.persistence.agent_run import AgentRun from langbot.pkg.entity.persistence import monitoring as models from langbot.pkg.entity.persistence.workspace import Workspace from langbot.pkg.persistence.mgr import PersistenceManager, PersistenceMode @@ -158,6 +160,56 @@ async def _read(service, method, context, *args, **kwargs): return await getattr(service, method)(context, *args, **kwargs) +async def test_inflight_snapshot_reads_recent_utc_rows_and_terminal_transitions(service, cloud_database): + _, admin = cloud_database + now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) + old = now - datetime.timedelta(hours=1) + async with admin.begin() as conn: + for workspace, run_id, status, created_at in [ + (WORKSPACE_A, 'inflight-running', 'running', old), + (WORKSPACE_A, 'inflight-recent', 'completed', now), + (WORKSPACE_B, 'inflight-private', 'running', now), + ]: + await conn.execute( + sa.insert(AgentRun).values( + run_id=run_id, workspace_id=workspace, runner_id='runner', status=status, created_at=created_at + ) + ) + for message_id, timestamp in [('inflight-message', now), ('inflight-old-message', old)]: + await conn.execute( + sa.insert(models.MonitoringMessage).values( + id=message_id, + workspace_uuid=WORKSPACE_A, + timestamp=timestamp, + **RESOURCE, + message_content='hello', + session_id='session', + status='success', + level='info', + ) + ) + + try: + # The SSE producer owns its tenant scope after the HTTP handler has returned. + snapshot = await service.get_inflight_snapshot(_context(WORKSPACE_A)) + assert snapshot['active_total'] == 1 + assert {row['id'] for row in snapshot['items']} == {'inflight-running', 'inflight-recent', 'inflight-message'} + async with admin.begin() as conn: + await conn.execute( + sa.update(AgentRun).where(AgentRun.run_id == 'inflight-running').values(status='completed') + ) + snapshot = await service.get_inflight_snapshot(_context(WORKSPACE_A), snapshot['items']) + assert snapshot['active_total'] == 0 + assert next(row for row in snapshot['items'] if row['id'] == 'inflight-running')['status_group'] == 'completed' + finally: + async with admin.begin() as conn: + await conn.execute( + sa.delete(AgentRun).where( + AgentRun.run_id.in_(['inflight-running', 'inflight-recent', 'inflight-private']) + ) + ) + + def _query(context, sender_id): return SimpleNamespace( _execution_context=context, diff --git a/tests/unit_tests/api/http/test_entitlement_context.py b/tests/unit_tests/api/http/test_entitlement_context.py index 600eb1082..56232c999 100644 --- a/tests/unit_tests/api/http/test_entitlement_context.py +++ b/tests/unit_tests/api/http/test_entitlement_context.py @@ -76,3 +76,21 @@ def test_execution_context_preserves_entitlement_revision(): ) assert ExecutionContext.from_request(request).entitlement_revision == 11 + + +@pytest.mark.asyncio +async def test_handler_entitlement_denial_is_403_not_internal_error(): + from langbot.pkg.api.http.controller.group import AuthType + from langbot.pkg.cloud.entitlements import EntitlementFeatureUnavailableError + + router = _router(SimpleNamespace(mode='cloud')) + router.path = '/policy' + router.name = 'policy' + + @router.route('', methods=['GET'], auth_type=AuthType.NONE) + async def denied(): + raise EntitlementFeatureUnavailableError('platform.telegram', entitlement_revision=2) + + response = await router.quart_app.test_client().get('/policy') + assert response.status_code == 403 + assert (await response.get_json())['code'] == 'entitlement_unavailable' diff --git a/tests/unit_tests/api/http/test_route_tenant_scope.py b/tests/unit_tests/api/http/test_route_tenant_scope.py index 4b4cb96e6..26e5ae271 100644 --- a/tests/unit_tests/api/http/test_route_tenant_scope.py +++ b/tests/unit_tests/api/http/test_route_tenant_scope.py @@ -10,6 +10,7 @@ from sqlalchemy.ext.asyncio import create_async_engine from langbot.pkg.api.http.controller import group from langbot.pkg.persistence.mgr import PersistenceManager, PersistenceMode +from langbot.pkg.entity.persistence.metadata import WorkspaceMetadata pytestmark = pytest.mark.asyncio @@ -20,6 +21,8 @@ async def test_authenticated_route_does_not_hold_database_session_during_externa release = asyncio.Event() observations: list[bool] = [] engine = create_async_engine('sqlite+aiosqlite:///:memory:') + async with engine.begin() as connection: + await connection.run_sync(WorkspaceMetadata.__table__.create) persistence = PersistenceManager(object(), mode=PersistenceMode.CLOUD_RUNTIME) persistence.db = SimpleNamespace(get_engine=lambda: engine) @@ -60,7 +63,7 @@ async def test_authenticated_route_does_not_hold_database_session_during_externa ) ) try: - await entered.wait() + await asyncio.wait_for(entered.wait(), timeout=5) assert observations == [True] release.set() response = await request diff --git a/tests/unit_tests/api/service/test_monitoring_executions.py b/tests/unit_tests/api/service/test_monitoring_executions.py index 5d2ba0168..63fbd32b5 100644 --- a/tests/unit_tests/api/service/test_monitoring_executions.py +++ b/tests/unit_tests/api/service/test_monitoring_executions.py @@ -820,3 +820,27 @@ async def test_inflight_viewers_share_work_and_cleanup(): assert 'one' not in hub.channels and 'run' not in hub.run_workspaces await other.aclose() assert not hub.channels + + +@pytest.mark.asyncio +async def test_inflight_snapshot_failure_is_logged_and_recovers(caplog): + import asyncio + from unittest.mock import AsyncMock + from langbot.pkg.utils.inflight import InflightHub + + hub = InflightHub() + snapshot = {'items': [], 'active_total': 0, 'truncated': False} + loader = AsyncMock(side_effect=[RuntimeError('snapshot database failure'), snapshot]) + stream = hub.watch('workspace', loader) + try: + assert await asyncio.wait_for(anext(stream), 2) == {'kind': 'unavailable'} + errors = [ + record for record in caplog.records if record.message == 'Failed to load in-flight monitoring snapshot' + ] + assert len(errors) == 1 + assert errors[0].exc_info[0] is RuntimeError + hub.notify('workspace') + assert await asyncio.wait_for(anext(stream), 2) == {'kind': 'snapshot', 'data': snapshot} + finally: + await stream.aclose() + assert not hub.channels diff --git a/tests/unit_tests/api/service/test_monitoring_tenancy.py b/tests/unit_tests/api/service/test_monitoring_tenancy.py index 2e2b4216f..e745757c1 100644 --- a/tests/unit_tests/api/service/test_monitoring_tenancy.py +++ b/tests/unit_tests/api/service/test_monitoring_tenancy.py @@ -423,3 +423,21 @@ async def test_cleanup_commits_sqlite_delete_before_vacuum(tmp_path): assert remaining == 3 finally: await engine.dispose() + + +async def test_cloud_cleanup_uses_plan_retention_and_isolates_workspaces(service): + from unittest.mock import AsyncMock + + service.ap.deployment = SimpleNamespace(mode='cloud') + service.ap.entitlement_resolver = SimpleNamespace(resolve=AsyncMock(return_value=SimpleNamespace(limits={'chat_history.retention_days': 7}))) + old = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) - datetime.timedelta(days=10) + for workspace in (WORKSPACE_A, WORKSPACE_B): + await service.ap.persistence_mgr.execute_async(sqlalchemy.insert(MonitoringMessage).values( + id=f'policy-{workspace}', workspace_uuid=workspace, timestamp=old, + bot_id='bot', bot_name='Bot', pipeline_id='pipeline', pipeline_name='Pipeline', + message_content='history', session_id='session', status='success', level='info', + )) + deleted = await service.cleanup_expired_records(_context(WORKSPACE_A), retention_days=90) + assert deleted['monitoring_messages'] == 1 + rows = await service.ap.persistence_mgr.execute_async(sqlalchemy.select(MonitoringMessage.workspace_uuid)) + assert rows.scalars().all() == [WORKSPACE_B] diff --git a/tests/unit_tests/api/service/test_provider_cascade.py b/tests/unit_tests/api/service/test_provider_cascade.py index 1fd58e98d..971dafc3b 100644 --- a/tests/unit_tests/api/service/test_provider_cascade.py +++ b/tests/unit_tests/api/service/test_provider_cascade.py @@ -15,6 +15,7 @@ from langbot.pkg.api.http.controller.groups.provider.providers import ModelProvi from langbot.pkg.api.http.service.provider import ModelProviderService from langbot.pkg.entity.persistence.model import CodexCredential, EmbeddingModel, LLMModel, ModelProvider, RerankModel from langbot.pkg.entity.persistence.user import User +from langbot.pkg.entity.persistence.metadata import WorkspaceMetadata from langbot.pkg.entity.persistence.workspace import Workspace from langbot.pkg.persistence.mgr import PersistenceManager, PersistenceMode from langbot.pkg.provider.modelmgr.modelmgr import ModelManager @@ -51,7 +52,7 @@ async def deletion(tmp_path): } async with engine.begin() as conn: - for table in (User, Workspace, ModelProvider, CodexCredential, *MODEL_TYPES): + for table in (User, Workspace, WorkspaceMetadata, ModelProvider, CodexCredential, *MODEL_TYPES): await conn.run_sync(table.__table__.create) for workspace in contexts: await conn.execute( diff --git a/tests/unit_tests/api/service/test_user_service.py b/tests/unit_tests/api/service/test_user_service.py index 12b440b32..add2ea7b3 100644 --- a/tests/unit_tests/api/service/test_user_service.py +++ b/tests/unit_tests/api/service/test_user_service.py @@ -357,7 +357,7 @@ class TestUserServiceAuthenticate: service = UserService(ap) # Execute & Verify - with pytest.raises(ValueError, match='用户不存在'): + with pytest.raises(ValueError, match='Resource not found'): await service.authenticate('nonexistent@example.com', 'password') async def test_authenticate_space_user_without_password_raises_error(self): @@ -377,7 +377,7 @@ class TestUserServiceAuthenticate: service = UserService(ap) # Execute & Verify - with pytest.raises(ValueError, match='请使用 LangBot 账号登录'): + with pytest.raises(ValueError, match='Please sign in with your LangBot Account'): await service.authenticate('space@example.com', 'password') @@ -418,7 +418,6 @@ class TestUserServiceGenerateJwtToken: assert token is not None - class TestUserServiceVerifyJwtToken: """Tests for verify_jwt_token method.""" diff --git a/tests/unit_tests/api/test_bots_controller_errors.py b/tests/unit_tests/api/test_bots_controller_errors.py index c4949a7f8..1d8730c61 100644 --- a/tests/unit_tests/api/test_bots_controller_errors.py +++ b/tests/unit_tests/api/test_bots_controller_errors.py @@ -114,7 +114,12 @@ async def test_runtime_error_redacts_persisted_secrets_on_partial_update(): ) service = BotService(ap) service.get_bot = AsyncMock( - return_value={'uuid': 'bot-1', 'enable': True, 'adapter_config': {'app_secret': 'persisted-secret-value'}} + return_value={ + 'uuid': 'bot-1', + 'adapter': 'aiocqhttp', + 'enable': True, + 'adapter_config': {'app_secret': 'persisted-secret-value'}, + } ) with pytest.raises(BotApplyError) as captured: await service.update_bot('workspace-test', 'bot-1', {'enable': True}) diff --git a/tests/unit_tests/api/test_extensions_runtime_fence.py b/tests/unit_tests/api/test_extensions_runtime_fence.py index 12f36917e..02bff861f 100644 --- a/tests/unit_tests/api/test_extensions_runtime_fence.py +++ b/tests/unit_tests/api/test_extensions_runtime_fence.py @@ -99,7 +99,11 @@ async def test_extensions_route_redacts_plugin_secrets_without_mutating_runtime_ @pytest.mark.asyncio async def test_extensions_parallel_reads_open_explicit_child_task_scopes(): + from langbot.pkg.entity.persistence.metadata import WorkspaceMetadata + engine = create_async_engine('sqlite+aiosqlite:///:memory:') + async with engine.begin() as connection: + await connection.run_sync(WorkspaceMetadata.__table__.create) account = SimpleNamespace(uuid='account-a', user='owner@example.com') ap = SimpleNamespace() ap.persistence_mgr = PersistenceManager(ap) diff --git a/tests/unit_tests/api/test_mcp_server.py b/tests/unit_tests/api/test_mcp_server.py index 228b23ffa..3615f8286 100644 --- a/tests/unit_tests/api/test_mcp_server.py +++ b/tests/unit_tests/api/test_mcp_server.py @@ -65,3 +65,15 @@ async def test_mcp_server_exposes_bot_event_route_tools(): assert 'test_bot_event_route' not in tool_names assert 'list_processors' in tool_names assert 'list_agents' not in tool_names + assert 'get_workspace_message_language' in tool_names + language_tool = next(tool for tool in tools if tool.name == 'set_workspace_message_language') + assert set(language_tool.inputSchema['properties']['language']['enum']) == { + 'en_US', + 'zh_Hans', + 'zh_Hant', + 'ja_JP', + 'es_ES', + 'ru_RU', + 'th_TH', + 'vi_VN', + } diff --git a/tests/unit_tests/cloud/test_plan_policy.py b/tests/unit_tests/cloud/test_plan_policy.py new file mode 100644 index 000000000..20b5b36e8 --- /dev/null +++ b/tests/unit_tests/cloud/test_plan_policy.py @@ -0,0 +1,44 @@ +from types import SimpleNamespace +from unittest.mock import AsyncMock + +import pytest + +from langbot.pkg.cloud.entitlements import EntitlementFeatureUnavailableError, EntitlementUnavailableError +from langbot.pkg.cloud.plan_policy import require_workspace_platform, workspace_history_retention_days + + +def cloud_app(): + snapshots = { + 'restricted': SimpleNamespace(features={'platform.telegram': False}, limits={'chat_history.retention_days': 7}, entitlement_revision=2), + 'open': SimpleNamespace(features={}, limits={'chat_history.retention_days': 90}, entitlement_revision=3), + } + return SimpleNamespace(deployment=SimpleNamespace(mode='cloud'), entitlement_resolver=SimpleNamespace(resolve=AsyncMock(side_effect=lambda ws: snapshots[ws]))) + + +@pytest.mark.asyncio +async def test_platform_policy_is_scoped_and_covers_aliases(): + ap = cloud_app() + for adapter in ['telegram', 'telegram-omni', 'telegram-eba']: + with pytest.raises(EntitlementFeatureUnavailableError): + await require_workspace_platform(ap, 'restricted', adapter) + await require_workspace_platform(ap, 'open', adapter) + await require_workspace_platform(ap, 'restricted', 'discord') + + +@pytest.mark.asyncio +async def test_retention_uses_workspace_entitlement(): + ap = cloud_app() + assert await workspace_history_retention_days(ap, 'restricted', 100) == 7 + assert await workspace_history_retention_days(ap, 'open', 100) == 90 + + +@pytest.mark.asyncio +async def test_oss_and_unavailable_projection(): + ap = SimpleNamespace(deployment=SimpleNamespace(mode='local')) + await require_workspace_platform(ap, 'any', 'telegram') + assert await workspace_history_retention_days(ap, 'any', 60) == 60 + ap.deployment.mode = 'cloud' + with pytest.raises(EntitlementUnavailableError): + await require_workspace_platform(ap, 'any', 'telegram') + with pytest.raises(EntitlementUnavailableError): + await workspace_history_retention_days(ap, 'any') diff --git a/tests/unit_tests/pipeline/conftest.py b/tests/unit_tests/pipeline/conftest.py index 22d81e2b4..07567c1f7 100644 --- a/tests/unit_tests/pipeline/conftest.py +++ b/tests/unit_tests/pipeline/conftest.py @@ -88,6 +88,12 @@ class MockApplication: def _create_mock_persistence_manager(self): persistence_mgr = AsyncMock() persistence_mgr.execute_async = AsyncMock() + result = Mock(scalar_one_or_none=Mock(return_value=None)) + uow = AsyncMock() + uow.execute = AsyncMock(return_value=result) + boundary = AsyncMock() + boundary.__aenter__.return_value = uow + persistence_mgr.tenant_uow = Mock(return_value=boundary) return persistence_mgr def _create_mock_query_pool(self): diff --git a/tests/unit_tests/pipeline/test_banwords.py b/tests/unit_tests/pipeline/test_banwords.py index 2dcaf2cf4..a33a0a2e1 100644 --- a/tests/unit_tests/pipeline/test_banwords.py +++ b/tests/unit_tests/pipeline/test_banwords.py @@ -82,7 +82,7 @@ async def test_invalid_sensitive_word_regex_still_blocks(): result = await filt.process(Mock(), 'any message') assert result.level == entities.ResultLevel.BLOCK - assert result.user_notice == '内容检查规则执行失败,请联系管理员' + assert result.user_notice == 'Content checking failed. Please contact the administrator.' assert 'rejected' in result.console_notice.lower() or 'invalid' in result.console_notice.lower() @@ -97,7 +97,7 @@ async def test_oversized_word_list_is_blocked(): assert result.level == entities.ResultLevel.BLOCK assert result.replacement == '' - assert result.user_notice == '内容检查规则执行失败,请联系管理员' + assert result.user_notice == 'Content checking failed. Please contact the administrator.' assert 'at most 256 regex patterns are allowed' in result.console_notice.lower() diff --git a/tests/unit_tests/platform/test_botmgr_execution_trace.py b/tests/unit_tests/platform/test_botmgr_execution_trace.py index 2002f3045..1d805f77f 100644 --- a/tests/unit_tests/platform/test_botmgr_execution_trace.py +++ b/tests/unit_tests/platform/test_botmgr_execution_trace.py @@ -39,6 +39,7 @@ def make_bot(event_bindings: list[dict], config=None, agent=None): bot = object.__new__(RuntimeBot) bot.bot_entity = SimpleNamespace( uuid='bot-1', + adapter='aiocqhttp', workspace_uuid=TEST_CONTEXT.workspace_uuid, event_bindings=event_bindings, plugin_processors=[], @@ -49,6 +50,7 @@ def make_bot(event_bindings: list[dict], config=None, agent=None): bot.logger = SimpleNamespace(info=AsyncMock(), warning=AsyncMock(), error=AsyncMock(), debug=AsyncMock()) bot.adapter = FakeAdapter() bot.ap = SimpleNamespace( + workspace_service=SimpleNamespace(get_execution_binding=AsyncMock()), telemetry=SimpleNamespace(execution=counters), agent_service=SimpleNamespace(get_agent=AsyncMock(return_value=agent)), pipeline_service=SimpleNamespace(get_pipeline=AsyncMock(return_value=None)), @@ -505,11 +507,13 @@ async def test_pending_event_cancelled_during_dispatch_never_uploads(): bot._dispatch_eba_event_to_processor = waiting_dispatch task = asyncio.create_task(bot._handle_platform_event(message_received_event(), FakeAdapter())) - await started.wait() - await counters.flush() - task.cancel() - with pytest.raises(asyncio.CancelledError): - await task + try: + await asyncio.wait_for(started.wait(), timeout=5) + await counters.flush() + finally: + task.cancel() + with pytest.raises(asyncio.CancelledError): + await task await assert_no_upload(counters, manager) diff --git a/tests/unit_tests/platform/test_botmgr_tenancy.py b/tests/unit_tests/platform/test_botmgr_tenancy.py index 6a1b0a6d2..9687ff8bf 100644 --- a/tests/unit_tests/platform/test_botmgr_tenancy.py +++ b/tests/unit_tests/platform/test_botmgr_tenancy.py @@ -38,6 +38,7 @@ def _runtime(application, workspace_uuid: str, bot_uuid: str) -> RuntimeBot: uuid=bot_uuid, workspace_uuid=workspace_uuid, name='Same Name', + adapter='aiocqhttp', enable=True, event_bindings=[], ) @@ -327,6 +328,7 @@ def test_runtime_bot_rejects_workspace_mismatch(): uuid=BOT_A, workspace_uuid=WORKSPACE_A, name='Bot', + adapter='aiocqhttp', enable=True, event_bindings=[], ) @@ -386,6 +388,7 @@ async def test_platform_callback_carries_scope_without_holding_database_session( uuid=BOT_A, workspace_uuid=WORKSPACE_A, name='Bot', + adapter='aiocqhttp', enable=True, event_bindings=[], ) diff --git a/tests/unit_tests/platform/test_lark_eba_adapter.py b/tests/unit_tests/platform/test_lark_eba_adapter.py index 209e9a2a6..9db1d3c28 100644 --- a/tests/unit_tests/platform/test_lark_eba_adapter.py +++ b/tests/unit_tests/platform/test_lark_eba_adapter.py @@ -881,9 +881,9 @@ async def test_lark_webhook_dispatches_native_form_submission(): response = await adapter.handle_unified_webhook('bot-1', '', request) - assert response['toast'] == {'type': 'success', 'content': 'Submitted / 已提交'} + assert response['toast'] == {'type': 'success', 'content': 'Submitted'} assert response['card']['type'] == 'raw' - assert response['card']['data']['elements'][0]['text']['content'] == '**Submitted / 已提交**' + assert response['card']['data']['elements'][0]['text']['content'] == '**Submitted**' assert len(calls) == 1 assert calls[0].action == 'interaction.submitted' assert calls[0].data['callback_token'] == 'callback-token' @@ -912,7 +912,7 @@ async def test_lark_webhook_cardkit_submission_uses_async_card_update_only(): response = await adapter.handle_unified_webhook('bot-1', '', request) - assert response == {'toast': {'type': 'success', 'content': 'Submitted / 已提交'}} + assert response == {'toast': {'type': 'success', 'content': 'Submitted'}} def test_lark_stream_card_separates_multiple_reasoning_rounds(): diff --git a/tests/unit_tests/platform/test_plugin_subscriptions.py b/tests/unit_tests/platform/test_plugin_subscriptions.py index d074bf659..64f56aa57 100644 --- a/tests/unit_tests/platform/test_plugin_subscriptions.py +++ b/tests/unit_tests/platform/test_plugin_subscriptions.py @@ -14,8 +14,13 @@ from langbot.pkg.persistence.tenant_uow import PersistenceScope, PersistenceScop def make_bot(subscriptions): bot = object.__new__(RuntimeBot) - bot.bot_entity = SimpleNamespace(uuid='bot', event_bindings=[], plugin_processors=subscriptions) + bot.bot_entity = SimpleNamespace( + uuid='bot', adapter='aiocqhttp', event_bindings=[], plugin_processors=subscriptions + ) bot.execution_context = 'workspace' + bot.workspace_uuid = 'workspace' + bot.placement_generation = 1 + bot.ap = SimpleNamespace(workspace_service=SimpleNamespace(get_execution_binding=AsyncMock())) bot._record_adapter_event = AsyncMock() bot._record_event_route_trace = AsyncMock() bot.logger = SimpleNamespace(error=AsyncMock()) @@ -124,7 +129,8 @@ async def test_cloud_deliveries_own_their_scope_and_preserve_parent(primary_fail ) bot.ap = SimpleNamespace( - persistence_mgr=SimpleNamespace(mode=SimpleNamespace(value='cloud_runtime'), tenant_scope=tenant_scope) + workspace_service=SimpleNamespace(get_execution_binding=AsyncMock()), + persistence_mgr=SimpleNamespace(mode=SimpleNamespace(value='cloud_runtime'), tenant_scope=tenant_scope), ) seen = [] diff --git a/tests/unit_tests/platform/test_routing_rules.py b/tests/unit_tests/platform/test_routing_rules.py index 08fe64051..c35788a39 100644 --- a/tests/unit_tests/platform/test_routing_rules.py +++ b/tests/unit_tests/platform/test_routing_rules.py @@ -38,6 +38,7 @@ class TestEventRouteTrace: bot = object.__new__(RuntimeBot) bot.bot_entity = SimpleNamespace( uuid='bot-1', + adapter='aiocqhttp', workspace_uuid=TEST_CONTEXT.workspace_uuid, event_bindings=event_bindings, ) @@ -703,7 +704,10 @@ async def test_installed_event_processor_never_receives_unbound_events(): from langbot_plugin.api.entities.builtin.platform.events import MemberJoinedEvent bot = TestEventRouteTrace._make_bot([]) - bot.ap = SimpleNamespace(plugin_connector=SimpleNamespace(emit_event=AsyncMock())) + bot.ap = SimpleNamespace( + workspace_service=active_workspace_service(), + plugin_connector=SimpleNamespace(emit_event=AsyncMock()), + ) bot._record_adapter_event = AsyncMock() await bot._handle_platform_event(MemberJoinedEvent(), Mock()) bot.ap.plugin_connector.emit_event.assert_not_called() diff --git a/tests/unit_tests/platform/test_websocket_session_isolation.py b/tests/unit_tests/platform/test_websocket_session_isolation.py index 18dad8a29..d6c123695 100644 --- a/tests/unit_tests/platform/test_websocket_session_isolation.py +++ b/tests/unit_tests/platform/test_websocket_session_isolation.py @@ -596,7 +596,8 @@ def test_widget_sends_stable_session_id_to_all_conversation_endpoints(): assert 'window.sessionStorage' in widget assert 'window.localStorage' not in widget assert 'session_id=' in widget - assert widget.count('encodeURIComponent(state.sessionId)') >= 3 + assert widget.count('encodeURIComponent(state.sessionId)') >= 2 + assert 'endpoint.searchParams.set("session_id", state.sessionId)' in widget assert 'loadHistory(true)' in widget assert 'messageVersion !== state.messageVersion' in widget assert 'scheduleHistoryReload();' in widget diff --git a/tests/unit_tests/provider/test_litellmchat.py b/tests/unit_tests/provider/test_litellmchat.py index f73fac2e4..311367d5f 100644 --- a/tests/unit_tests/provider/test_litellmchat.py +++ b/tests/unit_tests/provider/test_litellmchat.py @@ -767,7 +767,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(error) - assert '请求参数错误' in str(exc_info.value) + assert 'Invalid request parameters' in str(exc_info.value) def test_authentication_error(self): """Test AuthenticationError translation""" @@ -778,7 +778,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(error) - assert 'API key 无效' in str(exc_info.value) + assert 'Invalid API key' in str(exc_info.value) def test_rate_limit_error(self): """Test RateLimitError translation""" @@ -789,7 +789,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(error) - assert '请求过于频繁' in str(exc_info.value) + assert 'Rate limit exceeded' in str(exc_info.value) def test_timeout_error(self): """Test Timeout translation""" @@ -800,7 +800,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(error) - assert '请求超时' in str(exc_info.value) + assert 'Request timed out' in str(exc_info.value) def test_context_window_error(self): """Test ContextWindowExceededError translation""" @@ -811,7 +811,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(error) - assert '上下文长度超限' in str(exc_info.value) + assert 'Context length exceeded' in str(exc_info.value) def test_unknown_error(self): """Test unknown error translation""" @@ -820,7 +820,7 @@ class TestHandleLiteLLMError: with pytest.raises(errors.RequesterError) as exc_info: requester._handle_litellm_error(Exception('unknown')) - assert '未知错误' in str(exc_info.value) + assert 'Unknown error' in str(exc_info.value) class TestInvokeLLM: @@ -976,7 +976,7 @@ class TestInvokeLLM: messages=messages, ) - assert 'API key 无效' in str(exc_info.value) + assert 'Invalid API key' in str(exc_info.value) class TestInvokeEmbedding: diff --git a/tests/unit_tests/provider/test_request_policy.py b/tests/unit_tests/provider/test_request_policy.py index 5fb873d17..c8b0eb448 100644 --- a/tests/unit_tests/provider/test_request_policy.py +++ b/tests/unit_tests/provider/test_request_policy.py @@ -43,7 +43,7 @@ def test_policy_precedence_zero_and_no_mutation(): ], ) def test_invalid_policy(policy): - with pytest.raises(RequesterError, match='模型请求失败'): + with pytest.raises(RequesterError, match='Model request failed|模型请求失败'): RequestPolicy.resolve({'request_policy': policy}) diff --git a/tests/unit_tests/provider/test_requester_base.py b/tests/unit_tests/provider/test_requester_base.py index 4ed1335fb..017c9e705 100644 --- a/tests/unit_tests/provider/test_requester_base.py +++ b/tests/unit_tests/provider/test_requester_base.py @@ -563,7 +563,7 @@ def test_requester_error_message_format(): """Test RequesterError message format.""" error = RequesterError('API returned 500') - assert '模型请求失败' in str(error) + assert 'Model request failed' in str(error) assert 'API returned 500' in str(error) diff --git a/tests/unit_tests/test_backend_i18n.py b/tests/unit_tests/test_backend_i18n.py new file mode 100644 index 000000000..a43f4113d --- /dev/null +++ b/tests/unit_tests/test_backend_i18n.py @@ -0,0 +1,107 @@ +"""Runtime language isolation, catalog completeness, and Pipeline overrides.""" + +import asyncio +import json +import string +from pathlib import Path +from types import SimpleNamespace + +import pytest + +from langbot.pkg import i18n +from langbot.pkg.i18n.adapters import adapter_t, localized_adapter +from langbot.pkg.provider.modelmgr.errors import RequesterError + + +def test_catalogs_have_matching_keys_and_placeholders(): + folder = Path(i18n.__file__).parent / 'locales' + catalogs = { + locale: json.loads((folder / f'{locale}.json').read_text(encoding='utf-8')) + for locale in i18n.SUPPORTED_LANGUAGES + } + english = catalogs['en_US'] + formatter = string.Formatter() + + def fields(text): + return {name for _, name, _, _ in formatter.parse(text) if name is not None} + + for locale, catalog in catalogs.items(): + assert catalog.keys() == english.keys(), locale + for key, text in catalog.items(): + assert text.strip(), (locale, key) + assert fields(text) == fields(key), (locale, key) + + +@pytest.mark.asyncio +async def test_concurrent_requests_and_children_keep_their_language(): + async def render(locale): + with i18n.language_scope(locale): + + async def child(): + await asyncio.sleep(0) + return str(RequesterError(i18n.t('Request timed out'))) + + return await asyncio.create_task(child()) + + assert await asyncio.gather(render('zh_Hans'), render('ja_JP'), render('en_US')) == [ + '模型请求失败: 请求超时', + 'モデルへのリクエストに失敗しました: リクエストがタイムアウトしました', + 'Model request failed: Request timed out', + ] + assert i18n.language.get() == 'en_US' + with pytest.raises(RuntimeError), i18n.language_scope('zh_Hans'): + raise RuntimeError('interrupted') + assert i18n.language.get() == 'en_US' + + +def test_pipeline_overrides_inherit_language_and_preserve_literal_braces(): + query = SimpleNamespace(pipeline_config={'output': {'misc': {}}}) + with i18n.language_scope('zh_Hans'): + assert i18n.pipeline_notice(query, 'failure-hint', 'Request failed.') == '请求失败。' + query.pipeline_config['output']['misc']['failure-hint'] = 'Request failed.' + assert i18n.pipeline_notice(query, 'failure-hint', 'Request failed.') == '请求失败。' + query.pipeline_config['output']['misc']['failure-hint'] = 'My custom notice {literal}' + assert i18n.pipeline_notice(query, 'failure-hint', 'Request failed.') == 'My custom notice {literal}' + query.pipeline_config['output']['misc']['tool-call-hint'] = 'Using {tools}; keep {other}' + assert i18n.pipeline_notice(query, 'tool-call-hint', 'Calling {tools}...', tools='search') == ( + 'Using search; keep {other}' + ) + + +def test_diagnostics_are_never_parsed_or_rewritten(): + diagnostic = 'upstream: {"error": "some provider detail"}' + with i18n.language_scope('zh_Hans'): + assert i18n.t(diagnostic) == diagnostic + assert i18n.error_text('permission_denied', 'Missing Workspace permission: workspace.update') == ( + '没有执行此操作的权限' + ) + assert i18n.t('Please do not replace model not found in user content') == ( + 'Please do not replace model not found in user content' + ) + + +@pytest.mark.asyncio +async def test_adapter_callbacks_use_their_owner_not_the_callers_language(): + app = SimpleNamespace(_message_language_cache={'bot-workspace': ('ja_JP', float('inf'))}) + + class Adapter: + logger = SimpleNamespace(ap=app, execution_context=SimpleNamespace(workspace_uuid='bot-workspace')) + + @localized_adapter + async def reply(self): + return i18n.t('Submitted') + + with i18n.language_scope('zh_Hans'): + assert await Adapter().reply() == '送信済み' + assert adapter_t(Adapter(), 'Submitted') == '送信済み' + assert i18n.language.get() == 'zh_Hans' + + +def test_lark_card_uses_selected_language(): + from langbot.pkg.platform.adapters.lark.stream_card import build_card + + with i18n.language_scope('ja_JP'): + card = json.dumps(build_card('reasonanswer'), ensure_ascii=False) + assert '思考過程' in card + assert 'AI による生成コンテンツ' in card + assert 'Thinking' not in card diff --git a/tests/unit_tests/test_workspace_subscription_limits.py b/tests/unit_tests/test_workspace_subscription_limits.py new file mode 100644 index 000000000..c16604ed9 --- /dev/null +++ b/tests/unit_tests/test_workspace_subscription_limits.py @@ -0,0 +1,41 @@ +import asyncio +from types import SimpleNamespace + +import pytest + +from langbot.pkg.cloud.entitlements import EntitlementSnapshot, EntitlementUnavailableError +from langbot.pkg.api.http.service.workspace_limits import workspace_limits + + +def test_oss_retains_instance_limits(): + ap = SimpleNamespace(instance_config=SimpleNamespace(data={'system': {'limitation': {'max_bots': 7}}})) + assert asyncio.run(workspace_limits(ap, 'one')) == {'max_bots': 7} + + +def test_cloud_uses_signed_workspace_limits(): + class Resolver: + async def resolve(self, workspace_uuid, **kwargs): + assert workspace_uuid == 'one' + return EntitlementSnapshot( + instance_uuid='i', + workspace_uuid='one', + entitlement_revision=1, + status='active', + not_before=0, + expires_at=9999999999, + limits={'bots.max': 2, 'pipelines.max': 3, 'plugins.max': 4, 'knowledge_bases.max': 5}, + ) + + ap = SimpleNamespace(deployment=SimpleNamespace(mode='cloud'), entitlement_resolver=Resolver()) + assert asyncio.run(workspace_limits(ap, 'one')) == { + 'max_bots': 2, + 'max_pipelines': 3, + 'max_extensions': 4, + 'max_knowledge_bases': 5, + } + + +def test_cloud_missing_resolver_fails_closed(): + ap = SimpleNamespace(deployment=SimpleNamespace(mode='cloud')) + with pytest.raises(EntitlementUnavailableError): + asyncio.run(workspace_limits(ap, 'one')) diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index a861a5328..4838d2a6f 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -29,70 +29,70 @@ dependencies: version: 4.6.2 '@hookform/resolvers': specifier: ^5.0.1 - version: 5.2.2(react-hook-form@7.71.1) + version: 5.9.1(react-hook-form@7.90.0)(zod@3.25.76) '@radix-ui/react-alert-dialog': specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-avatar': specifier: ^1.1.11 - version: 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.2.7(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-checkbox': specifier: ^1.3.1 - version: 1.3.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.3.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-collapsible': specifier: ^1.1.12 - version: 1.1.12(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-context-menu': specifier: ^2.2.15 - version: 2.2.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-dialog': specifier: ^1.1.14 - version: 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.16 - version: 2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-hover-card': specifier: ^1.1.13 - version: 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-label': specifier: ^2.1.6 - version: 2.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 2.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-popover': specifier: ^1.1.14 - version: 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-progress': specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.17(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-scroll-area': specifier: ^1.2.9 - version: 1.2.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-select': specifier: ^2.2.4 - version: 2.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-separator': specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-slider': specifier: ^1.4.7 - version: 1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.5.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-slot': specifier: ^1.2.3 - version: 1.2.4(@types/react@19.2.10)(react@19.2.1) + version: 1.4.0(@types/react@19.2.18)(react@19.2.1) '@radix-ui/react-switch': specifier: ^1.2.4 - version: 1.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-tabs': specifier: ^1.1.11 - version: 1.1.13(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.22(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-toggle': specifier: ^1.1.8 - version: 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.19(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-toggle-group': specifier: ^1.1.9 - version: 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@radix-ui/react-tooltip': specifier: ^1.2.7 - version: 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) '@remixicon/react': specifier: ^4.9.0 version: 4.9.0(react@19.2.1) @@ -101,16 +101,16 @@ dependencies: version: 14.0.0 '@tailwindcss/postcss': specifier: ^4.1.5 - version: 4.1.18 + version: 4.3.3 '@tanstack/react-table': specifier: ^8.21.3 version: 8.21.3(react-dom@19.2.1)(react@19.2.1) '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.16) + version: 6.1.2(vite@8.3.4) axios: specifier: ^1.16.0 - version: 1.17.0 + version: 1.20.0 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -119,19 +119,19 @@ dependencies: version: 2.1.1 cmdk: specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.1.1(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) highlight.js: specifier: ^11.11.1 - version: 11.11.1 + version: 11.12.0 i18next: specifier: ^25.1.2 - version: 25.8.0(typescript@5.9.3) + version: 25.10.10(typescript@5.9.3) i18next-browser-languagedetector: specifier: ^8.1.0 - version: 8.2.0 + version: 8.2.1 input-otp: specifier: ^1.4.2 - version: 1.4.2(react-dom@19.2.1)(react@19.2.1) + version: 1.5.0(react-dom@19.2.1)(react@19.2.1) lodash: specifier: ^4.18.0 version: 4.18.1 @@ -140,13 +140,13 @@ dependencies: version: 0.507.0(react@19.2.1) postcss: specifier: ^8.5.10 - version: 8.5.15 + version: 8.5.29 qrcode: specifier: ^1.5.4 version: 1.5.4 radix-ui: specifier: ^1.6.0 - version: 1.6.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + version: 1.7.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) react: specifier: 19.2.1 version: 19.2.1 @@ -155,22 +155,22 @@ dependencies: version: 19.2.1(react@19.2.1) react-hook-form: specifier: ^7.56.3 - version: 7.71.1(react@19.2.1) + version: 7.90.0(@types/react@19.2.18)(react@19.2.1) react-i18next: specifier: ^15.5.1 - version: 15.7.4(i18next@25.8.0)(react-dom@19.2.1)(react@19.2.1)(typescript@5.9.3) + version: 15.7.4(i18next@25.10.10)(react-dom@19.2.1)(react@19.2.1)(typescript@5.9.3) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.10)(react@19.2.1) + version: 10.1.0(@types/react@19.2.18)(react@19.2.1) react-photo-view: specifier: ^1.2.7 version: 1.2.7(react-dom@19.2.1)(react@19.2.1) react-router-dom: specifier: ^7.15.0 - version: 7.17.0(react-dom@19.2.1)(react@19.2.1) + version: 7.18.4(react-dom@19.2.1)(react@19.2.1) react-syntax-highlighter: specifier: ^16.1.0 - version: 16.1.0(react@19.2.1) + version: 16.1.2(react@19.2.1) recharts: specifier: 2.15.4 version: 2.15.4(react-dom@19.2.1)(react@19.2.1) @@ -194,19 +194,19 @@ dependencies: version: 4.0.1 sonner: specifier: ^2.0.3 - version: 2.0.7(react-dom@19.2.1)(react@19.2.1) + version: 2.0.8(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) tailwind-merge: specifier: ^3.2.0 - version: 3.4.0 + version: 3.7.0 tailwindcss: specifier: ^4.1.5 - version: 4.1.18 + version: 4.3.3 uuidjs: specifier: ^5.1.0 version: 5.1.0 vite: specifier: ^8.0.16 - version: 8.0.16(@types/node@20.19.30) + version: 8.3.4(@types/node@20.19.43) zod: specifier: ^3.24.4 version: 3.25.76 @@ -214,22 +214,22 @@ dependencies: devDependencies: '@playwright/test': specifier: ^1.61.0 - version: 1.61.0 + version: 1.64.0 '@types/debug': specifier: ^4.1.12 - version: 4.1.12 + version: 4.1.13 '@types/estree': specifier: ^1.0.8 - version: 1.0.8 + version: 1.0.9 '@types/estree-jsx': specifier: ^1.0.5 version: 1.0.5 '@types/hast': specifier: ^3.0.4 - version: 3.0.4 + version: 3.0.5 '@types/lodash': specifier: ^4.17.16 - version: 4.17.23 + version: 4.17.26 '@types/mdast': specifier: ^4.0.4 version: 4.0.4 @@ -238,16 +238,16 @@ devDependencies: version: 2.1.0 '@types/node': specifier: ^20 - version: 20.19.30 + version: 20.19.43 '@types/qrcode': specifier: ^1.5.6 version: 1.5.6 '@types/react': specifier: ~19.2.7 - version: 19.2.10 + version: 19.2.18 '@types/react-dom': specifier: ~19.2.3 - version: 19.2.3(@types/react@19.2.10) + version: 19.2.7(@types/react@19.2.18) '@types/react-syntax-highlighter': specifier: ^15.5.13 version: 15.5.13 @@ -256,25 +256,25 @@ devDependencies: version: 3.0.3 eslint: specifier: ^9 - version: 9.39.2 + version: 9.39.5 eslint-config-prettier: specifier: ^10.1.2 - version: 10.1.8(eslint@9.39.2) + version: 10.1.8(eslint@9.39.5) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint-config-prettier@10.1.8)(eslint@9.39.2)(prettier@3.8.1) + version: 5.5.6(eslint-config-prettier@10.1.8)(eslint@9.39.5)(prettier@3.9.10) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.2) + version: 7.37.5(eslint@9.39.5) eslint-plugin-react-hooks: specifier: ^5.2.0 - version: 5.2.0(eslint@9.39.2) + version: 5.2.0(eslint@9.39.5) lint-staged: specifier: ^15.5.1 version: 15.5.2 prettier: specifier: ^3.5.3 - version: 3.8.1 + version: 3.9.10 tw-animate-css: specifier: ^1.2.9 version: 1.4.0 @@ -283,17 +283,17 @@ devDependencies: version: 5.9.3 typescript-eslint: specifier: ^8.31.1 - version: 8.54.0(eslint@9.39.2)(typescript@5.9.3) + version: 8.71.1(eslint@9.39.5)(typescript@5.9.3) packages: - /@alloc/quick-lru@5.2.0: - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + /@alloc/quick-lru@5.3.0: + resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==} engines: {node: '>=10'} dev: false - /@babel/runtime@7.28.6: - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + /@babel/runtime@7.29.10: + resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==} engines: {node: '>=6.9.0'} dev: false @@ -340,38 +340,13 @@ packages: tslib: 2.8.1 dev: false - /@emnapi/core@1.10.0: - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - requiresBuild: true - dependencies: - '@emnapi/wasi-threads': 1.2.1 - tslib: 2.8.1 - dev: false - optional: true - - /@emnapi/runtime@1.10.0: - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - requiresBuild: true - dependencies: - tslib: 2.8.1 - dev: false - optional: true - - /@emnapi/wasi-threads@1.2.1: - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - requiresBuild: true - dependencies: - tslib: 2.8.1 - dev: false - optional: true - - /@eslint-community/eslint-utils@4.9.1(eslint@9.39.2): - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + /@eslint-community/eslint-utils@4.10.1(eslint@9.39.5): + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 9.39.2 + eslint: 9.39.5 eslint-visitor-keys: 3.4.3 dev: true @@ -380,13 +355,13 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint/config-array@0.21.1: - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + /@eslint/config-array@0.21.2: + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: '@eslint/object-schema': 2.1.7 debug: 4.4.3 - minimatch: 3.1.3 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color dev: true @@ -405,25 +380,25 @@ packages: '@types/json-schema': 7.0.15 dev: true - /@eslint/eslintrc@3.3.3: - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + /@eslint/eslintrc@3.3.7: + resolution: {integrity: sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - ajv: 6.12.6 + ajv: 6.15.0 debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.2.0 - minimatch: 3.1.3 + js-yaml: 4.3.2 + minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color dev: true - /@eslint/js@9.39.2: - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + /@eslint/js@9.39.5: + resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -446,56 +421,138 @@ packages: tslib: 2.8.1 dev: false - /@floating-ui/core@1.7.4: - resolution: {integrity: sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==} + /@floating-ui/core@1.8.0: + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} dependencies: - '@floating-ui/utils': 0.2.10 + '@floating-ui/utils': 0.2.12 dev: false - /@floating-ui/dom@1.7.5: - resolution: {integrity: sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==} + /@floating-ui/dom@1.8.0: + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} dependencies: - '@floating-ui/core': 1.7.4 - '@floating-ui/utils': 0.2.10 + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 dev: false - /@floating-ui/react-dom@2.1.7(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==} + /@floating-ui/react-dom@2.1.9(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@floating-ui/dom': 1.7.5 + '@floating-ui/dom': 1.8.0 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@floating-ui/utils@0.2.10: - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + /@floating-ui/utils@0.2.12: + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} dev: false - /@hookform/resolvers@5.2.2(react-hook-form@7.71.1): - resolution: {integrity: sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==} + /@hookform/resolvers@5.9.1(react-hook-form@7.90.0)(zod@3.25.76): + resolution: {integrity: sha512-7b7vsbraJxKgjVSA1Nur9tLwj539WGJUBLA7QNvXnFoT2pM5Z7G+6rlukk4B2/QrTZy6huRtH6wKeESPKuIr6w==} peerDependencies: + '@sinclair/typebox': '>=0.25.24' + '@standard-schema/spec': ^1.0.0 + '@typeschema/main': '>=0.13.7' + '@vinejs/vine': ^2.0.0 || ^3.0.0 || ^4.0.0 + ajv: ^8.12.0 + ajv-errors: ^3.0.0 + ajv-formats: ^2.1.1 + arktype: ^2.0.0 + ata-validator: ^1.2.0 + class-transformer: '>=0.4.0' + class-validator: '>=0.12.0' + computed-types: ^1.0.0 + effect: ^3.10.3 + fluentvalidation-ts: ^3.0.0 + fp-ts: ^2.7.0 + io-ts: ^2.0.0 + joi: ^17.0.0 || ^18.0.0 + nope-validator: '>=0.12.0' react-hook-form: ^7.55.0 + superstruct: '>=0.12.0' + typanion: ^3.3.2 + valibot: '>=0.31.0 || ^1.0.0-beta.4 || ^1.0.0-rc' + vest: '>=6.0.0' + yup: ^1.0.0 + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@sinclair/typebox': + optional: true + '@standard-schema/spec': + optional: true + '@typeschema/main': + optional: true + '@vinejs/vine': + optional: true + ajv: + optional: true + ajv-errors: + optional: true + ajv-formats: + optional: true + arktype: + optional: true + ata-validator: + optional: true + class-transformer: + optional: true + class-validator: + optional: true + computed-types: + optional: true + effect: + optional: true + fluentvalidation-ts: + optional: true + fp-ts: + optional: true + io-ts: + optional: true + joi: + optional: true + nope-validator: + optional: true + superstruct: + optional: true + typanion: + optional: true + valibot: + optional: true + vest: + optional: true + yup: + optional: true + zod: + optional: true dependencies: '@standard-schema/utils': 0.3.0 - react-hook-form: 7.71.1(react@19.2.1) + react-hook-form: 7.90.0(@types/react@19.2.18)(react@19.2.1) + zod: 3.25.76 dev: false - /@humanfs/core@0.19.1: - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - dev: true - - /@humanfs/node@0.16.7: - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + /@humanfs/core@0.19.2: + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} dependencies: - '@humanfs/core': 0.19.1 + '@humanfs/types': 0.15.0 + dev: true + + /@humanfs/node@0.16.8: + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 '@humanwhocodes/retry': 0.4.3 dev: true + /@humanfs/types@0.15.0: + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + dev: true + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -509,7 +566,7 @@ packages: /@jridgewell/gen-mapping@0.3.13: resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 dev: false @@ -525,65 +582,44 @@ packages: engines: {node: '>=6.0.0'} dev: false - /@jridgewell/sourcemap-codec@1.5.5: - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + /@jridgewell/sourcemap-codec@1.6.0: + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} dev: false /@jridgewell/trace-mapping@0.3.31: resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 dev: false - /@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0): - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} - requiresBuild: true - peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 - dev: false - optional: true - - /@oxc-project/types@0.133.0: - resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + /@oxc-project/types@0.153.0: + resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==} dev: false - /@pkgr/core@0.2.9: - resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + /@pkgr/core@0.3.6: + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} dev: true - /@playwright/test@1.61.0: - resolution: {integrity: sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==} - engines: {node: '>=18'} + /@playwright/test@1.64.0: + resolution: {integrity: sha512-oTN9FNYuN6bqQMwiho6jJKLCG2/QOYCixGXuCjRmzOq23eODeukuY2XiAVoVpAECbuezMt1MHQjAiQxK8F+Y+g==} + engines: {node: '>=20'} hasBin: true dependencies: - playwright: 1.61.0 + playwright: 1.64.0 dev: true - /@radix-ui/number@1.1.1: - resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - dev: false - /@radix-ui/number@1.1.3: resolution: {integrity: sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA==} dev: false - /@radix-ui/primitive@1.1.3: - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - dev: false - /@radix-ui/primitive@1.1.7: resolution: {integrity: sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q==} dev: false - /@radix-ui/react-accessible-icon@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-WTQwcAvQf5sOcuUyi90lKPbhwcvQ+j55cjrSmeaN+L2vKU3DooOvlKw2MDeiJ5IkV5N905KW0/fGojKOBhD11A==} + /@radix-ui/react-accessible-icon@1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-I+T/Hc6SY3WbFVZ9Ne1o0DJbpjQpTpLIBZcVzYiHCQ9z1yGUd/G88u5SKyM6eJ223txAOS7bp7bb9k0Ocfkjwg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -595,15 +631,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-accordion@1.2.20(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==} + /@radix-ui/react-accordion@1.2.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-2fmc6COuKLq2k3P7JZrOt9Zf8HT9nTQhHN5V+A3ih7ftqoyDcoEUrPoLq8ngr7QwTd7hpQ2xoUKWtvy1Xw9RAQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -616,47 +652,22 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collapsible': 1.1.20(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collapsible': 1.1.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-alert-dialog@1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-VAYOiQRqj3GPpYJE0I9J+X8Ip05cyVlNdKOFeiGS2Ou1HHGfpl0BxOyZm6nmVDyU+W+NF3/XLzmjHmVGydhwgA==} + /@radix-ui/react-alert-dialog@1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-dRvB59HhcjIWcCPKzK5Px1yQ8pIULQQrxqgyepCqin7tNXi/xvmC86WkyMOKhuCbjz3+v9Q6oE7/tUN5NQ9dCg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -669,18 +680,18 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dialog': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-arrow@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==} + /@radix-ui/react-arrow@1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-nXPI1tzJsnQw8oXvB2r49rO9TIbbJ8VFeaWDiBsqY8+iwO5xb7WjUsrXDagjAgPKTdhW8WODQnAltUhBx8I+sg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -692,15 +703,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + /@radix-ui/react-aspect-ratio@1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-w2u6oiTzb7WkWwV3ZClX/llYYlTbilUOkHIKkwb+PWWytQ/IdEVRNLIChjbcXy/mkqcKKM3wEhrOilJW+uPHDg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -712,59 +723,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-aspect-ratio@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-fy+dyVR+90nelK8rqIznFlxzx7uPcGbhxH8Nfr2bHb4UfSe+e3hklOC0luK0hDwVwnRX7xTRySpsrQVeW+/oNQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-avatar@1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-avatar@1.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-4ULOTJ/mqy2hT9GlWa/MFHxHSvH3nJzHnZM1waNsc5Bonv7i70aNenghXmD97S6OJ81ekXONGGt4nT1r0PfEdA==} + /@radix-ui/react-avatar@1.2.7(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-6AizCpbU3Zngojp9vQak8Lt4AXwdKJ2lkRYAfpoETraT+qKVNeRqytiADzneHetFEB0Wu4+qeSfmZEq0PiVDmQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -777,19 +744,19 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-checkbox@1.3.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ==} + /@radix-ui/react-checkbox@1.3.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-gNOS2lLrpQxNLWHhCX0sayfVRiyB5gQp7nQIzpl+PM1Hkab52utsKtD27alAr78uqhpvX51kwqDp71hM5hNSwg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -802,74 +769,20 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-collapsible@1.1.20(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==} + /@radix-ui/react-collapsible@1.1.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-IzkusZHCZBnED5skW+b+syl8d+e3+zelvxZ2Ed9lfawqEBfa5osPj53sTJ+q/uNmGAj9e7wMYgyzwPu/luWJ4Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -882,21 +795,21 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-collection@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==} + /@radix-ui/react-collection@1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-yEQrjfI5eBbeYEJXOASpm+gs9eNHY8+UjkZ81GzcuwdLrSMOlEM8jnGoGdeGo92oiBMkuwZUhHTsnsrDiJLcyA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -908,53 +821,17 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-compose-refs@1.1.5(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-compose-refs@1.1.5(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} peerDependencies: '@types/react': '*' @@ -963,37 +840,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-context-menu@2.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-CtXP35dxaB5T3zXSd+E3uHe/QpXcpYnZmxp6OaIbfthtfW4wyb77M23BG+bwIJDtsMwEP/YssdsmNyZu7jhWew==} + /@radix-ui/react-context-menu@2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-s8ABBkEuAOyhDub0Y99f8lVRlVsd28mUnOHtuqGg8LuHnefkmPN5rYzA2g8MAPLjAZMisnDHhN4dBHUM7ZF7Rg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1006,43 +858,17 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-menu': 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-context@1.1.2(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-context@1.1.3(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-context@1.2.2(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-context@1.2.2(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==} peerDependencies: '@types/react': '*' @@ -1051,12 +877,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} + /@radix-ui/react-dialog@1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-l5CX8HdNL+9cc4s7HkNyplumSA3FIx68sg9dttBHKr286fRBwq1MBniDVTeI/tkof92/APntMQvC1YG1Khb0Cg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1068,28 +894,42 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) aria-hidden: 1.2.6 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) + react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.1) dev: false - /@radix-ui/react-dialog@1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==} + /@radix-ui/react-direction@1.1.5(@types/react@19.2.18)(react@19.2.1): + resolution: {integrity: sha512-/NlO/rOqQabmg+GGr86vCmbJVhqTv85NfM9g6Gknf/JVygXeZ6e6HM/RW1omerW9HsFtecwNqgEAKV6UqDsvpA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 19.2.18 + react: 19.2.1 + dev: false + + /@radix-ui/react-dismissable-layer@1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-35WHRrycfnj2m4LvPiKMKHGLM3Y2WvUA744CkRdxjs1BGDX1c8PVMfmiSGTUwnHRbqdtIoxveYTXvcJSt7VfgQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1102,78 +942,18 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - aria-hidden: 1.2.6 - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) - dev: false - - /@radix-ui/react-direction@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-direction@1.1.4(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-dismissable-layer@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==} + /@radix-ui/react-dropdown-menu@2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-45QO76jn/a+cRl6OPgZKCKnIMdfYZaOa6SuAJeKHFiM3orX6bnscuFQJDx3qS4Agp/RE+eKv+9gmUL8t3Ma7bw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1186,82 +966,19 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-menu': 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-dropdown-menu@2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-focus-guards@1.1.6(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-focus-guards@1.1.6(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==} peerDependencies: '@types/react': '*' @@ -1270,12 +987,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-focus-scope@1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==} + /@radix-ui/react-focus-scope@1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-I5S7vsAOozx2lWSBAyuXjWIJ/A8qx4fjbv6115WoaRYQSb1yZDaeNHonUAQzXyE8oD+0whJHbQRl4HIE2gQ0Xw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1287,39 +1004,17 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-form@0.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Q4TLEn2A7TAypxwmd6R9EwrlXDvkfYSDMrq9/887AXAGh+G1rH+kYJKSTv+Si9Y0JPKTwKYv6PviAJosysNimA==} + /@radix-ui/react-form@0.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-5ELeC+bQUHXEjU51svw11DynjGFlaUjo5QOUCr5hptvLLtBiqWtva2O3IWdjrFWQwitw6k6KpHHEyI61/kCVeg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1332,47 +1027,19 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-label': 2.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-label': 2.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-hover-card@1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-H8qONfZd3ltrU3+jHCIgITbWo6e1iTKvP9DHdrvYbX48ooRM5FjEDTn16AMwdfuOGkWdZEhpl3PLL/Wk/AnHDQ==} + /@radix-ui/react-hover-card@1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-0w/tZHRo1fv4WsfcyaOdi5eDftFA8wQkr8WCOOuxw7fx9S2ERfshQioM269aFZsmyAHd0X1LWoZ2BQTlA/JYUw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1385,35 +1052,22 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-id@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-id@1.1.4(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-id@1.1.4(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} peerDependencies: '@types/react': '*' @@ -1422,13 +1076,13 @@ packages: '@types/react': optional: true dependencies: - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-label@2.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g==} + /@radix-ui/react-label@2.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-2vTQj72YFmeoTxWKJEMbO/9uQt6zzLgbzi0+nWBffq49oo6KhIDP/D+fA2im0wsxBCAX7QfaF3xgsYBVdDbNFQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1440,15 +1094,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} + /@radix-ui/react-menu@2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-e8JaQc0ijBbTx37YVI09Nfq8ThUWJ4L1rvZ3Hvaufehco9/ug9+U3PHz9ue6w3gKd91UcKf9fgDWejeSO+VSKQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1460,52 +1114,32 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) aria-hidden: 1.2.6 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) + react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.1) dev: false - /@radix-ui/react-menu@2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA==} + /@radix-ui/react-menubar@1.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-JIQiKcXsgl6BtwcMe7BMLvCGH2p9Czgcmxl6Ie9Zoi+MW1mmitkcm5We01m/ndLYVI8PpRJnM/RcLV0eOCxaJQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1518,31 +1152,23 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - aria-hidden: 1.2.6 + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-menu': 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) dev: false - /@radix-ui/react-menubar@1.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-eeVs0vf7cuqXaM0qLQCPcufImiJNVBXdJDLu7ZGYl2732UH23Qat/foNGrr6vYV3/DdTsBqASoggUFgH14OcZA==} + /@radix-ui/react-navigation-menu@1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-hZqTqDwc8Z5aI4rGIyPqCSJ2JoSNorqX/F1/gqNHkZzWJO6JuYzL7hn5sWOZJjpkfT+cbxWWRbKVU/IeiOM9ag==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1555,56 +1181,28 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-navigation-menu@1.2.22(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-one-time-password-field@0.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Tj9P6ntAJEw52oq/F0AGknXR4XncxEt7XU47O3xJQOiWfLzEy3d9gtgKfvjSzGxzHkfL+VzvxGu2KTFsloJqXw==} + /@radix-ui/react-one-time-password-field@0.1.17(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-+6jmOqjSNBr7F1uSc7HSDqD3XL54A2qA99I9rIH4JoOD/jDScw8tUmDz6HCAkjytbrE/cdL66i+QkeDyZ0WNyw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1618,24 +1216,24 @@ packages: dependencies: '@radix-ui/number': 1.1.3 '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-password-toggle-field@0.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-4gvFnmDXu3dgj21CqsufzIameRvlRd4SBqaWhcrlrNhRo0Y5i/49AmRJYe1fdAM3G2VNBbmin4b0D6cdQocwgw==} + /@radix-ui/react-password-toggle-field@0.1.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-+SWSgf3HRpE4zUira+p6t5KUR473PSqewtQgj9qzl3znZPRWPCGycwXNTfHwkiRTD3tEXwNIXJg0i1NTteiULw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1648,55 +1246,21 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - aria-hidden: 1.2.6 - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) - dev: false - - /@radix-ui/react-popover@1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==} + /@radix-ui/react-popover@1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-e70Nh+0iQ+hRAIM2nAGib5BhaDL2Rjlzxw9kIzsU2nz+t3/t82Z5qtPhY5nTnfj8FbmrU6RRIKH8RF3ynCe+vw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1709,28 +1273,29 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) aria-hidden: 1.2.6 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) + react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.1) dev: false - /@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + /@radix-ui/react-popper@1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-y92/9iIdG1FyNvow0Y0qP5WJZ7oRTAKDVKCy9kJnhZfItwIKYtt0KKQeOhBKfXz0ETizduKwDRbrQHrTQScs5A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1742,53 +1307,24 @@ packages: '@types/react-dom': optional: true dependencies: - '@floating-ui/react-dom': 2.1.7(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/rect': 1.1.1 - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-popper@1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@floating-ui/react-dom': 2.1.7(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-rect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) + '@floating-ui/react-dom': 2.1.9(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-arrow': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-rect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) '@radix-ui/rect': 1.1.3 - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-portal@1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==} + /@radix-ui/react-portal@1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-ygFIJ+QXNKf72AAq8x3hd22+ws7pYpmc1S0E4kW0Je+qD4qEb3FvxeKVQRGrVDMOkQaYfsB+Qs+KDh81a1gAOw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1800,16 +1336,16 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + /@radix-ui/react-presence@1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1821,16 +1357,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-presence@1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==} + /@radix-ui/react-primitive@2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-RzcaSw5aKl0OPhBJ1wbolKSF6nVvN+0o/QLeIVq+09npiPdnCkPggy2k6gI6yetxl4ZyrlBPYFgCB8BQJZwXcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1842,15 +1377,15 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + /@radix-ui/react-progress@1.1.17(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-A+RfMARd9u+UaVbLQDmysGlAGuaFQrF+uxF3v+7+xU8tkKoYxtCSs+6HHnIKJVgam2sGZ7c0hLRPWSnmnFyGJQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1862,118 +1397,16 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-primitive@2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-progress@1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-5XnomAsoZZCY+KNTxbIghpGqPruZvKFNlvcAljVAOdDRDsH4/OZQxhtwo5wdtoDM5R6MhJBb2sPnDuRFep3lzg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-radio-group@1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ==} + /@radix-ui/react-radio-group@1.4.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-MaOOZ1TlaYoOeSDnHeVIONss0rp5ngOTY5HJY+Xkq16PAopnj21iU9r9m0O/77cBYu8Ksaq3BcjlaOdpbfbzzg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1986,50 +1419,22 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-roving-focus@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==} + /@radix-ui/react-roving-focus@1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-+ZjbkU21fTSJdn4nq/IFKUdKS+JSZHORBZ8ma1f6YpOMNzRt0xf3sVAWVK/+ktHCajPy4HYDsyHXZIZmOMxzIA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2042,52 +1447,24 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-scroll-area@1.2.18(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==} + /@radix-ui/react-scroll-area@1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-1WSuAXaahfeLmFX/dfYo/ftg1filMfaWjVye2d40VlgtWMMq/NOVocfukZEXkG+dwrAoNI+qpo9bjhNSJ/XC8g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2101,21 +1478,22 @@ packages: dependencies: '@radix-ui/number': 1.1.3 '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} + /@radix-ui/react-select@2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-Tz9xOpV9Rbca5WTk7pzmfAECV3zb++uScT9mP3Px7ziAhH7SlK53b0uwMw8VubPhRK4x7uDKCy5fwevT8I0fAg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2127,35 +1505,56 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/number': 1.1.3 + '@radix-ui/primitive': 1.1.7 + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) aria-hidden: 1.2.6 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) + react-remove-scroll: 2.7.2(@types/react@19.2.18)(react@19.2.1) dev: false - /@radix-ui/react-select@2.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg==} + /@radix-ui/react-separator@1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-vugPjGQBXbJVVkftKqv/BVeZ108SyRGT3FR1oa14az6qyLgX8jPhnZYHgdSB7Gw8UJusqwb9eaK6mluOnsn/Vg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) + react: 19.2.1 + react-dom: 19.2.1(react@19.2.1) + dev: false + + /@radix-ui/react-slider@1.5.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-ZOBLK7KZvGL02V+4VwVbj8NYM4vPrAtyZdrgHSv+AMS9VL+5yAdnQF3DZT4Y8cbCp1Yn4xdp92orvez8fJa77w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2169,104 +1568,23 @@ packages: dependencies: '@radix-ui/number': 1.1.3 '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - aria-hidden: 1.2.6 - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - react-remove-scroll: 2.7.2(@types/react@19.2.10)(react@19.2.1) - dev: false - - /@radix-ui/react-separator@1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-slider@1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/number': 1.1.3 - '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-slot@1.2.3(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + /@radix-ui/react-slot@1.4.0(@types/react@19.2.18)(react@19.2.1): + resolution: {integrity: sha512-IuMVHZ+Ah5fkctu3X3qeFrV/ZrBcuWuDTFUUPfS/L5hvoTjzhp/HdWGE14CsQombPdEidsa33HVlYZXi49PZ1Q==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2274,67 +1592,13 @@ packages: '@types/react': optional: true dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-slot@1.2.4(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-slot@1.3.3(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-switch@1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw==} + /@radix-ui/react-switch@1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-rr+zuoAeHWK3m6H4HgjOUiu3VsrQ/9JkjwY/uMnTgHJGPe9WNzDP/MOuIV7S+65p42DIxjGL0hAHktqBq82+2A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2347,46 +1611,19 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-tabs@1.1.21(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==} + /@radix-ui/react-tabs@1.1.22(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-GmVH+P3wx1ZPMuH7WajQzygZIbqgnsb5h8z4Ow3sQMuDqgcqISSBNom6MLVNJvfrkuJTtqfXc3ZolHjX+w0CHg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2399,21 +1636,21 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-toast@1.2.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-ofhyAsYaocRGOs/n0XWdUOSVzEAG6BfrMVM8z0c0kLEWY38w/0WuMFPTJP/HVaZPYkMvHZoKIIhNcjbTCBILPg==} + /@radix-ui/react-toast@1.2.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-XR9pDEz9CH0ez98zPXQZOpF46anvbarkoOpjXpPSX7gm21vEl5Tzoe1PSQd3EY1OTOHac4lNq+TPx/2Z7jObdQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2426,51 +1663,25 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-toggle-group@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA==} + /@radix-ui/react-toggle-group@1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-O+Sjiv64DfnByHYtnKEXmn63uUskU/X61vjf69X1v8JFn/ZvuNNLdJTBfYurVTSDv4/RJnJGtGgb/uvuS/rRJw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2483,42 +1694,20 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toggle': 1.1.18(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toggle': 1.1.19(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-toggle@1.1.18(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug==} + /@radix-ui/react-toggle@1.1.19(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-l7FQHtuZjUJ0vKLdhKu5LzZ8Jw6K60QEC1tC22QNLuXN2PkydSoqEhKTCqwxBFZJ52NTCjzudDvl9sUsZeUbPw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2531,16 +1720,16 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-toolbar@1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-Ph0IvtYw4VB12ZnZg+YtrGs8yJQsnizwo/zu0R4Y/nWugtJzA7Pg1eWeuDR9+LSqn+xjamss+UOSOJJJ4gx8jw==} + /@radix-ui/react-toolbar@1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-5gyzL6B5/zjBwU3ATBWAVZ4xXQC5F8E9CB4BmYC1UvZ08pN2OJQoooeIwJtZZ/2rz4sTiQmbGfdDvmU73wRJCQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2553,20 +1742,20 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-separator': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toggle-group': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-separator': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toggle-group': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-tooltip@1.2.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg==} + /@radix-ui/react-tooltip@1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-4HM4b1Cft1CBXCGDRDG3S/fh8GedBuVOMNh145wMIfTbVqcuv+tyj03nZqYgFevWJMYo58H0s+8P6s6NaUHWtA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2579,69 +1768,25 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-callback-ref@1.1.4(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==} peerDependencies: '@types/react': '*' @@ -2650,26 +1795,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-controllable-state@1.2.6(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==} peerDependencies: '@types/react': '*' @@ -2679,27 +1809,13 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-effect-event@0.0.5(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-effect-event@0.0.5(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} peerDependencies: '@types/react': '*' @@ -2708,26 +1824,12 @@ packages: '@types/react': optional: true dependencies: - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-escape-keydown@1.1.5(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-escape-keydown@1.1.5(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-ge3ipobwSXTj4JyVtswQ7qZj0ZHdtbGuOno/LrgAAeSxtsJ6Vs4Gz5IkPH2bmqpjcLUFoqGhA/mueuIf63UXlA==} peerDependencies: '@types/react': '*' @@ -2736,26 +1838,12 @@ packages: '@types/react': optional: true dependencies: - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - use-sync-external-store: 1.6.0(react@19.2.1) - dev: false - - /@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} peerDependencies: '@types/react': '*' @@ -2764,24 +1852,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} peerDependencies: '@types/react': '*' @@ -2790,24 +1865,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-previous@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-previous@1.1.4(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-previous@1.1.4(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==} peerDependencies: '@types/react': '*' @@ -2816,25 +1878,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-rect@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/rect': 1.1.1 - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-use-rect@1.1.4(@types/react@19.2.10)(react@19.2.1): + /@radix-ui/react-use-rect@1.1.4(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==} peerDependencies: '@types/react': '*' @@ -2844,12 +1892,12 @@ packages: optional: true dependencies: '@radix-ui/rect': 1.1.3 - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-size@1.1.1(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + /@radix-ui/react-use-size@1.1.5(@types/react@19.2.18)(react@19.2.1): + resolution: {integrity: sha512-V1McDQkMGzgivwqdu7u96APs7oi0Jvj9LTzgq3WWrDZqxWdAqU9yZnZQqk5OizGFR8badUQwZsrlao7MOlWYOA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -2857,27 +1905,13 @@ packages: '@types/react': optional: true dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@types/react': 19.2.18 react: 19.2.1 dev: false - /@radix-ui/react-use-size@1.1.4(@types/react@19.2.10)(react@19.2.1): - resolution: {integrity: sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@types/react': 19.2.10 - react: 19.2.1 - dev: false - - /@radix-ui/react-visually-hidden@1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==} + /@radix-ui/react-visually-hidden@1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-/iPLVHRBzKWvekN+5xaDmXw80f+nleYYceomVORrGjuJe0LF2SCbSH4f/LG4hu32q92QSuPZx4hmSACYBVBfzQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -2889,37 +1923,13 @@ packages: '@types/react-dom': optional: true dependencies: - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) - react: 19.2.1 - react-dom: 19.2.1(react@19.2.1) - dev: false - - /@radix-ui/rect@1.1.1: - resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - dev: false - /@radix-ui/rect@1.1.3: resolution: {integrity: sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw==} dev: false @@ -2932,8 +1942,17 @@ packages: react: 19.2.1 dev: false - /@rolldown/binding-android-arm64@1.0.3: - resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + /@rolldown/binding-android-arm-eabi@1.2.13: + resolution: {integrity: sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@rolldown/binding-android-arm64@1.2.13: + resolution: {integrity: sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -2941,8 +1960,8 @@ packages: dev: false optional: true - /@rolldown/binding-darwin-arm64@1.0.3: - resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + /@rolldown/binding-darwin-arm64@1.2.13: + resolution: {integrity: sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -2950,8 +1969,8 @@ packages: dev: false optional: true - /@rolldown/binding-darwin-x64@1.0.3: - resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + /@rolldown/binding-darwin-x64@1.2.13: + resolution: {integrity: sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -2959,8 +1978,8 @@ packages: dev: false optional: true - /@rolldown/binding-freebsd-x64@1.0.3: - resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + /@rolldown/binding-freebsd-x64@1.2.13: + resolution: {integrity: sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -2968,8 +1987,8 @@ packages: dev: false optional: true - /@rolldown/binding-linux-arm-gnueabihf@1.0.3: - resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + /@rolldown/binding-linux-arm-gnueabihf@1.2.13: + resolution: {integrity: sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -2977,68 +1996,62 @@ packages: dev: false optional: true - /@rolldown/binding-linux-arm64-gnu@1.0.3: - resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + /@rolldown/binding-linux-arm64-gnu@1.2.13: + resolution: {integrity: sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@rolldown/binding-linux-arm64-musl@1.0.3: - resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + /@rolldown/binding-linux-arm64-musl@1.2.13: + resolution: {integrity: sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /@rolldown/binding-linux-ppc64-gnu@1.0.3: - resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + /@rolldown/binding-linux-ppc64-gnu@1.2.13: + resolution: {integrity: sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@rolldown/binding-linux-s390x-gnu@1.0.3: - resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + /@rolldown/binding-linux-s390x-gnu@1.2.13: + resolution: {integrity: sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@rolldown/binding-linux-x64-gnu@1.0.3: - resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + /@rolldown/binding-linux-x64-gnu@1.2.13: + resolution: {integrity: sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@rolldown/binding-linux-x64-musl@1.0.3: - resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + /@rolldown/binding-linux-x64-musl@1.2.13: + resolution: {integrity: sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /@rolldown/binding-openharmony-arm64@1.0.3: - resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + /@rolldown/binding-openharmony-arm64@1.2.13: + resolution: {integrity: sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -3046,20 +2059,8 @@ packages: dev: false optional: true - /@rolldown/binding-wasm32-wasi@1.0.3: - resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - requiresBuild: true - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - dev: false - optional: true - - /@rolldown/binding-win32-arm64-msvc@1.0.3: - resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + /@rolldown/binding-win32-arm64-msvc@1.2.13: + resolution: {integrity: sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -3067,8 +2068,8 @@ packages: dev: false optional: true - /@rolldown/binding-win32-x64-msvc@1.0.3: - resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + /@rolldown/binding-win32-x64-msvc@1.2.13: + resolution: {integrity: sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -3076,10 +2077,6 @@ packages: dev: false optional: true - /@rolldown/pluginutils@1.0.0-rc.7: - resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} - dev: false - /@rolldown/pluginutils@1.0.1: resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} dev: false @@ -3092,105 +2089,101 @@ packages: resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} dev: false - /@tailwindcss/node@4.1.18: - resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} + /@tailwindcss/node@4.3.3: + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.18.4 - jiti: 2.6.1 - lightningcss: 1.30.2 + enhanced-resolve: 5.26.0 + jiti: 2.7.0 + lightningcss: 1.32.0 magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.1.18 + source-map-js: 1.2.2 + tailwindcss: 4.3.3 dev: false - /@tailwindcss/oxide-android-arm64@4.1.18: - resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-android-arm64@4.3.3: + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} cpu: [arm64] os: [android] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-darwin-arm64@4.1.18: - resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-darwin-arm64@4.3.3: + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} cpu: [arm64] os: [darwin] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-darwin-x64@4.1.18: - resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-darwin-x64@4.3.3: + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} cpu: [x64] os: [darwin] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-freebsd-x64@4.1.18: - resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-freebsd-x64@4.3.3: + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} cpu: [x64] os: [freebsd] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18: - resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3: + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} cpu: [arm] os: [linux] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-linux-arm64-gnu@4.1.18: - resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-linux-arm64-gnu@4.3.3: + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-linux-arm64-musl@4.1.18: - resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-linux-arm64-musl@4.3.3: + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} cpu: [arm64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-linux-x64-gnu@4.1.18: - resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-linux-x64-gnu@4.3.3: + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-linux-x64-musl@4.1.18: - resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-linux-x64-musl@4.3.3: + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-wasm32-wasi@4.1.18: - resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} + /@tailwindcss/oxide-wasm32-wasi@4.3.3: + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] requiresBuild: true @@ -3204,50 +2197,50 @@ packages: - '@emnapi/wasi-threads' - tslib - /@tailwindcss/oxide-win32-arm64-msvc@4.1.18: - resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-win32-arm64-msvc@4.3.3: + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} cpu: [arm64] os: [win32] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide-win32-x64-msvc@4.1.18: - resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} - engines: {node: '>= 10'} + /@tailwindcss/oxide-win32-x64-msvc@4.3.3: + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} cpu: [x64] os: [win32] requiresBuild: true dev: false optional: true - /@tailwindcss/oxide@4.1.18: - resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} - engines: {node: '>= 10'} + /@tailwindcss/oxide@4.3.3: + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-x64': 4.1.18 - '@tailwindcss/oxide-freebsd-x64': 4.1.18 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-x64-musl': 4.1.18 - '@tailwindcss/oxide-wasm32-wasi': 4.1.18 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 dev: false - /@tailwindcss/postcss@4.1.18: - resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==} + /@tailwindcss/postcss@4.3.3: + resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.18 - '@tailwindcss/oxide': 4.1.18 - postcss: 8.5.15 - tailwindcss: 4.1.18 + '@alloc/quick-lru': 5.3.0 + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + postcss: 8.5.29 + tailwindcss: 4.3.3 dev: false /@tanstack/react-table@8.21.3(react-dom@19.2.1)(react@19.2.1): @@ -3267,14 +2260,6 @@ packages: engines: {node: '>=12'} dev: false - /@tybys/wasm-util@0.10.1: - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - requiresBuild: true - dependencies: - tslib: 2.8.1 - dev: false - optional: true - /@types/d3-array@3.2.2: resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} dev: false @@ -3303,8 +2288,8 @@ packages: '@types/d3-time': 3.0.4 dev: false - /@types/d3-shape@3.1.8: - resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + /@types/d3-shape@3.2.0: + resolution: {integrity: sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==} dependencies: '@types/d3-path': 3.1.1 dev: false @@ -3317,21 +2302,21 @@ packages: resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} dev: false - /@types/debug@4.1.12: - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + /@types/debug@4.1.13: + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} dependencies: '@types/ms': 2.1.0 /@types/estree-jsx@1.0.5: resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 - /@types/estree@1.0.8: - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + /@types/estree@1.0.9: + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - /@types/hast@3.0.4: - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + /@types/hast@3.0.5: + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} dependencies: '@types/unist': 3.0.3 @@ -3339,8 +2324,8 @@ packages: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true - /@types/lodash@4.17.23: - resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} + /@types/lodash@4.17.26: + resolution: {integrity: sha512-48NWfiY6oNcKOh47Z4h+sIvwcQR91h6KPhaYKgeMIrkT2jV82Gy90SErj60vW8jQbeMSOSbhIv3bZ7JoqPPVhA==} dev: true /@types/mdast@4.0.4: @@ -3351,36 +2336,36 @@ packages: /@types/ms@2.1.0: resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - /@types/node@20.19.30: - resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==} + /@types/node@20.19.43: + resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} dependencies: undici-types: 6.21.0 - /@types/prismjs@1.26.5: - resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} + /@types/prismjs@1.26.6: + resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==} dev: false /@types/qrcode@1.5.6: resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} dependencies: - '@types/node': 20.19.30 + '@types/node': 20.19.43 dev: true - /@types/react-dom@19.2.3(@types/react@19.2.10): - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + /@types/react-dom@19.2.7(@types/react@19.2.18): + resolution: {integrity: sha512-I8bPpDLcHBv1qiIiXDCy71Rt8eQDKJP0sMSWJphDdAcdqiJ1sGpZamavoEIRZmYzjia9LuEb2HlYdDpmoENpvQ==} peerDependencies: '@types/react': ^19.2.0 dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 /@types/react-syntax-highlighter@15.5.13: resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 dev: true - /@types/react@19.2.10: - resolution: {integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==} + /@types/react@19.2.18: + resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} dependencies: csstype: 3.2.3 @@ -3391,177 +2376,180 @@ packages: /@types/unist@3.0.3: resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - /@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0)(eslint@9.39.2)(typescript@5.9.3): - resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==} + /@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1)(eslint@9.39.5)(typescript@5.9.3): + resolution: {integrity: sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.54.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser': ^8.71.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 - eslint: 9.39.2 - ignore: 7.0.5 + '@typescript-eslint/parser': 8.71.1(eslint@9.39.5)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/type-utils': 8.71.1(eslint@9.39.5)(typescript@5.9.3) + '@typescript-eslint/utils': 8.71.1(eslint@9.39.5)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.71.1 + eslint: 9.39.5 + ignore: 7.0.12 natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3): - resolution: {integrity: sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==} + /@typescript-eslint/parser@8.71.1(eslint@9.39.5)(typescript@5.9.3): + resolution: {integrity: sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' dependencies: - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.71.1 debug: 4.4.3 - eslint: 9.39.2 + eslint: 9.39.5 typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/project-service@8.54.0(typescript@5.9.3): - resolution: {integrity: sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==} + /@typescript-eslint/project-service@8.71.1(typescript@5.9.3): + resolution: {integrity: sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' dependencies: - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@5.9.3) + '@typescript-eslint/types': 8.71.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@8.54.0: - resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==} + /@typescript-eslint/scope-manager@8.71.1: + resolution: {integrity: sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/visitor-keys': 8.71.1 dev: true - /@typescript-eslint/tsconfig-utils@8.54.0(typescript@5.9.3): - resolution: {integrity: sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==} + /@typescript-eslint/tsconfig-utils@8.71.1(typescript@5.9.3): + resolution: {integrity: sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' dependencies: typescript: 5.9.3 dev: true - /@typescript-eslint/type-utils@8.54.0(eslint@9.39.2)(typescript@5.9.3): - resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==} + /@typescript-eslint/type-utils@8.71.1(eslint@9.39.5)(typescript@5.9.3): + resolution: {integrity: sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.71.1(eslint@9.39.5)(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.2 - ts-api-utils: 2.4.0(typescript@5.9.3) + eslint: 9.39.5 + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@8.54.0: - resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} + /@typescript-eslint/types@8.71.1: + resolution: {integrity: sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true - /@typescript-eslint/typescript-estree@8.54.0(typescript@5.9.3): - resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==} + /@typescript-eslint/typescript-estree@8.71.1(typescript@5.9.3): + resolution: {integrity: sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' dependencies: - '@typescript-eslint/project-service': 8.54.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/project-service': 8.71.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@5.9.3) + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/visitor-keys': 8.71.1 debug: 4.4.3 - minimatch: 9.0.7 - semver: 7.7.3 - tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@8.54.0(eslint@9.39.2)(typescript@5.9.3): - resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==} + /@typescript-eslint/utils@8.71.1(eslint@9.39.5)(typescript@5.9.3): + resolution: {integrity: sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - eslint: 9.39.2 + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5) + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@5.9.3) + eslint: 9.39.5 typescript: 5.9.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/visitor-keys@8.54.0: - resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==} + /@typescript-eslint/visitor-keys@8.71.1: + resolution: {integrity: sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.54.0 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.71.1 + eslint-visitor-keys: 5.0.1 dev: true - /@ungap/structured-clone@1.3.0: - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + /@ungap/structured-clone@1.4.0: + resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==} dev: false - /@vitejs/plugin-react@6.0.1(vite@8.0.16): - resolution: {integrity: sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==} + /@vitejs/plugin-react@6.1.2(vite@8.3.4): + resolution: {integrity: sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.152.0 vite: ^8.0.0 peerDependenciesMeta: '@rolldown/plugin-babel': optional: true babel-plugin-react-compiler: optional: true + oxc-transform-react: + optional: true dependencies: - '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.16(@types/node@20.19.30) + '@rolldown/pluginutils': 1.0.1 + vite: 8.3.4(@types/node@20.19.43) dev: false - /acorn-jsx@5.3.2(acorn@8.15.0): + /acorn-jsx@5.3.2(acorn@8.19.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.15.0 + acorn: 8.19.0 dev: true - /acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + /acorn@8.19.0: + resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==} engines: {node: '>=0.4.0'} hasBin: true dev: true @@ -3575,8 +2563,8 @@ packages: - supports-color dev: false - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + /ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -3584,8 +2572,8 @@ packages: uri-js: 4.4.1 dev: true - /ansi-escapes@7.2.0: - resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} + /ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} dependencies: environment: 1.1.0 @@ -3596,8 +2584,8 @@ packages: engines: {node: '>=8'} dev: false - /ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + /ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} engines: {node: '>=12'} dev: true @@ -3631,16 +2619,16 @@ packages: is-array-buffer: 3.0.5 dev: true - /array-includes@3.1.9: - resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + /array-includes@3.2.0: + resolution: {integrity: sha512-VXY5eFRarnXcYxwBjJzPmEhH55+rmP79/+ueDhi0F+TuqfHCItagIHqxeUZrmgrOPa31QTh9H85DjX3FfJ0FTg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 is-string: 1.1.1 math-intrinsics: 1.1.0 dev: true @@ -3649,11 +2637,11 @@ packages: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 es-shim-unscopables: 1.1.0 dev: true @@ -3661,9 +2649,9 @@ packages: resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-shim-unscopables: 1.1.0 dev: true @@ -3671,9 +2659,9 @@ packages: resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-shim-unscopables: 1.1.0 dev: true @@ -3681,9 +2669,9 @@ packages: resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 es-shim-unscopables: 1.1.0 dev: true @@ -3693,9 +2681,9 @@ packages: engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -3717,10 +2705,10 @@ packages: possible-typed-array-names: 1.1.0 dev: true - /axios@1.17.0: - resolution: {integrity: sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==} + /axios@1.20.0: + resolution: {integrity: sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==} dependencies: - follow-redirects: 1.16.0 + follow-redirects: 1.16.1 form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 @@ -3742,16 +2730,16 @@ packages: engines: {node: 18 || 20 || >=22} dev: true - /brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + /brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 dev: true - /brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - engines: {node: 18 || 20 || >=22} + /brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} dependencies: balanced-match: 4.0.4 dev: true @@ -3770,8 +2758,8 @@ packages: es-errors: 1.3.0 function-bind: 1.1.2 - /call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + /call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} engines: {node: '>= 0.4'} dependencies: call-bind-apply-helpers: 1.0.2 @@ -3865,16 +2853,16 @@ packages: engines: {node: '>=6'} dev: false - /cmdk@1.1.1(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): + /cmdk@1.1.1(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc dependencies: - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dialog': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-id': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) transitivePeerDependencies: @@ -4117,7 +3105,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.10 csstype: 3.2.3 dev: false @@ -4137,12 +3125,12 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false - /enhanced-resolve@5.18.4: - resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} + /enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} engines: {node: '>=10.13.0'} dependencies: graceful-fs: 4.2.11 - tapable: 2.3.0 + tapable: 2.3.3 dev: false /entities@6.0.1: @@ -4155,24 +3143,34 @@ packages: engines: {node: '>=18'} dev: true - /es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + /es-abstract-get@1.0.0: + resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + is-callable: 1.2.7 + object-inspect: 1.13.4 + dev: true + + /es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} engines: {node: '>= 0.4'} dependencies: 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-bind: 1.0.9 call-bound: 1.0.4 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.1.1 + es-object-atoms: 1.1.2 es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 + es-to-primitive: 1.3.4 + function.prototype.name: 1.2.0 get-intrinsic: 1.3.0 get-proto: 1.0.1 get-symbol-description: 1.1.0 @@ -4181,7 +3179,7 @@ packages: has-property-descriptors: 1.0.2 has-proto: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 internal-slot: 1.1.0 is-array-buffer: 3.0.5 is-callable: 1.2.7 @@ -4197,22 +3195,22 @@ packages: object-inspect: 1.13.4 object-keys: 1.1.1 object.assign: 4.1.7 - own-keys: 1.0.1 + own-keys: 1.0.2 regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 + safe-array-concat: 1.1.4 safe-push-apply: 1.0.0 safe-regex-test: 1.1.0 set-proto: 1.0.0 stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 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 + typed-array-byte-offset: 1.0.5 + typed-array-length: 1.0.8 unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 + which-typed-array: 1.1.24 dev: true /es-define-property@1.0.1: @@ -4223,14 +3221,14 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - /es-iterator-helpers@1.3.1: - resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==} + /es-iterator-helpers@1.4.0: + resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 @@ -4243,11 +3241,10 @@ packages: internal-slot: 1.1.0 iterator.prototype: 1.1.5 math-intrinsics: 1.1.0 - safe-array-concat: 1.1.3 dev: true - /es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + /es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 @@ -4259,19 +3256,22 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 /es-shim-unscopables@1.1.0: resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} engines: {node: '>= 0.4'} dependencies: - hasown: 2.0.2 + hasown: 2.0.4 dev: true - /es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + /es-to-primitive@1.3.4: + resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} engines: {node: '>= 0.4'} dependencies: + es-abstract-get: 1.0.0 + es-define-property: 1.0.1 + es-errors: 1.3.0 is-callable: 1.2.7 is-date-object: 1.1.0 is-symbol: 1.1.1 @@ -4287,17 +3287,17 @@ packages: engines: {node: '>=12'} dev: false - /eslint-config-prettier@10.1.8(eslint@9.39.2): + /eslint-config-prettier@10.1.8(eslint@9.39.5): resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 9.39.2 + eslint: 9.39.5 dev: true - /eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8)(eslint@9.39.2)(prettier@3.8.1): - resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} + /eslint-plugin-prettier@5.5.6(eslint-config-prettier@10.1.8)(eslint@9.39.5)(prettier@3.9.10): + resolution: {integrity: sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -4310,46 +3310,46 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 9.39.2 - eslint-config-prettier: 10.1.8(eslint@9.39.2) - prettier: 3.8.1 + eslint: 9.39.5 + eslint-config-prettier: 10.1.8(eslint@9.39.5) + prettier: 3.9.10 prettier-linter-helpers: 1.0.1 - synckit: 0.11.12 + synckit: 0.11.13 dev: true - /eslint-plugin-react-hooks@5.2.0(eslint@9.39.2): + /eslint-plugin-react-hooks@5.2.0(eslint@9.39.5): resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} 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 dependencies: - eslint: 9.39.2 + eslint: 9.39.5 dev: true - /eslint-plugin-react@7.37.5(eslint@9.39.2): + /eslint-plugin-react@7.37.5(eslint@9.39.5): resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 dependencies: - array-includes: 3.1.9 + array-includes: 3.2.0 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.3.1 - eslint: 9.39.2 + es-iterator-helpers: 1.4.0 + eslint: 9.39.5 estraverse: 5.3.0 - hasown: 2.0.2 + hasown: 2.0.4 jsx-ast-utils: 3.3.5 minimatch: 3.1.3 object.entries: 1.1.9 object.fromentries: 2.0.8 object.values: 1.2.1 prop-types: 15.8.1 - resolve: 2.0.0-next.6 + resolve: 2.0.0-next.7 semver: 6.3.1 - string.prototype.matchall: 4.0.12 + string.prototype.matchall: 4.1.0 string.prototype.repeat: 1.0.0 dev: true @@ -4371,9 +3371,15 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true - /eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + /eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + dev: true + + /eslint@9.39.5: + resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -4381,19 +3387,19 @@ packages: jiti: optional: true dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 + '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 + '@eslint/eslintrc': 3.3.7 + '@eslint/js': 9.39.5 '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.12.6 + '@types/estree': 1.0.9 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 @@ -4412,7 +3418,7 @@ packages: is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 - minimatch: 3.1.3 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -4423,8 +3429,8 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) + acorn: 8.19.0 + acorn-jsx: 5.3.2(acorn@8.19.0) eslint-visitor-keys: 4.2.1 dev: true @@ -4491,8 +3497,8 @@ packages: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} dev: true - /fast-equals@5.4.0: - resolution: {integrity: sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==} + /fast-equals@5.4.4: + resolution: {integrity: sha512-d9/I4rfMfUlO9HOkQqLJgfyRM4siqk1SF3Gjxm4OAMZzV+kCKHe1t/bHxn3xtCPHs3HCQFcvqzkTuanzqECQxw==} engines: {node: '>=6.0.0'} dev: false @@ -4510,7 +3516,7 @@ packages: format: 0.2.2 dev: false - /fdir@6.5.0(picomatch@4.0.4): + /fdir@6.5.0(picomatch@4.0.7): resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -4519,7 +3525,7 @@ packages: picomatch: optional: true dependencies: - picomatch: 4.0.4 + picomatch: 4.0.7 /file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -4555,16 +3561,16 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} dependencies: - flatted: 3.4.2 + flatted: 3.4.4 keyv: 4.5.4 dev: true - /flatted@3.4.2: - resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + /flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} dev: true - /follow-redirects@1.16.0: - resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + /follow-redirects@1.16.1: + resolution: {integrity: sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -4596,14 +3602,6 @@ packages: engines: {node: '>=0.4.x'} dev: false - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -4615,16 +3613,19 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - /function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + /function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 - define-properties: 1.2.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 functions-have-names: 1.2.3 - hasown: 2.0.2 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 is-callable: 1.2.7 + is-document.all: 1.0.0 dev: true /functions-have-names@1.2.3: @@ -4641,8 +3642,8 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dev: false - /get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + /get-east-asian-width@1.7.0: + resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==} engines: {node: '>=18'} dev: true @@ -4653,12 +3654,12 @@ packages: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 function-bind: 1.1.2 get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 /get-nonce@1.0.1: @@ -4671,7 +3672,7 @@ packages: engines: {node: '>= 0.4'} dependencies: dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 /get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} @@ -4752,27 +3753,20 @@ packages: dependencies: has-symbols: 1.1.0 - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - /hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 - dev: false /hast-util-from-parse5@8.0.3: resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/unist': 3.0.3 devlop: 1.1.0 hastscript: 9.0.1 - property-information: 7.1.0 + property-information: 7.2.0 vfile: 6.0.3 vfile-location: 5.0.3 web-namespaces: 2.0.1 @@ -4781,27 +3775,27 @@ packages: /hast-util-heading-rank@3.0.0: resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 dev: false /hast-util-is-element@3.0.0: resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 dev: false /hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 dev: false /hast-util-raw@9.1.0: resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/unist': 3.0.3 - '@ungap/structured-clone': 1.3.0 + '@ungap/structured-clone': 1.4.0 hast-util-from-parse5: 8.0.3 hast-util-to-parse5: 8.0.1 html-void-elements: 3.0.0 @@ -4817,16 +3811,16 @@ packages: /hast-util-sanitize@5.0.2: resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==} dependencies: - '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.3.0 + '@types/hast': 3.0.5 + '@ungap/structured-clone': 1.4.0 unist-util-position: 5.0.0 dev: false /hast-util-to-jsx-runtime@2.3.6: resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} dependencies: - '@types/estree': 1.0.8 - '@types/hast': 3.0.4 + '@types/estree': 1.0.9 + '@types/hast': 3.0.5 '@types/unist': 3.0.3 comma-separated-tokens: 2.0.3 devlop: 1.1.0 @@ -4835,7 +3829,7 @@ packages: mdast-util-mdx-expression: 2.0.1 mdast-util-mdx-jsx: 3.2.0 mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 + property-information: 7.2.0 space-separated-tokens: 2.0.2 style-to-js: 1.1.21 unist-util-position: 5.0.0 @@ -4847,10 +3841,10 @@ packages: /hast-util-to-parse5@8.0.1: resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 comma-separated-tokens: 2.0.3 devlop: 1.1.0 - property-information: 7.1.0 + property-information: 7.2.0 space-separated-tokens: 2.0.2 web-namespaces: 2.0.1 zwitch: 2.0.4 @@ -4859,13 +3853,13 @@ packages: /hast-util-to-string@3.0.1: resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 dev: false /hast-util-to-text@4.0.2: resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/unist': 3.0.3 hast-util-is-element: 3.0.0 unist-util-find-after: 5.0.0 @@ -4874,16 +3868,16 @@ packages: /hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 dev: false /hastscript@9.0.1: resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 - property-information: 7.1.0 + property-information: 7.2.0 space-separated-tokens: 2.0.2 dev: false @@ -4891,8 +3885,13 @@ packages: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: false - /highlight.js@11.11.1: - resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + /highlight.js@11.11.2: + resolution: {integrity: sha512-oaXMACAU0kzOMXBjWpNcX+vlwSBCIAiZ9BHa7gA15NOTtT2L/l8OSZDuqS2XppOhZBPJ7hm4o8ep2kyuip2uEQ==} + engines: {node: '>=12.0.0'} + dev: false + + /highlight.js@11.12.0: + resolution: {integrity: sha512-nbfWpyRMcMrPMmDwJB+dhX/eiaPKtc2RB+0QZskqJ3WjRA/FDS0e9hZrx8EC/lbEv8gXy98FcDbNa/dspAaJMg==} engines: {node: '>=12.0.0'} dev: false @@ -4900,8 +3899,8 @@ packages: resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} dev: false - /html-parse-stringify@3.0.1: - resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + /html-parse-stringify@3.1.0: + resolution: {integrity: sha512-E0oAXcELOtsXe+BmpJ2EZyedbldPpriV5vICzEuo6xjC/D1lDukOI7KrpfQGF2Qc4wWEy0nk3bFORS2K5ZAhFQ==} dependencies: void-elements: 3.1.0 dev: false @@ -4929,21 +3928,21 @@ packages: engines: {node: '>=16.17.0'} dev: true - /i18next-browser-languagedetector@8.2.0: - resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==} + /i18next-browser-languagedetector@8.2.1: + resolution: {integrity: sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==} dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.10 dev: false - /i18next@25.8.0(typescript@5.9.3): - resolution: {integrity: sha512-urrg4HMFFMQZ2bbKRK7IZ8/CTE7D8H4JRlAwqA2ZwDRFfdd0K/4cdbNNLgfn9mo+I/h9wJu61qJzH7jCFAhUZQ==} + /i18next@25.10.10(typescript@5.9.3): + resolution: {integrity: sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==} peerDependencies: - typescript: ^5 + typescript: ^5 || ^6 peerDependenciesMeta: typescript: optional: true dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.10 typescript: 5.9.3 dev: false @@ -4952,8 +3951,8 @@ packages: engines: {node: '>= 4'} dev: true - /ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + /ignore@7.0.12: + resolution: {integrity: sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==} engines: {node: '>= 4'} dev: true @@ -4974,8 +3973,8 @@ packages: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} dev: false - /input-otp@1.4.2(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} + /input-otp@1.5.0(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-3AcfdW1sNG0FmSA5hHMBXG7jNW5CdcdKs8ln8JOmn6S2SRkoXoJx+2UwC+ZvjflfnOdHJx0SfQ9/YjlxVYLtGQ==} peerDependencies: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc @@ -4989,8 +3988,8 @@ packages: engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 + hasown: 2.0.4 + side-channel: 1.1.1 dev: true /internmap@2.0.3: @@ -5013,7 +4012,7 @@ packages: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 get-intrinsic: 1.3.0 dev: true @@ -5049,11 +4048,11 @@ packages: engines: {node: '>= 0.4'} dev: true - /is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + /is-core-module@2.17.0: + resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} engines: {node: '>= 0.4'} dependencies: - hasown: 2.0.2 + hasown: 2.0.4 dev: true /is-data-view@1.0.2: @@ -5077,6 +4076,13 @@ packages: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} dev: false + /is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + dependencies: + call-bound: 1.0.4 + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -5103,7 +4109,7 @@ packages: resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} engines: {node: '>=18'} dependencies: - get-east-asian-width: 1.4.0 + get-east-asian-width: 1.7.0 dev: true /is-generator-function@1.1.2: @@ -5163,7 +4169,7 @@ packages: call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 dev: true /is-set@2.0.3: @@ -5204,7 +4210,7 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} dependencies: - which-typed-array: 1.1.20 + which-typed-array: 1.1.24 dev: true /is-weakmap@2.0.2: @@ -5240,23 +4246,23 @@ packages: engines: {node: '>= 0.4'} dependencies: define-data-property: 1.1.4 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 get-proto: 1.0.1 has-symbols: 1.1.0 set-function-name: 2.0.2 dev: true - /jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + /jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true dev: false /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - /js-yaml@4.2.0: - resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + /js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true dependencies: argparse: 2.0.1 @@ -5278,7 +4284,7 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} dependencies: - array-includes: 3.1.9 + array-includes: 3.2.0 array.prototype.flat: 1.3.3 object.assign: 4.1.7 object.values: 1.2.1 @@ -5298,15 +4304,6 @@ packages: type-check: 0.4.0 dev: true - /lightningcss-android-arm64@1.30.2: - resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - /lightningcss-android-arm64@1.32.0: resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} @@ -5316,11 +4313,11 @@ packages: dev: false optional: true - /lightningcss-darwin-arm64@1.30.2: - resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + /lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] - os: [darwin] + os: [android] requiresBuild: true dev: false optional: true @@ -5334,10 +4331,10 @@ packages: dev: false optional: true - /lightningcss-darwin-x64@1.30.2: - resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + /lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} - cpu: [x64] + cpu: [arm64] os: [darwin] requiresBuild: true dev: false @@ -5352,11 +4349,11 @@ packages: dev: false optional: true - /lightningcss-freebsd-x64@1.30.2: - resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + /lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] - os: [freebsd] + os: [darwin] requiresBuild: true dev: false optional: true @@ -5370,11 +4367,11 @@ packages: dev: false optional: true - /lightningcss-linux-arm-gnueabihf@1.30.2: - resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + /lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] + cpu: [x64] + os: [freebsd] requiresBuild: true dev: false optional: true @@ -5388,12 +4385,11 @@ packages: dev: false optional: true - /lightningcss-linux-arm64-gnu@1.30.2: - resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + /lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} - cpu: [arm64] + cpu: [arm] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true @@ -5403,17 +4399,15 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /lightningcss-linux-arm64-musl@1.30.2: - resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + /lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true @@ -5423,17 +4417,15 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /lightningcss-linux-x64-gnu@1.30.2: - resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + /lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} - cpu: [x64] + cpu: [arm64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true @@ -5443,17 +4435,15 @@ packages: engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] requiresBuild: true dev: false optional: true - /lightningcss-linux-x64-musl@1.30.2: - resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + /lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true @@ -5463,16 +4453,15 @@ packages: engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] requiresBuild: true dev: false optional: true - /lightningcss-win32-arm64-msvc@1.30.2: - resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + /lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] + cpu: [x64] + os: [linux] requiresBuild: true dev: false optional: true @@ -5486,10 +4475,10 @@ packages: dev: false optional: true - /lightningcss-win32-x64-msvc@1.30.2: - resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + /lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} - cpu: [x64] + cpu: [arm64] os: [win32] requiresBuild: true dev: false @@ -5504,24 +4493,14 @@ packages: dev: false optional: true - /lightningcss@1.30.2: - resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + /lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.30.2 - lightningcss-darwin-arm64: 1.30.2 - lightningcss-darwin-x64: 1.30.2 - lightningcss-freebsd-x64: 1.30.2 - lightningcss-linux-arm-gnueabihf: 1.30.2 - lightningcss-linux-arm64-gnu: 1.30.2 - lightningcss-linux-arm64-musl: 1.30.2 - lightningcss-linux-x64-gnu: 1.30.2 - lightningcss-linux-x64-musl: 1.30.2 - lightningcss-win32-arm64-msvc: 1.30.2 - lightningcss-win32-x64-msvc: 1.30.2 + cpu: [x64] + os: [win32] + requiresBuild: true dev: false + optional: true /lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} @@ -5542,6 +4521,25 @@ packages: lightningcss-win32-x64-msvc: 1.32.0 dev: false + /lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + dev: false + /lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -5559,9 +4557,9 @@ packages: lilconfig: 3.1.3 listr2: 8.3.3 micromatch: 4.0.8 - pidtree: 0.6.0 + pidtree: 0.6.1 string-argv: 0.3.2 - yaml: 2.8.2 + yaml: 2.9.1 transitivePeerDependencies: - supports-color dev: true @@ -5604,10 +4602,10 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} dependencies: - ansi-escapes: 7.2.0 + ansi-escapes: 7.3.0 cli-cursor: 5.0.0 slice-ansi: 7.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 dev: true @@ -5631,9 +4629,9 @@ packages: /lowlight@3.3.0: resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 devlop: 1.1.0 - highlight.js: 11.11.1 + highlight.js: 11.11.2 dev: false /lucide-react@0.507.0(react@19.2.1): @@ -5647,7 +4645,7 @@ packages: /magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 dev: false /markdown-table@3.0.4: @@ -5658,8 +4656,8 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - /mdast-util-find-and-replace@3.0.2: - resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + /mdast-util-find-and-replace@3.0.3: + resolution: {integrity: sha512-xPgpDNl0/OXHsI7TlaIs22lWnH3KlpvZdXG1ET/m/YT2Hhdkx8lJV4kLphE6l9simyM4KPDFBwas08BgEob6Jw==} dependencies: '@types/mdast': 4.0.4 escape-string-regexp: 5.0.0 @@ -5667,20 +4665,20 @@ packages: unist-util-visit-parents: 6.0.2 dev: false - /mdast-util-from-markdown@2.0.2: - resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + /mdast-util-from-markdown@2.1.0: + resolution: {integrity: sha512-KRLgmPaP2H1ul2bpoJkOS+9pAcDAAj9Nu1mqLnh8NLeJG5tlvj42TH80PIGBpROWlRXLk0lDrWNuZCFy/tsB4A==} dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 - micromark: 4.0.2 + micromark: 4.0.3 micromark-util-decode-numeric-character-reference: 2.0.2 micromark-util-decode-string: 2.0.1 micromark-util-normalize-identifier: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - supports-color @@ -5692,7 +4690,7 @@ packages: '@types/mdast': 4.0.4 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.2 + mdast-util-find-and-replace: 3.0.3 micromark-util-character: 2.1.1 dev: false @@ -5701,19 +4699,19 @@ packages: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 micromark-util-normalize-identifier: 2.0.1 transitivePeerDependencies: - supports-color dev: false - /mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + /mdast-util-gfm-strikethrough@2.0.1: + resolution: {integrity: sha512-OuJHqvr455pwu2OaOrir7dbzqs4jlWKOtlu9L6GjcIjjQwNyw02VntQsr/Ek6/A13vgnXfUhBekWRUP1OkNivw==} dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5724,8 +4722,8 @@ packages: '@types/mdast': 4.0.4 devlop: 1.1.0 markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5735,8 +4733,8 @@ packages: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5744,13 +4742,13 @@ packages: /mdast-util-gfm@3.1.0: resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} dependencies: - mdast-util-from-markdown: 2.0.2 + mdast-util-from-markdown: 2.1.0 mdast-util-gfm-autolink-literal: 2.0.1 mdast-util-gfm-footnote: 2.1.0 - mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.1 mdast-util-gfm-table: 2.0.0 mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.2 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5759,11 +4757,11 @@ packages: resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5772,13 +4770,13 @@ packages: resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 '@types/unist': 3.0.3 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 @@ -5791,11 +4789,11 @@ packages: resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} dependencies: '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 transitivePeerDependencies: - supports-color dev: false @@ -5810,9 +4808,9 @@ packages: /mdast-util-to-hast@13.2.1: resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.0 + '@ungap/structured-clone': 1.4.0 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.1 trim-lines: 3.0.1 @@ -5821,16 +4819,18 @@ packages: vfile: 6.0.3 dev: false - /mdast-util-to-markdown@2.1.2: - resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + /mdast-util-to-markdown@2.2.0: + resolution: {integrity: sha512-2Jn/ADrHFFyyniBMi0bncTbJqU78K3/TEYvzvwrWWzD9MYPUa/Gm4r3nOeKFQg/PDM5BsbDYdc8ackW4NTY6NA==} 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-character: 2.1.1 micromark-util-classify-character: 2.0.1 micromark-util-decode-string: 2.0.1 + micromark-util-html-tag-name: 2.0.1 unist-util-visit: 5.1.0 zwitch: 2.0.4 dev: false @@ -5845,25 +4845,26 @@ packages: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true - /micromark-core-commonmark@2.0.3: - resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + /micromark-core-commonmark@2.0.4: + resolution: {integrity: sha512-wxEeE8v8XVvOrxn1TZj74qYhAtTQsSqufHVS3uNVyT1MupXxhyaHk8/9xDNPh9BmL77QNDgWTkZ3RsYHB2ry7w==} dependencies: decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-factory-destination: 2.0.1 micromark-factory-label: 2.0.1 - micromark-factory-space: 2.0.1 + micromark-factory-space: 2.1.0 micromark-factory-title: 2.0.1 micromark-factory-whitespace: 2.0.1 micromark-util-character: 2.1.1 micromark-util-chunked: 2.0.1 micromark-util-classify-character: 2.0.1 + micromark-util-edit-map: 1.0.0 micromark-util-html-tag-name: 2.0.1 micromark-util-normalize-identifier: 2.0.1 micromark-util-resolve-all: 2.0.1 micromark-util-subtokenize: 2.1.0 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm-autolink-literal@2.1.0: @@ -5872,20 +4873,20 @@ packages: micromark-util-character: 2.1.1 micromark-util-sanitize-uri: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm-footnote@2.1.0: resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} dependencies: devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 + micromark-core-commonmark: 2.0.4 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-normalize-identifier: 2.0.1 micromark-util-sanitize-uri: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm-strikethrough@2.1.0: @@ -5896,33 +4897,33 @@ packages: micromark-util-classify-character: 2.0.1 micromark-util-resolve-all: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false - /micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + /micromark-extension-gfm-table@2.1.2: + resolution: {integrity: sha512-pRzm4kDTu0MjlmBkxmS9yYhw60nncfcEwu9NNdPFSQEFXS95ZKyIIyTSHu/o3ReBUrLKYEq+7YaXCRn/bPB4MA==} dependencies: devlop: 1.1.0 - micromark-factory-space: 2.0.1 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm-tagfilter@2.0.0: resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} dependencies: - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm-task-list-item@2.1.0: resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} dependencies: devlop: 1.1.0 - micromark-factory-space: 2.0.1 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-extension-gfm@3.0.0: @@ -5931,11 +4932,11 @@ packages: 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.1 + micromark-extension-gfm-table: 2.1.2 micromark-extension-gfm-tagfilter: 2.0.0 micromark-extension-gfm-task-list-item: 2.1.0 micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-factory-destination@2.0.1: @@ -5943,7 +4944,7 @@ packages: dependencies: micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-factory-label@2.0.1: @@ -5952,39 +4953,39 @@ packages: devlop: 1.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false - /micromark-factory-space@2.0.1: - resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + /micromark-factory-space@2.1.0: + resolution: {integrity: sha512-fS8hnLIjnjvdQIj39Geug8wWsR0HrYZ43KShKxNfwT7t2LOHo/LbWZEzEaSOjwtjdCsjoE6syHhonEzW0zv0+Q==} dependencies: micromark-util-character: 2.1.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-factory-title@2.0.1: resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} dependencies: - micromark-factory-space: 2.0.1 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-factory-whitespace@2.0.1: resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} dependencies: - micromark-factory-space: 2.0.1 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-character@2.1.1: resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} dependencies: micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-chunked@2.0.1: @@ -5998,14 +4999,14 @@ packages: dependencies: micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-combine-extensions@2.0.1: resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} dependencies: micromark-util-chunked: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-decode-numeric-character-reference@2.0.2: @@ -6023,6 +5024,12 @@ packages: micromark-util-symbol: 2.0.1 dev: false + /micromark-util-edit-map@1.0.0: + resolution: {integrity: sha512-Pa2ljlsEL6sVwFaYeyrOLSYbQt73JvGbPOYFq+9AElXiSnfI5Q4465RRZ1sHv7lDjDOnGRDDaqPXqClqWK/q1Q==} + dependencies: + micromark-util-types: 2.0.3 + dev: false + /micromark-util-encode@2.0.1: resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} dev: false @@ -6040,7 +5047,7 @@ packages: /micromark-util-resolve-all@2.0.1: resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} dependencies: - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-sanitize-uri@2.0.1: @@ -6057,37 +5064,38 @@ packages: devlop: 1.1.0 micromark-util-chunked: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 dev: false /micromark-util-symbol@2.0.1: resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} dev: false - /micromark-util-types@2.0.2: - resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + /micromark-util-types@2.0.3: + resolution: {integrity: sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==} dev: false - /micromark@4.0.2: - resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + /micromark@4.0.3: + resolution: {integrity: sha512-oGYfQzHSG5dOMovQcJ3fyTmZlWAWpi0XA0sJwJs+i6OT88o1+Jtw/8z0CmdowSLxGhhFK89rQ/oXph/wN02PNw==} dependencies: - '@types/debug': 4.1.12 + '@types/debug': 4.1.13 debug: 4.4.3 decode-named-character-reference: 1.3.0 devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 + micromark-core-commonmark: 2.0.4 + micromark-factory-space: 2.1.0 micromark-util-character: 2.1.1 micromark-util-chunked: 2.0.1 micromark-util-combine-extensions: 2.0.1 micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-edit-map: 1.0.0 micromark-util-encode: 2.0.1 micromark-util-normalize-identifier: 2.0.1 micromark-util-resolve-all: 2.0.1 micromark-util-sanitize-uri: 2.0.1 micromark-util-subtokenize: 2.1.0 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 + micromark-util-types: 2.0.3 transitivePeerDependencies: - supports-color dev: false @@ -6122,24 +5130,30 @@ packages: engines: {node: '>=18'} dev: true + /minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + dependencies: + brace-expansion: 5.0.12 + dev: true + /minimatch@3.1.3: resolution: {integrity: sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==} dependencies: - brace-expansion: 1.1.12 + brace-expansion: 1.1.21 dev: true - /minimatch@9.0.7: - resolution: {integrity: sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==} - engines: {node: '>=16 || 14 >=14.17'} + /minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} dependencies: - brace-expansion: 5.0.6 + brace-expansion: 1.1.21 dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - /nanoid@3.3.12: - resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + /nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: false @@ -6148,8 +5162,8 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /node-exports-info@1.6.0: - resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} + /node-exports-info@1.6.2: + resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==} engines: {node: '>= 0.4'} dependencies: array.prototype.flatmap: 1.3.3 @@ -6183,10 +5197,10 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 has-symbols: 1.1.0 object-keys: 1.1.1 dev: true @@ -6195,30 +5209,30 @@ packages: resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 dev: true /object.fromentries@2.0.8: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 dev: true /object.values@1.2.1: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 dev: true /onetime@6.0.0: @@ -6247,10 +5261,11 @@ packages: word-wrap: 1.2.5 dev: true - /own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + /own-keys@1.0.2: + resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} engines: {node: '>= 0.4'} dependencies: + call-bound: 1.0.4 get-intrinsic: 1.3.0 object-keys: 1.1.1 safe-push-apply: 1.0.0 @@ -6341,30 +5356,28 @@ packages: engines: {node: '>=8.6'} dev: true - /picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + /picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + /pidtree@0.6.1: + resolution: {integrity: sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==} engines: {node: '>=0.10'} hasBin: true dev: true - /playwright-core@1.61.0: - resolution: {integrity: sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==} - engines: {node: '>=18'} + /playwright-core@1.64.0: + resolution: {integrity: sha512-T9r+MZkTECl2+oUcZ26YgZzTrYidTsIhYYkJix+6iDOymOb1FB2RLLSOxRGnZGv5DStt+aduIVbt+E8WygXYpg==} + engines: {node: '>=20'} hasBin: true dev: true - /playwright@1.61.0: - resolution: {integrity: sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==} - engines: {node: '>=18'} + /playwright@1.64.0: + resolution: {integrity: sha512-kVzTnYFYEyQ9RGzBjNCd2+yEqWmVbxl3AHPynv3qQ6JTjv4a+kwRcnqQwIpuP3NnrnIrE/Q6wWAIAvMfIE2/Yg==} + engines: {node: '>=20'} hasBin: true dependencies: - playwright-core: 1.61.0 - optionalDependencies: - fsevents: 2.3.2 + playwright-core: 1.64.0 dev: true /pngjs@5.0.0: @@ -6377,13 +5390,13 @@ packages: engines: {node: '>= 0.4'} dev: true - /postcss@8.5.15: - resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + /postcss@8.5.29: + resolution: {integrity: sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.12 + nanoid: 3.3.20 picocolors: 1.1.1 - source-map-js: 1.2.1 + source-map-js: 1.2.2 dev: false /prelude-ls@1.2.1: @@ -6398,8 +5411,8 @@ packages: fast-diff: 1.3.0 dev: true - /prettier@3.8.1: - resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + /prettier@3.9.10: + resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==} engines: {node: '>=14'} hasBin: true dev: true @@ -6416,8 +5429,8 @@ packages: object-assign: 4.1.1 react-is: 16.13.1 - /property-information@7.1.0: - resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + /property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} dev: false /proxy-from-env@2.1.0: @@ -6440,8 +5453,8 @@ packages: yargs: 15.4.1 dev: false - /radix-ui@1.6.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-QBdhh1arIEUvPC0dQ5+nwWAxt7+N+oP/9jPwjJkGFoSk/sqxg32gJtSXGtFh8frAIcS6oC9cx2Q+7KYCQLOAeA==} + /radix-ui@1.7.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-x+z5TV2v6u0QpAQ4dQfNMcvtIdSQ1Op2oqBEyfDXjNldRZbMTP+hcjr5Iie31bep81Axeioa+70Ww7pZDzTEQQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -6454,62 +5467,62 @@ packages: optional: true dependencies: '@radix-ui/primitive': 1.1.7 - '@radix-ui/react-accessible-icon': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-accordion': 1.2.20(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-alert-dialog': 1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-arrow': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-aspect-ratio': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-avatar': 1.2.6(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-checkbox': 1.3.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-collapsible': 1.1.20(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-collection': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context': 1.2.2(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-context-menu': 2.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-dialog': 1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-direction': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-dismissable-layer': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-dropdown-menu': 2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-focus-scope': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-form': 0.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-hover-card': 1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-label': 2.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-menu': 2.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-menubar': 1.1.24(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-navigation-menu': 1.2.22(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-one-time-password-field': 0.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-password-toggle-field': 0.1.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-popover': 1.1.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-popper': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-portal': 1.1.17(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-presence': 1.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-primitive': 2.1.10(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-progress': 1.1.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-radio-group': 1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-roving-focus': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-scroll-area': 1.2.18(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-select': 2.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-separator': 1.1.15(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slider': 1.4.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-slot': 1.3.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-switch': 1.3.7(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-tabs': 1.1.21(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toast': 1.2.23(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toggle': 1.1.18(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toggle-group': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-toolbar': 1.1.19(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-tooltip': 1.2.16(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-escape-keydown': 1.1.5(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-use-size': 1.1.4(@types/react@19.2.10)(react@19.2.1) - '@radix-ui/react-visually-hidden': 1.2.11(@types/react-dom@19.2.3)(@types/react@19.2.10)(react-dom@19.2.1)(react@19.2.1) - '@types/react': 19.2.10 - '@types/react-dom': 19.2.3(@types/react@19.2.10) + '@radix-ui/react-accessible-icon': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-accordion': 1.2.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-alert-dialog': 1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-arrow': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-aspect-ratio': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-avatar': 1.2.7(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-checkbox': 1.3.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-collapsible': 1.1.21(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-collection': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context': 1.2.2(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-context-menu': 2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-dialog': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-direction': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-dismissable-layer': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-dropdown-menu': 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-focus-guards': 1.1.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-focus-scope': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-form': 0.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-hover-card': 1.1.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-label': 2.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-menu': 2.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-menubar': 1.1.25(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-navigation-menu': 1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-one-time-password-field': 0.1.17(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-password-toggle-field': 0.1.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-popover': 1.2.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-popper': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-portal': 1.1.18(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-presence': 1.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-primitive': 2.1.11(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-progress': 1.1.17(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-radio-group': 1.4.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-roving-focus': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-scroll-area': 1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-select': 2.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-separator': 1.1.16(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slider': 1.5.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-slot': 1.4.0(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-switch': 1.3.8(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-tabs': 1.1.22(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toast': 1.2.24(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toggle': 1.1.19(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toggle-group': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-toolbar': 1.1.20(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-tooltip': 1.3.0(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@radix-ui/react-use-callback-ref': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-controllable-state': 1.2.6(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-escape-keydown': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-use-size': 1.1.5(@types/react@19.2.18)(react@19.2.1) + '@radix-ui/react-visually-hidden': 1.2.12(@types/react-dom@19.2.7)(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1) + '@types/react': 19.2.18 + '@types/react-dom': 19.2.7(@types/react@19.2.18) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false @@ -6523,16 +5536,21 @@ packages: scheduler: 0.27.0 dev: false - /react-hook-form@7.71.1(react@19.2.1): - resolution: {integrity: sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==} + /react-hook-form@7.90.0(@types/react@19.2.18)(react@19.2.1): + resolution: {integrity: sha512-+NdG0FLzCPhFOp2NNxaUYLF9fyZhNjx9FTBBSYWF71/l6BBlmIc/j6xlp3DbaHWLJbIG7Zd8oznA19xJClU97w==} engines: {node: '>=18.0.0'} peerDependencies: + '@types/react': '*' react: ^16.8.0 || ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true dependencies: + '@types/react': 19.2.18 react: 19.2.1 dev: false - /react-i18next@15.7.4(i18next@25.8.0)(react-dom@19.2.1)(react@19.2.1)(typescript@5.9.3): + /react-i18next@15.7.4(i18next@25.10.10)(react-dom@19.2.1)(react@19.2.1)(typescript@5.9.3): resolution: {integrity: sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==} peerDependencies: i18next: '>= 23.4.0' @@ -6548,9 +5566,9 @@ packages: typescript: optional: true dependencies: - '@babel/runtime': 7.28.6 - html-parse-stringify: 3.0.1 - i18next: 25.8.0(typescript@5.9.3) + '@babel/runtime': 7.29.10 + html-parse-stringify: 3.1.0 + i18next: 25.10.10(typescript@5.9.3) react: 19.2.1 react-dom: 19.2.1(react@19.2.1) typescript: 5.9.3 @@ -6563,15 +5581,15 @@ packages: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} dev: false - /react-markdown@10.1.0(@types/react@19.2.10)(react@19.2.1): + /react-markdown@10.1.0(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} peerDependencies: '@types/react': '>=18' react: '>=18' dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 - '@types/react': 19.2.10 + '@types/react': 19.2.18 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -6596,7 +5614,7 @@ packages: react-dom: 19.2.1(react@19.2.1) dev: false - /react-remove-scroll-bar@2.3.8(@types/react@19.2.10)(react@19.2.1): + /react-remove-scroll-bar@2.3.8(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} peerDependencies: @@ -6606,13 +5624,13 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 - react-style-singleton: 2.2.3(@types/react@19.2.10)(react@19.2.1) + react-style-singleton: 2.2.3(@types/react@19.2.18)(react@19.2.1) tslib: 2.8.1 dev: false - /react-remove-scroll@2.7.2(@types/react@19.2.10)(react@19.2.1): + /react-remove-scroll@2.7.2(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} engines: {node: '>=10'} peerDependencies: @@ -6622,17 +5640,17 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.10)(react@19.2.1) - react-style-singleton: 2.2.3(@types/react@19.2.10)(react@19.2.1) + react-remove-scroll-bar: 2.3.8(@types/react@19.2.18)(react@19.2.1) + react-style-singleton: 2.2.3(@types/react@19.2.18)(react@19.2.1) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.10)(react@19.2.1) - use-sidecar: 1.1.3(@types/react@19.2.10)(react@19.2.1) + use-callback-ref: 1.3.3(@types/react@19.2.18)(react@19.2.1) + use-sidecar: 1.1.3(@types/react@19.2.18)(react@19.2.1) dev: false - /react-router-dom@7.17.0(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-fyU2yjGups/hE6Xz0I5ZYbVL8Gx29eCjgpHaRaTaVU+OOAdfRX05KsvyRm0GO8YQwOkhpU3MurW1jyMUJn+zSw==} + /react-router-dom@7.18.4(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -6640,11 +5658,11 @@ packages: dependencies: react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - react-router: 7.17.0(react-dom@19.2.1)(react@19.2.1) + react-router: 7.18.4(react-dom@19.2.1)(react@19.2.1) dev: false - /react-router@7.17.0(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ==} + /react-router@7.18.4(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==} engines: {node: '>=20.0.0'} peerDependencies: react: '>=18' @@ -6665,14 +5683,14 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 dependencies: - fast-equals: 5.4.0 + fast-equals: 5.4.4 prop-types: 15.8.1 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) react-transition-group: 4.4.5(react-dom@19.2.1)(react@19.2.1) dev: false - /react-style-singleton@2.2.3(@types/react@19.2.10)(react@19.2.1): + /react-style-singleton@2.2.3(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} peerDependencies: @@ -6682,19 +5700,19 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 get-nonce: 1.0.1 react: 19.2.1 tslib: 2.8.1 dev: false - /react-syntax-highlighter@16.1.0(react@19.2.1): - resolution: {integrity: sha512-E40/hBiP5rCNwkeBN1vRP+xow1X0pndinO+z3h7HLsHyjztbyjfzNWNKuAsJj+7DLam9iT4AaaOZnueCU+Nplg==} + /react-syntax-highlighter@16.1.2(react@19.2.1): + resolution: {integrity: sha512-4dM0+mYtfnhgwYWAvFx56fgyjIYk2yFopfiICFvMDhRfeSGRNd+ngFALdPD9q7llyGAmiE6pzOSOwI8Lf9ca1w==} engines: {node: '>= 16.20.2'} peerDependencies: react: '>= 0.14.0' dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.10 highlight.js: 10.7.3 highlightjs-vue: 1.0.0 lowlight: 1.20.0 @@ -6709,7 +5727,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.29.10 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -6731,6 +5749,7 @@ packages: /recharts@2.15.4(react-dom@19.2.1)(react@19.2.1): resolution: {integrity: sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==} engines: {node: '>=14'} + deprecated: 1.x and 2.x branches are no longer active. Bump to Recharts v3 to receive latest features and bugfixes. See https://github.com/recharts/recharts/wiki/3.0-migration-guide peerDependencies: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -6751,11 +5770,11 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 get-proto: 1.0.1 which-builtin-type: 1.2.1 @@ -6764,8 +5783,8 @@ packages: /refractor@5.0.0: resolution: {integrity: sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==} dependencies: - '@types/hast': 3.0.4 - '@types/prismjs': 1.26.5 + '@types/hast': 3.0.5 + '@types/prismjs': 1.26.6 hastscript: 9.0.1 parse-entities: 4.0.2 dev: false @@ -6774,7 +5793,7 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 es-errors: 1.3.0 get-proto: 1.0.1 @@ -6785,8 +5804,8 @@ packages: /rehype-autolink-headings@7.1.0: resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} dependencies: - '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.3.0 + '@types/hast': 3.0.5 + '@ungap/structured-clone': 1.4.0 hast-util-heading-rank: 3.0.0 hast-util-is-element: 3.0.0 unified: 11.0.5 @@ -6796,7 +5815,7 @@ packages: /rehype-highlight@7.0.2: resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 hast-util-to-text: 4.0.2 lowlight: 3.3.0 unist-util-visit: 5.1.0 @@ -6806,7 +5825,7 @@ packages: /rehype-raw@7.0.0: resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 hast-util-raw: 9.1.0 vfile: 6.0.3 dev: false @@ -6814,14 +5833,14 @@ packages: /rehype-sanitize@6.0.0: resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 hast-util-sanitize: 5.0.2 dev: false /rehype-slug@6.0.0: resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 github-slugger: 2.0.0 hast-util-heading-rank: 3.0.0 hast-util-to-string: 3.0.1 @@ -6845,8 +5864,8 @@ packages: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.2 - micromark-util-types: 2.0.2 + mdast-util-from-markdown: 2.1.0 + micromark-util-types: 2.0.3 unified: 11.0.5 transitivePeerDependencies: - supports-color @@ -6855,7 +5874,7 @@ packages: /remark-rehype@11.1.2: resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} dependencies: - '@types/hast': 3.0.4 + '@types/hast': 3.0.5 '@types/mdast': 4.0.4 mdast-util-to-hast: 13.2.1 unified: 11.0.5 @@ -6866,7 +5885,7 @@ packages: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} dependencies: '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.2 + mdast-util-to-markdown: 2.2.0 unified: 11.0.5 dev: false @@ -6884,14 +5903,14 @@ packages: engines: {node: '>=4'} dev: true - /resolve@2.0.0-next.6: - resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==} + /resolve@2.0.0-next.7: + resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} engines: {node: '>= 0.4'} hasBin: true dependencies: es-errors: 1.3.0 - is-core-module: 2.16.1 - node-exports-info: 1.6.0 + is-core-module: 2.17.0 + node-exports-info: 1.6.2 object-keys: 1.1.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -6909,36 +5928,36 @@ packages: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} dev: true - /rolldown@1.0.3: - resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + /rolldown@1.2.13: + resolution: {integrity: sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true dependencies: - '@oxc-project/types': 0.133.0 + '@oxc-project/types': 0.153.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.3 - '@rolldown/binding-darwin-arm64': 1.0.3 - '@rolldown/binding-darwin-x64': 1.0.3 - '@rolldown/binding-freebsd-x64': 1.0.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.3 - '@rolldown/binding-linux-arm64-musl': 1.0.3 - '@rolldown/binding-linux-ppc64-gnu': 1.0.3 - '@rolldown/binding-linux-s390x-gnu': 1.0.3 - '@rolldown/binding-linux-x64-gnu': 1.0.3 - '@rolldown/binding-linux-x64-musl': 1.0.3 - '@rolldown/binding-openharmony-arm64': 1.0.3 - '@rolldown/binding-wasm32-wasi': 1.0.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.3 - '@rolldown/binding-win32-x64-msvc': 1.0.3 + '@rolldown/binding-android-arm-eabi': 1.2.13 + '@rolldown/binding-android-arm64': 1.2.13 + '@rolldown/binding-darwin-arm64': 1.2.13 + '@rolldown/binding-darwin-x64': 1.2.13 + '@rolldown/binding-freebsd-x64': 1.2.13 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.13 + '@rolldown/binding-linux-arm64-gnu': 1.2.13 + '@rolldown/binding-linux-arm64-musl': 1.2.13 + '@rolldown/binding-linux-ppc64-gnu': 1.2.13 + '@rolldown/binding-linux-s390x-gnu': 1.2.13 + '@rolldown/binding-linux-x64-gnu': 1.2.13 + '@rolldown/binding-linux-x64-musl': 1.2.13 + '@rolldown/binding-openharmony-arm64': 1.2.13 + '@rolldown/binding-win32-arm64-msvc': 1.2.13 + '@rolldown/binding-win32-x64-msvc': 1.2.13 dev: false - /safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + /safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 get-intrinsic: 1.3.0 has-symbols: 1.1.0 @@ -6971,8 +5990,8 @@ packages: hasBin: true dev: true - /semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + /semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} hasBin: true dev: true @@ -7013,7 +6032,7 @@ packages: dependencies: dunder-proto: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 dev: true /shebang-command@2.0.0: @@ -7028,8 +6047,8 @@ packages: engines: {node: '>=8'} dev: true - /side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + /side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 @@ -7057,13 +6076,13 @@ packages: side-channel-map: 1.0.1 dev: true - /side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + /side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} engines: {node: '>= 0.4'} dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 - side-channel-list: 1.0.0 + side-channel-list: 1.0.1 side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 dev: true @@ -7089,18 +6108,23 @@ packages: is-fullwidth-code-point: 5.1.0 dev: true - /sonner@2.0.7(react-dom@19.2.1)(react@19.2.1): - resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} + /sonner@2.0.8(@types/react@19.2.18)(react-dom@19.2.1)(react@19.2.1): + resolution: {integrity: sha512-UM/ByIoFra8yzV75n1o0Puu0bw5U/9UNnDacrJNspekBewIfsQ3D6ez1nvlWpt7aTsO6rujQtifBpycwIivqlg==} peerDependencies: + '@types/react': ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true dependencies: + '@types/react': 19.2.18 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) dev: false - /source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + /source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} dev: false @@ -7135,66 +6159,67 @@ packages: engines: {node: '>=18'} dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 dev: true - /string.prototype.matchall@4.0.12: - resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + /string.prototype.matchall@4.1.0: + resolution: {integrity: sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 gopd: 1.2.0 has-symbols: 1.1.0 internal-slot: 1.1.0 regexp.prototype.flags: 1.5.4 set-function-name: 2.0.2 - side-channel: 1.1.0 + side-channel: 1.1.1 dev: true /string.prototype.repeat@1.0.0: resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} dependencies: define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 dev: true - /string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + /string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 dev: true - /string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + /string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 dev: true /string.prototype.trimstart@1.0.8: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 dev: true /stringify-entities@4.0.4: @@ -7211,11 +6236,11 @@ packages: ansi-regex: 5.0.1 dev: false - /strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + /strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.4.0 dev: true /strip-final-newline@3.0.0: @@ -7252,23 +6277,23 @@ packages: engines: {node: '>= 0.4'} dev: true - /synckit@0.11.12: - resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + /synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} dependencies: - '@pkgr/core': 0.2.9 + '@pkgr/core': 0.3.6 dev: true - /tailwind-merge@3.4.0: - resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} + /tailwind-merge@3.7.0: + resolution: {integrity: sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA==} dev: false - /tailwindcss@4.1.18: - resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} + /tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} dev: false - /tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + /tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} dev: false @@ -7276,21 +6301,12 @@ packages: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} dev: false - /tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - dev: true - /tinyglobby@0.2.17: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - dev: false + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -7307,8 +6323,8 @@ packages: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} dev: false - /ts-api-utils@2.4.0(typescript@5.9.3): - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + /ts-api-utils@2.5.0(typescript@5.9.3): + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -7344,31 +6360,30 @@ packages: resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 dev: true - /typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + /typed-array-byte-offset@1.0.5: + resolution: {integrity: sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 - has-proto: 1.2.0 is-typed-array: 1.1.15 reflect.getprototypeof: 1.0.10 dev: true - /typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + /typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 is-typed-array: 1.1.15 @@ -7376,18 +6391,18 @@ packages: reflect.getprototypeof: 1.0.10 dev: true - /typescript-eslint@8.54.0(eslint@9.39.2)(typescript@5.9.3): - resolution: {integrity: sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==} + /typescript-eslint@8.71.1(eslint@9.39.5)(typescript@5.9.3): + resolution: {integrity: sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' dependencies: - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0)(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) - eslint: 9.39.2 + '@typescript-eslint/eslint-plugin': 8.71.1(@typescript-eslint/parser@8.71.1)(eslint@9.39.5)(typescript@5.9.3) + '@typescript-eslint/parser': 8.71.1(eslint@9.39.5)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.71.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.71.1(eslint@9.39.5)(typescript@5.9.3) + eslint: 9.39.5 typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7469,7 +6484,7 @@ packages: punycode: 2.3.1 dev: true - /use-callback-ref@1.3.3(@types/react@19.2.10)(react@19.2.1): + /use-callback-ref@1.3.3(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} peerDependencies: @@ -7479,12 +6494,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 react: 19.2.1 tslib: 2.8.1 dev: false - /use-sidecar@1.1.3(@types/react@19.2.10)(react@19.2.1): + /use-sidecar@1.1.3(@types/react@19.2.18)(react@19.2.1): resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: @@ -7494,20 +6509,12 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 19.2.10 + '@types/react': 19.2.18 detect-node-es: 1.1.0 react: 19.2.1 tslib: 2.8.1 dev: false - /use-sync-external-store@1.6.0(react@19.2.1): - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - dependencies: - react: 19.2.1 - dev: false - /uuidjs@5.1.0: resolution: {integrity: sha512-HAQPtUkr7t5Ud3uCwRcqtBRNagu/2aerrrBQE6PzgSluGijvFF75UaOq22Xw545GGviRjSLhc4c8CaSMI5h4Ng==} hasBin: true @@ -7541,7 +6548,7 @@ packages: '@types/d3-ease': 3.0.2 '@types/d3-interpolate': 3.0.4 '@types/d3-scale': 4.0.9 - '@types/d3-shape': 3.1.8 + '@types/d3-shape': 3.2.0 '@types/d3-time': 3.0.4 '@types/d3-timer': 3.0.2 d3-array: 3.2.4 @@ -7553,13 +6560,13 @@ packages: d3-timer: 3.0.1 dev: false - /vite@8.0.16(@types/node@20.19.30): - resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + /vite@8.3.4(@types/node@20.19.43): + resolution: {integrity: sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.18 + '@vitejs/devtools': ^0.7.1 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -7596,11 +6603,11 @@ packages: yaml: optional: true dependencies: - '@types/node': 20.19.30 - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.15 - rolldown: 1.0.3 + '@types/node': 20.19.43 + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.29 + rolldown: 1.2.13 tinyglobby: 0.2.17 optionalDependencies: fsevents: 2.3.3 @@ -7631,7 +6638,7 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bound: 1.0.4 - function.prototype.name: 1.1.8 + function.prototype.name: 1.2.0 has-tostringtag: 1.0.2 is-async-function: 2.1.1 is-date-object: 1.1.0 @@ -7642,7 +6649,7 @@ packages: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.20 + which-typed-array: 1.1.24 dev: true /which-collection@1.0.2: @@ -7659,12 +6666,12 @@ packages: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} dev: false - /which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + /which-typed-array@1.1.24: + resolution: {integrity: sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 for-each: 0.3.5 get-proto: 1.0.1 @@ -7700,15 +6707,15 @@ packages: dependencies: ansi-styles: 6.2.3 string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 dev: true /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} dev: false - /yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + /yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} engines: {node: '>= 14.6'} hasBin: true dev: true diff --git a/web/src/app/RootLayout.tsx b/web/src/app/RootLayout.tsx index 3a5dffb12..444de4b4a 100644 --- a/web/src/app/RootLayout.tsx +++ b/web/src/app/RootLayout.tsx @@ -1,15 +1,9 @@ import { Outlet } from 'react-router-dom'; import { useDocumentTitle } from '@/hooks/useDocumentTitle'; -import { BetaBanner } from '@/components/BetaBanner'; // Top-level route layout: drives the dynamic document title from the active // route and renders the matched child route via . export default function RootLayout() { useDocumentTitle(); - return ( - <> - - - - ); + return ; } diff --git a/web/src/app/global.css b/web/src/app/global.css index a1be44406..7458cdc84 100644 --- a/web/src/app/global.css +++ b/web/src/app/global.css @@ -195,3 +195,28 @@ body:has([data-tour-modal='true']) [data-tour-modal='false'] { display: none; } + +/* Reserve native scrollbar space before content overflows. Extending the + utilities also covers responsive variants, nested panels and popup menus. + Horizontal-only scrollers and custom overlay scroll areas stay unchanged. */ +@utility overflow-auto { + scrollbar-gutter: stable; +} + +@utility overflow-y-auto { + scrollbar-gutter: stable; +} + +@utility overflow-scroll { + scrollbar-gutter: stable; +} + +@utility overflow-y-scroll { + scrollbar-gutter: stable; +} + +@layer base { + textarea { + scrollbar-gutter: stable; + } +} diff --git a/web/src/app/home/agents/components/AgentApiToolPicker.tsx b/web/src/app/home/agents/components/AgentApiToolPicker.tsx index 812e739ca..ca32fe68a 100644 --- a/web/src/app/home/agents/components/AgentApiToolPicker.tsx +++ b/web/src/app/home/agents/components/AgentApiToolPicker.tsx @@ -319,8 +319,7 @@ export default function AgentApiToolPicker({ const expanded = expandedTool === tool.key; const parameterNames = Object.keys( (tool.parameters.properties as - | Record - | undefined) ?? {}, + Record | undefined) ?? {}, ); return (
diff --git a/web/src/app/home/agents/runner-marketplace.ts b/web/src/app/home/agents/runner-marketplace.ts index 328d68029..ebec6c3e9 100644 --- a/web/src/app/home/agents/runner-marketplace.ts +++ b/web/src/app/home/agents/runner-marketplace.ts @@ -20,9 +20,7 @@ const RUNNER_INSTALL_INTENT_KEY_PREFIX = 'langbot-runner-install'; const RUNNER_INSTALL_INTENT_EVENT = 'langbot-runner-install-change'; export type RunnerMarketplaceErrorCode = - | 'version-unavailable' - | 'install-timeout' - | 'registration-timeout'; + 'version-unavailable' | 'install-timeout' | 'registration-timeout'; export class RunnerMarketplaceError extends Error { constructor(public readonly code: RunnerMarketplaceErrorCode) { diff --git a/web/src/app/home/bots/components/bot-form/BotForm.tsx b/web/src/app/home/bots/components/bot-form/BotForm.tsx index 0d036c221..0ae7d6dff 100644 --- a/web/src/app/home/bots/components/bot-form/BotForm.tsx +++ b/web/src/app/home/bots/components/bot-form/BotForm.tsx @@ -498,8 +498,7 @@ const BotForm = forwardRef(function BotForm( .then((res) => { const bot = res.bot; const runtimeValues = bot.adapter_runtime_values as - | Record - | undefined; + Record | undefined; resolve({ adapter: bot.adapter, description: bot.description, @@ -509,11 +508,9 @@ const BotForm = forwardRef(function BotForm( event_bindings: bot.event_bindings ?? [], plugin_processors: bot.plugin_processors ?? [], webhook_full_url: runtimeValues?.webhook_full_url as - | string - | undefined, + string | undefined, extra_webhook_full_url: runtimeValues?.extra_webhook_full_url as - | string - | undefined, + string | undefined, }); }) .catch((err) => { diff --git a/web/src/app/home/bots/components/bot-form/EventBindingsEditor.tsx b/web/src/app/home/bots/components/bot-form/EventBindingsEditor.tsx index f8b18954f..06fcae3d7 100644 --- a/web/src/app/home/bots/components/bot-form/EventBindingsEditor.tsx +++ b/web/src/app/home/bots/components/bot-form/EventBindingsEditor.tsx @@ -144,17 +144,9 @@ interface EventBindingsEditorProps { } type FilterField = - | 'chat_type' - | 'chat_id' - | 'message_text' - | 'message_element_types'; + 'chat_type' | 'chat_id' | 'message_text' | 'message_element_types'; type FilterOperator = - | 'eq' - | 'neq' - | 'contains' - | 'not_contains' - | 'starts_with' - | 'regex'; + 'eq' | 'neq' | 'contains' | 'not_contains' | 'starts_with' | 'regex'; interface FilterRow { field: FilterField; diff --git a/web/src/app/home/components/dynamic-form/StructuredFieldValue.ts b/web/src/app/home/components/dynamic-form/StructuredFieldValue.ts index 09a4c34e0..6e4415452 100644 --- a/web/src/app/home/components/dynamic-form/StructuredFieldValue.ts +++ b/web/src/app/home/components/dynamic-form/StructuredFieldValue.ts @@ -1,10 +1,5 @@ export type JsonValue = - | null - | boolean - | number - | string - | JsonValue[] - | { [key: string]: JsonValue }; + null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }; export type PromptMessage = { role: string; content?: string | null | JsonValue[]; diff --git a/web/src/app/home/components/dynamic-form/ToolResourceSelectors.tsx b/web/src/app/home/components/dynamic-form/ToolResourceSelectors.tsx index df729d634..4b06b991c 100644 --- a/web/src/app/home/components/dynamic-form/ToolResourceSelectors.tsx +++ b/web/src/app/home/components/dynamic-form/ToolResourceSelectors.tsx @@ -204,19 +204,17 @@ function buildToolSourceGroups( (rightIndex === -1 ? TOOL_SOURCE_ORDER.length : rightIndex) ); }) - .map( - ([source, providerGroups]): ToolSourceGroup => ({ - key: source, - label: sourceLabels[source] || source, - groups: Array.from(providerGroups.values()).sort((left, right) => - left.name.localeCompare(right.name), - ), - total: Array.from(providerGroups.values()).reduce( - (count, group) => count + group.tools.length, - 0, - ), - }), - ); + .map(([source, providerGroups]): ToolSourceGroup => ({ + key: source, + label: sourceLabels[source] || source, + groups: Array.from(providerGroups.values()).sort((left, right) => + left.name.localeCompare(right.name), + ), + total: Array.from(providerGroups.values()).reduce( + (count, group) => count + group.tools.length, + 0, + ), + })); } function buildMCPToolOwners(servers: MCPServer[]) { diff --git a/web/src/app/home/components/guided-tour/TourOverlay.tsx b/web/src/app/home/components/guided-tour/TourOverlay.tsx index e1a05476f..a52b542a9 100644 --- a/web/src/app/home/components/guided-tour/TourOverlay.tsx +++ b/web/src/app/home/components/guided-tour/TourOverlay.tsx @@ -45,6 +45,12 @@ export function getTourPosition( ? rect.bottom + VIEWPORT_GAP : rect.top - height - VIEWPORT_GAP; } + // The mobile sidebar can still be sliding in when its target is measured. + // Clamp the card independently of that temporarily off-screen target. + left = Math.max( + VIEWPORT_GAP, + Math.min(left, viewportWidth - width - VIEWPORT_GAP), + ); top = Math.max( VIEWPORT_GAP, Math.min(top, viewportHeight - height - VIEWPORT_GAP), diff --git a/web/src/app/home/components/inflight/InFlightMonitor.tsx b/web/src/app/home/components/inflight/InFlightMonitor.tsx index 13425cf28..3e831ee23 100644 --- a/web/src/app/home/components/inflight/InFlightMonitor.tsx +++ b/web/src/app/home/components/inflight/InFlightMonitor.tsx @@ -166,7 +166,7 @@ function WorkspaceMonitor() {