From 4950afca75a7ebcfad97cc873bf9b479ba92028b Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Fri, 22 Sep 2023 14:47:17 +0900 Subject: [PATCH 01/46] fix: allow `ResourceSlotColumn` to return `None` (#1469) --- changes/1469.fix.md | 2 + ..._kernel_requested_slots_to_not_nullable.py | 61 +++++++++++++++++++ src/ai/backend/manager/models/base.py | 6 +- src/ai/backend/manager/models/kernel.py | 3 +- 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 changes/1469.fix.md create mode 100644 src/ai/backend/manager/models/alembic/versions/85615e005fa3_kernel_requested_slots_to_not_nullable.py diff --git a/changes/1469.fix.md b/changes/1469.fix.md new file mode 100644 index 0000000000..e723b5eb0c --- /dev/null +++ b/changes/1469.fix.md @@ -0,0 +1,2 @@ +Enable `ResourceSlotColumn` to return `None` since we need to distinguish between empty `ResourceSlot` value and `None`. +Alter `kernels.requested_slots` column into not nullable since the value of the column should not be null. diff --git a/src/ai/backend/manager/models/alembic/versions/85615e005fa3_kernel_requested_slots_to_not_nullable.py b/src/ai/backend/manager/models/alembic/versions/85615e005fa3_kernel_requested_slots_to_not_nullable.py new file mode 100644 index 0000000000..7b45d460a3 --- /dev/null +++ b/src/ai/backend/manager/models/alembic/versions/85615e005fa3_kernel_requested_slots_to_not_nullable.py @@ -0,0 +1,61 @@ +"""kernel_requested_slots_to_not_nullable + +Revision ID: 85615e005fa3 +Revises: a083c6c962e5 +Create Date: 2023-09-22 12:37:31.725324 + +""" +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql as pgsql + +from ai.backend.manager.models.base import GUID, mapper_registry + +# revision identifiers, used by Alembic. +revision = "85615e005fa3" +down_revision = "a083c6c962e5" +branch_labels = None +depends_on = None + + +BATCH_SIZE = 100 + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + connection = op.get_bind() + kernels = sa.Table( + "kernels", + mapper_registry.metadata, + sa.Column( + "id", + GUID, + primary_key=True, + ), + sa.Column("requested_slots", pgsql.JSONB()), + extend_existing=True, + ) + + while True: + select_stmt = ( + sa.select([kernels.c.id]).where(kernels.c.requested_slots.is_(None)).limit(BATCH_SIZE) + ) + result = connection.execute(select_stmt).fetchall() + kernel_ids_to_update = [row.id for row in result] + + stmt = ( + sa.update(kernels) + .where(kernels.c.id.in_(kernel_ids_to_update)) + .values(requested_slots={}) + ) + result = connection.execute(stmt) + if len(kernel_ids_to_update) < BATCH_SIZE: + break + op.alter_column("kernels", "requested_slots", nullable=False) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column("kernels", "requested_slots", nullable=True) + # ### end Alembic commands ### diff --git a/src/ai/backend/manager/models/base.py b/src/ai/backend/manager/models/base.py index 9e07d2f2d4..a2498cd9a3 100644 --- a/src/ai/backend/manager/models/base.py +++ b/src/ai/backend/manager/models/base.py @@ -236,9 +236,11 @@ def process_bind_param( return value.to_json() return value - def process_result_value(self, raw_value: Dict[str, str], dialect) -> ResourceSlot: + def process_result_value( + self, raw_value: dict[str, str] | None, dialect + ) -> ResourceSlot | None: if raw_value is None: - return ResourceSlot() + return None # legacy handling interim_value: Dict[str, Any] = raw_value mem = raw_value.get("mem") diff --git a/src/ai/backend/manager/models/kernel.py b/src/ai/backend/manager/models/kernel.py index b98f68474d..0dd80bfb2c 100644 --- a/src/ai/backend/manager/models/kernel.py +++ b/src/ai/backend/manager/models/kernel.py @@ -39,6 +39,7 @@ ClusterMode, KernelId, RedisConnectionInfo, + ResourceSlot, SessionId, SessionResult, SessionTypes, @@ -429,7 +430,7 @@ async def handle_kernel_exception( # Resource occupation sa.Column("container_id", sa.String(length=64)), sa.Column("occupied_slots", ResourceSlotColumn(), nullable=False), - sa.Column("requested_slots", ResourceSlotColumn(), nullable=True), + sa.Column("requested_slots", ResourceSlotColumn(), nullable=False, default=ResourceSlot()), sa.Column("occupied_shares", pgsql.JSONB(), nullable=False, default={}), # legacy sa.Column("environ", sa.ARRAY(sa.String), nullable=True), sa.Column("mounts", sa.ARRAY(sa.String), nullable=True), # list of list; legacy since 22.03 From 257189555b7152fd2cd94c6138e5711c17281da8 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Fri, 22 Sep 2023 15:17:20 +0900 Subject: [PATCH 02/46] feature: limit the number of containers per agents (#1338) Co-authored-by: Joongi Kim --- changes/1338.feature.md | 1 + src/ai/backend/agent/agent.py | 10 ++++ src/ai/backend/manager/models/agent.py | 7 +++ src/ai/backend/manager/registry.py | 2 +- .../backend/manager/scheduler/dispatcher.py | 50 +++++++++++++++++-- tests/manager/conftest.py | 7 ++- tests/manager/test_scheduler.py | 4 ++ 7 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 changes/1338.feature.md diff --git a/changes/1338.feature.md b/changes/1338.feature.md new file mode 100644 index 0000000000..fa0c17986a --- /dev/null +++ b/changes/1338.feature.md @@ -0,0 +1 @@ +Implement limitation of the number of containers per agent. diff --git a/src/ai/backend/agent/agent.py b/src/ai/backend/agent/agent.py index 6d4b4f82d3..30debf62b2 100644 --- a/src/ai/backend/agent/agent.py +++ b/src/ai/backend/agent/agent.py @@ -1242,6 +1242,7 @@ async def sync_container_lifecycles(self, interval: float) -> None: known_kernels: Dict[KernelId, ContainerId] = {} alive_kernels: Dict[KernelId, ContainerId] = {} kernel_session_map: Dict[KernelId, SessionId] = {} + own_kernels: dict[KernelId, ContainerId] = {} terminated_kernels = {} async with self.registry_lock: @@ -1270,6 +1271,7 @@ async def sync_container_lifecycles(self, interval: float) -> None: alive_kernels[kernel_id] = container.id session_id = SessionId(UUID(container.labels["ai.backend.session-id"])) kernel_session_map[kernel_id] = session_id + own_kernels[kernel_id] = container.id for kernel_id, kernel_obj in self.kernel_registry.items(): known_kernels[kernel_id] = kernel_obj["container_id"] session_id = kernel_obj.session_id @@ -1304,6 +1306,14 @@ async def sync_container_lifecycles(self, interval: float) -> None: for kernel_id, ev in terminated_kernels.items(): await self.container_lifecycle_queue.put(ev) + # Set container count + await self.set_container_count(len(own_kernels.keys())) + + async def set_container_count(self, container_count: int) -> None: + await redis_helper.execute( + self.redis_stat_pool, lambda r: r.set(f"container_count.{self.id}", container_count) + ) + async def clean_all_kernels(self, blocking: bool = False) -> None: kernel_ids = [*self.kernel_registry.keys()] clean_events = {} diff --git a/src/ai/backend/manager/models/agent.py b/src/ai/backend/manager/models/agent.py index ed80e29951..95a4a1210b 100644 --- a/src/ai/backend/manager/models/agent.py +++ b/src/ai/backend/manager/models/agent.py @@ -142,6 +142,7 @@ class Meta: hardware_metadata = graphene.JSONString() auto_terminate_abusing_kernel = graphene.Boolean() local_config = graphene.JSONString() + container_count = graphene.Int() # Legacy fields mem_slots = graphene.Int() @@ -241,6 +242,12 @@ async def resolve_local_config(self, info: graphene.ResolveInfo) -> Mapping[str, }, } + async def resolve_container_count(self, info: graphene.ResolveInfo) -> int: + ctx: GraphQueryContext = info.context + rs = ctx.redis_stat + cnt = await redis_helper.execute(rs, lambda r: r.get(f"container_count.{self.id}")) + return int(cnt) if cnt is not None else 0 + _queryfilter_fieldspec: Mapping[str, FieldSpecItem] = { "id": ("id", None), "status": ("status", enum_field_getter(AgentStatus)), diff --git a/src/ai/backend/manager/registry.py b/src/ai/backend/manager/registry.py index b13e49183b..f9435cf292 100644 --- a/src/ai/backend/manager/registry.py +++ b/src/ai/backend/manager/registry.py @@ -2398,7 +2398,7 @@ async def _fetch_session() -> Row: .select_from(kernels) .where( (kernels.c.session_id == session_id) - & (kernels.c.cluster_role == DEFAULT_ROLE), + & (kernels.c.cluster_role == DEFAULT_ROLE) ) ) result = await conn.execute(query) diff --git a/src/ai/backend/manager/scheduler/dispatcher.py b/src/ai/backend/manager/scheduler/dispatcher.py index aa1809a105..74aa6853dd 100644 --- a/src/ai/backend/manager/scheduler/dispatcher.py +++ b/src/ai/backend/manager/scheduler/dispatcher.py @@ -13,10 +13,13 @@ import async_timeout import sqlalchemy as sa from dateutil.tz import tzutc +from redis.asyncio import Redis +from redis.asyncio.client import Pipeline as RedisPipeline from sqlalchemy.exc import DBAPIError from sqlalchemy.ext.asyncio import AsyncSession as SASession from sqlalchemy.orm import noload, selectinload +from ai.backend.common import redis_helper from ai.backend.common.distributed import GlobalTimer from ai.backend.common.events import ( AgentStartedEvent, @@ -613,6 +616,28 @@ async def _update_session_status_data() -> None: if num_scheduled > 0: await self.event_producer.produce_event(DoPrepareEvent()) + async def _filter_agent_by_container_limit( + self, candidate_agents: list[AgentRow] + ) -> list[AgentRow]: + raw_value = await self.shared_config.etcd.get("config/agent/max-container-count") + if raw_value is None: + return candidate_agents + max_container_count = int(raw_value) + + async def _pipe_builder(r: Redis) -> RedisPipeline: + pipe = r.pipeline() + for ag in candidate_agents: + await pipe.get(f"container_count.{ag.id}") + return pipe + + raw_counts = await redis_helper.execute(self.registry.redis_stat, _pipe_builder) + + def _check(cnt: str | None) -> bool: + _cnt = int(cnt) if cnt is not None else 0 + return max_container_count > _cnt + + return [ag for ag, count in zip(candidate_agents, raw_counts) if _check(count)] + async def _schedule_single_node_session( self, sched_ctx: SchedulingContext, @@ -647,6 +672,16 @@ async def _schedule_single_node_session( f"arch: {requested_architecture})" ), ) + available_candidate_agents = await self._filter_agent_by_container_limit( + compatible_candidate_agents + ) + if not available_candidate_agents: + raise InstanceNotAvailable( + extra_msg=( + "No agents found to be available because all agents have reached the hard" + " limit of the number of containers." + ), + ) # If sess_ctx.agent_id is already set for manual assignment by superadmin, # skip assign_agent_for_session(). @@ -657,7 +692,7 @@ async def _schedule_single_node_session( else: # Let the scheduler check the resource availability and decide the target agent cand_agent = scheduler.assign_agent_for_session( - compatible_candidate_agents, + available_candidate_agents, sess_ctx, scheduler.sgroup_opts.agent_selection_strategy, agent_selection_resource_priority, @@ -867,10 +902,19 @@ async def _schedule_multi_node_session( f"arch: {kernel.architecture})" ), ) - + available_candidate_agents = await self._filter_agent_by_container_limit( + compatible_candidate_agents + ) + if not available_candidate_agents: + raise InstanceNotAvailable( + extra_msg=( + "No agents found to be available because all agents have" + " reached the hard limit of the number of containers." + ), + ) # Let the scheduler check the resource availability and decide the target agent agent_id = scheduler.assign_agent_for_kernel( - compatible_candidate_agents, + available_candidate_agents, kernel, scheduler.sgroup_opts.agent_selection_strategy, agent_selection_resource_priority, diff --git a/tests/manager/conftest.py b/tests/manager/conftest.py index 0a2413b0a4..1ff7962bd0 100644 --- a/tests/manager/conftest.py +++ b/tests/manager/conftest.py @@ -754,13 +754,17 @@ class DummyEtcd: async def get_prefix(self, key: str) -> Mapping[str, Any]: return {} + async def get(self, key: str) -> Any: + return None + @pytest.fixture async def registry_ctx(mocker): mock_local_config = MagicMock() mock_shared_config = MagicMock() mock_shared_config.update_resource_slots = AsyncMock() - mock_shared_config.etcd = None + mocked_etcd = DummyEtcd() + mock_shared_config.etcd = mocked_etcd mock_db = MagicMock() mock_dbconn = MagicMock() mock_dbsess = MagicMock() @@ -787,7 +791,6 @@ async def registry_ctx(mocker): mock_event_dispatcher = MagicMock() mock_event_producer = MagicMock() mock_event_producer.produce_event = AsyncMock() - mocked_etcd = DummyEtcd() # mocker.object.patch(mocked_etcd, 'get_prefix', AsyncMock(return_value={})) hook_plugin_ctx = HookPluginContext(mocked_etcd, {}) # type: ignore diff --git a/tests/manager/test_scheduler.py b/tests/manager/test_scheduler.py index 1dc140ee34..2bd8e4c4f6 100644 --- a/tests/manager/test_scheduler.py +++ b/tests/manager/test_scheduler.py @@ -1144,6 +1144,7 @@ async def test_manually_assign_agent_available( registry_ctx: tuple[ AgentRegistry, MagicMock, MagicMock, MagicMock, MagicMock, MagicMock, MagicMock ], + mocker, example_agents, example_pending_sessions, ): @@ -1160,6 +1161,9 @@ async def test_manually_assign_agent_available( ) = registry_ctx mock_sched_ctx = MagicMock() mock_check_result = MagicMock() + mock_redis_wrapper = MagicMock() + mock_redis_wrapper.execute = AsyncMock(return_value=[0 for _ in example_agents]) + mocker.patch("ai.backend.manager.scheduler.dispatcher.redis_helper", mock_redis_wrapper) scheduler = FIFOSlotScheduler(ScalingGroupOpts(), {}) sgroup_name = example_agents[0].scaling_group candidate_agents = example_agents From 37d42e30c8268724d832ee2047c853e719afce00 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Fri, 22 Sep 2023 15:20:04 +0900 Subject: [PATCH 03/46] add GraphQL query to query vfolder with id (#432) Co-authored-by: Joongi Kim --- changes/432.feature | 1 + src/ai/backend/manager/models/gql.py | 28 +++++++++++++++++ src/ai/backend/manager/models/vfolder.py | 39 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 changes/432.feature diff --git a/changes/432.feature b/changes/432.feature new file mode 100644 index 0000000000..af414a3bc7 --- /dev/null +++ b/changes/432.feature @@ -0,0 +1 @@ +Add a GraphQL query to get the information of a virtual folder by ID. diff --git a/src/ai/backend/manager/models/gql.py b/src/ai/backend/manager/models/gql.py index d68fd0173c..6c3939431c 100644 --- a/src/ai/backend/manager/models/gql.py +++ b/src/ai/backend/manager/models/gql.py @@ -459,6 +459,11 @@ class Queries(graphene.ObjectType): order=graphene.String(), ) + vfolder = graphene.Field( + VirtualFolder, + id=graphene.String(), + ) + vfolder_list = graphene.Field( # legacy non-paginated list VirtualFolderList, limit=graphene.Int(required=True), @@ -1387,6 +1392,29 @@ async def resolve_storage_volume_list( ) return StorageVolumeList(items, total_count) + @staticmethod + @privileged_query(UserRole.SUPERADMIN) + async def resolve_vfolder( + executor: AsyncioExecutor, + info: graphene.ResolveInfo, + id: str, + *, + domain_name: str = None, + group_id: uuid.UUID = None, + user_id: uuid.UUID = None, + ) -> Optional[VirtualFolder]: + graph_ctx: GraphQueryContext = info.context + user_role = graph_ctx.user["role"] + loader = graph_ctx.dataloader_manager.get_loader( + graph_ctx, + "VirtualFolder.by_id", + user_uuid=user_id, + user_role=user_role, + domain_name=domain_name, + group_id=group_id, + ) + return await loader.load(id) + @staticmethod @scoped_query(autofill_user=False, user_key="user_id") async def resolve_vfolder_list( diff --git a/src/ai/backend/manager/models/vfolder.py b/src/ai/backend/manager/models/vfolder.py index ef29c9824b..152d58a56c 100644 --- a/src/ai/backend/manager/models/vfolder.py +++ b/src/ai/backend/manager/models/vfolder.py @@ -1196,6 +1196,45 @@ async def load_slice( if (obj := cls.from_row(graph_ctx, r)) is not None ] + @classmethod + async def batch_load_by_id( + cls, + graph_ctx: GraphQueryContext, + ids: list[str], + *, + domain_name: str | None = None, + group_id: uuid.UUID | None = None, + user_id: uuid.UUID | None = None, + filter: str | None = None, + ) -> Sequence[Sequence[VirtualFolder]]: + from .user import UserRow + + j = sa.join(VFolderRow, UserRow, VFolderRow.user == UserRow.uuid) + query = ( + sa.select(VFolderRow) + .select_from(j) + .where(VFolderRow.id.in_(ids)) + .order_by(sa.desc(VFolderRow.created_at)) + ) + if user_id is not None: + query = query.where(VFolderRow.user == user_id) + if domain_name is not None: + query = query.where(UserRow.domain_name == domain_name) + if group_id is not None: + query = query.where(VFolderRow.group == group_id) + if filter is not None: + qfparser = QueryFilterParser(cls._queryfilter_fieldspec) + query = qfparser.append_filter(query, filter) + async with graph_ctx.db.begin_readonly_session() as db_sess: + return await batch_multiresult( + graph_ctx, + db_sess, + query, + cls, + ids, + lambda row: row["user"], + ) + @classmethod async def batch_load_by_user( cls, From 60b17867aafc117d46f821dbaef65c48d9a485b3 Mon Sep 17 00:00:00 2001 From: JinMyeong Kim <84405002+kimjinmyeong@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:39:43 +0900 Subject: [PATCH 04/46] feat: Add example-session-templates (#1496) --- .../manager/example-session-templates.json | 127 +++++++++--------- .../manager/example-session-templates.yaml | 54 ++++++++ 2 files changed, 117 insertions(+), 64 deletions(-) create mode 100644 fixtures/manager/example-session-templates.yaml diff --git a/fixtures/manager/example-session-templates.json b/fixtures/manager/example-session-templates.json index 4e69cca076..850c894cbf 100755 --- a/fixtures/manager/example-session-templates.json +++ b/fixtures/manager/example-session-templates.json @@ -1,71 +1,70 @@ -{ - "session_templates": [ - { - "id": "c1b8441a-ba46-4a83-8727-de6645f521b4", - "is_active": true, - "domain_name": "default", - "group_id": "2de2b969-1d04-48a6-af16-0bc8adb3c831", - "user_uuid": "f38dea23-50fa-42a0-b5ae-338f5f4693f4", - "type": "TASK", - "name": "jupyter", - "template": { - "api_version": "6", - "kind": "task_template", - "metadata": { - "name": "cr.backend.ai/testing/ngc-pytorch", - "tag": "20.11-py3" +[ + { + "id": "c1b8441a-ba46-4a83-8727-de6645f521b4", + "is_active": true, + "domain_name": "default", + "group_id": "2de2b969-1d04-48a6-af16-0bc8adb3c831", + "user_uuid": "f38dea23-50fa-42a0-b5ae-338f5f4693f4", + "type": "TASK", + "name": "python_x86", + "template": { + "api_version": "6", + "kind": "task_template", + "metadata": { + "name": "cr.backend.ai/multiarch/python", + "tag": "3.10-ubuntu20.04" + }, + "spec": { + "session_type": "interactive", + "kernel": { + "image": "cr.backend.ai/multiarch/python:3.10-ubuntu20.04", + "environ": {}, + "architecture": "x86_64", + "run": null, + "git": null }, - "spec": { - "session_type": "interactive", - "kernel": { - "image": "cr.backend.ai/testing/ngc-pytorch:20.11-py3", - "environ": {}, - "run": null, - "git": null - }, - "scaling_group": "default", - "mounts": { - }, - "resources": { - "cpu": "2", - "mem": "4g", - "cuda.shares": "0.2" - } + "scaling_group": "default", + "mounts": { + }, + "resources": { + "cpu": "2", + "mem": "4g" } } - }, - { - "id": "59062449-4f57-4434-975d-add2a593438c", - "is_active": true, - "domain_name": "default", - "group_id": "2de2b969-1d04-48a6-af16-0bc8adb3c831", - "user_uuid": "f38dea23-50fa-42a0-b5ae-338f5f4693f4", - "type": "TASK", - "name": "rstudio", - "template": { - "api_version": "6", - "kind": "task_template", - "metadata": { - "name": "cr.backend.ai/cloud/r-base", - "tag": "4.0" + } + }, + { + "id": "59062449-4f57-4434-975d-add2a593438c", + "is_active": true, + "domain_name": "default", + "group_id": "2de2b969-1d04-48a6-af16-0bc8adb3c831", + "user_uuid": "f38dea23-50fa-42a0-b5ae-338f5f4693f4", + "type": "TASK", + "name": "python_aarch64", + "template": { + "api_version": "6", + "kind": "task_template", + "metadata": { + "name": "cr.backend.ai/multiarch/python", + "tag": "3.10-ubuntu20.04" + }, + "spec": { + "session_type": "interactive", + "kernel": { + "image": "cr.backend.ai/multiarch/python:3.10-ubuntu20.04", + "environ": {}, + "architecture": "aarch64", + "run": null, + "git": null + }, + "scaling_group": "default", + "mounts": { }, - "spec": { - "session_type": "interactive", - "kernel": { - "image": "cr.backend.ai/cloud/r-base:4.0", - "environ": {}, - "run": null, - "git": null - }, - "scaling_group": "default", - "mounts": { - }, - "resources": { - "cpu": "1", - "mem": "2g" - } + "resources": { + "cpu": "2", + "mem": "4g" } } } - ] -} + } +] diff --git a/fixtures/manager/example-session-templates.yaml b/fixtures/manager/example-session-templates.yaml new file mode 100644 index 0000000000..007052581f --- /dev/null +++ b/fixtures/manager/example-session-templates.yaml @@ -0,0 +1,54 @@ +--- +id: c1b8441a-ba46-4a83-8727-de6645f521b4 +is_active: true +domain_name: default +group_id: 2de2b969-1d04-48a6-af16-0bc8adb3c831 +user_uuid: f38dea23-50fa-42a0-b5ae-338f5f4693f4 +type: TASK +name: python_x86 +template: + api_version: '6' + kind: task_template + metadata: + name: cr.backend.ai/multiarch/python + tag: 3.10-ubuntu20.04 + spec: + session_type: interactive + kernel: + image: cr.backend.ai/multiarch/python:3.10-ubuntu20.04 + environ: {} + architecture: x86_64 + run: null + git: null + scaling_group: default + mounts: {} + resources: + cpu: '2' + mem: 4g +--- +id: 59062449-4f57-4434-975d-add2a593438c +is_active: true +domain_name: default +group_id: 2de2b969-1d04-48a6-af16-0bc8adb3c831 +user_uuid: f38dea23-50fa-42a0-b5ae-338f5f4693f4 +type: TASK +name: python_aarch64 +template: + api_version: '6' + kind: task_template + metadata: + name: cr.backend.ai/multiarch/python + tag: 3.10-ubuntu20.04 + spec: + session_type: interactive + kernel: + image: cr.backend.ai/multiarch/python:3.10-ubuntu20.04 + environ: {} + architecture: aarch64 + run: null + git: null + scaling_group: default + mounts: {} + resources: + cpu: '2' + mem: 4g From c5089d750b5521b77f15357330ec7d5a8b4d2c80 Mon Sep 17 00:00:00 2001 From: Jeongseok Kang Date: Fri, 22 Sep 2023 17:22:33 +0900 Subject: [PATCH 05/46] fix: Add `pipeline.endpoint` default value to webserver halfstack.conf (#1592) --- changes/1592.fix.md | 1 + configs/webserver/halfstack.conf | 1 + configs/webserver/sample.conf | 6 ++++-- src/ai/backend/manager/config.py | 5 ----- src/ai/backend/web/config.py | 22 +++++++++++++++++----- 5 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 changes/1592.fix.md diff --git a/changes/1592.fix.md b/changes/1592.fix.md new file mode 100644 index 0000000000..cb9a8914b8 --- /dev/null +++ b/changes/1592.fix.md @@ -0,0 +1 @@ +Add `pipeline.endpoint` default value to `configs/webserver/halfstack.conf` to be able to run immediately after install diff --git a/configs/webserver/halfstack.conf b/configs/webserver/halfstack.conf index 8afd31d5c9..112eb2c854 100644 --- a/configs/webserver/halfstack.conf +++ b/configs/webserver/halfstack.conf @@ -32,6 +32,7 @@ max_file_upload_size = 4294967296 [plugin] [pipeline] +endpoint = "http://127.0.0.1:9500" jwt.secret = "7<:~[X,^Z1XM!*,Pe:PHR!bv,H~Q#l177<7gf_XHD6.<*<.t<[o|V5W(=0x:jTh-" [ui] diff --git a/configs/webserver/sample.conf b/configs/webserver/sample.conf index 1555e4be83..10d04a3794 100644 --- a/configs/webserver/sample.conf +++ b/configs/webserver/sample.conf @@ -95,8 +95,10 @@ max_file_upload_size = 4294967296 #page = "" [pipeline] -#endpoint = "http://mlops.com:9500" -jwt.secret = "7<:~[X,^Z1XM!*,Pe:PHR!bv,H~Q#l177<7gf_XHD6.<*<.t<[o|V5W(=0x:jTh-" +# Endpoint to the pipeline service +#endpoint = "http://127.0.0.1:9500" +# A secret to sign JWTs used to authenticate users from the pipeline service +#jwt.secret = "7<:~[X,^Z1XM!*,Pe:PHR!bv,H~Q#l177<7gf_XHD6.<*<.t<[o|V5W(=0x:jTh-" [ui] brand = "Lablup Cloud" diff --git a/src/ai/backend/manager/config.py b/src/ai/backend/manager/config.py index fcce528b8d..a218ae3c21 100644 --- a/src/ai/backend/manager/config.py +++ b/src/ai/backend/manager/config.py @@ -289,11 +289,6 @@ t.Key("aiomonitor-webui-port", default=49100): t.ToInt[1:65535], } ).allow_extra("*"), - t.Key("pipeline", default=None): t.Null | t.Dict( - { - t.Key("event-queue", default=None): t.Null | tx.HostPortPair, - }, - ).allow_extra("*"), t.Key("docker-registry"): t.Dict( { # deprecated in v20.09 t.Key("ssl-verify", default=True): t.ToBool, diff --git a/src/ai/backend/web/config.py b/src/ai/backend/web/config.py index fa3b064e56..f773ee655d 100644 --- a/src/ai/backend/web/config.py +++ b/src/ai/backend/web/config.py @@ -1,5 +1,6 @@ import os from pathlib import Path +from typing import Any, Mapping import pkg_resources import trafaret as t @@ -16,6 +17,15 @@ "valid_until": "", } +_config_defaults: Mapping[str, Any] = { + "pipeline": { + "endpoint": "http://127.0.0.1:9500", + "jwt": { + "secret": "7<:~[X,^Z1XM!*,Pe:PHR!bv,H~Q#l177<7gf_XHD6.<*<.t<[o|V5W(=0x:jTh-", + }, + }, +} + config_iv = t.Dict( { t.Key("service"): t.Dict( @@ -86,14 +96,16 @@ t.Key("page", default=None): t.Null | tx.StringList(empty_str_as_empty_list=True), } ).allow_extra("*"), - t.Key("pipeline", default=None): t.Null | t.Dict( + t.Key("pipeline", default=_config_defaults["pipeline"]): t.Dict( { - t.Key("endpoint"): tx.URL, - t.Key("jwt"): t.Dict( + t.Key("endpoint", default=_config_defaults["pipeline"]["endpoint"]): tx.URL, + t.Key("jwt", default=_config_defaults["pipeline"]["jwt"]): t.Dict( { - t.Key("secret"): t.String, + t.Key( + "secret", default=_config_defaults["pipeline"]["jwt"]["secret"] + ): t.String, }, - ), + ).allow_extra("*"), }, ).allow_extra("*"), t.Key("ui"): t.Dict( From b136ac93d1e4ccc0387e3fb1af8dc9643b35e61f Mon Sep 17 00:00:00 2001 From: Nayeon Keum Date: Fri, 22 Sep 2023 18:00:18 +0900 Subject: [PATCH 06/46] fix: outdated nfs mount for k8s agent backend (#1527) Co-authored-by: Joongi Kim Co-authored-by: Kyujin Cho --- changes/1526.feature.md | 1 + changes/1527.fix.md | 1 + configs/agent/halfstack.toml | 2 + scripts/install-dev.sh | 16 +++++ src/ai/backend/agent/kubernetes/agent.py | 86 +++++++++++++++++++---- src/ai/backend/agent/kubernetes/kernel.py | 3 + src/ai/backend/runner/entrypoint.sh | 3 + src/ai/backend/runner/fantompass.py | 2 +- 8 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 changes/1526.feature.md create mode 100644 changes/1527.fix.md diff --git a/changes/1526.feature.md b/changes/1526.feature.md new file mode 100644 index 0000000000..9e0fc2d695 --- /dev/null +++ b/changes/1526.feature.md @@ -0,0 +1 @@ +Introduce the k8s agent backend mode to `install-dev.sh` with `--agent-backend` option diff --git a/changes/1527.fix.md b/changes/1527.fix.md new file mode 100644 index 0000000000..43db792dd3 --- /dev/null +++ b/changes/1527.fix.md @@ -0,0 +1 @@ +Update outdated nfs mount for kubernetes agent backend \ No newline at end of file diff --git a/configs/agent/halfstack.toml b/configs/agent/halfstack.toml index 6e6034792f..1cf836a6d4 100644 --- a/configs/agent/halfstack.toml +++ b/configs/agent/halfstack.toml @@ -31,6 +31,8 @@ sandbox-type = "docker" scratch-type = "hostdir" scratch-root = "./scratches" scratch-size = "1G" +scratch-nfs-address = "" +scratch-nfs-options = "" [watcher] diff --git a/scripts/install-dev.sh b/scripts/install-dev.sh index c9e2951208..0b0954c745 100755 --- a/scripts/install-dev.sh +++ b/scripts/install-dev.sh @@ -114,6 +114,10 @@ usage() { echo " The port for the agent's watcher service." echo " (default: 6019)" echo "" + echo " ${LWHITE}--agent-backend mode${NC}" + echo " Mode for backend agent(docker, kubernetes)." + echo " (default: docker)" + echo "" echo " ${LWHITE}--ipc-base-path PATH${NC}" echo " The base path for IPC sockets and shared temporary files." echo " (default: /tmp/backend.ai/ipc)" @@ -295,6 +299,7 @@ WEBSERVER_PORT="8090" WSPROXY_PORT="5050" AGENT_RPC_PORT="6011" AGENT_WATCHER_PORT="6019" +AGENT_BACKEND="docker" IPC_BASE_PATH="/tmp/backend.ai/ipc" VAR_BASE_PATH=$(relpath "${ROOT_PATH}/var/lib/backend.ai") VFOLDER_REL_PATH="vfroot/local" @@ -343,6 +348,8 @@ while [ $# -gt 0 ]; do --var-base-path=*) VAR_BASE_PATH="${1#*=}" ;; --codespaces-on-create) CODESPACES_ON_CREATE=1 ;; --codespaces-post-create) CODESPACES_POST_CREATE=1 ;; + --agent-backend) AGENT_BACKEND=$2; shift ;; + --agent-backend=*) AGENT_BACKEND="${1#*=}" ;; --configure-ha) CONFIGURE_HA=1 ;; *) echo "Unknown option: $1" @@ -872,6 +879,15 @@ configure_backendai() { sed_inplace "s/port = 6009/port = ${AGENT_WATCHER_PORT}/" ./agent.toml sed_inplace "s@\(# \)\{0,1\}ipc-base-path = .*@ipc-base-path = "'"'"${IPC_BASE_PATH}"'"'"@" ./agent.toml sed_inplace "s@\(# \)\{0,1\}var-base-path = .*@var-base-path = "'"'"${VAR_BASE_PATH}"'"'"@" ./agent.toml + + # configure backend mode + if [ $AGENT_BACKEND = "k8s" ] || [ $AGENT_BACKEND = "kubernetes" ]; then + sed_inplace "s/mode = \"docker\"/mode = \"kubernetes\"/" ./agent.toml + sed_inplace "s/scratch-type = \"hostdir\"/scratch-type = \"k8s-nfs\"/" ./agent.toml + elif [ $AGENT_BACKEND = "docker" ]; then + sed '/scratch-nfs-/d' ./agent.toml > ./agent.toml.sed + mv ./agent.toml.sed ./agent.toml + fi sed_inplace "s@\(# \)\{0,1\}mount-path = .*@mount-path = "'"'"${ROOT_PATH}/${VFOLDER_REL_PATH}"'"'"@" ./agent.toml if [ $ENABLE_CUDA -eq 1 ]; then sed_inplace "s/# allow-compute-plugins =.*/allow-compute-plugins = [\"ai.backend.accelerator.cuda_open\"]/" ./agent.toml diff --git a/src/ai/backend/agent/kubernetes/agent.py b/src/ai/backend/agent/kubernetes/agent.py index 32fc5bd759..71237f7202 100644 --- a/src/ai/backend/agent/kubernetes/agent.py +++ b/src/ai/backend/agent/kubernetes/agent.py @@ -2,9 +2,11 @@ import functools import hashlib import logging +import os import random import shutil import signal +import sys import uuid from decimal import Decimal from io import StringIO @@ -90,7 +92,7 @@ class KubernetesKernelCreationContext(AbstractKernelCreationContext[KubernetesKe static_pvc_name: str workers: Mapping[str, Mapping[str, str]] config_maps: List[ConfigMap] - + agent_sockpath: Path volume_mounts: List[KubernetesVolumeMount] volumes: List[KubernetesAbstractVolume] @@ -101,6 +103,7 @@ def __init__( agent_id: AgentId, kernel_config: KernelCreationConfig, local_config: Mapping[str, Any], + agent_sockpath: Path, computers: MutableMapping[DeviceName, ComputerContext], workers: Mapping[str, Mapping[str, str]], static_pvc_name: str, @@ -116,12 +119,18 @@ def __init__( restarting=restarting, ) scratch_dir = (self.local_config["container"]["scratch-root"] / str(kernel_id)).resolve() + rel_scratch_dir = Path(str(kernel_id)) # need relative path for nfs mount self.scratch_dir = scratch_dir + self.rel_scratch_dir = rel_scratch_dir self.work_dir = scratch_dir / "work" self.config_dir = scratch_dir / "config" + self.rel_work_dir = self.rel_scratch_dir / "work" + self.rel_config_dir = self.rel_scratch_dir / "config" + self.static_pvc_name = static_pvc_name self.workers = workers + self.agent_sockpath = agent_sockpath self.volume_mounts = [] self.volumes = [ @@ -192,7 +201,9 @@ async def prepare_scratch(self) -> None: def _create_scratch_dirs(): self.work_dir.resolve().mkdir(parents=True, exist_ok=True) + self.work_dir.chmod(0o755) self.config_dir.resolve().mkdir(parents=True, exist_ok=True) + self.config_dir.chmod(0o755) # Mount scratch directory as PV # Config files can be mounted via ConfigMap @@ -232,6 +243,18 @@ def _clone_dotfiles(): shutil.copy(zshrc_path.resolve(), self.work_dir / ".zshrc") shutil.copy(vimrc_path.resolve(), self.work_dir / ".vimrc") shutil.copy(tmux_conf_path.resolve(), self.work_dir / ".tmux.conf") + if KernelFeatures.UID_MATCH in self.kernel_features: + uid = self.local_config["container"]["kernel-uid"] + gid = self.local_config["container"]["kernel-gid"] + if os.geteuid() == 0: # only possible when I am root. + os.chown(self.work_dir, uid, gid) + os.chown(self.work_dir / ".jupyter", uid, gid) + os.chown(self.work_dir / ".jupyter" / "custom", uid, gid) + os.chown(self.work_dir / ".bashrc", uid, gid) + os.chown(self.work_dir / ".bash_profile", uid, gid) + os.chown(self.work_dir / ".zshrc", uid, gid) + os.chown(self.work_dir / ".vimrc", uid, gid) + os.chown(self.work_dir / ".tmux.conf", uid, gid) await loop.run_in_executor(None, _clone_dotfiles) @@ -240,7 +263,16 @@ async def get_intrinsic_mounts(self) -> Sequence[Mount]: # Mount scratch directory Mount( MountTypes.K8S_GENERIC, - Path(str(self.kernel_id)), + self.rel_config_dir, + Path("/home/config"), + MountPermission.READ_ONLY, + opts={ + "name": f"kernel-{self.kernel_id}-scratches", + }, + ), + Mount( + MountTypes.K8S_GENERIC, + self.rel_work_dir, Path("/home/work"), MountPermission.READ_WRITE, opts={ @@ -249,6 +281,21 @@ async def get_intrinsic_mounts(self) -> Sequence[Mount]: ), ] + rel_agent_sockpath = Path(str(self.agent_sockpath).split("/")[-1]) + # agent-socket mount + if sys.platform != "darwin": + mounts.append( + Mount( + MountTypes.K8S_GENERIC, + rel_agent_sockpath, + Path("/opt/kernel/agent.sock"), + MountPermission.READ_WRITE, + opts={ + "name": f"kernel-{self.kernel_id}-scratches", + }, + ) + ) + # TODO: Find way to mount extra volumes return mounts @@ -450,9 +497,11 @@ async def generate_deployment_object( "env": [{"name": k, "value": v} for k, v in environ.items()], "volumeMounts": [cattr.unstructure(v) for v in self.volume_mounts], "ports": [{"containerPort": x} for x in ports], + "securityContext": {"privileged": True}, } ], "volumes": [cattr.unstructure(v) for v in self.volumes], + "securityContext": {"privileged": True}, }, }, }, @@ -465,7 +514,6 @@ async def spawn( service_ports, ) -> KubernetesKernel: loop = current_loop() - if self.restarting: pass else: @@ -473,19 +521,22 @@ async def spawn( def _write_user_bootstrap_script(): (self.work_dir / "bootstrap.sh").write_text(bootstrap) - if ( - KernelFeatures.UID_MATCH in self.kernel_features - ): # UID Match won't work on K8s - # uid = self.local_config['container']['kernel-uid'] - # gid = self.local_config['container']['kernel-gid'] - # if os.geteuid() == 0: - # os.chown(self.work_dir / 'bootstrap.sh', uid, gid) - pass + if KernelFeatures.UID_MATCH in self.kernel_features: + uid = self.local_config["container"]["kernel-uid"] + gid = self.local_config["container"]["kernel-gid"] + if os.geteuid() == 0: + os.chown(self.work_dir / "bootstrap.sh", uid, gid) await loop.run_in_executor(None, _write_user_bootstrap_script) def _write_config(file_name: str, content: str): - (self.config_dir / file_name).write_text(content) + file_path = self.config_dir / file_name + file_path.write_text(content) + if KernelFeatures.UID_MATCH in self.kernel_features: + uid = self.local_config["container"]["kernel-uid"] + gid = self.local_config["container"]["kernel-gid"] + if os.geteuid() == 0: + os.chown(str(file_path), uid, gid) with StringIO() as buf: for k, v in environ.items(): @@ -572,6 +623,15 @@ def _write_config(file_name: str, content: str): file_path.parent.mkdir(parents=True, exist_ok=True) await loop.run_in_executor(None, file_path.write_text, dotfile["data"]) + tmp = Path(file_path) + while tmp != self.work_dir: + tmp.chmod(int(dotfile["perm"], 8)) + if KernelFeatures.UID_MATCH in self.kernel_features and os.geteuid() == 0: + uid = self.local_config["container"]["kernel-uid"] + gid = self.local_config["container"]["kernel-gid"] + os.chown(tmp, uid, gid) + tmp = tmp.parent + # TODO: Mark shmem feature as unsupported when advertising agent kernel_obj = KubernetesKernel( @@ -744,6 +804,7 @@ class KubernetesAgent( ): workers: MutableMapping[str, MutableMapping[str, str]] = {} k8s_ptask_group: aiotools.PersistentTaskGroup + agent_sockpath: Path def __init__( self, @@ -966,6 +1027,7 @@ async def init_kernel_context( self.id, kernel_config, self.local_config, + self.agent_sockpath, self.computers, self.workers, "backend-ai-static-pvc", diff --git a/src/ai/backend/agent/kubernetes/kernel.py b/src/ai/backend/agent/kubernetes/kernel.py index bcf9b6ffc1..c4eeac6bd3 100644 --- a/src/ai/backend/agent/kubernetes/kernel.py +++ b/src/ai/backend/agent/kubernetes/kernel.py @@ -473,6 +473,9 @@ async def copy_runner_files(scratch_path: Path) -> None: "*.so", "DO_NOT_STORE_PERSISTENT_FILES_HERE.md", "extract_dotfiles.py", + "fantompass.py", + "hash_phrase.py", + "words.json", ] for target_glob in target_files: diff --git a/src/ai/backend/runner/entrypoint.sh b/src/ai/backend/runner/entrypoint.sh index 6f5dd4bf34..eadbb96942 100755 --- a/src/ai/backend/runner/entrypoint.sh +++ b/src/ai/backend/runner/entrypoint.sh @@ -97,6 +97,9 @@ else # Correct the ownership of agent socket. chown $USER_ID:$GROUP_ID /opt/kernel/agent.sock + # Ensure ownership of agent home directory. + chown -R $USER_NAME:$GROUP_NAME /home + # Extract dotfiles /opt/kernel/su-exec $USER_ID:$GROUP_ID /opt/backend.ai/bin/python /opt/kernel/extract_dotfiles.py diff --git a/src/ai/backend/runner/fantompass.py b/src/ai/backend/runner/fantompass.py index 31e02830ee..34907cf408 100644 --- a/src/ai/backend/runner/fantompass.py +++ b/src/ai/backend/runner/fantompass.py @@ -20,7 +20,7 @@ default="-", ) parser.add_argument( - "--no-capitalize", help="Don`\t capitalize the words in the password", action="store_true" + "--no-capitalize", help="Don't capitalize the words in the password", action="store_true" ) parser.add_argument( "-e", From c89b010da64148a2a56b3eb4ac74f3b158aeedff Mon Sep 17 00:00:00 2001 From: Gyubong Date: Fri, 22 Sep 2023 18:00:50 +0900 Subject: [PATCH 07/46] fix: Make `RedisHelperConfig` optional and make default configs (#1593) Co-authored-by: Joongi Kim --- changes/1593.fix.md | 1 + configs/webserver/halfstack.conf | 7 +++-- configs/webserver/sample.conf | 7 +++-- scripts/install-dev.sh | 2 +- src/ai/backend/common/config.py | 16 +++++----- src/ai/backend/manager/config.py | 6 +--- src/ai/backend/web/config.py | 4 ++- tests/agent/conftest.py | 6 +--- tests/common/redis_helper/test_connect.py | 8 ++--- tests/common/redis_helper/test_list.py | 8 ++--- .../common/redis_helper/test_list_cluster.py | 6 ++-- tests/common/redis_helper/test_pipeline.py | 8 ++--- tests/common/redis_helper/test_pubsub.py | 8 ++--- .../redis_helper/test_stream_consume.py | 6 ++-- .../test_stream_consume_cluster.py | 6 ++-- .../redis_helper/test_stream_subscribe.py | 6 ++-- .../test_stream_subscribe_cluster.py | 6 ++-- tests/common/redis_helper/utils.py | 8 ----- tests/common/test_distributed.py | 29 +++++++------------ tests/common/test_events.py | 18 +++++------- tests/manager/conftest.py | 7 ++--- 21 files changed, 76 insertions(+), 97 deletions(-) create mode 100644 changes/1593.fix.md diff --git a/changes/1593.fix.md b/changes/1593.fix.md new file mode 100644 index 0000000000..e54fab6c9b --- /dev/null +++ b/changes/1593.fix.md @@ -0,0 +1 @@ +Make `RedisHelperConfig` optional and give default values when it is not specified. diff --git a/configs/webserver/halfstack.conf b/configs/webserver/halfstack.conf index 112eb2c854..e12ebe9429 100644 --- a/configs/webserver/halfstack.conf +++ b/configs/webserver/halfstack.conf @@ -51,9 +51,10 @@ redis.addr = "localhost:6379" # redis.service_name = "mymaster" # redis.sentinel = "127.0.0.1:9503,127.0.0.1:9504,127.0.0.1:9505" -redis.redis_helper_config.socket_timeout = 5 -redis.redis_helper_config.socket_connect_timeout = 2 -redis.redis_helper_config.reconnect_poll_timeout = 0.3 +# redis.redis_helper_config.socket_timeout = 5 +# redis.redis_helper_config.socket_connect_timeout = 2 +# redis.redis_helper_config.reconnect_poll_timeout = 0.3 + max_age = 604800 # 1 week flush_on_startup = false login_block_time = 1200 # 20 min (in sec) diff --git a/configs/webserver/sample.conf b/configs/webserver/sample.conf index 10d04a3794..5b0f5d8c4a 100644 --- a/configs/webserver/sample.conf +++ b/configs/webserver/sample.conf @@ -123,9 +123,10 @@ redis.addr = "localhost:6379" # redis.db = 0 # redis.password = "mysecret" -redis.redis_helper_config.socket_timeout = 5 -redis.redis_helper_config.socket_connect_timeout = 2 -redis.redis_helper_config.reconnect_poll_timeout = 0.3 +# Customizes the settings of the Redis connection object used in the web server. +# redis.redis_helper_config.socket_timeout = 5 +# redis.redis_helper_config.socket_connect_timeout = 2 +# redis.redis_helper_config.reconnect_poll_timeout = 0.3 max_age = 604800 # 1 week flush_on_startup = false diff --git a/scripts/install-dev.sh b/scripts/install-dev.sh index 0b0954c745..a74fee3df4 100755 --- a/scripts/install-dev.sh +++ b/scripts/install-dev.sh @@ -864,7 +864,7 @@ configure_backendai() { ./backend.ai mgr etcd put config/redis/addr "127.0.0.1:${REDIS_PORT}" fi - ./backend.ai mgr etcd put-json config/redis/redis-helper-config ./configs/manager/sample.etcd.redis-helper.json + ./backend.ai mgr etcd put-json config/redis/redis_helper_config ./configs/manager/sample.etcd.redis-helper.json cp configs/manager/sample.etcd.volumes.json ./dev.etcd.volumes.json MANAGER_AUTH_KEY=$(python -c 'import secrets; print(secrets.token_hex(32), end="")') diff --git a/src/ai/backend/common/config.py b/src/ai/backend/common/config.py index 00b57e6280..942aae5db8 100644 --- a/src/ai/backend/common/config.py +++ b/src/ai/backend/common/config.py @@ -11,12 +11,14 @@ from . import validators as tx from .etcd import AsyncEtcd, ConfigScopes from .exception import ConfigurationError +from .types import RedisHelperConfig __all__ = ( "ConfigurationError", "etcd_config_iv", "redis_config_iv", "redis_helper_config_iv", + "redis_helper_default_config", "vfolder_config_iv", "model_definition_iv", "read_from_file", @@ -27,7 +29,6 @@ "merge", ) - etcd_config_iv = t.Dict( { t.Key("etcd"): t.Dict( @@ -41,6 +42,12 @@ } ).allow_extra("*") +redis_helper_default_config: RedisHelperConfig = { + "socket_timeout": 5.0, + "socket_connect_timeout": 2.0, + "reconnect_poll_timeout": 0.3, +} + redis_helper_config_iv = t.Dict( { t.Key("socket_timeout", default=5.0): t.Float, @@ -55,16 +62,11 @@ t.Key("password", default=None): t.Null | t.String, t.Key( "redis_helper_config", - { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, - }, + default=redis_helper_default_config, ): redis_helper_config_iv, } ).allow_extra("*") - vfolder_config_iv = t.Dict( { tx.AliasedKey(["mount", "_mount"], default=None): t.Null | tx.Path(type="dir"), diff --git a/src/ai/backend/manager/config.py b/src/ai/backend/manager/config.py index a218ae3c21..5781bf03a4 100644 --- a/src/ai/backend/manager/config.py +++ b/src/ai/backend/manager/config.py @@ -321,11 +321,7 @@ "redis": { "addr": None, "password": None, - "redis_helper_config": { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, - }, + "redis_helper_config": config.redis_helper_default_config, }, "docker": { "registry": {}, diff --git a/src/ai/backend/web/config.py b/src/ai/backend/web/config.py index f773ee655d..e980365d68 100644 --- a/src/ai/backend/web/config.py +++ b/src/ai/backend/web/config.py @@ -138,7 +138,9 @@ ), t.Key("service_name", default=None): t.Null | t.String, t.Key("password", default=None): t.Null | t.String, - t.Key("redis_helper_config"): config.redis_helper_config_iv, + t.Key( + "redis_helper_config", default=config.redis_helper_default_config + ): config.redis_helper_config_iv, } ), t.Key("max_age", default=604800): t.ToInt, # seconds (default: 1 week) diff --git a/tests/agent/conftest.py b/tests/agent/conftest.py index 5b5c5378a8..dc54faeb82 100644 --- a/tests/agent/conftest.py +++ b/tests/agent/conftest.py @@ -99,11 +99,7 @@ def local_config(test_id, logging_config, etcd_container, redis_container): # n sentinel=None, service_name=None, password=None, - redis_helper_config={ - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, - }, + redis_helper_config=config.redis_helper_default_config, ), "plugins": {}, } diff --git a/tests/common/redis_helper/test_connect.py b/tests/common/redis_helper/test_connect.py index 31cdb3e8b6..77a03cfe58 100644 --- a/tests/common/redis_helper/test_connect.py +++ b/tests/common/redis_helper/test_connect.py @@ -17,12 +17,12 @@ wait_exponential, ) -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common import validators as tx from ai.backend.common.types import HostPortPair from .types import RedisClusterInfo -from .utils import interrupt, redis_helper_config, with_timeout +from .utils import interrupt, with_timeout if TYPE_CHECKING: from typing import Any @@ -77,7 +77,7 @@ async def test_instantiate_redisconninfo() -> None: "sentinel": sentinels, "service_name": "mymaster", "password": "develove", - "redis_helper_config": redis_helper_config, + "redis_helper_config": config.redis_helper_default_config, } ) @@ -95,7 +95,7 @@ async def test_instantiate_redisconninfo() -> None: "sentinel": parsed_addresses, "service_name": "mymaster", "password": "develove", - "redis_helper_config": redis_helper_config, + "redis_helper_config": config.redis_helper_default_config, }, ) diff --git a/tests/common/redis_helper/test_list.py b/tests/common/redis_helper/test_list.py index 02008ab03c..9d1b9aa742 100644 --- a/tests/common/redis_helper/test_list.py +++ b/tests/common/redis_helper/test_list.py @@ -10,11 +10,11 @@ from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import TimeoutError as RedisTimeoutError -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import HostPortPair, RedisConnectionInfo from .docker import DockerRedisNode -from .utils import interrupt, redis_helper_config +from .utils import interrupt @pytest.mark.redis @@ -44,7 +44,7 @@ async def pop(r: RedisConnectionInfo, key: str) -> None: addr = redis_container[1] r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.2), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) @@ -125,7 +125,7 @@ async def pop(r: RedisConnectionInfo, key: str) -> None: addr = redis_container[1] r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.2), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) diff --git a/tests/common/redis_helper/test_list_cluster.py b/tests/common/redis_helper/test_list_cluster.py index 6541cc7597..435e486879 100644 --- a/tests/common/redis_helper/test_list_cluster.py +++ b/tests/common/redis_helper/test_list_cluster.py @@ -7,11 +7,11 @@ import pytest from redis.asyncio.sentinel import Sentinel -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import RedisConnectionInfo from .types import RedisClusterInfo -from .utils import interrupt, redis_helper_config, with_timeout +from .utils import interrupt, with_timeout @pytest.mark.redis @@ -52,7 +52,7 @@ async def pop(s: RedisConnectionInfo, key: str) -> None: r = RedisConnectionInfo( s.master_for(service_name="mymaster"), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=s, service_name="mymaster", ) diff --git a/tests/common/redis_helper/test_pipeline.py b/tests/common/redis_helper/test_pipeline.py index 1c9bf009d4..231fdc7102 100644 --- a/tests/common/redis_helper/test_pipeline.py +++ b/tests/common/redis_helper/test_pipeline.py @@ -8,11 +8,11 @@ from redis.asyncio.client import Pipeline from redis.asyncio.sentinel import Sentinel +from ai.backend.common import config from ai.backend.common.redis_helper import execute from ai.backend.common.types import HostPortPair, RedisConnectionInfo from .types import RedisClusterInfo -from .utils import redis_helper_config @pytest.mark.redis @@ -21,7 +21,7 @@ async def test_pipeline_single_instance(redis_container: Tuple[str, HostPortPair addr = redis_container[1] rconn = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.5), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) @@ -46,7 +46,7 @@ async def test_pipeline_single_instance_retries(redis_container: Tuple[str, Host addr = redis_container[1] rconn = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.5), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) @@ -90,7 +90,7 @@ async def test_pipeline_sentinel_cluster(redis_cluster: RedisClusterInfo) -> Non rconn = RedisConnectionInfo( s.master_for(service_name="mymaster"), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=s, service_name="mymaster", ) diff --git a/tests/common/redis_helper/test_pubsub.py b/tests/common/redis_helper/test_pubsub.py index 7c62f20e0c..1b95e95e1f 100644 --- a/tests/common/redis_helper/test_pubsub.py +++ b/tests/common/redis_helper/test_pubsub.py @@ -10,11 +10,11 @@ from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import TimeoutError as RedisTimeoutError -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import HostPortPair, RedisConnectionInfo from .docker import DockerRedisNode -from .utils import interrupt, redis_helper_config +from .utils import interrupt @pytest.mark.redis @@ -42,7 +42,7 @@ async def subscribe(pubsub: PubSub) -> None: r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.5), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) @@ -131,7 +131,7 @@ async def subscribe(pubsub: PubSub) -> None: r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.5), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) diff --git a/tests/common/redis_helper/test_stream_consume.py b/tests/common/redis_helper/test_stream_consume.py index 7d4d44855d..24564f8cbb 100644 --- a/tests/common/redis_helper/test_stream_consume.py +++ b/tests/common/redis_helper/test_stream_consume.py @@ -11,11 +11,11 @@ from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import TimeoutError as RedisTimeoutError -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import HostPortPair, RedisConnectionInfo from .docker import DockerRedisNode -from .utils import interrupt, redis_helper_config, with_timeout +from .utils import interrupt, with_timeout @pytest.mark.redis @@ -64,7 +64,7 @@ async def consume( r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.2), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) diff --git a/tests/common/redis_helper/test_stream_consume_cluster.py b/tests/common/redis_helper/test_stream_consume_cluster.py index bcce1fbcdf..cc73381af6 100644 --- a/tests/common/redis_helper/test_stream_consume_cluster.py +++ b/tests/common/redis_helper/test_stream_consume_cluster.py @@ -9,11 +9,11 @@ from aiotools.context import aclosing from redis.asyncio.sentinel import Sentinel -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import RedisConnectionInfo from .types import RedisClusterInfo -from .utils import interrupt, redis_helper_config, with_timeout +from .utils import interrupt, with_timeout @pytest.mark.redis @@ -65,7 +65,7 @@ async def consume( r = RedisConnectionInfo( s.master_for(service_name="mymaster"), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=s, service_name="mymaster", ) diff --git a/tests/common/redis_helper/test_stream_subscribe.py b/tests/common/redis_helper/test_stream_subscribe.py index e86ad0a328..d4f395f727 100644 --- a/tests/common/redis_helper/test_stream_subscribe.py +++ b/tests/common/redis_helper/test_stream_subscribe.py @@ -10,11 +10,11 @@ from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import TimeoutError as RedisTimeoutError -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import HostPortPair, RedisConnectionInfo from .docker import DockerRedisNode -from .utils import interrupt, redis_helper_config +from .utils import interrupt @pytest.mark.redis @@ -51,7 +51,7 @@ async def consume( r = RedisConnectionInfo( Redis.from_url(url=f"redis://{addr.host}:{addr.port}", socket_timeout=0.2), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=None, service_name=None, ) diff --git a/tests/common/redis_helper/test_stream_subscribe_cluster.py b/tests/common/redis_helper/test_stream_subscribe_cluster.py index 1c0f9241a3..9ebec47a8e 100644 --- a/tests/common/redis_helper/test_stream_subscribe_cluster.py +++ b/tests/common/redis_helper/test_stream_subscribe_cluster.py @@ -9,11 +9,11 @@ from aiotools.context import aclosing from redis.asyncio.sentinel import Sentinel -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.types import RedisConnectionInfo from .types import RedisClusterInfo -from .utils import interrupt, redis_helper_config, with_timeout +from .utils import interrupt, with_timeout @pytest.mark.redis @@ -56,7 +56,7 @@ async def consume( r = RedisConnectionInfo( s.master_for(service_name="mymaster"), - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, sentinel=s, service_name="mymaster", ) diff --git a/tests/common/redis_helper/utils.py b/tests/common/redis_helper/utils.py index 4e891b418b..b75ad7851f 100644 --- a/tests/common/redis_helper/utils.py +++ b/tests/common/redis_helper/utils.py @@ -20,8 +20,6 @@ from redis.exceptions import TimeoutError as RedisTimeoutError from typing_extensions import ParamSpec -from ai.backend.common.types import RedisHelperConfig - if TYPE_CHECKING: from .types import AbstractRedisNode @@ -37,12 +35,6 @@ }, } -redis_helper_config: RedisHelperConfig = { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, -} - async def simple_run_cmd( cmdargs: Sequence[Union[str, bytes]], **kwargs diff --git a/tests/common/test_distributed.py b/tests/common/test_distributed.py index 57995893d7..1d40eae07b 100644 --- a/tests/common/test_distributed.py +++ b/tests/common/test_distributed.py @@ -17,23 +17,12 @@ from etcetra.types import HostPortPair as EtcdHostPortPair from redis.asyncio import Redis +from ai.backend.common import config from ai.backend.common.distributed import GlobalTimer from ai.backend.common.etcd import AsyncEtcd, ConfigScopes from ai.backend.common.events import AbstractEvent, EventDispatcher, EventProducer from ai.backend.common.lock import AbstractDistributedLock, EtcdLock, FileLock, RedisLock -from ai.backend.common.types import ( - AgentId, - EtcdRedisConfig, - HostPortPair, - RedisConnectionInfo, - RedisHelperConfig, -) - -redis_helper_config: RedisHelperConfig = { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, -} +from ai.backend.common.types import AgentId, EtcdRedisConfig, HostPortPair, RedisConnectionInfo @dataclass @@ -94,7 +83,9 @@ async def _tick(context: Any, source: AgentId, event: NoopEvent) -> None: print("_tick") event_records.append(time.monotonic()) - redis_config = EtcdRedisConfig(addr=redis_addr, redis_helper_config=redis_helper_config) + redis_config = EtcdRedisConfig( + addr=redis_addr, redis_helper_config=config.redis_helper_default_config + ) event_dispatcher = await EventDispatcher.new( redis_config, consumer_group=EVENT_DISPATCHER_CONSUMER_GROUP, @@ -136,7 +127,7 @@ async def _tick(context: Any, source: AgentId, event: NoopEvent) -> None: queue.put(time.monotonic()) redis_config = EtcdRedisConfig( - addr=timer_ctx.redis_addr, redis_helper_config=redis_helper_config + addr=timer_ctx.redis_addr, redis_helper_config=config.redis_helper_default_config ) event_dispatcher = await EventDispatcher.new( redis_config, @@ -202,7 +193,7 @@ async def _tick(context: Any, source: AgentId, event: NoopEvent) -> None: self.event_records.append(time.monotonic()) redis_config = EtcdRedisConfig( - addr=self.redis_addr, redis_helper_config=redis_helper_config + addr=self.redis_addr, redis_helper_config=config.redis_helper_default_config ) event_dispatcher = await EventDispatcher.new( redis_config, @@ -284,7 +275,7 @@ async def test_gloal_timer_redlock(test_case_ns, redis_container) -> None: Redis.from_url(f"redis://{redis_addr.host}:{redis_addr.port}"), sentinel=None, service_name=None, - redis_helper_config=redis_helper_config, + redis_helper_config=config.redis_helper_default_config, ) lock_factory = lambda: RedisLock(f"{test_case_ns}lock", r, debug=True) @@ -388,7 +379,9 @@ async def _tick(context: Any, source: AgentId, event: NoopEvent) -> None: print("_tick") event_records.append(time.monotonic()) - redis_config = EtcdRedisConfig(addr=redis_container[1], redis_helper_config=redis_helper_config) + redis_config = EtcdRedisConfig( + addr=redis_container[1], redis_helper_config=config.redis_helper_default_config + ) event_dispatcher = await EventDispatcher.new( redis_config, consumer_group=EVENT_DISPATCHER_CONSUMER_GROUP, diff --git a/tests/common/test_events.py b/tests/common/test_events.py index 81297716cf..c3923fa0d3 100644 --- a/tests/common/test_events.py +++ b/tests/common/test_events.py @@ -6,7 +6,7 @@ import attrs import pytest -from ai.backend.common import redis_helper +from ai.backend.common import config, redis_helper from ai.backend.common.events import ( AbstractEvent, CoalescingOptions, @@ -14,13 +14,7 @@ EventDispatcher, EventProducer, ) -from ai.backend.common.types import AgentId, EtcdRedisConfig, RedisHelperConfig - -redis_helper_config: RedisHelperConfig = { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, -} +from ai.backend.common.types import AgentId, EtcdRedisConfig @attrs.define(slots=True, frozen=True) @@ -44,7 +38,9 @@ def deserialize(cls, value: tuple): async def test_dispatch(redis_container) -> None: app = object() - redis_config = EtcdRedisConfig(addr=redis_container[1], redis_helper_config=redis_helper_config) + redis_config = EtcdRedisConfig( + addr=redis_container[1], redis_helper_config=config.redis_helper_default_config + ) dispatcher = await EventDispatcher.new( redis_config, consumer_group=EVENT_DISPATCHER_CONSUMER_GROUP, @@ -96,7 +92,9 @@ async def handle_exception( ) -> None: exception_log.append(type(exc).__name__) - redis_config = EtcdRedisConfig(addr=redis_container[1], redis_helper_config=redis_helper_config) + redis_config = EtcdRedisConfig( + addr=redis_container[1], redis_helper_config=config.redis_helper_default_config + ) dispatcher = await EventDispatcher.new( redis_config, consumer_group=EVENT_DISPATCHER_CONSUMER_GROUP, diff --git a/tests/manager/conftest.py b/tests/manager/conftest.py index 1ff7962bd0..2228e3a8ed 100644 --- a/tests/manager/conftest.py +++ b/tests/manager/conftest.py @@ -33,6 +33,7 @@ from dateutil.tz import tzutc from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.common import config from ai.backend.common.auth import PublicKey, SecretKey from ai.backend.common.config import ConfigurationError, etcd_config_iv, redis_config_iv from ai.backend.common.logging import LocalLogger @@ -171,11 +172,7 @@ def local_config( "host": redis_addr.host, "port": redis_addr.port, }, - "redis_helper_config": { - "socket_timeout": 5.0, - "socket_connect_timeout": 2.0, - "reconnect_poll_timeout": 0.3, - }, + "redis_helper_config": config.redis_helper_default_config, } ), "db": { From 0db8c99a88ff09c4ae1f0d9255bc3bd5d4d9cfe0 Mon Sep 17 00:00:00 2001 From: Sanghun Lee Date: Fri, 22 Sep 2023 18:12:45 +0900 Subject: [PATCH 08/46] fix: handle external error in storage proxy API (#1591) --- changes/1591.fix.md | 1 + src/ai/backend/storage/api/manager.py | 50 +++++++++++++++++++-------- 2 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 changes/1591.fix.md diff --git a/changes/1591.fix.md b/changes/1591.fix.md new file mode 100644 index 0000000000..c8b22b1773 --- /dev/null +++ b/changes/1591.fix.md @@ -0,0 +1 @@ +Handle external error of storage proxy to return error response with detail message rather than just leaving it. diff --git a/src/ai/backend/storage/api/manager.py b/src/ai/backend/storage/api/manager.py index 7cf0554fdd..0abc14f6f8 100644 --- a/src/ai/backend/storage/api/manager.py +++ b/src/ai/backend/storage/api/manager.py @@ -42,6 +42,7 @@ from .. import __version__ from ..exception import ( + ExternalError, InvalidQuotaConfig, InvalidSubpathError, QuotaScopeAlreadyExists, @@ -121,6 +122,21 @@ def handle_fs_errors( ) +@ctxmgr +def handle_external_errors() -> Iterator[None]: + try: + yield + except ExternalError as e: + raise web.HTTPInternalServerError( + body=json.dumps( + { + "msg": str(e), + } + ), + content_type="application/json", + ) + + async def get_volumes(request: web.Request) -> web.Response: async def _get_caps(ctx: RootContext, volume_name: str) -> List[str]: async with ctx.get_volume(volume_name) as volume: @@ -193,9 +209,10 @@ class Params(TypedDict): ctx: RootContext = request.app["ctx"] async with ctx.get_volume(params["volume"]) as volume: try: - await volume.quota_model.create_quota_scope( - params["qsid"], params["options"], params["extra_args"] - ) + with handle_external_errors(): + await volume.quota_model.create_quota_scope( + params["qsid"], params["options"], params["extra_args"] + ) except QuotaScopeAlreadyExists: return web.json_response( {"msg": "Volume already exists with given quota scope."}, @@ -224,7 +241,8 @@ class Params(TypedDict): await log_manager_api_entry(log, "get_quota_scope", params) ctx: RootContext = request.app["ctx"] async with ctx.get_volume(params["volume"]) as volume: - quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) + with handle_external_errors(): + quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) if not quota_usage: raise QuotaScopeNotFoundError return web.json_response( @@ -259,16 +277,17 @@ class Params(TypedDict): await log_manager_api_entry(log, "update_quota_scope", params) ctx: RootContext = request.app["ctx"] async with ctx.get_volume(params["volume"]) as volume: - quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) - if not quota_usage: - await volume.quota_model.create_quota_scope(params["qsid"], params["options"]) - try: - await volume.quota_model.update_quota_scope(params["qsid"], params["options"]) - except InvalidQuotaConfig: - return web.json_response( - {"msg": "Invalid quota config option"}, - status=400, - ) + with handle_external_errors(): + quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) + if not quota_usage: + await volume.quota_model.create_quota_scope(params["qsid"], params["options"]) + try: + await volume.quota_model.update_quota_scope(params["qsid"], params["options"]) + except InvalidQuotaConfig: + return web.json_response( + {"msg": "Invalid quota config option"}, + status=400, + ) return web.Response(status=204) @@ -292,7 +311,8 @@ class Params(TypedDict): await log_manager_api_entry(log, "unset_quota", params) ctx: RootContext = request.app["ctx"] async with ctx.get_volume(params["volume"]) as volume: - quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) + with handle_external_errors(): + quota_usage = await volume.quota_model.describe_quota_scope(params["qsid"]) if not quota_usage: raise QuotaScopeNotFoundError await volume.quota_model.unset_quota(params["qsid"]) From b5097936b5151f413c49fb005b816a17249c1129 Mon Sep 17 00:00:00 2001 From: Kyujin Cho Date: Fri, 22 Sep 2023 18:17:22 +0900 Subject: [PATCH 09/46] fix: remove orphan routings from database (#1590) Co-authored-by: Joongi Kim --- changes/1590.fix.md | 1 + .../backend/manager/models/scaling_group.py | 1 + src/ai/backend/manager/registry.py | 2 ++ .../backend/manager/scheduler/dispatcher.py | 29 +++++++++++++------ 4 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 changes/1590.fix.md diff --git a/changes/1590.fix.md b/changes/1590.fix.md new file mode 100644 index 0000000000..6a5fec2962 --- /dev/null +++ b/changes/1590.fix.md @@ -0,0 +1 @@ +Collect orphan routings (route which its belonging session is already terminated) diff --git a/src/ai/backend/manager/models/scaling_group.py b/src/ai/backend/manager/models/scaling_group.py index 15e281fd7a..4e3bec2140 100644 --- a/src/ai/backend/manager/models/scaling_group.py +++ b/src/ai/backend/manager/models/scaling_group.py @@ -37,6 +37,7 @@ __all__: Sequence[str] = ( # table defs "scaling_groups", + "ScalingGroupOpts", "ScalingGroupRow", "sgroups_for_domains", "sgroups_for_groups", diff --git a/src/ai/backend/manager/registry.py b/src/ai/backend/manager/registry.py index f9435cf292..0886327bf2 100644 --- a/src/ai/backend/manager/registry.py +++ b/src/ai/backend/manager/registry.py @@ -2125,6 +2125,8 @@ async def destroy_session( ) async with self.db.begin_readonly_session() as db_session: target_session = (await db_session.scalars(query)).first() + if not target_session: + raise SessionNotFound match target_session.status: case SessionStatus.PENDING: diff --git a/src/ai/backend/manager/scheduler/dispatcher.py b/src/ai/backend/manager/scheduler/dispatcher.py index 74aa6853dd..e30dd7241c 100644 --- a/src/ai/backend/manager/scheduler/dispatcher.py +++ b/src/ai/backend/manager/scheduler/dispatcher.py @@ -51,7 +51,7 @@ from ai.backend.manager.utils import query_userinfo from ai.backend.plugin.entrypoint import scan_entrypoints -from ..api.exceptions import GenericBadRequest, InstanceNotAvailable +from ..api.exceptions import GenericBadRequest, InstanceNotAvailable, SessionNotFound from ..defs import SERVICE_MAX_RETRIES, LockID from ..exceptions import convert_to_status_data from ..models import ( @@ -62,6 +62,8 @@ KernelRow, KernelStatus, RouteStatus, + RoutingRow, + ScalingGroupOpts, ScalingGroupRow, SessionRow, SessionStatus, @@ -72,7 +74,6 @@ recalc_concurrency_used, users, ) -from ..models.scaling_group import ScalingGroupOpts from ..models.utils import ExtendedAsyncSAEngine as SAEngine from ..models.utils import execute_with_retry, sql_json_increment, sql_json_merge from .predicates import ( @@ -1250,14 +1251,20 @@ async def scale_services( SessionRow.id.in_(ids_of_session_to_destroy), eager_loading_op=kernel_loading_op ) result = await db_session.execute(query) - target_sessions_to_destory = result.scalars().all() + target_sessions_to_destroy = result.scalars().all() + + already_destroyed_sessions: list[SessionId] = [] # TODO: Update logic to not to wait for sessions to actually terminate - for session in target_sessions_to_destory: - await self.registry.destroy_session( - session, - forced=False, - reason=KernelLifecycleEventReason.SERVICE_SCALED_DOWN, - ) + for session in target_sessions_to_destroy: + try: + await self.registry.destroy_session( + session, + forced=False, + reason=KernelLifecycleEventReason.SERVICE_SCALED_DOWN, + ) + except SessionNotFound: + # Session already terminated while leaving routing alive + already_destroyed_sessions.append(session.id) user_ids = tuple( {endpoint.created_user for endpoint in endpoints_to_expand.keys()} @@ -1367,6 +1374,10 @@ async def _delete(): .where(EndpointRow.id.in_([e.id for e in endpoints_to_mark_terminated])) ) await db_sess.execute(query) + query = sa.delete(RoutingRow).where( + RoutingRow.session.in_(already_destroyed_sessions) + ) + await db_sess.execute(query) await execute_with_retry(_delete) From d4b9f41b86b437707152ec864a6f4bed66dcea2a Mon Sep 17 00:00:00 2001 From: Kyujin Cho Date: Fri, 22 Sep 2023 21:12:24 +0900 Subject: [PATCH 10/46] Squashed 'src/ai/backend/web/static/' changes from d7922db8a..3b16fd142 3b16fd142 Updated to v23.09.0.beta.3 git-subtree-dir: src/ai/backend/web/static git-subtree-split: 3b16fd14239137e55766b176e3dd6c1ad034b809 --- asset-manifest.json | 172 ++- ...backend-ai-agent-summary-view-6314e538.js} | 2 +- ...d.js => backend-ai-agent-view-4d995ee2.js} | 2 +- ...i-change-forgot-password-view-10f21c08.js} | 2 +- ...=> backend-ai-credential-view-a6f83713.js} | 2 +- ...ae.js => backend-ai-data-view-d067f2be.js} | 8 +- ...=> backend-ai-edu-applauncher-8acae0e5.js} | 2 +- ...nd-ai-email-verification-view-f7125d4d.js} | 2 +- ...> backend-ai-environment-view-0ed5b6b7.js} | 2 +- ...a.js => backend-ai-error-view-e546570b.js} | 2 +- ....js => backend-ai-import-view-b7523da0.js} | 2 +- ...> backend-ai-information-view-7511523a.js} | 2 +- ....js => backend-ai-list-status-fa13c15b.js} | 2 +- ...> backend-ai-maintenance-view-d24087a2.js} | 2 +- ...js => backend-ai-multi-select-1943e543.js} | 2 +- ...end-ai-permission-denied-view-20b6fa23.js} | 2 +- ...> backend-ai-resource-monitor-21ef3974.js} | 18 +- .../backend-ai-serving-list-b146c06f.js | 3 - .../backend-ai-serving-list-f5b0ed1e.js | 5 + ...> backend-ai-session-launcher-676818a7.js} | 18 +- ...js => backend-ai-session-view-8572e752.js} | 4 +- .../backend-ai-session-view-next-1b94c155.js | 3 - .../backend-ai-session-view-next-ced7118d.js | 3 + ...s => backend-ai-settings-view-7091b7da.js} | 2 +- ...=> backend-ai-statistics-view-bd0d921d.js} | 10 +- ...ai-storage-host-settings-view-fe71709b.js} | 2 +- ...js => backend-ai-summary-view-3fb3e65a.js} | 6 +- ... backend-ai-usersettings-view-9fd5f370.js} | 2 +- ...940dc0.js => backend-ai-webui-75df15ed.js} | 270 ++-- dist/components/backend-ai-webui.js | 2 +- ...tils-2ca2933c.js => dir-utils-f5050166.js} | 2 +- ...5.js => lablup-activity-panel-86e1deef.js} | 2 +- ...98261.js => lablup-codemirror-59c15e56.js} | 2 +- ...ablup-grid-sort-filter-column-54638b7b.js} | 2 +- ....js => lablup-loading-spinner-02aea3b9.js} | 2 +- ...c65.js => lablup-progress-bar-b230f3e3.js} | 2 +- ....js => media-query-controller-bc25d693.js} | 2 +- ...b83.js => mwc-check-list-item-5618f22b.js} | 2 +- ...-b8bed217.js => mwc-formfield-5cf6c683.js} | 2 +- ...tch-405e373b.js => mwc-switch-13f7c132.js} | 8 +- ...ar-f47ea595.js => mwc-tab-bar-45ba859c.js} | 2 +- ...{slider-b4cf5b64.js => slider-3f740add.js} | 6 +- ...id-7aa99257.js => vaadin-grid-461d199a.js} | 6 +- ... => vaadin-grid-filter-column-2b22f222.js} | 2 +- ... vaadin-grid-selection-column-29a490b5.js} | 2 +- ...js => vaadin-grid-sort-column-d722536e.js} | 2 +- ...8594ac1d.js => vaadin-iconset-c8fcdcfd.js} | 2 +- ...em-a4241857.js => vaadin-item-19772d96.js} | 2 +- ...89617.js => vaadin-item-mixin-57783787.js} | 2 +- index.html | 2 +- manifest.json | 2 +- resources/device_metadata.json | 4 +- resources/i18n/de.json | 555 +++++-- resources/i18n/el.json | 555 +++++-- resources/i18n/en.json | 197 +-- resources/i18n/es.json | 555 +++++-- resources/i18n/fi.json | 555 +++++-- resources/i18n/fr.json | 829 ++++------ resources/i18n/id.json | 809 ++++------ resources/i18n/it.json | 555 +++++-- resources/i18n/ja.json | 555 +++++-- resources/i18n/ko.json | 194 +-- resources/i18n/mn.json | 809 ++++------ resources/i18n/ms.json | 555 +++++-- resources/i18n/pl.json | 555 +++++-- resources/i18n/pt-BR.json | 1376 +++++++++++++++++ resources/i18n/pt.json | 555 +++++-- resources/i18n/ru.json | 829 ++++------ resources/i18n/tr.json | 555 +++++-- resources/i18n/vi.json | 555 +++++-- resources/i18n/zh-CN.json | 1376 +++++++++++++++++ resources/i18n/zh-TW.json | 1376 +++++++++++++++++ resources/storage_metadata.json | 5 + static/js/110.4c990d8f.chunk.js | 2 + static/js/110.4c990d8f.chunk.js.map | 1 + static/js/111.06ae856a.chunk.js | 2 + static/js/111.06ae856a.chunk.js.map | 1 + static/js/114.fd36729b.chunk.js | 2 + static/js/114.fd36729b.chunk.js.map | 1 + static/js/138.c507137d.chunk.js | 2 + static/js/138.c507137d.chunk.js.map | 1 + static/js/156.04ecc44c.chunk.js | 2 + static/js/156.04ecc44c.chunk.js.map | 1 + static/js/164.ce3398da.chunk.js | 2 + static/js/164.ce3398da.chunk.js.map | 1 + static/js/183.7ef52b0e.chunk.js | 2 + static/js/183.7ef52b0e.chunk.js.map | 1 + static/js/185.b1163da8.chunk.js | 3 + static/js/185.b1163da8.chunk.js.LICENSE.txt | 10 + static/js/185.b1163da8.chunk.js.map | 1 + static/js/20.a3968d90.chunk.js | 2 + static/js/20.a3968d90.chunk.js.map | 1 + static/js/209.47ee8c54.chunk.js | 2 + static/js/209.47ee8c54.chunk.js.map | 1 + static/js/229.433b20b1.chunk.js | 2 + static/js/229.433b20b1.chunk.js.map | 1 + static/js/230.0396ec8b.chunk.js | 2 + static/js/230.0396ec8b.chunk.js.map | 1 + static/js/266.b289d330.chunk.js | 2 + static/js/266.b289d330.chunk.js.map | 1 + static/js/284.be0edfd4.chunk.js | 2 + static/js/284.be0edfd4.chunk.js.map | 1 + static/js/341.d380d2bc.chunk.js | 2 + static/js/341.d380d2bc.chunk.js.map | 1 + static/js/360.d1869f7a.chunk.js | 2 + static/js/360.d1869f7a.chunk.js.map | 1 + static/js/427.8c42092f.chunk.js | 2 + static/js/427.8c42092f.chunk.js.map | 1 + static/js/448.a7113ead.chunk.js | 2 + static/js/448.a7113ead.chunk.js.map | 1 + static/js/456.e33eea6f.chunk.js | 2 + static/js/456.e33eea6f.chunk.js.map | 1 + static/js/486.6f07b950.chunk.js | 3 + static/js/486.6f07b950.chunk.js.LICENSE.txt | 5 + static/js/486.6f07b950.chunk.js.map | 1 + static/js/49.b8c5ebc8.chunk.js | 2 + static/js/49.b8c5ebc8.chunk.js.map | 1 + static/js/499.279cfd4e.chunk.js | 2 + static/js/499.279cfd4e.chunk.js.map | 1 + static/js/524.3fdcdcd0.chunk.js | 2 + static/js/524.3fdcdcd0.chunk.js.map | 1 + static/js/556.6e8e358c.chunk.js | 2 + static/js/556.6e8e358c.chunk.js.map | 1 + static/js/562.7450914b.chunk.js | 2 + static/js/562.7450914b.chunk.js.map | 1 + static/js/619.3a1ed2cd.chunk.js | 2 + static/js/619.3a1ed2cd.chunk.js.map | 1 + static/js/651.5ad26983.chunk.js | 2 + static/js/651.5ad26983.chunk.js.map | 1 + static/js/66.8acfb03b.chunk.js | 2 + static/js/66.8acfb03b.chunk.js.map | 1 + static/js/664.9ffc68f5.chunk.js | 2 + static/js/664.9ffc68f5.chunk.js.map | 1 + static/js/666.8975bcc8.chunk.js | 3 + static/js/666.8975bcc8.chunk.js.LICENSE.txt | 10 + static/js/666.8975bcc8.chunk.js.map | 1 + static/js/674.e0d526eb.chunk.js | 2 + static/js/674.e0d526eb.chunk.js.map | 1 + static/js/681.8ef57b6e.chunk.js | 3 + static/js/681.8ef57b6e.chunk.js.LICENSE.txt | 8 + static/js/681.8ef57b6e.chunk.js.map | 1 + static/js/689.94fd0e8e.chunk.js | 2 + static/js/689.94fd0e8e.chunk.js.map | 1 + static/js/703.2d8f0316.chunk.js | 2 + static/js/703.2d8f0316.chunk.js.map | 1 + static/js/864.857b1ea3.chunk.js | 2 + static/js/864.857b1ea3.chunk.js.map | 1 + static/js/869.749826c3.chunk.js | 2 + static/js/869.749826c3.chunk.js.map | 1 + static/js/898.62dc8c0e.chunk.js | 2 + static/js/898.62dc8c0e.chunk.js.map | 1 + static/js/917.8a62d2bb.chunk.js | 2 + static/js/917.8a62d2bb.chunk.js.map | 1 + static/js/936.a2ea0fd5.chunk.js | 2 + static/js/936.a2ea0fd5.chunk.js.map | 1 + static/js/957.cd0722c7.chunk.js | 2 + static/js/957.cd0722c7.chunk.js.map | 1 + static/js/975.1f7d8524.chunk.js | 2 + static/js/975.1f7d8524.chunk.js.map | 1 + static/js/997.d8f4d384.chunk.js | 2 + static/js/997.d8f4d384.chunk.js.map | 1 + static/js/main.4379dbfb.js | 3 + static/js/main.4379dbfb.js.LICENSE.txt | 78 + static/js/main.4379dbfb.js.map | 1 + sw.js | 2 +- sw.js.map | 2 +- version.json | 2 +- 167 files changed, 10357 insertions(+), 4415 deletions(-) rename dist/components/{backend-ai-agent-summary-view-815e1e2f.js => backend-ai-agent-summary-view-6314e538.js} (98%) rename dist/components/{backend-ai-agent-view-299a9bbd.js => backend-ai-agent-view-4d995ee2.js} (99%) rename dist/components/{backend-ai-change-forgot-password-view-46841886.js => backend-ai-change-forgot-password-view-10f21c08.js} (98%) rename dist/components/{backend-ai-credential-view-6be055b5.js => backend-ai-credential-view-a6f83713.js} (99%) rename dist/components/{backend-ai-data-view-89775fae.js => backend-ai-data-view-d067f2be.js} (94%) rename dist/components/{backend-ai-edu-applauncher-57dee371.js => backend-ai-edu-applauncher-8acae0e5.js} (99%) rename dist/components/{backend-ai-email-verification-view-36a8105e.js => backend-ai-email-verification-view-f7125d4d.js} (98%) rename dist/components/{backend-ai-environment-view-de8e7c4b.js => backend-ai-environment-view-0ed5b6b7.js} (99%) rename dist/components/{backend-ai-error-view-0e8ee26a.js => backend-ai-error-view-e546570b.js} (92%) rename dist/components/{backend-ai-import-view-06e22683.js => backend-ai-import-view-b7523da0.js} (97%) rename dist/components/{backend-ai-information-view-e387dfbf.js => backend-ai-information-view-7511523a.js} (81%) rename dist/components/{backend-ai-list-status-caaae261.js => backend-ai-list-status-fa13c15b.js} (98%) rename dist/components/{backend-ai-maintenance-view-8a93fcd4.js => backend-ai-maintenance-view-d24087a2.js} (99%) rename dist/components/{backend-ai-multi-select-d9f981f2.js => backend-ai-multi-select-1943e543.js} (98%) rename dist/components/{backend-ai-permission-denied-view-5d18811d.js => backend-ai-permission-denied-view-20b6fa23.js} (94%) rename dist/components/{backend-ai-resource-monitor-2978fbc4.js => backend-ai-resource-monitor-21ef3974.js} (98%) delete mode 100644 dist/components/backend-ai-serving-list-b146c06f.js create mode 100644 dist/components/backend-ai-serving-list-f5b0ed1e.js rename dist/components/{backend-ai-session-launcher-a8a7a98f.js => backend-ai-session-launcher-676818a7.js} (79%) rename dist/components/{backend-ai-session-view-10661148.js => backend-ai-session-view-8572e752.js} (99%) delete mode 100644 dist/components/backend-ai-session-view-next-1b94c155.js create mode 100644 dist/components/backend-ai-session-view-next-ced7118d.js rename dist/components/{backend-ai-settings-view-3fe8a670.js => backend-ai-settings-view-7091b7da.js} (99%) rename dist/components/{backend-ai-statistics-view-a1bd3d63.js => backend-ai-statistics-view-bd0d921d.js} (98%) rename dist/components/{backend-ai-storage-host-settings-view-3f5096c9.js => backend-ai-storage-host-settings-view-fe71709b.js} (78%) rename dist/components/{backend-ai-summary-view-ddcff4e7.js => backend-ai-summary-view-3fb3e65a.js} (65%) rename dist/components/{backend-ai-usersettings-view-cef43866.js => backend-ai-usersettings-view-9fd5f370.js} (98%) rename dist/components/{backend-ai-webui-a9940dc0.js => backend-ai-webui-75df15ed.js} (91%) rename dist/components/{dir-utils-2ca2933c.js => dir-utils-f5050166.js} (99%) rename dist/components/{lablup-activity-panel-d2e7b975.js => lablup-activity-panel-86e1deef.js} (98%) rename dist/components/{lablup-codemirror-85098261.js => lablup-codemirror-59c15e56.js} (99%) rename dist/components/{lablup-grid-sort-filter-column-9fd9aaa5.js => lablup-grid-sort-filter-column-54638b7b.js} (90%) rename dist/components/{lablup-loading-spinner-8b3da9d1.js => lablup-loading-spinner-02aea3b9.js} (95%) rename dist/components/{lablup-progress-bar-c7f68c65.js => lablup-progress-bar-b230f3e3.js} (97%) rename dist/components/{media-query-controller-7de4b65f.js => media-query-controller-bc25d693.js} (92%) rename dist/components/{mwc-check-list-item-d2338b83.js => mwc-check-list-item-5618f22b.js} (93%) rename dist/components/{mwc-formfield-b8bed217.js => mwc-formfield-5cf6c683.js} (97%) rename dist/components/{mwc-switch-405e373b.js => mwc-switch-13f7c132.js} (98%) rename dist/components/{mwc-tab-bar-f47ea595.js => mwc-tab-bar-45ba859c.js} (99%) rename dist/components/{slider-b4cf5b64.js => slider-3f740add.js} (98%) rename dist/components/{vaadin-grid-7aa99257.js => vaadin-grid-461d199a.js} (93%) rename dist/components/{vaadin-grid-filter-column-26a38357.js => vaadin-grid-filter-column-2b22f222.js} (97%) rename dist/components/{vaadin-grid-selection-column-3b7b0ad4.js => vaadin-grid-selection-column-29a490b5.js} (98%) rename dist/components/{vaadin-grid-sort-column-4f44c0ff.js => vaadin-grid-sort-column-d722536e.js} (99%) rename dist/components/{vaadin-iconset-8594ac1d.js => vaadin-iconset-c8fcdcfd.js} (99%) rename dist/components/{vaadin-item-a4241857.js => vaadin-item-19772d96.js} (84%) rename dist/components/{vaadin-item-mixin-88c89617.js => vaadin-item-mixin-57783787.js} (91%) create mode 100644 resources/i18n/pt-BR.json create mode 100644 resources/i18n/zh-CN.json create mode 100644 resources/i18n/zh-TW.json create mode 100644 static/js/110.4c990d8f.chunk.js create mode 100644 static/js/110.4c990d8f.chunk.js.map create mode 100644 static/js/111.06ae856a.chunk.js create mode 100644 static/js/111.06ae856a.chunk.js.map create mode 100644 static/js/114.fd36729b.chunk.js create mode 100644 static/js/114.fd36729b.chunk.js.map create mode 100644 static/js/138.c507137d.chunk.js create mode 100644 static/js/138.c507137d.chunk.js.map create mode 100644 static/js/156.04ecc44c.chunk.js create mode 100644 static/js/156.04ecc44c.chunk.js.map create mode 100644 static/js/164.ce3398da.chunk.js create mode 100644 static/js/164.ce3398da.chunk.js.map create mode 100644 static/js/183.7ef52b0e.chunk.js create mode 100644 static/js/183.7ef52b0e.chunk.js.map create mode 100644 static/js/185.b1163da8.chunk.js create mode 100644 static/js/185.b1163da8.chunk.js.LICENSE.txt create mode 100644 static/js/185.b1163da8.chunk.js.map create mode 100644 static/js/20.a3968d90.chunk.js create mode 100644 static/js/20.a3968d90.chunk.js.map create mode 100644 static/js/209.47ee8c54.chunk.js create mode 100644 static/js/209.47ee8c54.chunk.js.map create mode 100644 static/js/229.433b20b1.chunk.js create mode 100644 static/js/229.433b20b1.chunk.js.map create mode 100644 static/js/230.0396ec8b.chunk.js create mode 100644 static/js/230.0396ec8b.chunk.js.map create mode 100644 static/js/266.b289d330.chunk.js create mode 100644 static/js/266.b289d330.chunk.js.map create mode 100644 static/js/284.be0edfd4.chunk.js create mode 100644 static/js/284.be0edfd4.chunk.js.map create mode 100644 static/js/341.d380d2bc.chunk.js create mode 100644 static/js/341.d380d2bc.chunk.js.map create mode 100644 static/js/360.d1869f7a.chunk.js create mode 100644 static/js/360.d1869f7a.chunk.js.map create mode 100644 static/js/427.8c42092f.chunk.js create mode 100644 static/js/427.8c42092f.chunk.js.map create mode 100644 static/js/448.a7113ead.chunk.js create mode 100644 static/js/448.a7113ead.chunk.js.map create mode 100644 static/js/456.e33eea6f.chunk.js create mode 100644 static/js/456.e33eea6f.chunk.js.map create mode 100644 static/js/486.6f07b950.chunk.js create mode 100644 static/js/486.6f07b950.chunk.js.LICENSE.txt create mode 100644 static/js/486.6f07b950.chunk.js.map create mode 100644 static/js/49.b8c5ebc8.chunk.js create mode 100644 static/js/49.b8c5ebc8.chunk.js.map create mode 100644 static/js/499.279cfd4e.chunk.js create mode 100644 static/js/499.279cfd4e.chunk.js.map create mode 100644 static/js/524.3fdcdcd0.chunk.js create mode 100644 static/js/524.3fdcdcd0.chunk.js.map create mode 100644 static/js/556.6e8e358c.chunk.js create mode 100644 static/js/556.6e8e358c.chunk.js.map create mode 100644 static/js/562.7450914b.chunk.js create mode 100644 static/js/562.7450914b.chunk.js.map create mode 100644 static/js/619.3a1ed2cd.chunk.js create mode 100644 static/js/619.3a1ed2cd.chunk.js.map create mode 100644 static/js/651.5ad26983.chunk.js create mode 100644 static/js/651.5ad26983.chunk.js.map create mode 100644 static/js/66.8acfb03b.chunk.js create mode 100644 static/js/66.8acfb03b.chunk.js.map create mode 100644 static/js/664.9ffc68f5.chunk.js create mode 100644 static/js/664.9ffc68f5.chunk.js.map create mode 100644 static/js/666.8975bcc8.chunk.js create mode 100644 static/js/666.8975bcc8.chunk.js.LICENSE.txt create mode 100644 static/js/666.8975bcc8.chunk.js.map create mode 100644 static/js/674.e0d526eb.chunk.js create mode 100644 static/js/674.e0d526eb.chunk.js.map create mode 100644 static/js/681.8ef57b6e.chunk.js create mode 100644 static/js/681.8ef57b6e.chunk.js.LICENSE.txt create mode 100644 static/js/681.8ef57b6e.chunk.js.map create mode 100644 static/js/689.94fd0e8e.chunk.js create mode 100644 static/js/689.94fd0e8e.chunk.js.map create mode 100644 static/js/703.2d8f0316.chunk.js create mode 100644 static/js/703.2d8f0316.chunk.js.map create mode 100644 static/js/864.857b1ea3.chunk.js create mode 100644 static/js/864.857b1ea3.chunk.js.map create mode 100644 static/js/869.749826c3.chunk.js create mode 100644 static/js/869.749826c3.chunk.js.map create mode 100644 static/js/898.62dc8c0e.chunk.js create mode 100644 static/js/898.62dc8c0e.chunk.js.map create mode 100644 static/js/917.8a62d2bb.chunk.js create mode 100644 static/js/917.8a62d2bb.chunk.js.map create mode 100644 static/js/936.a2ea0fd5.chunk.js create mode 100644 static/js/936.a2ea0fd5.chunk.js.map create mode 100644 static/js/957.cd0722c7.chunk.js create mode 100644 static/js/957.cd0722c7.chunk.js.map create mode 100644 static/js/975.1f7d8524.chunk.js create mode 100644 static/js/975.1f7d8524.chunk.js.map create mode 100644 static/js/997.d8f4d384.chunk.js create mode 100644 static/js/997.d8f4d384.chunk.js.map create mode 100644 static/js/main.4379dbfb.js create mode 100644 static/js/main.4379dbfb.js.LICENSE.txt create mode 100644 static/js/main.4379dbfb.js.map diff --git a/asset-manifest.json b/asset-manifest.json index 348c2c4fd1..7d273251cd 100644 --- a/asset-manifest.json +++ b/asset-manifest.json @@ -1,99 +1,101 @@ { "files": { - "main.js": "/static/js/main.b4d2f8b4.js", - "static/js/910.90e558be.chunk.js": "/static/js/910.90e558be.chunk.js", - "static/js/703.e911111e.chunk.js": "/static/js/703.e911111e.chunk.js", - "static/js/266.5bddc1df.chunk.js": "/static/js/266.5bddc1df.chunk.js", - "static/js/997.4cc992ff.chunk.js": "/static/js/997.4cc992ff.chunk.js", - "static/js/392.27045adb.chunk.js": "/static/js/392.27045adb.chunk.js", - "static/js/864.7fe907d4.chunk.js": "/static/js/864.7fe907d4.chunk.js", - "static/js/936.4d23fbe4.chunk.js": "/static/js/936.4d23fbe4.chunk.js", - "static/js/49.afac110c.chunk.js": "/static/js/49.afac110c.chunk.js", + "main.js": "/static/js/main.4379dbfb.js", + "static/js/111.06ae856a.chunk.js": "/static/js/111.06ae856a.chunk.js", + "static/js/703.2d8f0316.chunk.js": "/static/js/703.2d8f0316.chunk.js", + "static/js/266.b289d330.chunk.js": "/static/js/266.b289d330.chunk.js", + "static/js/997.d8f4d384.chunk.js": "/static/js/997.d8f4d384.chunk.js", + "static/js/975.1f7d8524.chunk.js": "/static/js/975.1f7d8524.chunk.js", + "static/js/864.857b1ea3.chunk.js": "/static/js/864.857b1ea3.chunk.js", + "static/js/936.a2ea0fd5.chunk.js": "/static/js/936.a2ea0fd5.chunk.js", + "static/js/49.b8c5ebc8.chunk.js": "/static/js/49.b8c5ebc8.chunk.js", "static/js/959.8aea2948.chunk.js": "/static/js/959.8aea2948.chunk.js", - "static/js/556.fbaa1103.chunk.js": "/static/js/556.fbaa1103.chunk.js", - "static/js/20.c9570a63.chunk.js": "/static/js/20.c9570a63.chunk.js", - "static/js/917.065a856f.chunk.js": "/static/js/917.065a856f.chunk.js", - "static/js/229.69683696.chunk.js": "/static/js/229.69683696.chunk.js", - "static/js/230.eaf4e10d.chunk.js": "/static/js/230.eaf4e10d.chunk.js", - "static/js/341.a184613c.chunk.js": "/static/js/341.a184613c.chunk.js", + "static/js/556.6e8e358c.chunk.js": "/static/js/556.6e8e358c.chunk.js", + "static/js/20.a3968d90.chunk.js": "/static/js/20.a3968d90.chunk.js", + "static/js/917.8a62d2bb.chunk.js": "/static/js/917.8a62d2bb.chunk.js", + "static/js/229.433b20b1.chunk.js": "/static/js/229.433b20b1.chunk.js", + "static/js/230.0396ec8b.chunk.js": "/static/js/230.0396ec8b.chunk.js", + "static/js/341.d380d2bc.chunk.js": "/static/js/341.d380d2bc.chunk.js", "static/js/112.a04be76d.chunk.js": "/static/js/112.a04be76d.chunk.js", - "static/js/609.a492aab7.chunk.js": "/static/js/609.a492aab7.chunk.js", - "static/js/499.8cd8c959.chunk.js": "/static/js/499.8cd8c959.chunk.js", - "static/js/681.6c82cf3b.chunk.js": "/static/js/681.6c82cf3b.chunk.js", - "static/js/843.9960807e.chunk.js": "/static/js/843.9960807e.chunk.js", - "static/js/689.4e62f8da.chunk.js": "/static/js/689.4e62f8da.chunk.js", + "static/js/666.8975bcc8.chunk.js": "/static/js/666.8975bcc8.chunk.js", + "static/js/499.279cfd4e.chunk.js": "/static/js/499.279cfd4e.chunk.js", + "static/js/185.b1163da8.chunk.js": "/static/js/185.b1163da8.chunk.js", + "static/js/681.8ef57b6e.chunk.js": "/static/js/681.8ef57b6e.chunk.js", + "static/js/156.04ecc44c.chunk.js": "/static/js/156.04ecc44c.chunk.js", + "static/js/689.94fd0e8e.chunk.js": "/static/js/689.94fd0e8e.chunk.js", "static/js/667.d630f5ff.chunk.js": "/static/js/667.d630f5ff.chunk.js", - "static/js/551.38a12964.chunk.js": "/static/js/551.38a12964.chunk.js", - "static/js/296.d9af0052.chunk.js": "/static/js/296.d9af0052.chunk.js", - "static/js/842.e47574eb.chunk.js": "/static/js/842.e47574eb.chunk.js", - "static/js/312.c5a4d21d.chunk.js": "/static/js/312.c5a4d21d.chunk.js", - "static/js/301.a2e3cb5c.chunk.js": "/static/js/301.a2e3cb5c.chunk.js", - "static/js/600.2a4581b5.chunk.js": "/static/js/600.2a4581b5.chunk.js", - "static/js/204.d0e4c0b0.chunk.js": "/static/js/204.d0e4c0b0.chunk.js", - "static/js/66.35aed0e7.chunk.js": "/static/js/66.35aed0e7.chunk.js", - "static/js/360.d59a54f7.chunk.js": "/static/js/360.d59a54f7.chunk.js", - "static/js/722.6674b248.chunk.js": "/static/js/722.6674b248.chunk.js", - "static/js/532.904cdf13.chunk.js": "/static/js/532.904cdf13.chunk.js", - "static/js/486.0d9dd578.chunk.js": "/static/js/486.0d9dd578.chunk.js", - "static/js/242.d54f242f.chunk.js": "/static/js/242.d54f242f.chunk.js", - "static/js/674.a97776a3.chunk.js": "/static/js/674.a97776a3.chunk.js", - "static/js/973.a461fab5.chunk.js": "/static/js/973.a461fab5.chunk.js", - "static/js/630.e858b90f.chunk.js": "/static/js/630.e858b90f.chunk.js", - "static/js/111.4c4408f6.chunk.js": "/static/js/111.4c4408f6.chunk.js", - "static/js/456.bce0df58.chunk.js": "/static/js/456.bce0df58.chunk.js", - "static/js/913.f9c07837.chunk.js": "/static/js/913.f9c07837.chunk.js", - "static/js/114.ecb84549.chunk.js": "/static/js/114.ecb84549.chunk.js", - "static/js/183.ec5284a4.chunk.js": "/static/js/183.ec5284a4.chunk.js", - "static/js/898.ed2721d9.chunk.js": "/static/js/898.ed2721d9.chunk.js", + "static/js/651.5ad26983.chunk.js": "/static/js/651.5ad26983.chunk.js", + "static/js/957.cd0722c7.chunk.js": "/static/js/957.cd0722c7.chunk.js", + "static/js/427.8c42092f.chunk.js": "/static/js/427.8c42092f.chunk.js", + "static/js/164.ce3398da.chunk.js": "/static/js/164.ce3398da.chunk.js", + "static/js/110.4c990d8f.chunk.js": "/static/js/110.4c990d8f.chunk.js", + "static/js/619.3a1ed2cd.chunk.js": "/static/js/619.3a1ed2cd.chunk.js", + "static/js/66.8acfb03b.chunk.js": "/static/js/66.8acfb03b.chunk.js", + "static/js/360.d1869f7a.chunk.js": "/static/js/360.d1869f7a.chunk.js", + "static/js/448.a7113ead.chunk.js": "/static/js/448.a7113ead.chunk.js", + "static/js/524.3fdcdcd0.chunk.js": "/static/js/524.3fdcdcd0.chunk.js", + "static/js/486.6f07b950.chunk.js": "/static/js/486.6f07b950.chunk.js", + "static/js/869.749826c3.chunk.js": "/static/js/869.749826c3.chunk.js", + "static/js/562.7450914b.chunk.js": "/static/js/562.7450914b.chunk.js", + "static/js/674.e0d526eb.chunk.js": "/static/js/674.e0d526eb.chunk.js", + "static/js/284.be0edfd4.chunk.js": "/static/js/284.be0edfd4.chunk.js", + "static/js/664.9ffc68f5.chunk.js": "/static/js/664.9ffc68f5.chunk.js", + "static/js/456.e33eea6f.chunk.js": "/static/js/456.e33eea6f.chunk.js", + "static/js/114.fd36729b.chunk.js": "/static/js/114.fd36729b.chunk.js", + "static/js/209.47ee8c54.chunk.js": "/static/js/209.47ee8c54.chunk.js", + "static/js/183.7ef52b0e.chunk.js": "/static/js/183.7ef52b0e.chunk.js", + "static/js/138.c507137d.chunk.js": "/static/js/138.c507137d.chunk.js", + "static/js/898.62dc8c0e.chunk.js": "/static/js/898.62dc8c0e.chunk.js", "index.html": "/index.html", "static/media/getFetch.cjs": "/static/media/getFetch.40f37ddea2378391108f.cjs", - "main.b4d2f8b4.js.map": "/static/js/main.b4d2f8b4.js.map", - "910.90e558be.chunk.js.map": "/static/js/910.90e558be.chunk.js.map", - "703.e911111e.chunk.js.map": "/static/js/703.e911111e.chunk.js.map", - "266.5bddc1df.chunk.js.map": "/static/js/266.5bddc1df.chunk.js.map", - "997.4cc992ff.chunk.js.map": "/static/js/997.4cc992ff.chunk.js.map", - "392.27045adb.chunk.js.map": "/static/js/392.27045adb.chunk.js.map", - "864.7fe907d4.chunk.js.map": "/static/js/864.7fe907d4.chunk.js.map", - "936.4d23fbe4.chunk.js.map": "/static/js/936.4d23fbe4.chunk.js.map", - "49.afac110c.chunk.js.map": "/static/js/49.afac110c.chunk.js.map", + "main.4379dbfb.js.map": "/static/js/main.4379dbfb.js.map", + "111.06ae856a.chunk.js.map": "/static/js/111.06ae856a.chunk.js.map", + "703.2d8f0316.chunk.js.map": "/static/js/703.2d8f0316.chunk.js.map", + "266.b289d330.chunk.js.map": "/static/js/266.b289d330.chunk.js.map", + "997.d8f4d384.chunk.js.map": "/static/js/997.d8f4d384.chunk.js.map", + "975.1f7d8524.chunk.js.map": "/static/js/975.1f7d8524.chunk.js.map", + "864.857b1ea3.chunk.js.map": "/static/js/864.857b1ea3.chunk.js.map", + "936.a2ea0fd5.chunk.js.map": "/static/js/936.a2ea0fd5.chunk.js.map", + "49.b8c5ebc8.chunk.js.map": "/static/js/49.b8c5ebc8.chunk.js.map", "959.8aea2948.chunk.js.map": "/static/js/959.8aea2948.chunk.js.map", - "556.fbaa1103.chunk.js.map": "/static/js/556.fbaa1103.chunk.js.map", - "20.c9570a63.chunk.js.map": "/static/js/20.c9570a63.chunk.js.map", - "917.065a856f.chunk.js.map": "/static/js/917.065a856f.chunk.js.map", - "229.69683696.chunk.js.map": "/static/js/229.69683696.chunk.js.map", - "230.eaf4e10d.chunk.js.map": "/static/js/230.eaf4e10d.chunk.js.map", - "341.a184613c.chunk.js.map": "/static/js/341.a184613c.chunk.js.map", + "556.6e8e358c.chunk.js.map": "/static/js/556.6e8e358c.chunk.js.map", + "20.a3968d90.chunk.js.map": "/static/js/20.a3968d90.chunk.js.map", + "917.8a62d2bb.chunk.js.map": "/static/js/917.8a62d2bb.chunk.js.map", + "229.433b20b1.chunk.js.map": "/static/js/229.433b20b1.chunk.js.map", + "230.0396ec8b.chunk.js.map": "/static/js/230.0396ec8b.chunk.js.map", + "341.d380d2bc.chunk.js.map": "/static/js/341.d380d2bc.chunk.js.map", "112.a04be76d.chunk.js.map": "/static/js/112.a04be76d.chunk.js.map", - "609.a492aab7.chunk.js.map": "/static/js/609.a492aab7.chunk.js.map", - "499.8cd8c959.chunk.js.map": "/static/js/499.8cd8c959.chunk.js.map", - "681.6c82cf3b.chunk.js.map": "/static/js/681.6c82cf3b.chunk.js.map", - "843.9960807e.chunk.js.map": "/static/js/843.9960807e.chunk.js.map", - "689.4e62f8da.chunk.js.map": "/static/js/689.4e62f8da.chunk.js.map", + "666.8975bcc8.chunk.js.map": "/static/js/666.8975bcc8.chunk.js.map", + "499.279cfd4e.chunk.js.map": "/static/js/499.279cfd4e.chunk.js.map", + "185.b1163da8.chunk.js.map": "/static/js/185.b1163da8.chunk.js.map", + "681.8ef57b6e.chunk.js.map": "/static/js/681.8ef57b6e.chunk.js.map", + "156.04ecc44c.chunk.js.map": "/static/js/156.04ecc44c.chunk.js.map", + "689.94fd0e8e.chunk.js.map": "/static/js/689.94fd0e8e.chunk.js.map", "667.d630f5ff.chunk.js.map": "/static/js/667.d630f5ff.chunk.js.map", - "551.38a12964.chunk.js.map": "/static/js/551.38a12964.chunk.js.map", - "296.d9af0052.chunk.js.map": "/static/js/296.d9af0052.chunk.js.map", - "842.e47574eb.chunk.js.map": "/static/js/842.e47574eb.chunk.js.map", - "312.c5a4d21d.chunk.js.map": "/static/js/312.c5a4d21d.chunk.js.map", - "301.a2e3cb5c.chunk.js.map": "/static/js/301.a2e3cb5c.chunk.js.map", - "600.2a4581b5.chunk.js.map": "/static/js/600.2a4581b5.chunk.js.map", - "204.d0e4c0b0.chunk.js.map": "/static/js/204.d0e4c0b0.chunk.js.map", - "66.35aed0e7.chunk.js.map": "/static/js/66.35aed0e7.chunk.js.map", - "360.d59a54f7.chunk.js.map": "/static/js/360.d59a54f7.chunk.js.map", - "722.6674b248.chunk.js.map": "/static/js/722.6674b248.chunk.js.map", - "532.904cdf13.chunk.js.map": "/static/js/532.904cdf13.chunk.js.map", - "486.0d9dd578.chunk.js.map": "/static/js/486.0d9dd578.chunk.js.map", - "242.d54f242f.chunk.js.map": "/static/js/242.d54f242f.chunk.js.map", - "674.a97776a3.chunk.js.map": "/static/js/674.a97776a3.chunk.js.map", - "973.a461fab5.chunk.js.map": "/static/js/973.a461fab5.chunk.js.map", - "630.e858b90f.chunk.js.map": "/static/js/630.e858b90f.chunk.js.map", - "111.4c4408f6.chunk.js.map": "/static/js/111.4c4408f6.chunk.js.map", - "456.bce0df58.chunk.js.map": "/static/js/456.bce0df58.chunk.js.map", - "913.f9c07837.chunk.js.map": "/static/js/913.f9c07837.chunk.js.map", - "114.ecb84549.chunk.js.map": "/static/js/114.ecb84549.chunk.js.map", - "183.ec5284a4.chunk.js.map": "/static/js/183.ec5284a4.chunk.js.map", - "898.ed2721d9.chunk.js.map": "/static/js/898.ed2721d9.chunk.js.map" + "651.5ad26983.chunk.js.map": "/static/js/651.5ad26983.chunk.js.map", + "957.cd0722c7.chunk.js.map": "/static/js/957.cd0722c7.chunk.js.map", + "427.8c42092f.chunk.js.map": "/static/js/427.8c42092f.chunk.js.map", + "164.ce3398da.chunk.js.map": "/static/js/164.ce3398da.chunk.js.map", + "110.4c990d8f.chunk.js.map": "/static/js/110.4c990d8f.chunk.js.map", + "619.3a1ed2cd.chunk.js.map": "/static/js/619.3a1ed2cd.chunk.js.map", + "66.8acfb03b.chunk.js.map": "/static/js/66.8acfb03b.chunk.js.map", + "360.d1869f7a.chunk.js.map": "/static/js/360.d1869f7a.chunk.js.map", + "448.a7113ead.chunk.js.map": "/static/js/448.a7113ead.chunk.js.map", + "524.3fdcdcd0.chunk.js.map": "/static/js/524.3fdcdcd0.chunk.js.map", + "486.6f07b950.chunk.js.map": "/static/js/486.6f07b950.chunk.js.map", + "869.749826c3.chunk.js.map": "/static/js/869.749826c3.chunk.js.map", + "562.7450914b.chunk.js.map": "/static/js/562.7450914b.chunk.js.map", + "674.e0d526eb.chunk.js.map": "/static/js/674.e0d526eb.chunk.js.map", + "284.be0edfd4.chunk.js.map": "/static/js/284.be0edfd4.chunk.js.map", + "664.9ffc68f5.chunk.js.map": "/static/js/664.9ffc68f5.chunk.js.map", + "456.e33eea6f.chunk.js.map": "/static/js/456.e33eea6f.chunk.js.map", + "114.fd36729b.chunk.js.map": "/static/js/114.fd36729b.chunk.js.map", + "209.47ee8c54.chunk.js.map": "/static/js/209.47ee8c54.chunk.js.map", + "183.7ef52b0e.chunk.js.map": "/static/js/183.7ef52b0e.chunk.js.map", + "138.c507137d.chunk.js.map": "/static/js/138.c507137d.chunk.js.map", + "898.62dc8c0e.chunk.js.map": "/static/js/898.62dc8c0e.chunk.js.map" }, "entrypoints": [ - "static/js/main.b4d2f8b4.js" + "static/js/main.4379dbfb.js" ] } \ No newline at end of file diff --git a/dist/components/backend-ai-agent-summary-view-815e1e2f.js b/dist/components/backend-ai-agent-summary-view-6314e538.js similarity index 98% rename from dist/components/backend-ai-agent-summary-view-815e1e2f.js rename to dist/components/backend-ai-agent-summary-view-6314e538.js index d2a45e96e6..14697c4983 100644 --- a/dist/components/backend-ai-agent-summary-view-815e1e2f.js +++ b/dist/components/backend-ai-agent-summary-view-6314e538.js @@ -1,4 +1,4 @@ -import{_ as t,n as e,b as s,e as i,B as a,c as o,I as r,a as n,i as l,f as d,l as c,x as p,t as u,g as _}from"./backend-ai-webui-a9940dc0.js";import"./lablup-progress-bar-c7f68c65.js";import"./mwc-switch-405e373b.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-sort-column-4f44c0ff.js";import"./backend-ai-list-status-caaae261.js";import"./lablup-activity-panel-d2e7b975.js";import"./mwc-tab-bar-f47ea595.js";import"./dir-utils-2ca2933c.js";let g=class extends a{constructor(){super(),this._enableAgentSchedulable=!1,this.condition="running",this.useHardwareMetadata=!1,this.agents=[],this.agentsObject=Object(),this.agentDetail=Object(),this.notification=Object(),this.agentDetailDialog=Object(),this.agentSettingDialog=Object(),this._boundEndpointRenderer=this.endpointRenderer.bind(this),this._boundResourceRenderer=this.resourceRenderer.bind(this),this._boundSchedulableRenderer=this.schedulableRenderer.bind(this),this.filter="",this.listCondition="loading"}static get styles(){return[o,r,n,l` +import{_ as t,n as e,b as s,e as i,B as a,c as o,I as r,a as n,i as l,f as d,l as c,x as p,t as u,g as _}from"./backend-ai-webui-75df15ed.js";import"./lablup-progress-bar-b230f3e3.js";import"./mwc-switch-13f7c132.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-sort-column-d722536e.js";import"./backend-ai-list-status-fa13c15b.js";import"./lablup-activity-panel-86e1deef.js";import"./mwc-tab-bar-45ba859c.js";import"./dir-utils-f5050166.js";let g=class extends a{constructor(){super(),this._enableAgentSchedulable=!1,this.condition="running",this.useHardwareMetadata=!1,this.agents=[],this.agentsObject=Object(),this.agentDetail=Object(),this.notification=Object(),this.agentDetailDialog=Object(),this.agentSettingDialog=Object(),this._boundEndpointRenderer=this.endpointRenderer.bind(this),this._boundResourceRenderer=this.resourceRenderer.bind(this),this._boundSchedulableRenderer=this.schedulableRenderer.bind(this),this.filter="",this.listCondition="loading"}static get styles(){return[o,r,n,l` vaadin-grid { border: 0; font-size: 14px; diff --git a/dist/components/backend-ai-agent-view-299a9bbd.js b/dist/components/backend-ai-agent-view-4d995ee2.js similarity index 99% rename from dist/components/backend-ai-agent-view-299a9bbd.js rename to dist/components/backend-ai-agent-view-4d995ee2.js index f436407660..22fd31fe7e 100644 --- a/dist/components/backend-ai-agent-view-299a9bbd.js +++ b/dist/components/backend-ai-agent-view-4d995ee2.js @@ -1,4 +1,4 @@ -import{_ as e,n as t,b as i,e as s,B as a,c as o,I as r,a as l,i as n,f as d,l as c,x as u,t as p,g as h,u as g,N as v,O as b}from"./backend-ai-webui-a9940dc0.js";import"./lablup-progress-bar-c7f68c65.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-sort-column-4f44c0ff.js";import"./backend-ai-multi-select-d9f981f2.js";import"./mwc-switch-405e373b.js";import"./vaadin-item-a4241857.js";import"./backend-ai-list-status-caaae261.js";import"./backend-ai-storage-host-settings-view-3f5096c9.js";import"./lablup-activity-panel-d2e7b975.js";import"./mwc-tab-bar-f47ea595.js";import"./dir-utils-2ca2933c.js";import"./mwc-check-list-item-d2338b83.js";import"./vaadin-item-mixin-88c89617.js";var m;let _=m=class extends a{constructor(){super(...arguments),this._enableAgentSchedulable=!1,this.condition="running",this.list_condition="loading",this.useHardwareMetadata=!1,this.agents=[],this.agentsObject=Object(),this.agentDetail=Object(),this.notification=Object(),this.enableAgentSchedulable=!1,this._boundEndpointRenderer=this.endpointRenderer.bind(this),this._boundRegionRenderer=this.regionRenderer.bind(this),this._boundContactDateRenderer=this.contactDateRenderer.bind(this),this._boundResourceRenderer=this.resourceRenderer.bind(this),this._boundUtilizationRenderer=this.utilizationRenderer.bind(this),this._boundDiskRenderer=this.diskRenderer.bind(this),this._boundStatusRenderer=this.statusRenderer.bind(this),this._boundControlRenderer=this.controlRenderer.bind(this),this._boundSchedulableRenderer=this.schedulableRenderer.bind(this),this.filter="",this.listCondition="loading"}static get styles(){return[o,r,l,n` +import{_ as e,n as t,b as i,e as s,B as a,c as o,I as r,a as l,i as n,f as d,l as c,x as u,t as p,g as h,w as g,p as v,q as b}from"./backend-ai-webui-75df15ed.js";import"./lablup-progress-bar-b230f3e3.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-sort-column-d722536e.js";import"./backend-ai-multi-select-1943e543.js";import"./mwc-switch-13f7c132.js";import"./vaadin-item-19772d96.js";import"./backend-ai-list-status-fa13c15b.js";import"./backend-ai-storage-host-settings-view-fe71709b.js";import"./lablup-activity-panel-86e1deef.js";import"./mwc-tab-bar-45ba859c.js";import"./dir-utils-f5050166.js";import"./mwc-check-list-item-5618f22b.js";import"./vaadin-item-mixin-57783787.js";var m;let _=m=class extends a{constructor(){super(...arguments),this._enableAgentSchedulable=!1,this.condition="running",this.list_condition="loading",this.useHardwareMetadata=!1,this.agents=[],this.agentsObject=Object(),this.agentDetail=Object(),this.notification=Object(),this.enableAgentSchedulable=!1,this._boundEndpointRenderer=this.endpointRenderer.bind(this),this._boundRegionRenderer=this.regionRenderer.bind(this),this._boundContactDateRenderer=this.contactDateRenderer.bind(this),this._boundResourceRenderer=this.resourceRenderer.bind(this),this._boundUtilizationRenderer=this.utilizationRenderer.bind(this),this._boundDiskRenderer=this.diskRenderer.bind(this),this._boundStatusRenderer=this.statusRenderer.bind(this),this._boundControlRenderer=this.controlRenderer.bind(this),this._boundSchedulableRenderer=this.schedulableRenderer.bind(this),this.filter="",this.listCondition="loading"}static get styles(){return[o,r,l,n` .progress-bar-section { height: 20px; } diff --git a/dist/components/backend-ai-change-forgot-password-view-46841886.js b/dist/components/backend-ai-change-forgot-password-view-10f21c08.js similarity index 98% rename from dist/components/backend-ai-change-forgot-password-view-46841886.js rename to dist/components/backend-ai-change-forgot-password-view-10f21c08.js index 0214e4c759..d9849b9874 100644 --- a/dist/components/backend-ai-change-forgot-password-view-46841886.js +++ b/dist/components/backend-ai-change-forgot-password-view-10f21c08.js @@ -1,4 +1,4 @@ -import{_ as e,n as t,e as i,B as a,c as o,I as s,a as l,m as n,d,i as r,ar as c,as as h,g,x as p,t as w,Q as u}from"./backend-ai-webui-a9940dc0.js";let v=class extends a{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.passwordChangeDialog=Object(),this.failDialog=Object(),this.token=""}static get styles(){return[o,s,l,n,d,r` +import{_ as e,n as t,e as i,B as a,c as o,I as s,a as l,m as n,d,i as r,ar as c,as as h,g,x as p,t as w,Q as u}from"./backend-ai-webui-75df15ed.js";let v=class extends a{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.passwordChangeDialog=Object(),this.failDialog=Object(),this.token=""}static get styles(){return[o,s,l,n,d,r` mwc-textfield { width: 100%; } diff --git a/dist/components/backend-ai-credential-view-6be055b5.js b/dist/components/backend-ai-credential-view-a6f83713.js similarity index 99% rename from dist/components/backend-ai-credential-view-6be055b5.js rename to dist/components/backend-ai-credential-view-a6f83713.js index 812457bd05..fe793ef2a2 100644 --- a/dist/components/backend-ai-credential-view-6be055b5.js +++ b/dist/components/backend-ai-credential-view-a6f83713.js @@ -1,4 +1,4 @@ -import{_ as e,n as i,b as t,e as s,B as o,c as a,I as r,a as l,m as n,d as c,i as d,f as u,g as p,l as h,x as m,t as v,u as _,Q as y}from"./backend-ai-webui-a9940dc0.js";import{J as g}from"./json_to_csv-35c9e191.js";import"./backend-ai-list-status-caaae261.js";import"./lablup-grid-sort-filter-column-9fd9aaa5.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-filter-column-26a38357.js";import"./vaadin-grid-sort-column-4f44c0ff.js";import"./vaadin-iconset-8594ac1d.js";import"./vaadin-item-a4241857.js";import"./backend-ai-multi-select-d9f981f2.js";import"./mwc-switch-405e373b.js";import"./lablup-activity-panel-d2e7b975.js";import"./mwc-formfield-b8bed217.js";import"./mwc-tab-bar-f47ea595.js";import"./dir-utils-2ca2933c.js";import"./vaadin-item-mixin-88c89617.js";import"./mwc-check-list-item-d2338b83.js";var f;class b extends Error{constructor(e){super(e),Object.setPrototypeOf(this,b.prototype),this.title="Unable to delete keypair"}}let w=f=class extends o{constructor(){super(),this.keypairInfo={user_id:"1",access_key:"ABC",secret_key:"ABC",last_used:"",is_admin:!1,resource_policy:"",rate_limit:5e3,concurrency_used:0,num_queries:0,created_at:""},this.isAdmin=!1,this.condition="active",this.keypairs=[],this.resourcePolicy=Object(),this.indicator=Object(),this._boundKeyageRenderer=this.keyageRenderer.bind(this),this._boundControlRenderer=this.controlRenderer.bind(this),this._boundAccessKeyRenderer=this.accessKeyRenderer.bind(this),this._boundPermissionRenderer=this.permissionRenderer.bind(this),this._boundResourcePolicyRenderer=this.resourcePolicyRenderer.bind(this),this._boundAllocationRenderer=this.allocationRenderer.bind(this),this._boundUserIdRenderer=this.userIdRenderer.bind(this),this.keypairGrid=Object(),this.listCondition="loading",this._totalCredentialCount=0,this.isUserInfoMaskEnabled=!1,this.deleteKeyPairUserName="",this.deleteKeyPairAccessKey=""}static get styles(){return[a,r,l,n,c,d` +import{_ as e,n as i,b as t,e as s,B as o,c as a,I as r,a as l,m as n,d as c,i as d,f as u,g as p,l as h,x as m,t as v,w as _,Q as y}from"./backend-ai-webui-75df15ed.js";import{J as g}from"./json_to_csv-35c9e191.js";import"./backend-ai-list-status-fa13c15b.js";import"./lablup-grid-sort-filter-column-54638b7b.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-filter-column-2b22f222.js";import"./vaadin-grid-sort-column-d722536e.js";import"./vaadin-iconset-c8fcdcfd.js";import"./vaadin-item-19772d96.js";import"./backend-ai-multi-select-1943e543.js";import"./mwc-switch-13f7c132.js";import"./lablup-activity-panel-86e1deef.js";import"./mwc-formfield-5cf6c683.js";import"./mwc-tab-bar-45ba859c.js";import"./dir-utils-f5050166.js";import"./vaadin-item-mixin-57783787.js";import"./mwc-check-list-item-5618f22b.js";var f;class b extends Error{constructor(e){super(e),Object.setPrototypeOf(this,b.prototype),this.title="Unable to delete keypair"}}let w=f=class extends o{constructor(){super(),this.keypairInfo={user_id:"1",access_key:"ABC",secret_key:"ABC",last_used:"",is_admin:!1,resource_policy:"",rate_limit:5e3,concurrency_used:0,num_queries:0,created_at:""},this.isAdmin=!1,this.condition="active",this.keypairs=[],this.resourcePolicy=Object(),this.indicator=Object(),this._boundKeyageRenderer=this.keyageRenderer.bind(this),this._boundControlRenderer=this.controlRenderer.bind(this),this._boundAccessKeyRenderer=this.accessKeyRenderer.bind(this),this._boundPermissionRenderer=this.permissionRenderer.bind(this),this._boundResourcePolicyRenderer=this.resourcePolicyRenderer.bind(this),this._boundAllocationRenderer=this.allocationRenderer.bind(this),this._boundUserIdRenderer=this.userIdRenderer.bind(this),this.keypairGrid=Object(),this.listCondition="loading",this._totalCredentialCount=0,this.isUserInfoMaskEnabled=!1,this.deleteKeyPairUserName="",this.deleteKeyPairAccessKey=""}static get styles(){return[a,r,l,n,c,d` vaadin-grid { border: 0; font-size: 14px; diff --git a/dist/components/backend-ai-data-view-89775fae.js b/dist/components/backend-ai-data-view-d067f2be.js similarity index 94% rename from dist/components/backend-ai-data-view-89775fae.js rename to dist/components/backend-ai-data-view-d067f2be.js index 1b39d71a7a..6ccbb625ea 100644 --- a/dist/components/backend-ai-data-view-89775fae.js +++ b/dist/components/backend-ai-data-view-d067f2be.js @@ -1,4 +1,4 @@ -import{p as __extends,q as __assign,M as MDCFoundation,_ as __decorate,b as i,u as t,n,v as observer,w as e,y as ariaProperty,z as e$1,F as FormElement,R as RippleHandlers,x,A as addHasRemoveClass,C as o,E as l,i as i$1,e as e$2,G as Debouncer,H as animationFrame,J as FlattenedNodesObserver,P as PolymerElement,r as registerStyles,K as ElementMixin,T as ThemableMixin,k as html,B as BackendAIPage,c as BackendAiStyles,I as IronFlex,a as IronFlexAlignment,d as IronPositioning,t as translate,g as get,l as D,f as BackendAIPainKiller,o as o$1}from"./backend-ai-webui-a9940dc0.js";import"./backend-ai-list-status-caaae261.js";import"./backend-ai-session-launcher-a8a7a98f.js";import"./lablup-grid-sort-filter-column-9fd9aaa5.js";import"./lablup-loading-spinner-8b3da9d1.js";import"./mwc-formfield-b8bed217.js";import{C as ColumnBaseMixin,u as updateColumnOrders}from"./vaadin-grid-7aa99257.js";import"./vaadin-grid-filter-column-26a38357.js";import"./vaadin-grid-selection-column-3b7b0ad4.js";import"./vaadin-grid-sort-column-4f44c0ff.js";import"./vaadin-item-a4241857.js";import"./lablup-activity-panel-d2e7b975.js";import"./mwc-tab-bar-f47ea595.js";import"./lablup-codemirror-85098261.js";import"./lablup-progress-bar-c7f68c65.js";import"./slider-b4cf5b64.js";import"./mwc-check-list-item-d2338b83.js";import"./media-query-controller-7de4b65f.js";import"./dir-utils-2ca2933c.js";import"./vaadin-item-mixin-88c89617.js";!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).tus=e()}((function(){var define;return function e(t,i,o){function r(n,s){if(!i[n]){if(!t[n]){var l="function"==typeof require&&require;if(!s&&l)return l(n,!0);if(a)return a(n,!0);var d=new Error("Cannot find module '"+n+"'");throw d.code="MODULE_NOT_FOUND",d}var c=i[n]={exports:{}};t[n][0].call(c.exports,(function(e){return r(t[n][1][e]||e)}),c,c.exports,e,t,i,o)}return i[n].exports}for(var a="function"==typeof require&&require,n=0;nthis._bufferOffset&&(this._buffer=this._buffer.slice(e-this._bufferOffset),this._bufferOffset=e);var i=0===p(this._buffer);return this._done&&i?null:this._buffer.slice(0,t-e)}},{key:"close",value:function(){this._reader.cancel&&this._reader.cancel()}}]),e}();function p(e){return void 0===e?0:void 0!==e.size?e.size:e.length}var m=function(){function e(){l(this,e)}return c(e,[{key:"openFile",value:function(e,t){return(0,o.default)()&&e&&void 0!==e.uri?(0,r.default)(e.uri).then((function(e){return new u(e)})).catch((function(e){throw new Error("tus: cannot fetch `file.uri` as Blob, make sure the uri is correct and accessible. "+e)})):"function"==typeof e.slice&&void 0!==e.size?Promise.resolve(new u(e)):"function"==typeof e.read?(t=+t,isFinite(t)?Promise.resolve(new h(e,t)):Promise.reject(new Error("cannot create source for stream without a finite value for the `chunkSize` option"))):Promise.reject(new Error("source object may only be an instance of File, Blob, or Reader in this environment"))}}]),e}();i.default=m},{"./isCordova":5,"./isReactNative":6,"./readAsByteArray":7,"./uriToBlob":8}],2:[function(e,t,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=function(e,t){return(0,r.default)()?Promise.resolve(function(e,t){var i=e.exif?function(e){var t=0;if(0===e.length)return t;for(var i=0;ithis._offsetBeforeRetry&&(this._retryAttempt=0),b(e,this._retryAttempt,this.options))){var i=this.options.retryDelays[this._retryAttempt++];return this._offsetBeforeRetry=this._offset,void(this._retryTimeout=setTimeout((function(){t.start()}),i))}if("function"!=typeof this.options.onError)throw e;this.options.onError(e)}}},{key:"_emitSuccess",value:function(){this.options.removeFingerprintOnSuccess&&this._removeFromUrlStorage(),"function"==typeof this.options.onSuccess&&this.options.onSuccess()}},{key:"_emitProgress",value:function(e,t){"function"==typeof this.options.onProgress&&this.options.onProgress(e,t)}},{key:"_emitChunkComplete",value:function(e,t,i){"function"==typeof this.options.onChunkComplete&&this.options.onChunkComplete(e,t,i)}},{key:"_createUpload",value:function(){var e,t,i=this;this.options.endpoint?(e=this._openRequest("POST",this.options.endpoint),this.options.uploadLengthDeferred?e.setHeader("Upload-Defer-Length",1):e.setHeader("Upload-Length",this._size),""!==(t=m(this.options.metadata))&&e.setHeader("Upload-Metadata",t),(this.options.uploadDataDuringCreation&&!this.options.uploadLengthDeferred?(this._offset=0,this._addChunkToRequest(e)):this._sendRequest(e,null)).then((function(t){if(f(t.getStatus(),200)){var o=t.getHeader("Location");if(null!=o){if(i.url=v(i.options.endpoint,o),(0,s.log)("Created upload at ".concat(i.url)),"function"==typeof i.options._onUploadUrlAvailable&&i.options._onUploadUrlAvailable(),0===i._size)return i._emitSuccess(),void i._source.close();i._saveUploadInUrlStorage(),i.options.uploadDataDuringCreation?i._handleUploadResponse(e,t):(i._offset=0,i._performUpload())}else i._emitHttpError(e,t,"tus: invalid or missing Location header")}else i._emitHttpError(e,t,"tus: unexpected response while creating upload")})).catch((function(t){i._emitHttpError(e,null,"tus: failed to create upload",t)}))):this._emitError(new Error("tus: unable to create upload because no endpoint is provided"))}},{key:"_resumeUpload",value:function(){var e=this,t=this._openRequest("HEAD",this.url);this._sendRequest(t,null).then((function(i){var o=i.getStatus();if(!f(o,200))return f(o,400)&&e._removeFromUrlStorage(),423===o?void e._emitHttpError(t,i,"tus: upload is currently locked; retry later"):e.options.endpoint?(e.url=null,void e._createUpload()):void e._emitHttpError(t,i,"tus: unable to resume upload (new upload cannot be created without an endpoint)");var r=parseInt(i.getHeader("Upload-Offset"),10);if(isNaN(r))e._emitHttpError(t,i,"tus: invalid or missing offset value");else{var a=parseInt(i.getHeader("Upload-Length"),10);if(!isNaN(a)||e.options.uploadLengthDeferred){if("function"==typeof e.options._onUploadUrlAvailable&&e.options._onUploadUrlAvailable(),r===a)return e._emitProgress(a,a),void e._emitSuccess();e._offset=r,e._performUpload()}else e._emitHttpError(t,i,"tus: invalid or missing length value")}})).catch((function(i){e._emitHttpError(t,null,"tus: failed to resume upload",i)}))}},{key:"_performUpload",value:function(){var e,t=this;this._aborted||(this.options.overridePatchMethod?(e=this._openRequest("POST",this.url)).setHeader("X-HTTP-Method-Override","PATCH"):e=this._openRequest("PATCH",this.url),e.setHeader("Upload-Offset",this._offset),this._addChunkToRequest(e).then((function(i){f(i.getStatus(),200)?t._handleUploadResponse(e,i):t._emitHttpError(e,i,"tus: unexpected response while uploading chunk")})).catch((function(i){t._aborted||t._emitHttpError(e,null,"tus: failed to upload chunk at offset "+t._offset,i)})))}},{key:"_addChunkToRequest",value:function(e){var t=this,i=this._offset,o=this._offset+this.options.chunkSize;return e.setProgressHandler((function(e){t._emitProgress(i+e,t._size)})),e.setHeader("Content-Type","application/offset+octet-stream"),(o===1/0||o>this._size)&&!this.options.uploadLengthDeferred&&(o=this._size),this._source.slice(i,o).then((function(i){var o=i.value,r=i.done;return t.options.uploadLengthDeferred&&r&&(t._size=t._offset+(o&&o.size?o.size:0),e.setHeader("Upload-Length",t._size)),null===o?t._sendRequest(e):(t._emitProgress(t._offset,t._size),t._sendRequest(e,o))}))}},{key:"_handleUploadResponse",value:function(e,t){var i=parseInt(t.getHeader("Upload-Offset"),10);if(isNaN(i))this._emitHttpError(e,t,"tus: invalid or missing offset value");else{if(this._emitProgress(i,this._size),this._emitChunkComplete(i-this._offset,i,this._size),(this._offset=i)==this._size)return this._emitSuccess(),void this._source.close();this._performUpload()}}},{key:"_openRequest",value:function(e,t){var i=g(e,t,this.options);return this._req=i}},{key:"_removeFromUrlStorage",value:function(){var e=this;this._urlStorageKey&&(this._urlStorage.removeUpload(this._urlStorageKey).catch((function(t){e._emitError(t)})),this._urlStorageKey=null)}},{key:"_saveUploadInUrlStorage",value:function(){var e,t=this;this.options.storeFingerprintForResuming&&this._fingerprint&&(e={size:this._size,metadata:this.options.metadata,creationTime:(new Date).toString()},this._parallelUploads?e.parallelUploadUrls=this._parallelUploadUrls:e.uploadUrl=this.url,this._urlStorage.addUpload(this._fingerprint,e).then((function(e){return t._urlStorageKey=e})).catch((function(e){t._emitError(e)})))}},{key:"_sendRequest",value:function(e,t){var i=this,o=1>>6)+fromCharCode(128|63&t):fromCharCode(224|t>>>12&15)+fromCharCode(128|t>>>6&63)+fromCharCode(128|63&t);var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return fromCharCode(240|t>>>18&7)+fromCharCode(128|t>>>12&63)+fromCharCode(128|t>>>6&63)+fromCharCode(128|63&t)},re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,utob=function(e){return e.replace(re_utob,cb_utob)},cb_encode=function(e){var t=[0,2,1][e.length%3],i=e.charCodeAt(0)<<16|(1>>18),b64chars.charAt(i>>>12&63),2<=t?"=":b64chars.charAt(i>>>6&63),1<=t?"=":b64chars.charAt(63&i)].join("")},btoa=global.btoa?function(e){return global.btoa(e)}:function(e){return e.replace(/[\s\S]{1,3}/g,cb_encode)},_encode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(e){return(e.constructor===buffer.constructor?e:buffer.from(e)).toString("base64")}:function(e){return(e.constructor===buffer.constructor?e:new buffer(e)).toString("base64")}:function(e){return btoa(utob(e))},encode=function(e,t){return t?_encode(String(e)).replace(/[+\/]/g,(function(e){return"+"==e?"-":"_"})).replace(/=/g,""):_encode(String(e))},encodeURI=function(e){return encode(e,!0)},re_btou=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g"),cb_btou=function(e){switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return fromCharCode(55296+(t>>>10))+fromCharCode(56320+(1023&t));case 3:return fromCharCode((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return fromCharCode((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},btou=function(e){return e.replace(re_btou,cb_btou)},cb_decode=function(e){var t=e.length,i=t%4,o=(0>>16),fromCharCode(o>>>8&255),fromCharCode(255&o)];return r.length-=[0,0,2,1][i],r.join("")},atob=global.atob?function(e){return global.atob(e)}:function(e){return e.replace(/[\s\S]{1,4}/g,cb_decode)},_decode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(e){return(e.constructor===buffer.constructor?e:buffer.from(e,"base64")).toString()}:function(e){return(e.constructor===buffer.constructor?e:new buffer(e,"base64")).toString()}:function(e){return btou(atob(e))},decode=function(e){return _decode(String(e).replace(/[-_]/g,(function(e){return"-"==e?"+":"/"})).replace(/[^A-Za-z0-9\+\/]/g,""))},noConflict=function(){var e=global.Base64;return global.Base64=_Base64,e},noEnum;return global.Base64={VERSION:version,atob:atob,btoa:btoa,fromBase64:decode,toBase64:encode,utob:utob,encode:encode,encodeURI:encodeURI,btou:btou,decode:decode,noConflict:noConflict,__buffer__:buffer},"function"==typeof Object.defineProperty&&(noEnum=function(e){return{value:e,enumerable:!1,writable:!0,configurable:!0}},global.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",noEnum((function(){return decode(this)}))),Object.defineProperty(String.prototype,"toBase64",noEnum((function(e){return encode(this,e)}))),Object.defineProperty(String.prototype,"toBase64URI",noEnum((function(){return encode(this,!0)})))}),global.Meteor&&(Base64=global.Base64),void 0!==module&&module.exports&&(module.exports.Base64=global.Base64),{Base64:global.Base64}},"object"==typeof exports&&void 0!==module?module.exports=Hk(Gk):Hk(Gk)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],16:[function(e,t,i){var o=Object.prototype.hasOwnProperty;function r(e){return decodeURIComponent(e.replace(/\+/g," "))}i.stringify=function(e,t){t=t||"";var i=[];for(var r in"string"!=typeof t&&(t="?"),e)o.call(e,r)&&i.push(encodeURIComponent(r)+"="+encodeURIComponent(e[r]));return i.length?t+i.join("&"):""},i.parse=function(e){for(var t,i=/([^=?&]+)=?([^&]*)/g,o={};t=i.exec(e);){var a=r(t[1]),n=r(t[2]);a in o||(o[a]=n)}return o}},{}],17:[function(e,t,i){t.exports=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}},{}],18:[function(e,t,i){(function(i){var o=e("requires-port"),r=e("querystringify"),a=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,n=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,s=[["#","hash"],["?","query"],function(e){return e.replace("\\","/")},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],l={hash:1,query:1};function d(e){var t,o=i&&i.location||{},r={},a=typeof(e=e||o);if("blob:"===e.protocol)r=new u(unescape(e.pathname),{});else if("string"==a)for(t in r=new u(e,{}),l)delete r[t];else if("object"==a){for(t in e)t in l||(r[t]=e[t]);void 0===r.slashes&&(r.slashes=n.test(e.href))}return r}function c(e){var t=a.exec(e);return{protocol:t[1]?t[1].toLowerCase():"",slashes:!!t[2],rest:t[3]}}function u(e,t,i){if(!(this instanceof u))return new u(e,t,i);var a,n,l,h,p,m,f=s.slice(),g=typeof t,b=this,v=0;for("object"!=g&&"string"!=g&&(i=t,t=null),i&&"function"!=typeof i&&(i=r.parse),t=d(t),a=!(n=c(e||"")).protocol&&!n.slashes,b.slashes=n.slashes||a&&t.slashes,b.protocol=n.protocol||t.protocol||"",e=n.rest,n.slashes||(f[3]=[/(.*)/,"pathname"]);vthis._bufferOffset&&(this._buffer=this._buffer.slice(e-this._bufferOffset),this._bufferOffset=e);var i=0===p(this._buffer);return this._done&&i?null:this._buffer.slice(0,t-e)}},{key:"close",value:function(){this._reader.cancel&&this._reader.cancel()}}]),e}();function p(e){return void 0===e?0:void 0!==e.size?e.size:e.length}var m=function(){function e(){l(this,e)}return c(e,[{key:"openFile",value:function(e,t){return(0,o.default)()&&e&&void 0!==e.uri?(0,r.default)(e.uri).then((function(e){return new u(e)})).catch((function(e){throw new Error("tus: cannot fetch `file.uri` as Blob, make sure the uri is correct and accessible. "+e)})):"function"==typeof e.slice&&void 0!==e.size?Promise.resolve(new u(e)):"function"==typeof e.read?(t=+t,isFinite(t)?Promise.resolve(new h(e,t)):Promise.reject(new Error("cannot create source for stream without a finite value for the `chunkSize` option"))):Promise.reject(new Error("source object may only be an instance of File, Blob, or Reader in this environment"))}}]),e}();i.default=m},{"./isCordova":5,"./isReactNative":6,"./readAsByteArray":7,"./uriToBlob":8}],2:[function(e,t,i){Object.defineProperty(i,"__esModule",{value:!0}),i.default=function(e,t){return(0,r.default)()?Promise.resolve(function(e,t){var i=e.exif?function(e){var t=0;if(0===e.length)return t;for(var i=0;ithis._offsetBeforeRetry&&(this._retryAttempt=0),b(e,this._retryAttempt,this.options))){var i=this.options.retryDelays[this._retryAttempt++];return this._offsetBeforeRetry=this._offset,void(this._retryTimeout=setTimeout((function(){t.start()}),i))}if("function"!=typeof this.options.onError)throw e;this.options.onError(e)}}},{key:"_emitSuccess",value:function(){this.options.removeFingerprintOnSuccess&&this._removeFromUrlStorage(),"function"==typeof this.options.onSuccess&&this.options.onSuccess()}},{key:"_emitProgress",value:function(e,t){"function"==typeof this.options.onProgress&&this.options.onProgress(e,t)}},{key:"_emitChunkComplete",value:function(e,t,i){"function"==typeof this.options.onChunkComplete&&this.options.onChunkComplete(e,t,i)}},{key:"_createUpload",value:function(){var e,t,i=this;this.options.endpoint?(e=this._openRequest("POST",this.options.endpoint),this.options.uploadLengthDeferred?e.setHeader("Upload-Defer-Length",1):e.setHeader("Upload-Length",this._size),""!==(t=m(this.options.metadata))&&e.setHeader("Upload-Metadata",t),(this.options.uploadDataDuringCreation&&!this.options.uploadLengthDeferred?(this._offset=0,this._addChunkToRequest(e)):this._sendRequest(e,null)).then((function(t){if(f(t.getStatus(),200)){var o=t.getHeader("Location");if(null!=o){if(i.url=v(i.options.endpoint,o),(0,s.log)("Created upload at ".concat(i.url)),"function"==typeof i.options._onUploadUrlAvailable&&i.options._onUploadUrlAvailable(),0===i._size)return i._emitSuccess(),void i._source.close();i._saveUploadInUrlStorage(),i.options.uploadDataDuringCreation?i._handleUploadResponse(e,t):(i._offset=0,i._performUpload())}else i._emitHttpError(e,t,"tus: invalid or missing Location header")}else i._emitHttpError(e,t,"tus: unexpected response while creating upload")})).catch((function(t){i._emitHttpError(e,null,"tus: failed to create upload",t)}))):this._emitError(new Error("tus: unable to create upload because no endpoint is provided"))}},{key:"_resumeUpload",value:function(){var e=this,t=this._openRequest("HEAD",this.url);this._sendRequest(t,null).then((function(i){var o=i.getStatus();if(!f(o,200))return f(o,400)&&e._removeFromUrlStorage(),423===o?void e._emitHttpError(t,i,"tus: upload is currently locked; retry later"):e.options.endpoint?(e.url=null,void e._createUpload()):void e._emitHttpError(t,i,"tus: unable to resume upload (new upload cannot be created without an endpoint)");var r=parseInt(i.getHeader("Upload-Offset"),10);if(isNaN(r))e._emitHttpError(t,i,"tus: invalid or missing offset value");else{var a=parseInt(i.getHeader("Upload-Length"),10);if(!isNaN(a)||e.options.uploadLengthDeferred){if("function"==typeof e.options._onUploadUrlAvailable&&e.options._onUploadUrlAvailable(),r===a)return e._emitProgress(a,a),void e._emitSuccess();e._offset=r,e._performUpload()}else e._emitHttpError(t,i,"tus: invalid or missing length value")}})).catch((function(i){e._emitHttpError(t,null,"tus: failed to resume upload",i)}))}},{key:"_performUpload",value:function(){var e,t=this;this._aborted||(this.options.overridePatchMethod?(e=this._openRequest("POST",this.url)).setHeader("X-HTTP-Method-Override","PATCH"):e=this._openRequest("PATCH",this.url),e.setHeader("Upload-Offset",this._offset),this._addChunkToRequest(e).then((function(i){f(i.getStatus(),200)?t._handleUploadResponse(e,i):t._emitHttpError(e,i,"tus: unexpected response while uploading chunk")})).catch((function(i){t._aborted||t._emitHttpError(e,null,"tus: failed to upload chunk at offset "+t._offset,i)})))}},{key:"_addChunkToRequest",value:function(e){var t=this,i=this._offset,o=this._offset+this.options.chunkSize;return e.setProgressHandler((function(e){t._emitProgress(i+e,t._size)})),e.setHeader("Content-Type","application/offset+octet-stream"),(o===1/0||o>this._size)&&!this.options.uploadLengthDeferred&&(o=this._size),this._source.slice(i,o).then((function(i){var o=i.value,r=i.done;return t.options.uploadLengthDeferred&&r&&(t._size=t._offset+(o&&o.size?o.size:0),e.setHeader("Upload-Length",t._size)),null===o?t._sendRequest(e):(t._emitProgress(t._offset,t._size),t._sendRequest(e,o))}))}},{key:"_handleUploadResponse",value:function(e,t){var i=parseInt(t.getHeader("Upload-Offset"),10);if(isNaN(i))this._emitHttpError(e,t,"tus: invalid or missing offset value");else{if(this._emitProgress(i,this._size),this._emitChunkComplete(i-this._offset,i,this._size),(this._offset=i)==this._size)return this._emitSuccess(),void this._source.close();this._performUpload()}}},{key:"_openRequest",value:function(e,t){var i=g(e,t,this.options);return this._req=i}},{key:"_removeFromUrlStorage",value:function(){var e=this;this._urlStorageKey&&(this._urlStorage.removeUpload(this._urlStorageKey).catch((function(t){e._emitError(t)})),this._urlStorageKey=null)}},{key:"_saveUploadInUrlStorage",value:function(){var e,t=this;this.options.storeFingerprintForResuming&&this._fingerprint&&(e={size:this._size,metadata:this.options.metadata,creationTime:(new Date).toString()},this._parallelUploads?e.parallelUploadUrls=this._parallelUploadUrls:e.uploadUrl=this.url,this._urlStorage.addUpload(this._fingerprint,e).then((function(e){return t._urlStorageKey=e})).catch((function(e){t._emitError(e)})))}},{key:"_sendRequest",value:function(e,t){var i=this,o=1>>6)+fromCharCode(128|63&t):fromCharCode(224|t>>>12&15)+fromCharCode(128|t>>>6&63)+fromCharCode(128|63&t);var t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320);return fromCharCode(240|t>>>18&7)+fromCharCode(128|t>>>12&63)+fromCharCode(128|t>>>6&63)+fromCharCode(128|63&t)},re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,utob=function(e){return e.replace(re_utob,cb_utob)},cb_encode=function(e){var t=[0,2,1][e.length%3],i=e.charCodeAt(0)<<16|(1>>18),b64chars.charAt(i>>>12&63),2<=t?"=":b64chars.charAt(i>>>6&63),1<=t?"=":b64chars.charAt(63&i)].join("")},btoa=global.btoa?function(e){return global.btoa(e)}:function(e){return e.replace(/[\s\S]{1,3}/g,cb_encode)},_encode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(e){return(e.constructor===buffer.constructor?e:buffer.from(e)).toString("base64")}:function(e){return(e.constructor===buffer.constructor?e:new buffer(e)).toString("base64")}:function(e){return btoa(utob(e))},encode=function(e,t){return t?_encode(String(e)).replace(/[+\/]/g,(function(e){return"+"==e?"-":"_"})).replace(/=/g,""):_encode(String(e))},encodeURI=function(e){return encode(e,!0)},re_btou=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g"),cb_btou=function(e){switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return fromCharCode(55296+(t>>>10))+fromCharCode(56320+(1023&t));case 3:return fromCharCode((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return fromCharCode((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},btou=function(e){return e.replace(re_btou,cb_btou)},cb_decode=function(e){var t=e.length,i=t%4,o=(0>>16),fromCharCode(o>>>8&255),fromCharCode(255&o)];return r.length-=[0,0,2,1][i],r.join("")},atob=global.atob?function(e){return global.atob(e)}:function(e){return e.replace(/[\s\S]{1,4}/g,cb_decode)},_decode=buffer?buffer.from&&Uint8Array&&buffer.from!==Uint8Array.from?function(e){return(e.constructor===buffer.constructor?e:buffer.from(e,"base64")).toString()}:function(e){return(e.constructor===buffer.constructor?e:new buffer(e,"base64")).toString()}:function(e){return btou(atob(e))},decode=function(e){return _decode(String(e).replace(/[-_]/g,(function(e){return"-"==e?"+":"/"})).replace(/[^A-Za-z0-9\+\/]/g,""))},noConflict=function(){var e=global.Base64;return global.Base64=_Base64,e},noEnum;return global.Base64={VERSION:version,atob:atob,btoa:btoa,fromBase64:decode,toBase64:encode,utob:utob,encode:encode,encodeURI:encodeURI,btou:btou,decode:decode,noConflict:noConflict,__buffer__:buffer},"function"==typeof Object.defineProperty&&(noEnum=function(e){return{value:e,enumerable:!1,writable:!0,configurable:!0}},global.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",noEnum((function(){return decode(this)}))),Object.defineProperty(String.prototype,"toBase64",noEnum((function(e){return encode(this,e)}))),Object.defineProperty(String.prototype,"toBase64URI",noEnum((function(){return encode(this,!0)})))}),global.Meteor&&(Base64=global.Base64),void 0!==module&&module.exports&&(module.exports.Base64=global.Base64),{Base64:global.Base64}},"object"==typeof exports&&void 0!==module?module.exports=Hk(Gk):Hk(Gk)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],16:[function(e,t,i){var o=Object.prototype.hasOwnProperty;function r(e){return decodeURIComponent(e.replace(/\+/g," "))}i.stringify=function(e,t){t=t||"";var i=[];for(var r in"string"!=typeof t&&(t="?"),e)o.call(e,r)&&i.push(encodeURIComponent(r)+"="+encodeURIComponent(e[r]));return i.length?t+i.join("&"):""},i.parse=function(e){for(var t,i=/([^=?&]+)=?([^&]*)/g,o={};t=i.exec(e);){var a=r(t[1]),n=r(t[2]);a in o||(o[a]=n)}return o}},{}],17:[function(e,t,i){t.exports=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}},{}],18:[function(e,t,i){(function(i){var o=e("requires-port"),r=e("querystringify"),a=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,n=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,s=[["#","hash"],["?","query"],function(e){return e.replace("\\","/")},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],l={hash:1,query:1};function d(e){var t,o=i&&i.location||{},r={},a=typeof(e=e||o);if("blob:"===e.protocol)r=new u(unescape(e.pathname),{});else if("string"==a)for(t in r=new u(e,{}),l)delete r[t];else if("object"==a){for(t in e)t in l||(r[t]=e[t]);void 0===r.slashes&&(r.slashes=n.test(e.href))}return r}function c(e){var t=a.exec(e);return{protocol:t[1]?t[1].toLowerCase():"",slashes:!!t[2],rest:t[3]}}function u(e,t,i){if(!(this instanceof u))return new u(e,t,i);var a,n,l,h,p,m,f=s.slice(),g=typeof t,b=this,v=0;for("object"!=g&&"string"!=g&&(i=t,t=null),i&&"function"!=typeof i&&(i=r.parse),t=d(t),a=!(n=c(e||"")).protocol&&!n.slashes,b.slashes=n.slashes||a&&t.slashes,b.protocol=n.protocol||t.protocol||"",e=n.rest,n.slashes||(f[3]=[/(.*)/,"pathname"]);vgroup `} - `,e)}async _getCurrentKeypairResourcePolicy(){const e=globalThis.backendaiclient._config.accessKey;return(await globalThis.backendaiclient.keypair.info(e,["resource_policy"])).keypair.resource_policy}async _getVolumeInformation(){const e=await globalThis.backendaiclient.vfolder.list_hosts();this.volumeInfo=e.volume_info||{}}async _getAllowedVFolderHostsByCurrentUserInfo(){const[e,t]=await Promise.all([globalThis.backendaiclient.vfolder.list_hosts(),this._getCurrentKeypairResourcePolicy()]),i=globalThis.backendaiclient._config.domainName,o=globalThis.backendaiclient.current_group_id(),r=await globalThis.backendaiclient.storageproxy.getAllowedVFolderHostsByCurrentUserInfo(i,o,t),a=JSON.parse(r.domain.allowed_vfolder_hosts),n=JSON.parse(r.group.allowed_vfolder_hosts),s=JSON.parse(r.keypair_resource_policy.allowed_vfolder_hosts);this._unionedAllowedPermissionByVolume=Object.assign({},...e.allowed.map((e=>{return{[e]:(t=[a[e],n[e],s[e]],[...new Set([].concat(...t))])};var t}))),this.folderListGrid.clearCache()}_checkFolderSupportSizeQuota(e){var t;if(!e)return!1;const i=null===(t=this.volumeInfo[e])||void 0===t?void 0:t.backend;return!!this.quotaSupportStorageBackends.includes(i)}async refreshFolderList(){return this._triggerFolderListChanged(),this.folderListGrid&&this.folderListGrid.clearCache(),await this._refreshFolderList(!0,"refreshFolderList")}_refreshFolderList(e=!1,t="unknown"){var i;if(this._folderRefreshing||!this.active)return;if(Date.now()-this.lastQueryTime<1e3)return;this._folderRefreshing=!0,this.lastQueryTime=Date.now(),this.listCondition="loading",null===(i=this._listStatus)||void 0===i||i.show(),this._getMaxSize();let o=null;o=globalThis.backendaiclient.current_group_id(),globalThis.backendaiclient.vfolder.list(o).then((e=>{var t;const i=e.filter((e=>(this.enableInferenceWorkload||"general"!==this.storageType||e.name.startsWith(".")||"model"!=e.usage_mode)&&("general"!==this.storageType||e.name.startsWith(".")||"general"!=e.usage_mode)&&("data"!==this.storageType||e.name.startsWith(".")||"data"!=e.usage_mode)?"automount"===this.storageType&&e.name.startsWith(".")?e:"model"!==this.storageType||e.name.startsWith(".")||"model"!=e.usage_mode?void 0:e:e));this.folders=i,this._triggerFolderListChanged(),0==this.folders.length?this.listCondition="no-data":null===(t=this._listStatus)||void 0===t||t.hide(),this._folderRefreshing=!1})).catch((()=>{this._folderRefreshing=!1})),globalThis.backendaiclient.vfolder.list_hosts().then((t=>{this.active&&!e&&setTimeout((()=>{this._refreshFolderList(!1,"loop")}),3e4)}))}_refreshFolderUI(e){Object.prototype.hasOwnProperty.call(e.detail,"mini-ui")&&!0===e.detail["mini-ui"]?this.folderExplorerDialog.classList.add("mini_ui"):this.folderExplorerDialog.classList.remove("mini_ui")}async _checkImageSupported(){const e=(await globalThis.backendaiclient.image.list(["name","tag","registry","digest","installed","labels { key value }","resource_limits { key min max }"],!0,!0)).images;this.filebrowserSupportedImages=e.filter((e=>e.labels.find((e=>"ai.backend.service-ports"===e.key&&e.value.toLowerCase().includes("filebrowser"))))),this.systemRoleSupportedImages=e.filter((e=>e.labels.find((e=>"ai.backend.role"===e.key&&e.value.toLowerCase().includes("system")))))}async _viewStateChanged(e){await this.updateComplete,!1!==e&&(void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(async()=>{this.is_admin=globalThis.backendaiclient.is_admin,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.authenticated=!0,this._APIMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._maxFileUploadSize=globalThis.backendaiclient._config.maxFileUploadSize,this.directoryBasedUsage=globalThis.backendaiclient._config.directoryBasedUsage,this._getAllowedVFolderHostsByCurrentUserInfo(),this._checkImageSupported(),this._getVolumeInformation(),this._triggerFolderListChanged(),this._refreshFolderList(!1,"viewStatechanged")}),!0):(this.is_admin=globalThis.backendaiclient.is_admin,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.authenticated=!0,this._APIMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._maxFileUploadSize=globalThis.backendaiclient._config.maxFileUploadSize,this.directoryBasedUsage=globalThis.backendaiclient._config.directoryBasedUsage,this._getAllowedVFolderHostsByCurrentUserInfo(),this._checkImageSupported(),this._getVolumeInformation(),this._triggerFolderListChanged(),this._refreshFolderList(!1,"viewStatechanged")))}_folderExplorerDialog(){this.openDialog("folder-explorer-dialog")}_mkdirDialog(){this.mkdirNameInput.value="",this.openDialog("mkdir-dialog")}openDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).show()}closeDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).hide()}_indexFrom1(e){return e+1}_hasPermission(e,t){return!!e.permission.includes(t)||!(!e.permission.includes("w")||"r"!==t)}_getControlName(e){return e.target.closest("#controls").getAttribute("folder-name")}_getControlId(e){return e.target.closest("#controls").getAttribute("folder-id")}_getControlType(e){return e.target.closest("#controls").getAttribute("folder-type")}_infoFolder(e){const t=this._getControlName(e);globalThis.backendaiclient.vfolder.info(t).then((e=>{this.folderInfo=e,this.openDialog("info-folder-dialog")})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}_modifyFolderOptionDialog(e){globalThis.backendaiclient.vfolder.name=this._getControlName(e);globalThis.backendaiclient.vfolder.info(globalThis.backendaiclient.vfolder.name).then((e=>{this.folderInfo=e;const t=this.folderInfo.permission;let i=Object.keys(this.permissions).indexOf(t);i=i>0?i:0,this.updateFolderPermissionSelect.select(i),this.updateFolderCloneableSwitch&&(this.updateFolderCloneableSwitch.selected=this.folderInfo.cloneable),this.directoryBasedUsage&&this._checkFolderSupportSizeQuota(this.folderInfo.host)&&([this.quota.value,this.quota.unit]=globalThis.backendaiutils._humanReadableFileSize(this.folderInfo.max_size*this.quotaUnit.MiB).split(" "),this.modifyFolderQuotaInput.value=this.quota.value.toString(),this.modifyFolderQuotaUnitSelect.value="Bytes"==this.quota.unit?"MB":this.quota.unit),this.openDialog("modify-folder-dialog")})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}async _updateFolder(){var e;let t=!1,i=!1;const o={};if(this.updateFolderPermissionSelect){let t=this.updateFolderPermissionSelect.value;t=null!==(e=Object.keys(this.permissions).find((e=>this.permissions[e]===t)))&&void 0!==e?e:"",t&&this.folderInfo.permission!==t&&(o.permission=t)}this.updateFolderCloneableSwitch&&(i=this.updateFolderCloneableSwitch.selected,o.cloneable=i);const r=[];if(Object.keys(o).length>0){const e=globalThis.backendaiclient.vfolder.update_folder(o,globalThis.backendaiclient.vfolder.name);r.push(e)}if(this.directoryBasedUsage&&this._checkFolderSupportSizeQuota(this.folderInfo.host)){const e=this.modifyFolderQuotaInput.value?BigInt(Number(this.modifyFolderQuotaInput.value)*this.quotaUnit[this.modifyFolderQuotaUnitSelect.value]).toString():"0";if(this.quota.value!=Number(this.modifyFolderQuotaInput.value)||this.quota.unit!=this.modifyFolderQuotaUnitSelect.value){const t=globalThis.backendaiclient.vfolder.set_quota(this.folderInfo.host,this.folderInfo.id,e.toString());r.push(t)}}r.length>0&&await Promise.all(r).then((()=>{this.notification.text=get("data.folders.FolderUpdated"),this.notification.show(),this._refreshFolderList(!0,"updateFolder")})).catch((e=>{console.log(e),e&&e.message&&(t=!0,this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.show(!0,e))})),t||this.closeDialog("modify-folder-dialog")}async _updateFolderName(){globalThis.backendaiclient.vfolder.name=this.renameFolderName;const e=this.newFolderNameInput.value;if(this.newFolderNameInput.reportValidity(),e){if(!this.newFolderNameInput.checkValidity())return;try{await globalThis.backendaiclient.vfolder.rename(e),this.notification.text=get("data.folders.FolderRenamed"),this.notification.show(),this._refreshFolderList(!0,"updateFolder"),this.closeDialog("modify-folder-name-dialog")}catch(e){this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.show(!0,e)}}}_renameFolderDialog(e){this.renameFolderName=this._getControlName(e),this.newFolderNameInput.value="",this.openDialog("modify-folder-name-dialog")}async _deleteFolderDialog(e){this.deleteFolderName=this._getControlName(e),this.deleteFolderNameInput.value="",this.openDialog("delete-folder-dialog")}_deleteFolderWithCheck(){if(this.deleteFolderNameInput.value!==this.deleteFolderName)return this.notification.text=get("data.folders.FolderNameMismatched"),void this.notification.show();this.closeDialog("delete-folder-dialog"),this._deleteFolder(this.deleteFolderName)}_deleteFolder(e){globalThis.backendaiclient.vfolder.delete(e).then((async e=>{e.msg?(this.notification.text=get("data.folders.CannotDeleteFolder"),this.notification.show(!0)):(this.notification.text=get("data.folders.FolderDeleted"),this.notification.show(),await this.refreshFolderList(),this._triggerFolderListChanged())})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}_inferModel(e){const t=this._getControlName(e);this.sessionLauncher.customFolderMapping={},this.sessionLauncher.customFolderMapping[t]="mount",this.sessionLauncher._launchSessionDialog()}async _checkVfolderMounted(e=""){}_requestCloneFolder(e){}_leaveInvitedFolderDialog(e){this.leaveFolderName=this._getControlName(e),this.leaveFolderNameInput.value="",this.openDialog("leave-folder-dialog")}_leaveFolderWithCheck(){if(this.leaveFolderNameInput.value!==this.leaveFolderName)return this.notification.text=get("data.folders.FolderNameMismatched"),void this.notification.show();this.closeDialog("leave-folder-dialog"),this._leaveFolder(this.leaveFolderName)}_leaveFolder(e){globalThis.backendaiclient.vfolder.leave_invited(e).then((async e=>{this.notification.text=get("data.folders.FolderDisconnected"),this.notification.show(),await this.refreshFolderList(),this._triggerFolderListChanged()})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}async _getMaxSize(){const e=globalThis.backendaiclient._config.accessKey,t=(await globalThis.backendaiclient.keypair.info(e,["resource_policy"])).keypair.resource_policy,i=(await globalThis.backendaiclient.resourcePolicy.get(t,["max_vfolder_count","max_vfolder_size"])).keypair_resource_policy.max_vfolder_size;[this.maxSize.value,this.maxSize.unit]=globalThis.backendaiutils._humanReadableFileSize(i).split(" "),["Bytes","KB","MB"].includes(this.maxSize.unit)?(this.maxSize.value=this.maxSize.value<1?1:Math.round(this.maxSize.value),this.maxSize.unit="MB"):this.maxSize.value=Math.round(10*this.maxSize.value)/10}_triggerFolderListChanged(){const e=new CustomEvent("backend-ai-folder-list-changed");document.dispatchEvent(e)}_validateExistingFileName(){this.newFileNameInput.validityTransform=(e,t)=>{if(t.valid){const e=/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/]/gi;let t;return this.newFileNameInput.value===this.renameFileDialog.querySelector("#old-file-name").textContent?(this.newFileNameInput.validationMessage=get("data.EnterDifferentValue"),t=!1,{valid:t,customError:!t}):(t=!0,t=!e.test(this.newFileNameInput.value),t||(this.newFileNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot")),{valid:t,customError:!t})}return t.valueMissing?(this.newFileNameInput.validationMessage=get("data.FileandFoldernameRequired"),{valid:t.valid,customError:!t.valid}):(this.newFileNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:t.valid,customError:!t.valid})}}_validateFolderName(e=!1){var t;const i=e?this.newFolderNameInput:null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#add-folder-name");i.validityTransform=(t,o)=>{if(o.valid){let t;const o=/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/\s]/gi;if(e){if(i.value===this.renameFolderName)return i.validationMessage=get("data.EnterDifferentValue"),t=!1,{valid:t,customError:!t};t=!0}return t=!o.test(i.value),t||(i.validationMessage=get("data.Allowslettersnumbersand-_dot")),{valid:t,customError:!t}}return o.valueMissing?(i.validationMessage=get("data.FolderNameRequired"),{valid:o.valid,customError:!o.valid}):(i.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:o.valid,customError:!o.valid})}}async _clearExplorer(e=this.explorer.breadcrumb.join("/"),t=this.explorer.id,i=!1){const o=await globalThis.backendaiclient.vfolder.list_files(e,t);if(this.fileListGrid.selectedItems=[],this._APIMajorVersion<6)this.explorer.files=JSON.parse(o.files);else{const e=JSON.parse(o.files);e.forEach(((e,t)=>{let i="FILE";if(e.filename===o.items[t].name)i=o.items[t].type;else for(let t=0;t0&&this._isResourceEnough()),o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#filebrowser-img"),r=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#filebrowser-btn");if(o&&r){r.disabled=!i;const e=i?"":"apply-grayscale";o.setAttribute("class",e)}}_folderExplorer(e){const t=e.item.name,i=this._hasPermission(e.item,"w")||e.item.is_owner||"group"===e.item.type&&this.is_admin;this.vhost=e.item.host;const o={id:t,uuid:e.item.id,breadcrumb:["."]},r=new URLSearchParams;r.set("folder",t),window.history.replaceState({},"",`${location.pathname}?${r}`),this.isWritable=i,this.explorer=o,this._clearExplorer(o.breadcrumb.join("/"),o.id,!0)}_enqueueFolder(e){const t=e.target;t.setAttribute("disabled","true");const i=e.target.getAttribute("name");this.explorer.breadcrumb.push(i),this._clearExplorer().then((e=>{t.removeAttribute("disabled")}))}_gotoFolder(e){const t=e.target.getAttribute("dest");let i=this.explorer.breadcrumb;const o=i.indexOf(t);-1!==o&&(i=i.slice(0,o+1),this.explorer.breadcrumb=i,this._clearExplorer(i.join("/"),this.explorer.id,!1))}_mkdir(e){const t=this.mkdirNameInput.value,i=this.explorer;if(this.mkdirNameInput.reportValidity(),this.mkdirNameInput.checkValidity()){globalThis.backendaiclient.vfolder.mkdir([...i.breadcrumb,t].join("/"),i.id).catch((e=>{e&e.message?(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e)):e&&e.title&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.show(!0,e))})).then((e=>{this.closeDialog("mkdir-dialog"),this._clearExplorer()}))}}_isDir(e){return this._APIMajorVersion<6?e.mode.startsWith("d"):"DIRECTORY"===e.type}_addEventListenerDropZone(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#dropzone");t.addEventListener("dragleave",(()=>{t.style.display="none"})),this.folderExplorerDialog.addEventListener("dragover",(e=>(e.stopPropagation(),e.preventDefault(),!this.isWritable||(e.dataTransfer.dropEffect="copy",t.style.display="flex",!1)))),this.folderExplorerDialog.addEventListener("drop",(e=>{let i=!1;if(e.stopPropagation(),e.preventDefault(),t.style.display="none",this.isWritable){for(let t=0;t0&&i.size>this._maxFileUploadSize)return this.notification.text=get("data.explorer.FileUploadSizeLimit")+` (${globalThis.backendaiutils._humanReadableFileSize(this._maxFileUploadSize)})`,void this.notification.show();if(this.explorerFiles.find((e=>e.filename===i.name))){window.confirm(`${get("data.explorer.FileAlreadyExists")}\n${i.name}\n${get("data.explorer.DoYouWantToOverwrite")}`)&&(i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i))}else i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i)}else i||(this.filebrowserSupportedImages.length>0?(this.notification.text=get("data.explorer.ClickFilebrowserButton"),this.notification.show()):(this.notification.text=get("data.explorer.NoImagesSupportingFileBrowser"),this.notification.show())),i=!0;for(let e=0;e0&&r){const t=e.target.files[0];if(this.explorerFiles.find((e=>e.filename===this.getFolderName(t)))&&(s=window.confirm(`${get("data.explorer.FolderAlreadyExists")}\n${this.getFolderName(t)}\n${get("data.explorer.DoYouWantToOverwrite")}`),!s))return void(a.value="")}for(let t=0;t0&&i.size>this._maxFileUploadSize)return this.notification.text=get("data.explorer.FileUploadSizeLimit")+` (${globalThis.backendaiutils._humanReadableFileSize(this._maxFileUploadSize)})`,void this.notification.show();if(0!==i.size){if(this.explorerFiles.find((e=>e.filename===i.name))&&!s){window.confirm(`${get("data.explorer.FileAlreadyExists")}\n${i.name}\n${get("data.explorer.DoYouWantToOverwrite")}`)&&(i.id=o,i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i))}else i.id=o,i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i)}else n=!0}for(let e=0;e0&&(t=this.fileUploadQueue.shift(),this.fileUploadCount=this.fileUploadCount+1,t.start())}fileUpload(e){this._uploadFlag=!0,this.uploadFilesExist=this.uploadFiles.length>0;const t=this.explorer.breadcrumb.concat(e.webkitRelativePath||e.name).join("/");globalThis.backendaiclient.vfolder.create_upload_session(t,e,this.explorer.id).then((i=>{const o=(new Date).getTime(),r=new tus$1.Upload(e,{endpoint:i,retryDelays:[0,3e3,5e3,1e4,2e4],uploadUrl:i,chunkSize:15728640,metadata:{filename:t,filetype:e.type},onError:t=>{console.log("Failed because: "+t),this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],this.fileUploadCount=this.fileUploadCount-1,this.runFileUploadQueue()},onProgress:(t,i)=>{if(this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],!this._uploadFlag)return r.abort(),this.uploadFiles[this.uploadFiles.indexOf(e)].caption="Canceling...",this.uploadFiles=this.uploadFiles.slice(),void setTimeout((()=>{this.uploadFiles=[],this.uploadFilesExist=!1,this.fileUploadCount=this.fileUploadCount-1}),1e3);const a=(new Date).getTime(),n=(t/1048576/((a-o)/1e3)).toFixed(1)+"MB/s",s=Math.floor((i-t)/(t/(a-o)*1e3));let l=get("data.explorer.LessThan10Sec");if(s>=86400)l=get("data.explorer.MoreThanADay");else if(s>10){l=`${Math.floor(s/3600)}:${Math.floor(s%3600/60)}:${s%60}`}const d=(t/i*100).toFixed(1);this.uploadFiles[this.uploadFiles.indexOf(e)].progress=t/i,this.uploadFiles[this.uploadFiles.indexOf(e)].caption=`${d}% / Time left : ${l} / Speed : ${n}`,this.uploadFiles=this.uploadFiles.slice()},onSuccess:()=>{this._clearExplorer(),this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],this.uploadFiles[this.uploadFiles.indexOf(e)].complete=!0,this.uploadFiles=this.uploadFiles.slice(),setTimeout((()=>{this.uploadFiles.splice(this.uploadFiles.indexOf(e),1),this.uploadFilesExist=this.uploadFiles.length>0,this.uploadFiles=this.uploadFiles.slice(),this.fileUploadCount=this.fileUploadCount-1,this.runFileUploadQueue()}),1e3)}});this.runFileUploadQueue(r)}))}_cancelUpload(){this._uploadFlag=!1}_downloadFile(e,t=!1){const i=e.target.getAttribute("filename"),o=this.explorer.breadcrumb.concat(i).join("/");globalThis.backendaiclient.vfolder.request_download_token(o,this.explorer.id,t).then((e=>{const o=e.token;let r;if(r=this._APIMajorVersion<6?globalThis.backendaiclient.vfolder.get_download_url_with_token(o):`${e.url}?token=${e.token}&archive=${t}`,globalThis.iOSSafari)this.downloadURL=r,this.downloadFileDialog.show(),URL.revokeObjectURL(r);else{const e=document.createElement("a");e.style.display="none",e.addEventListener("click",(function(e){e.stopPropagation()})),e.href=r,e.download=i,document.body.appendChild(e),e.click(),document.body.removeChild(e),URL.revokeObjectURL(r)}}))}_compareFileExtension(){var e;const t=this.newFileNameInput.value,i=null!==(e=this.renameFileDialog.querySelector("#old-file-name").textContent)&&void 0!==e?e:"",o=/\.([0-9a-z]+)$/i,r=t.match(o),a=i.match(o);t.includes(".")&&r?this.newFileExtension=r[1].toLowerCase():this.newFileExtension="",i.includes(".")&&a?this.oldFileExtension=a[1].toLowerCase():this.oldFileExtension="",t?this.newFileExtension!==this.oldFileExtension?this.fileExtensionChangeDialog.show():this.oldFileExtension?this._keepFileExtension():this._renameFile():this._renameFile()}_keepFileExtension(){let e=this.newFileNameInput.value;e=this.newFileExtension?e.replace(new RegExp(this.newFileExtension+"$"),this.oldFileExtension):e+"."+this.oldFileExtension,this.newFileNameInput.value=e,this._renameFile()}_executeFileBrowser(){if(this._isResourceEnough())if(this.filebrowserSupportedImages.length>0){const e=localStorage.getItem("backendaiwebui.filebrowserNotification");null!=e&&"true"!==e||this.isWritable||this.fileBrowserNotificationDialog.show(),this._launchFileBrowserSession(),this._toggleFilebrowserButton()}else this.notification.text=get("data.explorer.NoImagesSupportingFileBrowser"),this.notification.show();else this.notification.text=get("data.explorer.NotEnoughResourceForFileBrowserSession"),this.notification.show()}_toggleShowFilebrowserNotification(e){const t=e.target;if(t){const e=(!t.checked).toString();localStorage.setItem("backendaiwebui.filebrowserNotification",e)}}async _launchFileBrowserSession(){let e;const t={},i=this.filebrowserSupportedImages.filter((e=>e.name.toLowerCase().includes("filebrowser")&&e.installed))[0],o=i.registry+"/"+i.name+":"+i.tag;t.mounts=[this.explorer.id],t.cpu=1,t.mem=this.minimumResource.mem+"g",t.domain=globalThis.backendaiclient._config.domainName,t.group_name=globalThis.backendaiclient.current_group;const r=await this.indicator.start("indeterminate");return globalThis.backendaiclient.get_resource_slots().then((e=>(r.set(20,get("data.explorer.ExecutingFileBrowser")),globalThis.backendaiclient.createIfNotExists(o,null,t,1e4,void 0)))).then((async t=>{const i=t.servicePorts;e={"session-uuid":t.sessionId,"session-name":t.sessionName,"access-key":"",runtime:"filebrowser",arguments:{"--root":"/home/work/"+this.explorer.id}},i.length>0&&i.filter((e=>"filebrowser"===e.name)).length>0&&globalThis.appLauncher.showLauncher(e),this.folderExplorerDialog.open&&this.closeDialog("folder-explorer-dialog"),r.end(1e3)})).catch((e=>{this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e),r.end(100)}))}_executeSSHProxyAgent(){var e,t;(null===(t=null===(e=this.volumeInfo[this.vhost])||void 0===e?void 0:e.sftp_scaling_groups)||void 0===t?void 0:t.length)>0?this.systemRoleSupportedImages.length>0?(this._launchSystemRoleSSHSession(),this._toggleSSHSessionButton()):(this.notification.text=get("data.explorer.NoImagesSupportingSystemSession"),this.notification.show()):(this.notification.text=get("data.explorer.SFTPSessionNotAvailable"),this.notification.show())}async _launchSystemRoleSSHSession(){var e;const t={},i=globalThis.backendaiclient._config.systemSSHImage,o=this.systemRoleSupportedImages.filter((e=>e.name.toLowerCase().includes("filebrowser")&&e.installed))[0],r=""!==i?i:o.registry+"/"+o.name+":"+o.tag;t.mounts=[this.explorer.id],t.cpu=1,t.mem="256m",t.domain=globalThis.backendaiclient._config.domainName,t.scaling_group=null===(e=this.volumeInfo[this.vhost])||void 0===e?void 0:e.sftp_scaling_groups[0],t.group_name=globalThis.backendaiclient.current_group;const a=await this.indicator.start("indeterminate");return(async()=>{try{await globalThis.backendaiclient.get_resource_slots(),a.set(50,get("data.explorer.StartingSSH/SFTPSession"));const e=await globalThis.backendaiclient.createIfNotExists(r,`sftp-${this.explorer.uuid}`,t,15e3,void 0);if("CANCELLED"===e.status)return this.notification.text=BackendAIPainKiller.relieve(get("data.explorer.NumberOfSFTPSessionsExceededTitle")),this.notification.detail=get("data.explorer.NumberOfSFTPSessionsExceededBody"),this.notification.show(!0,{title:get("data.explorer.NumberOfSFTPSessionsExceededTitle"),message:get("data.explorer.NumberOfSFTPSessionsExceededBody")}),void a.end(100);const i=await globalThis.backendaiclient.get_direct_access_info(e.sessionId),o=i.public_host.replace(/^https?:\/\//,""),n=i.sshd_ports,s=new CustomEvent("read-ssh-key-and-launch-ssh-dialog",{detail:{sessionUuid:e.sessionId,host:o,port:n}});document.dispatchEvent(s),a.end(100)}catch(e){this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e),a.end(100)}})()}_toggleSSHSessionButton(){var e,t;const i=this.systemRoleSupportedImages.length>0,o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#ssh-img"),r=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#ssh-btn");if(o&&r){r.disabled=!i;const e=i?"":"apply-grayscale";o.setAttribute("class",e)}}_openRenameFileDialog(e,t=!1){const i=e.target.getAttribute("filename");this.renameFileDialog.querySelector("#old-file-name").textContent=i,this.newFileNameInput.value=i,this.renameFileDialog.filename=i,this.renameFileDialog.show(),this.is_dir=t,this.newFileNameInput.addEventListener("focus",(e=>{const t=i.replace(/\.([0-9a-z]+)$/i,"").length;this.newFileNameInput.setSelectionRange(0,t)})),this.newFileNameInput.focus()}_renameFile(){const e=this.renameFileDialog.filename,t=this.explorer.breadcrumb.concat(e).join("/"),i=this.newFileNameInput.value;if(this.fileExtensionChangeDialog.hide(),this.newFileNameInput.reportValidity(),this.newFileNameInput.checkValidity()){if(e===i)return this.newFileNameInput.focus(),this.notification.text=get("data.folders.SameFileName"),void this.notification.show();globalThis.backendaiclient.vfolder.rename_file(t,i,this.explorer.id,this.is_dir).then((e=>{this.notification.text=get("data.folders.FileRenamed"),this.notification.show(),this._clearExplorer(),this.renameFileDialog.hide()})).catch((e=>{console.error(e),e&&e.message&&(this.notification.text=e.title,this.notification.detail=e.message,this.notification.show(!0,e))}))}}_openDeleteFileDialog(e){const t=e.target.getAttribute("filename");this.deleteFileDialog.filename=t,this.deleteFileDialog.files=[],this.deleteFileDialog.show()}_openDeleteMultipleFileDialog(e){this.deleteFileDialog.files=this.fileListGrid.selectedItems,this.deleteFileDialog.filename="",this.deleteFileDialog.show()}_deleteFileWithCheck(e){const t=this.deleteFileDialog.files;if(t.length>0){const e=[];t.forEach((t=>{const i=this.explorer.breadcrumb.concat(t.filename).join("/");e.push(i)}));globalThis.backendaiclient.vfolder.delete_files(e,!0,this.explorer.id).then((e=>{this.notification.text=1==t.length?get("data.folders.FileDeleted"):get("data.folders.MultipleFilesDeleted"),this.notification.show(),this._clearExplorer(),this.deleteFileDialog.hide()}))}else if(""!=this.deleteFileDialog.filename){const e=this.explorer.breadcrumb.concat(this.deleteFileDialog.filename).join("/");globalThis.backendaiclient.vfolder.delete_files([e],!0,this.explorer.id).then((e=>{this.notification.text=get("data.folders.FileDeleted"),this.notification.show(),this._clearExplorer(),this.deleteFileDialog.hide()}))}}_deleteFile(e){const t=e.target.getAttribute("filename"),i=this.explorer.breadcrumb.concat(t).join("/");globalThis.backendaiclient.vfolder.delete_files([i],!0,this.explorer.id).then((e=>{this.notification.text=get("data.folders.FileDeleted"),this.notification.show(),this._clearExplorer()}))}_isResourceEnough(){const e=new CustomEvent("backend-ai-calculate-current-resource");document.dispatchEvent(e);const t=globalThis.backendaioptions.get("current-resource");return!!(t&&(t.cpu="string"==typeof t.cpu?parseInt(t.cpu):t.cpu,t.cpu>=this.minimumResource.cpu&&t.mem>=this.minimumResource.mem))}_humanReadableTime(e){const t=new Date(1e3*e),i=t.getTimezoneOffset()/60,o=t.getHours();return t.setHours(o-i),t.toUTCString()}_isDownloadable(e){return!0}_initializeSharingFolderDialogLayout(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelectorAll("#share-folder-dialog mwc-textfield.share-email");t.length>1&&t.forEach((e=>{var t;"first-email"!==e.id&&(null===(t=e.parentNode)||void 0===t||t.removeChild(e))}))}_shareFolderDialog(e){this.selectedFolder=this._getControlName(e),this.selectedFolderType=this._getControlType(e),this._initializeSharingFolderDialogLayout(),this.openDialog("share-folder-dialog")}_modifyPermissionDialog(e){globalThis.backendaiclient.vfolder.list_invitees(e).then((e=>{this.invitees=e.shared,this.modifyPermissionDialog.updateComplete.then((()=>{this.openDialog("modify-permission-dialog")}))}))}_shareFolder(e){var t,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelectorAll("mwc-textfield.share-email"),r=Array.prototype.filter.call(o,(e=>e.isUiValid&&""!==e.value)).map((e=>e.value.trim())),a=(null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("mwc-radio[name=share-folder-permission][checked]")).value;if(0===r.length){this.notification.text=get("data.invitation.NoValidEmails"),this.notification.show(),this.shareFolderDialog.hide();for(const e of Array.from(o))e.value="";return}let n;n="user"===this.selectedFolderType?globalThis.backendaiclient.vfolder.invite(a,r,this.selectedFolder):globalThis.backendaiclient.vfolder.share(a,r,this.selectedFolder);const s=(e,t)=>e.filter((e=>!t.includes(e)));n.then((e=>{var t;let i;if("user"===this.selectedFolderType)if(e.invited_ids&&e.invited_ids.length>0){i=get("data.invitation.Invited");const t=s(r,e.invited_ids);t.length>0&&(i=get("data.invitation.FolderSharingNotAvailableToUser")+t.join(", "))}else i=get("data.invitation.NoOneWasInvited");else if(e.shared_emails&&e.shared_emails.length>0){i=get("data.invitation.Shared");const t=s(r,e.shared_emails);t.length>0&&(i=get("data.invitation.FolderSharingNotAvailableToUser")+t.join(", "))}else i=get("data.invitation.NoOneWasShared");this.notification.text=i,this.notification.show(),this.shareFolderDialog.hide();for(let e=o.length-1;e>0;e--){const i=o[e];null===(t=i.parentElement)||void 0===t||t.removeChild(i)}})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message),this.notification.show()}))}_validatePathName(){this.mkdirNameInput.validityTransform=(e,t)=>{if(t.valid){let e=/^([^`~!@#$%^&*()|+=?;:'",<>{}[\]\r\n/]{1,})+(\/[^`~!@#$%^&*()|+=?;:'",<>{}[\]\r\n/]{1,})*([/,\\]{0,1})$/gm.test(this.mkdirNameInput.value);return e&&"./"!==this.mkdirNameInput.value||(this.mkdirNameInput.validationMessage=get("data.explorer.ValueShouldBeStarted"),e=!1),{valid:e,customError:!e}}return t.valueMissing?(this.mkdirNameInput.validationMessage=get("data.explorer.ValueRequired"),{valid:t.valid,customError:!t.valid}):{valid:t.valid,customError:!t.valid}}}};__decorate([n({type:Number})],BackendAiStorageList.prototype,"_APIMajorVersion",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"storageType",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"folders",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"folderInfo",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"is_admin",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"enableStorageProxy",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"enableInferenceWorkload",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"authenticated",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"renameFolderName",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"deleteFolderName",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"leaveFolderName",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"explorer",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"explorerFiles",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"existingFile",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"invitees",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"selectedFolder",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"selectedFolderType",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"downloadURL",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"uploadFiles",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"currentUploadFile",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"fileUploadQueue",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"fileUploadCount",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"concurrentFileUploadLimit",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"vhost",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"vhosts",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"allowedGroups",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"indicator",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"notification",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"listCondition",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"allowed_folder_type",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"uploadFilesExist",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundIndexRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundTypeRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundFolderListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundControlFolderListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundControlFileListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundPermissionViewRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundOwnerRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundFileNameRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundCreatedTimeRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundPermissionRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundCloneableRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundQuotaRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundUploadListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundUploadProgressRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundInviteeInfoRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundIDRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundStatusRenderer",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"_uploadFlag",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"_folderRefreshing",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"lastQueryTime",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"isWritable",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"permissions",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"_maxFileUploadSize",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"selectAreaHeight",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"oldFileExtension",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"newFileExtension",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"is_dir",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"minimumResource",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"filebrowserSupportedImages",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"systemRoleSupportedImages",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"volumeInfo",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"quotaSupportStorageBackends",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"quotaUnit",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"maxSize",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"quota",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"directoryBasedUsage",void 0),__decorate([i("#loading-spinner")],BackendAiStorageList.prototype,"spinner",void 0),__decorate([i("#list-status")],BackendAiStorageList.prototype,"_listStatus",void 0),__decorate([i("#modify-folder-quota")],BackendAiStorageList.prototype,"modifyFolderQuotaInput",void 0),__decorate([i("#modify-folder-quota-unit")],BackendAiStorageList.prototype,"modifyFolderQuotaUnitSelect",void 0),__decorate([i("#file-list-grid")],BackendAiStorageList.prototype,"fileListGrid",void 0),__decorate([i("#folder-list-grid")],BackendAiStorageList.prototype,"folderListGrid",void 0),__decorate([i("#mkdir-name")],BackendAiStorageList.prototype,"mkdirNameInput",void 0),__decorate([i("#delete-folder-name")],BackendAiStorageList.prototype,"deleteFolderNameInput",void 0),__decorate([i("#new-folder-name")],BackendAiStorageList.prototype,"newFolderNameInput",void 0),__decorate([i("#new-file-name")],BackendAiStorageList.prototype,"newFileNameInput",void 0),__decorate([i("#leave-folder-name")],BackendAiStorageList.prototype,"leaveFolderNameInput",void 0),__decorate([i("#update-folder-permission")],BackendAiStorageList.prototype,"updateFolderPermissionSelect",void 0),__decorate([i("#update-folder-cloneable")],BackendAiStorageList.prototype,"updateFolderCloneableSwitch",void 0),__decorate([i("#rename-file-dialog")],BackendAiStorageList.prototype,"renameFileDialog",void 0),__decorate([i("#delete-file-dialog")],BackendAiStorageList.prototype,"deleteFileDialog",void 0),__decorate([i("#filebrowser-notification-dialog")],BackendAiStorageList.prototype,"fileBrowserNotificationDialog",void 0),__decorate([i("#file-extension-change-dialog")],BackendAiStorageList.prototype,"fileExtensionChangeDialog",void 0),__decorate([i("#folder-explorer-dialog")],BackendAiStorageList.prototype,"folderExplorerDialog",void 0),__decorate([i("#download-file-dialog")],BackendAiStorageList.prototype,"downloadFileDialog",void 0),__decorate([i("#modify-permission-dialog")],BackendAiStorageList.prototype,"modifyPermissionDialog",void 0),__decorate([i("#share-folder-dialog")],BackendAiStorageList.prototype,"shareFolderDialog",void 0),__decorate([i("#session-launcher")],BackendAiStorageList.prototype,"sessionLauncher",void 0),__decorate([t()],BackendAiStorageList.prototype,"_unionedAllowedPermissionByVolume",void 0),BackendAiStorageList=__decorate([e$2("backend-ai-storage-list")],BackendAiStorageList);let BackendAIData=class extends BackendAIPage{constructor(){super(...arguments),this.apiMajorVersion="",this.folderListFetchKey=new Date,this.is_admin=!1,this.enableStorageProxy=!1,this.enableInferenceWorkload=!1,this.authenticated=!1,this.vhost="",this.selectedVhost="",this.vhosts=[],this.usageModes=["General"],this.permissions=["Read-Write","Read-Only","Delete"],this.allowedGroups=[],this.allowed_folder_type=[],this.notification=Object(),this.folderLists=Object(),this._status="inactive",this.active=!1,this._vfolderInnatePermissionSupport=!1,this.storageInfo=Object(),this._activeTab="general",this._helpDescription="",this._helpDescriptionTitle="",this._helpDescriptionIcon="",this._helpDescriptionStorageProxyInfo=Object(),this.cloneFolderName="",this.quotaSupportStorageBackends=["xfs","weka","spectrumscale"],this.storageProxyInfo=Object(),this.folderType="user"}static get styles(){return[BackendAiStyles,IronFlex,IronFlexAlignment,IronPositioning,i$1` + `,e)}async _getCurrentKeypairResourcePolicy(){const e=globalThis.backendaiclient._config.accessKey;return(await globalThis.backendaiclient.keypair.info(e,["resource_policy"])).keypair.resource_policy}async _getVolumeInformation(){const e=await globalThis.backendaiclient.vfolder.list_hosts();this.volumeInfo=e.volume_info||{}}async _getAllowedVFolderHostsByCurrentUserInfo(){const[e,t]=await Promise.all([globalThis.backendaiclient.vfolder.list_hosts(),this._getCurrentKeypairResourcePolicy()]),i=globalThis.backendaiclient._config.domainName,o=globalThis.backendaiclient.current_group_id(),r=await globalThis.backendaiclient.storageproxy.getAllowedVFolderHostsByCurrentUserInfo(i,o,t),a=JSON.parse(r.domain.allowed_vfolder_hosts),n=JSON.parse(r.group.allowed_vfolder_hosts),s=JSON.parse(r.keypair_resource_policy.allowed_vfolder_hosts);this._unionedAllowedPermissionByVolume=Object.assign({},...e.allowed.map((e=>{return{[e]:(t=[a[e],n[e],s[e]],[...new Set([].concat(...t))])};var t}))),this.folderListGrid.clearCache()}_checkFolderSupportSizeQuota(e){var t;if(!e)return!1;const i=null===(t=this.volumeInfo[e])||void 0===t?void 0:t.backend;return!!this.quotaSupportStorageBackends.includes(i)}async refreshFolderList(){return this._triggerFolderListChanged(),this.folderListGrid&&this.folderListGrid.clearCache(),await this._refreshFolderList(!0,"refreshFolderList")}_refreshFolderList(e=!1,t="unknown"){var i;if(this._folderRefreshing||!this.active)return;if(Date.now()-this.lastQueryTime<1e3)return;this._folderRefreshing=!0,this.lastQueryTime=Date.now(),this.listCondition="loading",null===(i=this._listStatus)||void 0===i||i.show(),this._getMaxSize();let o=null;o=globalThis.backendaiclient.current_group_id(),globalThis.backendaiclient.vfolder.list(o).then((e=>{var t;const i=e.filter((e=>(this.enableInferenceWorkload||"general"!==this.storageType||e.name.startsWith(".")||"model"!=e.usage_mode)&&("general"!==this.storageType||e.name.startsWith(".")||"general"!=e.usage_mode)&&("data"!==this.storageType||e.name.startsWith(".")||"data"!=e.usage_mode)?"automount"===this.storageType&&e.name.startsWith(".")?e:"model"!==this.storageType||e.name.startsWith(".")||"model"!=e.usage_mode?void 0:e:e));this.folders=i,this._triggerFolderListChanged(),0==this.folders.length?this.listCondition="no-data":null===(t=this._listStatus)||void 0===t||t.hide(),this._folderRefreshing=!1})).catch((()=>{this._folderRefreshing=!1})),globalThis.backendaiclient.vfolder.list_hosts().then((t=>{this.active&&!e&&setTimeout((()=>{this._refreshFolderList(!1,"loop")}),3e4)}))}_refreshFolderUI(e){Object.prototype.hasOwnProperty.call(e.detail,"mini-ui")&&!0===e.detail["mini-ui"]?this.folderExplorerDialog.classList.add("mini_ui"):this.folderExplorerDialog.classList.remove("mini_ui")}async _checkImageSupported(){const e=(await globalThis.backendaiclient.image.list(["name","tag","registry","digest","installed","labels { key value }","resource_limits { key min max }"],!0,!0)).images;this.filebrowserSupportedImages=e.filter((e=>e.labels.find((e=>"ai.backend.service-ports"===e.key&&e.value.toLowerCase().includes("filebrowser"))))),this.systemRoleSupportedImages=e.filter((e=>e.labels.find((e=>"ai.backend.role"===e.key&&e.value.toLowerCase().includes("system")))))}async _viewStateChanged(e){await this.updateComplete,!1!==e&&(void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(async()=>{this.is_admin=globalThis.backendaiclient.is_admin,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.authenticated=!0,this._APIMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._maxFileUploadSize=globalThis.backendaiclient._config.maxFileUploadSize,this.directoryBasedUsage=globalThis.backendaiclient._config.directoryBasedUsage,this._getAllowedVFolderHostsByCurrentUserInfo(),this._checkImageSupported(),this._getVolumeInformation(),this._triggerFolderListChanged(),this._refreshFolderList(!1,"viewStatechanged")}),!0):(this.is_admin=globalThis.backendaiclient.is_admin,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.authenticated=!0,this._APIMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._maxFileUploadSize=globalThis.backendaiclient._config.maxFileUploadSize,this.directoryBasedUsage=globalThis.backendaiclient._config.directoryBasedUsage,this._getAllowedVFolderHostsByCurrentUserInfo(),this._checkImageSupported(),this._getVolumeInformation(),this._triggerFolderListChanged(),this._refreshFolderList(!1,"viewStatechanged")))}_folderExplorerDialog(){this.openDialog("folder-explorer-dialog")}_mkdirDialog(){this.mkdirNameInput.value="",this.openDialog("mkdir-dialog")}openDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).show()}closeDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).hide()}_indexFrom1(e){return e+1}_hasPermission(e,t){return!!e.permission.includes(t)||!(!e.permission.includes("w")||"r"!==t)}_getControlName(e){return e.target.closest("#controls").getAttribute("folder-name")}_getControlId(e){return e.target.closest("#controls").getAttribute("folder-id")}_getControlType(e){return e.target.closest("#controls").getAttribute("folder-type")}_infoFolder(e){const t=this._getControlName(e);globalThis.backendaiclient.vfolder.info(t).then((e=>{this.folderInfo=e,this.openDialog("info-folder-dialog")})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}_modifyFolderOptionDialog(e){globalThis.backendaiclient.vfolder.name=this._getControlName(e);globalThis.backendaiclient.vfolder.info(globalThis.backendaiclient.vfolder.name).then((e=>{this.folderInfo=e;const t=this.folderInfo.permission;let i=Object.keys(this.permissions).indexOf(t);i=i>0?i:0,this.updateFolderPermissionSelect.select(i),this.updateFolderCloneableSwitch&&(this.updateFolderCloneableSwitch.selected=this.folderInfo.cloneable),this.directoryBasedUsage&&this._checkFolderSupportSizeQuota(this.folderInfo.host)&&([this.quota.value,this.quota.unit]=globalThis.backendaiutils._humanReadableFileSize(this.folderInfo.max_size*this.quotaUnit.MiB).split(" "),this.modifyFolderQuotaInput.value=this.quota.value.toString(),this.modifyFolderQuotaUnitSelect.value="Bytes"==this.quota.unit?"MB":this.quota.unit),this.openDialog("modify-folder-dialog")})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}async _updateFolder(){var e;let t=!1,i=!1;const o={};if(this.updateFolderPermissionSelect){let t=this.updateFolderPermissionSelect.value;t=null!==(e=Object.keys(this.permissions).find((e=>this.permissions[e]===t)))&&void 0!==e?e:"",t&&this.folderInfo.permission!==t&&(o.permission=t)}this.updateFolderCloneableSwitch&&(i=this.updateFolderCloneableSwitch.selected,o.cloneable=i);const r=[];if(Object.keys(o).length>0){const e=globalThis.backendaiclient.vfolder.update_folder(o,globalThis.backendaiclient.vfolder.name);r.push(e)}if(this.directoryBasedUsage&&this._checkFolderSupportSizeQuota(this.folderInfo.host)){const e=this.modifyFolderQuotaInput.value?BigInt(Number(this.modifyFolderQuotaInput.value)*this.quotaUnit[this.modifyFolderQuotaUnitSelect.value]).toString():"0";if(this.quota.value!=Number(this.modifyFolderQuotaInput.value)||this.quota.unit!=this.modifyFolderQuotaUnitSelect.value){const t=globalThis.backendaiclient.vfolder.set_quota(this.folderInfo.host,this.folderInfo.id,e.toString());r.push(t)}}r.length>0&&await Promise.all(r).then((()=>{this.notification.text=get("data.folders.FolderUpdated"),this.notification.show(),this._refreshFolderList(!0,"updateFolder")})).catch((e=>{console.log(e),e&&e.message&&(t=!0,this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.show(!0,e))})),t||this.closeDialog("modify-folder-dialog")}async _updateFolderName(){globalThis.backendaiclient.vfolder.name=this.renameFolderName;const e=this.newFolderNameInput.value;if(this.newFolderNameInput.reportValidity(),e){if(!this.newFolderNameInput.checkValidity())return;try{await globalThis.backendaiclient.vfolder.rename(e),this.notification.text=get("data.folders.FolderRenamed"),this.notification.show(),this._refreshFolderList(!0,"updateFolder"),this.closeDialog("modify-folder-name-dialog")}catch(e){this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.show(!0,e)}}}_renameFolderDialog(e){this.renameFolderName=this._getControlName(e),this.newFolderNameInput.value="",this.openDialog("modify-folder-name-dialog")}async _deleteFolderDialog(e){this.deleteFolderName=this._getControlName(e),this.deleteFolderNameInput.value="",this.openDialog("delete-folder-dialog")}_deleteFolderWithCheck(){if(this.deleteFolderNameInput.value!==this.deleteFolderName)return this.notification.text=get("data.folders.FolderNameMismatched"),void this.notification.show();this.closeDialog("delete-folder-dialog"),this._deleteFolder(this.deleteFolderName)}_deleteFolder(e){globalThis.backendaiclient.vfolder.delete(e).then((async e=>{e.msg?(this.notification.text=get("data.folders.CannotDeleteFolder"),this.notification.show(!0)):(this.notification.text=get("data.folders.FolderDeleted"),this.notification.show(),await this.refreshFolderList(),this._triggerFolderListChanged())})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}_inferModel(e){const t=this._getControlName(e);this.sessionLauncher.customFolderMapping={},this.sessionLauncher.customFolderMapping[t]="mount",this.sessionLauncher._launchSessionDialog()}async _checkVfolderMounted(e=""){}_requestCloneFolder(e){}_leaveInvitedFolderDialog(e){this.leaveFolderName=this._getControlName(e),this.leaveFolderNameInput.value="",this.openDialog("leave-folder-dialog")}_leaveFolderWithCheck(){if(this.leaveFolderNameInput.value!==this.leaveFolderName)return this.notification.text=get("data.folders.FolderNameMismatched"),void this.notification.show();this.closeDialog("leave-folder-dialog"),this._leaveFolder(this.leaveFolderName)}_leaveFolder(e){globalThis.backendaiclient.vfolder.leave_invited(e).then((async e=>{this.notification.text=get("data.folders.FolderDisconnected"),this.notification.show(),await this.refreshFolderList(),this._triggerFolderListChanged()})).catch((e=>{console.log(e),e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e))}))}async _getMaxSize(){const e=globalThis.backendaiclient._config.accessKey,t=(await globalThis.backendaiclient.keypair.info(e,["resource_policy"])).keypair.resource_policy,i=(await globalThis.backendaiclient.resourcePolicy.get(t,["max_vfolder_count","max_vfolder_size"])).keypair_resource_policy.max_vfolder_size;[this.maxSize.value,this.maxSize.unit]=globalThis.backendaiutils._humanReadableFileSize(i).split(" "),["Bytes","KB","MB"].includes(this.maxSize.unit)?(this.maxSize.value=this.maxSize.value<1?1:Math.round(this.maxSize.value),this.maxSize.unit="MB"):this.maxSize.value=Math.round(10*this.maxSize.value)/10}_triggerFolderListChanged(){const e=new CustomEvent("backend-ai-folder-list-changed");document.dispatchEvent(e)}_validateExistingFileName(){this.newFileNameInput.validityTransform=(e,t)=>{if(t.valid){const e=/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/]/gi;let t;return this.newFileNameInput.value===this.renameFileDialog.querySelector("#old-file-name").textContent?(this.newFileNameInput.validationMessage=get("data.EnterDifferentValue"),t=!1,{valid:t,customError:!t}):(t=!0,t=!e.test(this.newFileNameInput.value),t||(this.newFileNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot")),{valid:t,customError:!t})}return t.valueMissing?(this.newFileNameInput.validationMessage=get("data.FileandFoldernameRequired"),{valid:t.valid,customError:!t.valid}):(this.newFileNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:t.valid,customError:!t.valid})}}_validateFolderName(e=!1){var t;const i=e?this.newFolderNameInput:null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#add-folder-name");i.validityTransform=(t,o)=>{if(o.valid){let t;const o=/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/\s]/gi;if(e){if(i.value===this.renameFolderName)return i.validationMessage=get("data.EnterDifferentValue"),t=!1,{valid:t,customError:!t};t=!0}return t=!o.test(i.value),t||(i.validationMessage=get("data.Allowslettersnumbersand-_dot")),{valid:t,customError:!t}}return o.valueMissing?(i.validationMessage=get("data.FolderNameRequired"),{valid:o.valid,customError:!o.valid}):(i.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:o.valid,customError:!o.valid})}}async _clearExplorer(e=this.explorer.breadcrumb.join("/"),t=this.explorer.id,i=!1){const o=await globalThis.backendaiclient.vfolder.list_files(e,t);if(this.fileListGrid.selectedItems=[],this._APIMajorVersion<6)this.explorer.files=JSON.parse(o.files);else{const e=JSON.parse(o.files);e.forEach(((e,t)=>{let i="FILE";if(e.filename===o.items[t].name)i=o.items[t].type;else for(let t=0;t0&&this._isResourceEnough()),o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#filebrowser-img"),r=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#filebrowser-btn");if(o&&r){r.disabled=!i;const e=i?"":"apply-grayscale";o.setAttribute("class",e)}}_folderExplorer(e){const t=e.item.name,i=this._hasPermission(e.item,"w")||e.item.is_owner||"group"===e.item.type&&this.is_admin;this.vhost=e.item.host;const o={id:t,uuid:e.item.id,breadcrumb:["."]},r=new URLSearchParams;r.set("folder",t),window.history.replaceState({},"",`${location.pathname}?${r}`),this.isWritable=i,this.explorer=o,this._clearExplorer(o.breadcrumb.join("/"),o.id,!0)}_enqueueFolder(e){const t=e.target;t.setAttribute("disabled","true");const i=e.target.getAttribute("name");this.explorer.breadcrumb.push(i),this._clearExplorer().then((e=>{t.removeAttribute("disabled")}))}_gotoFolder(e){const t=e.target.getAttribute("dest");let i=this.explorer.breadcrumb;const o=i.indexOf(t);-1!==o&&(i=i.slice(0,o+1),this.explorer.breadcrumb=i,this._clearExplorer(i.join("/"),this.explorer.id,!1))}_mkdir(e){const t=this.mkdirNameInput.value,i=this.explorer;if(this.mkdirNameInput.reportValidity(),this.mkdirNameInput.checkValidity()){globalThis.backendaiclient.vfolder.mkdir([...i.breadcrumb,t].join("/"),i.id).catch((e=>{e&e.message?(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e)):e&&e.title&&(this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.show(!0,e))})).then((e=>{this.closeDialog("mkdir-dialog"),this._clearExplorer()}))}}_isDir(e){return this._APIMajorVersion<6?e.mode.startsWith("d"):"DIRECTORY"===e.type}_addEventListenerDropZone(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#dropzone");t.addEventListener("dragleave",(()=>{t.style.display="none"})),this.folderExplorerDialog.addEventListener("dragover",(e=>(e.stopPropagation(),e.preventDefault(),!this.isWritable||(e.dataTransfer.dropEffect="copy",t.style.display="flex",!1)))),this.folderExplorerDialog.addEventListener("drop",(e=>{let i=!1;if(e.stopPropagation(),e.preventDefault(),t.style.display="none",this.isWritable){for(let t=0;t0&&i.size>this._maxFileUploadSize)return this.notification.text=get("data.explorer.FileUploadSizeLimit")+` (${globalThis.backendaiutils._humanReadableFileSize(this._maxFileUploadSize)})`,void this.notification.show();if(this.explorerFiles.find((e=>e.filename===i.name))){window.confirm(`${get("data.explorer.FileAlreadyExists")}\n${i.name}\n${get("data.explorer.DoYouWantToOverwrite")}`)&&(i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i))}else i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i)}else i||(this.filebrowserSupportedImages.length>0?(this.notification.text=get("data.explorer.ClickFilebrowserButton"),this.notification.show()):(this.notification.text=get("data.explorer.NoImagesSupportingFileBrowser"),this.notification.show())),i=!0;for(let e=0;e0&&r){const t=e.target.files[0];if(this.explorerFiles.find((e=>e.filename===this.getFolderName(t)))&&(s=window.confirm(`${get("data.explorer.FolderAlreadyExists")}\n${this.getFolderName(t)}\n${get("data.explorer.DoYouWantToOverwrite")}`),!s))return void(a.value="")}for(let t=0;t0&&i.size>this._maxFileUploadSize)return this.notification.text=get("data.explorer.FileUploadSizeLimit")+` (${globalThis.backendaiutils._humanReadableFileSize(this._maxFileUploadSize)})`,void this.notification.show();if(0!==i.size){if(this.explorerFiles.find((e=>e.filename===i.name))&&!s){window.confirm(`${get("data.explorer.FileAlreadyExists")}\n${i.name}\n${get("data.explorer.DoYouWantToOverwrite")}`)&&(i.id=o,i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i))}else i.id=o,i.progress=0,i.caption="",i.error=!1,i.complete=!1,this.uploadFiles.push(i)}else n=!0}for(let e=0;e0&&(t=this.fileUploadQueue.shift(),this.fileUploadCount=this.fileUploadCount+1,t.start())}fileUpload(e){this._uploadFlag=!0,this.uploadFilesExist=this.uploadFiles.length>0;const t=this.explorer.breadcrumb.concat(e.webkitRelativePath||e.name).join("/");globalThis.backendaiclient.vfolder.create_upload_session(t,e,this.explorer.id).then((i=>{const o=(new Date).getTime(),r=new tus$1.Upload(e,{endpoint:i,retryDelays:[0,3e3,5e3,1e4,2e4],uploadUrl:i,chunkSize:15728640,metadata:{filename:t,filetype:e.type},onError:t=>{console.log("Failed because: "+t),this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],this.fileUploadCount=this.fileUploadCount-1,this.runFileUploadQueue()},onProgress:(t,i)=>{if(this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],!this._uploadFlag)return r.abort(),this.uploadFiles[this.uploadFiles.indexOf(e)].caption="Canceling...",this.uploadFiles=this.uploadFiles.slice(),void setTimeout((()=>{this.uploadFiles=[],this.uploadFilesExist=!1,this.fileUploadCount=this.fileUploadCount-1}),1e3);const a=(new Date).getTime(),n=(t/1048576/((a-o)/1e3)).toFixed(1)+"MB/s",s=Math.floor((i-t)/(t/(a-o)*1e3));let l=get("data.explorer.LessThan10Sec");if(s>=86400)l=get("data.explorer.MoreThanADay");else if(s>10){l=`${Math.floor(s/3600)}:${Math.floor(s%3600/60)}:${s%60}`}const d=(t/i*100).toFixed(1);this.uploadFiles[this.uploadFiles.indexOf(e)].progress=t/i,this.uploadFiles[this.uploadFiles.indexOf(e)].caption=`${d}% / Time left : ${l} / Speed : ${n}`,this.uploadFiles=this.uploadFiles.slice()},onSuccess:()=>{this._clearExplorer(),this.currentUploadFile=this.uploadFiles[this.uploadFiles.indexOf(e)],this.uploadFiles[this.uploadFiles.indexOf(e)].complete=!0,this.uploadFiles=this.uploadFiles.slice(),setTimeout((()=>{this.uploadFiles.splice(this.uploadFiles.indexOf(e),1),this.uploadFilesExist=this.uploadFiles.length>0,this.uploadFiles=this.uploadFiles.slice(),this.fileUploadCount=this.fileUploadCount-1,this.runFileUploadQueue()}),1e3)}});this.runFileUploadQueue(r)}))}_cancelUpload(){this._uploadFlag=!1}_downloadFile(e,t=!1){const i=e.target.getAttribute("filename"),o=this.explorer.breadcrumb.concat(i).join("/");globalThis.backendaiclient.vfolder.request_download_token(o,this.explorer.id,t).then((e=>{const o=e.token;let r;if(r=this._APIMajorVersion<6?globalThis.backendaiclient.vfolder.get_download_url_with_token(o):`${e.url}?token=${e.token}&archive=${t}`,globalThis.iOSSafari)this.downloadURL=r,this.downloadFileDialog.show(),URL.revokeObjectURL(r);else{const e=document.createElement("a");e.style.display="none",e.addEventListener("click",(function(e){e.stopPropagation()})),e.href=r,e.download=i,document.body.appendChild(e),e.click(),document.body.removeChild(e),URL.revokeObjectURL(r)}}))}_compareFileExtension(){var e;const t=this.newFileNameInput.value,i=null!==(e=this.renameFileDialog.querySelector("#old-file-name").textContent)&&void 0!==e?e:"",o=/\.([0-9a-z]+)$/i,r=t.match(o),a=i.match(o);t.includes(".")&&r?this.newFileExtension=r[1].toLowerCase():this.newFileExtension="",i.includes(".")&&a?this.oldFileExtension=a[1].toLowerCase():this.oldFileExtension="",t?this.newFileExtension!==this.oldFileExtension?this.fileExtensionChangeDialog.show():this.oldFileExtension?this._keepFileExtension():this._renameFile():this._renameFile()}_keepFileExtension(){let e=this.newFileNameInput.value;e=this.newFileExtension?e.replace(new RegExp(this.newFileExtension+"$"),this.oldFileExtension):e+"."+this.oldFileExtension,this.newFileNameInput.value=e,this._renameFile()}_executeFileBrowser(){if(this._isResourceEnough())if(this.filebrowserSupportedImages.length>0){const e=localStorage.getItem("backendaiwebui.filebrowserNotification");null!=e&&"true"!==e||this.isWritable||this.fileBrowserNotificationDialog.show(),this._launchFileBrowserSession(),this._toggleFilebrowserButton()}else this.notification.text=get("data.explorer.NoImagesSupportingFileBrowser"),this.notification.show();else this.notification.text=get("data.explorer.NotEnoughResourceForFileBrowserSession"),this.notification.show()}_toggleShowFilebrowserNotification(e){const t=e.target;if(t){const e=(!t.checked).toString();localStorage.setItem("backendaiwebui.filebrowserNotification",e)}}async _launchFileBrowserSession(){let e;const t={},i=this.filebrowserSupportedImages.filter((e=>e.name.toLowerCase().includes("filebrowser")&&e.installed))[0],o=i.registry+"/"+i.name+":"+i.tag;t.mounts=[this.explorer.id],t.cpu=1,t.mem=this.minimumResource.mem+"g",t.domain=globalThis.backendaiclient._config.domainName,t.group_name=globalThis.backendaiclient.current_group;const r=await this.indicator.start("indeterminate");return globalThis.backendaiclient.get_resource_slots().then((e=>(r.set(20,get("data.explorer.ExecutingFileBrowser")),globalThis.backendaiclient.createIfNotExists(o,null,t,1e4,void 0)))).then((async t=>{const i=t.servicePorts;e={"session-uuid":t.sessionId,"session-name":t.sessionName,"access-key":"",runtime:"filebrowser",arguments:{"--root":"/home/work/"+this.explorer.id}},i.length>0&&i.filter((e=>"filebrowser"===e.name)).length>0&&globalThis.appLauncher.showLauncher(e),this.folderExplorerDialog.open&&this.closeDialog("folder-explorer-dialog"),r.end(1e3)})).catch((e=>{this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e),r.end(100)}))}_executeSSHProxyAgent(){var e,t;(null===(t=null===(e=this.volumeInfo[this.vhost])||void 0===e?void 0:e.sftp_scaling_groups)||void 0===t?void 0:t.length)>0?this.systemRoleSupportedImages.length>0?(this._launchSystemRoleSSHSession(),this._toggleSSHSessionButton()):(this.notification.text=get("data.explorer.NoImagesSupportingSystemSession"),this.notification.show()):(this.notification.text=get("data.explorer.SFTPSessionNotAvailable"),this.notification.show())}async _launchSystemRoleSSHSession(){var e;const t={},i=globalThis.backendaiclient._config.systemSSHImage,o=this.systemRoleSupportedImages.filter((e=>e.name.toLowerCase().includes("sftp-upload")&&e.installed))[0],r=""!==i?i:o.registry+"/"+o.name+":"+o.tag;t.mounts=[this.explorer.id],t.cpu=1,t.mem="256m",t.domain=globalThis.backendaiclient._config.domainName,t.scaling_group=null===(e=this.volumeInfo[this.vhost])||void 0===e?void 0:e.sftp_scaling_groups[0],t.group_name=globalThis.backendaiclient.current_group;const a=await this.indicator.start("indeterminate");return(async()=>{try{await globalThis.backendaiclient.get_resource_slots(),a.set(50,get("data.explorer.StartingSSH/SFTPSession"));const e=await globalThis.backendaiclient.createIfNotExists(r,`sftp-${this.explorer.uuid}`,t,15e3,void 0);if("CANCELLED"===e.status)return this.notification.text=BackendAIPainKiller.relieve(get("data.explorer.NumberOfSFTPSessionsExceededTitle")),this.notification.detail=get("data.explorer.NumberOfSFTPSessionsExceededBody"),this.notification.show(!0,{title:get("data.explorer.NumberOfSFTPSessionsExceededTitle"),message:get("data.explorer.NumberOfSFTPSessionsExceededBody")}),void a.end(100);const i=await globalThis.backendaiclient.get_direct_access_info(e.sessionId),o=i.public_host.replace(/^https?:\/\//,""),n=i.sshd_ports,s=new CustomEvent("read-ssh-key-and-launch-ssh-dialog",{detail:{sessionUuid:e.sessionId,host:o,port:n}});document.dispatchEvent(s),a.end(100)}catch(e){this.notification.text=BackendAIPainKiller.relieve(e.title),this.notification.detail=e.message,this.notification.show(!0,e),a.end(100)}})()}_toggleSSHSessionButton(){var e,t;const i=this.systemRoleSupportedImages.length>0,o=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#ssh-img"),r=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#ssh-btn");if(o&&r){r.disabled=!i;const e=i?"":"apply-grayscale";o.setAttribute("class",e)}}_openRenameFileDialog(e,t=!1){const i=e.target.getAttribute("filename");this.renameFileDialog.querySelector("#old-file-name").textContent=i,this.newFileNameInput.value=i,this.renameFileDialog.filename=i,this.renameFileDialog.show(),this.is_dir=t,this.newFileNameInput.addEventListener("focus",(e=>{const t=i.replace(/\.([0-9a-z]+)$/i,"").length;this.newFileNameInput.setSelectionRange(0,t)})),this.newFileNameInput.focus()}_renameFile(){const e=this.renameFileDialog.filename,t=this.explorer.breadcrumb.concat(e).join("/"),i=this.newFileNameInput.value;if(this.fileExtensionChangeDialog.hide(),this.newFileNameInput.reportValidity(),this.newFileNameInput.checkValidity()){if(e===i)return this.newFileNameInput.focus(),this.notification.text=get("data.folders.SameFileName"),void this.notification.show();globalThis.backendaiclient.vfolder.rename_file(t,i,this.explorer.id,this.is_dir).then((e=>{this.notification.text=get("data.folders.FileRenamed"),this.notification.show(),this._clearExplorer(),this.renameFileDialog.hide()})).catch((e=>{console.error(e),e&&e.message&&(this.notification.text=e.title,this.notification.detail=e.message,this.notification.show(!0,e))}))}}_openDeleteFileDialog(e){const t=e.target.getAttribute("filename");this.deleteFileDialog.filename=t,this.deleteFileDialog.files=[],this.deleteFileDialog.show()}_openDeleteMultipleFileDialog(e){this.deleteFileDialog.files=this.fileListGrid.selectedItems,this.deleteFileDialog.filename="",this.deleteFileDialog.show()}_deleteFileWithCheck(e){const t=this.deleteFileDialog.files;if(t.length>0){const e=[];t.forEach((t=>{const i=this.explorer.breadcrumb.concat(t.filename).join("/");e.push(i)}));globalThis.backendaiclient.vfolder.delete_files(e,!0,this.explorer.id).then((e=>{this.notification.text=1==t.length?get("data.folders.FileDeleted"):get("data.folders.MultipleFilesDeleted"),this.notification.show(),this._clearExplorer(),this.deleteFileDialog.hide()}))}else if(""!=this.deleteFileDialog.filename){const e=this.explorer.breadcrumb.concat(this.deleteFileDialog.filename).join("/");globalThis.backendaiclient.vfolder.delete_files([e],!0,this.explorer.id).then((e=>{this.notification.text=get("data.folders.FileDeleted"),this.notification.show(),this._clearExplorer(),this.deleteFileDialog.hide()}))}}_deleteFile(e){const t=e.target.getAttribute("filename"),i=this.explorer.breadcrumb.concat(t).join("/");globalThis.backendaiclient.vfolder.delete_files([i],!0,this.explorer.id).then((e=>{this.notification.text=get("data.folders.FileDeleted"),this.notification.show(),this._clearExplorer()}))}_isResourceEnough(){const e=new CustomEvent("backend-ai-calculate-current-resource");document.dispatchEvent(e);const t=globalThis.backendaioptions.get("current-resource");return!!(t&&(t.cpu="string"==typeof t.cpu?parseInt(t.cpu):t.cpu,t.cpu>=this.minimumResource.cpu&&t.mem>=this.minimumResource.mem))}_humanReadableTime(e){const t=new Date(1e3*e),i=t.getTimezoneOffset()/60,o=t.getHours();return t.setHours(o-i),t.toUTCString()}_isDownloadable(e){return!0}_initializeSharingFolderDialogLayout(){var e;const t=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelectorAll("#share-folder-dialog mwc-textfield.share-email");t.length>1&&t.forEach((e=>{var t;"first-email"!==e.id&&(null===(t=e.parentNode)||void 0===t||t.removeChild(e))}))}_shareFolderDialog(e){this.selectedFolder=this._getControlName(e),this.selectedFolderType=this._getControlType(e),this._initializeSharingFolderDialogLayout(),this.openDialog("share-folder-dialog")}_modifyPermissionDialog(e){globalThis.backendaiclient.vfolder.list_invitees(e).then((e=>{this.invitees=e.shared,this.modifyPermissionDialog.updateComplete.then((()=>{this.openDialog("modify-permission-dialog")}))}))}_shareFolder(e){var t,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelectorAll("mwc-textfield.share-email"),r=Array.prototype.filter.call(o,(e=>e.isUiValid&&""!==e.value)).map((e=>e.value.trim())),a=(null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("mwc-radio[name=share-folder-permission][checked]")).value;if(0===r.length){this.notification.text=get("data.invitation.NoValidEmails"),this.notification.show(),this.shareFolderDialog.hide();for(const e of Array.from(o))e.value="";return}let n;n="user"===this.selectedFolderType?globalThis.backendaiclient.vfolder.invite(a,r,this.selectedFolder):globalThis.backendaiclient.vfolder.share(a,r,this.selectedFolder);const s=(e,t)=>e.filter((e=>!t.includes(e)));n.then((e=>{var t;let i;if("user"===this.selectedFolderType)if(e.invited_ids&&e.invited_ids.length>0){i=get("data.invitation.Invited");const t=s(r,e.invited_ids);t.length>0&&(i=get("data.invitation.FolderSharingNotAvailableToUser")+t.join(", "))}else i=get("data.invitation.NoOneWasInvited");else if(e.shared_emails&&e.shared_emails.length>0){i=get("data.invitation.Shared");const t=s(r,e.shared_emails);t.length>0&&(i=get("data.invitation.FolderSharingNotAvailableToUser")+t.join(", "))}else i=get("data.invitation.NoOneWasShared");this.notification.text=i,this.notification.show(),this.shareFolderDialog.hide();for(let e=o.length-1;e>0;e--){const i=o[e];null===(t=i.parentElement)||void 0===t||t.removeChild(i)}})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message),this.notification.show()}))}_validatePathName(){this.mkdirNameInput.validityTransform=(e,t)=>{if(t.valid){let e=/^([^`~!@#$%^&*()|+=?;:'",<>{}[\]\r\n/]{1,})+(\/[^`~!@#$%^&*()|+=?;:'",<>{}[\]\r\n/]{1,})*([/,\\]{0,1})$/gm.test(this.mkdirNameInput.value);return e&&"./"!==this.mkdirNameInput.value||(this.mkdirNameInput.validationMessage=get("data.explorer.ValueShouldBeStarted"),e=!1),{valid:e,customError:!e}}return t.valueMissing?(this.mkdirNameInput.validationMessage=get("data.explorer.ValueRequired"),{valid:t.valid,customError:!t.valid}):{valid:t.valid,customError:!t.valid}}}};__decorate([n({type:Number})],BackendAiStorageList.prototype,"_APIMajorVersion",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"storageType",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"folders",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"folderInfo",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"is_admin",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"enableStorageProxy",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"enableInferenceWorkload",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"authenticated",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"renameFolderName",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"deleteFolderName",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"leaveFolderName",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"explorer",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"explorerFiles",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"existingFile",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"invitees",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"selectedFolder",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"selectedFolderType",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"downloadURL",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"uploadFiles",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"currentUploadFile",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"fileUploadQueue",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"fileUploadCount",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"concurrentFileUploadLimit",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"vhost",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"vhosts",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"allowedGroups",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"indicator",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"notification",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"listCondition",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"allowed_folder_type",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"uploadFilesExist",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundIndexRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundTypeRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundFolderListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundControlFolderListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundControlFileListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundPermissionViewRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundOwnerRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundFileNameRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundCreatedTimeRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundPermissionRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundCloneableRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundQuotaRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundUploadListRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundUploadProgressRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundInviteeInfoRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundIDRenderer",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"_boundStatusRenderer",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"_uploadFlag",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"_folderRefreshing",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"lastQueryTime",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"isWritable",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"permissions",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"_maxFileUploadSize",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"selectAreaHeight",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"oldFileExtension",void 0),__decorate([n({type:String})],BackendAiStorageList.prototype,"newFileExtension",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"is_dir",void 0),__decorate([n({type:Number})],BackendAiStorageList.prototype,"minimumResource",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"filebrowserSupportedImages",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"systemRoleSupportedImages",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"volumeInfo",void 0),__decorate([n({type:Array})],BackendAiStorageList.prototype,"quotaSupportStorageBackends",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"quotaUnit",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"maxSize",void 0),__decorate([n({type:Object})],BackendAiStorageList.prototype,"quota",void 0),__decorate([n({type:Boolean})],BackendAiStorageList.prototype,"directoryBasedUsage",void 0),__decorate([i("#loading-spinner")],BackendAiStorageList.prototype,"spinner",void 0),__decorate([i("#list-status")],BackendAiStorageList.prototype,"_listStatus",void 0),__decorate([i("#modify-folder-quota")],BackendAiStorageList.prototype,"modifyFolderQuotaInput",void 0),__decorate([i("#modify-folder-quota-unit")],BackendAiStorageList.prototype,"modifyFolderQuotaUnitSelect",void 0),__decorate([i("#file-list-grid")],BackendAiStorageList.prototype,"fileListGrid",void 0),__decorate([i("#folder-list-grid")],BackendAiStorageList.prototype,"folderListGrid",void 0),__decorate([i("#mkdir-name")],BackendAiStorageList.prototype,"mkdirNameInput",void 0),__decorate([i("#delete-folder-name")],BackendAiStorageList.prototype,"deleteFolderNameInput",void 0),__decorate([i("#new-folder-name")],BackendAiStorageList.prototype,"newFolderNameInput",void 0),__decorate([i("#new-file-name")],BackendAiStorageList.prototype,"newFileNameInput",void 0),__decorate([i("#leave-folder-name")],BackendAiStorageList.prototype,"leaveFolderNameInput",void 0),__decorate([i("#update-folder-permission")],BackendAiStorageList.prototype,"updateFolderPermissionSelect",void 0),__decorate([i("#update-folder-cloneable")],BackendAiStorageList.prototype,"updateFolderCloneableSwitch",void 0),__decorate([i("#rename-file-dialog")],BackendAiStorageList.prototype,"renameFileDialog",void 0),__decorate([i("#delete-file-dialog")],BackendAiStorageList.prototype,"deleteFileDialog",void 0),__decorate([i("#filebrowser-notification-dialog")],BackendAiStorageList.prototype,"fileBrowserNotificationDialog",void 0),__decorate([i("#file-extension-change-dialog")],BackendAiStorageList.prototype,"fileExtensionChangeDialog",void 0),__decorate([i("#folder-explorer-dialog")],BackendAiStorageList.prototype,"folderExplorerDialog",void 0),__decorate([i("#download-file-dialog")],BackendAiStorageList.prototype,"downloadFileDialog",void 0),__decorate([i("#modify-permission-dialog")],BackendAiStorageList.prototype,"modifyPermissionDialog",void 0),__decorate([i("#share-folder-dialog")],BackendAiStorageList.prototype,"shareFolderDialog",void 0),__decorate([i("#session-launcher")],BackendAiStorageList.prototype,"sessionLauncher",void 0),__decorate([t()],BackendAiStorageList.prototype,"_unionedAllowedPermissionByVolume",void 0),BackendAiStorageList=__decorate([e$2("backend-ai-storage-list")],BackendAiStorageList);let BackendAIData=class extends BackendAIPage{constructor(){super(...arguments),this.apiMajorVersion="",this.folderListFetchKey=new Date,this.is_admin=!1,this.enableStorageProxy=!1,this.enableInferenceWorkload=!1,this.authenticated=!1,this.vhost="",this.selectedVhost="",this.vhosts=[],this.usageModes=["General"],this.permissions=["Read-Write","Read-Only","Delete"],this.allowedGroups=[],this.allowed_folder_type=[],this.notification=Object(),this.folderLists=Object(),this._status="inactive",this.active=!1,this._vfolderInnatePermissionSupport=!1,this.storageInfo=Object(),this._activeTab="general",this._helpDescription="",this._helpDescriptionTitle="",this._helpDescriptionIcon="",this._helpDescriptionStorageProxyInfo=Object(),this.cloneFolderName="",this.quotaSupportStorageBackends=["xfs","weka","spectrumscale"],this.storageProxyInfo=Object(),this.folderType="user"}static get styles(){return[BackendAiStyles,IronFlex,IronFlexAlignment,IronPositioning,i$1` ul { padding-left: 0; } @@ -2157,7 +2157,7 @@ const progressBarStyles=i$1` ${this.vhosts.map((e=>{var t,i,o;const r=this.storageProxyInfo[e]&&(null===(t=this.storageProxyInfo[e])||void 0===t?void 0:t.usage)&&(null===(o=null===(i=this.storageProxyInfo[e])||void 0===i?void 0:i.usage)||void 0===o?void 0:o.percentage);return x`
@@ -2438,4 +2438,4 @@ const progressBarStyles=i$1` `:x``}
- `}firstUpdated(){var e;this.notification=globalThis.lablupNotification,this.folderLists=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelectorAll("backend-ai-storage-list"),fetch("resources/storage_metadata.json").then((e=>e.json())).then((e=>{const t=Object();for(const i in e.storageInfo)({}).hasOwnProperty.call(e.storageInfo,i)&&(t[i]={},"name"in e.storageInfo[i]&&(t[i].name=e.storageInfo[i].name),"description"in e.storageInfo[i]?t[i].description=e.storageInfo[i].description:t[i].description=get("data.NoStorageDescriptionFound"),"icon"in e.storageInfo[i]?t[i].icon=e.storageInfo[i].icon:t[i].icon="local.png","dialects"in e.storageInfo[i]&&e.storageInfo[i].dialects.forEach((e=>{t[e]=t[i]})));this.storageInfo=t})),this.options={responsive:!0,maintainAspectRatio:!0,legend:{display:!0,position:"bottom",align:"center",labels:{fontSize:20,boxWidth:10}}},void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(()=>{this._getStorageProxyInformation()}),!0):this._getStorageProxyInformation(),document.addEventListener("backend-ai-folder-list-changed",(()=>{this.folderListFetchKey=new Date})),document.addEventListener("backend-ai-vfolder-cloning",(e=>{if(e.detail){const t=e.detail;this.cloneFolderName=t.name,this._cloneFolderDialog()}}))}async _viewStateChanged(e){if(await this.updateComplete,!1===e)return;const t=()=>{this.is_admin=globalThis.backendaiclient.is_admin,this.authenticated=!0,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.enableInferenceWorkload&&!this.usageModes.includes("Model")&&this.usageModes.push("Model"),this.apiMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._getStorageProxyInformation(),globalThis.backendaiclient.isAPIVersionCompatibleWith("v4.20191215")&&(this._vfolderInnatePermissionSupport=!0),globalThis.backendaiclient.vfolder.list_allowed_types().then((e=>{this.allowed_folder_type=e}))};void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(()=>{t()}),!0):t()}_toggleFolderTypeInput(){var e;this.folderType=(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#add-folder-type")).value}_showTab(e){var t,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelectorAll(".tab-content");for(let e=0;e{this.notification.text=get("data.folders.FolderCreated"),this.notification.show(),this._refreshFolderList()})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message,this.notification.show(!0,e))})),this.closeDialog("add-folder-dialog")}}async _cloneFolder(){var e,t,i,o,r;const a=await this._checkFolderNameAlreadyExists(this.cloneFolderNameInput.value,!0),n=(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#clone-folder-host")).value;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#clone-folder-type")).value;const s=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("#clone-folder-usage-mode"),l=null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("#clone-folder-permission"),d=null===(r=this.shadowRoot)||void 0===r?void 0:r.querySelector("#clone-folder-cloneable");let c="",u="",h=!1;if(s&&(c=s.value,c=c.toLowerCase()),l)switch(u=l.value,u){case"Read-Write":default:u="rw";break;case"Read-Only":u="ro";break;case"Delete":u="wd"}if(h=!!d&&d.selected,this.cloneFolderNameInput.reportValidity(),this.cloneFolderNameInput.checkValidity()){const e={cloneable:h,permission:u,target_host:n,target_name:a,usage_mode:c};globalThis.backendaiclient.vfolder.clone(e,this.cloneFolderName).then((()=>{this.notification.text=get("data.folders.FolderCloned"),this.notification.show(),this._refreshFolderList()})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message,this.notification.show(!0,e))})),this.closeDialog("clone-folder-dialog")}}_validateFolderName(){this.addFolderNameInput.validityTransform=(e,t)=>{if(t.valid){let e=!/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/\s]/gi.test(this.addFolderNameInput.value);return e||(this.addFolderNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot")),this.addFolderNameInput.value.length>64&&(e=!1,this.addFolderNameInput.validationMessage=get("data.FolderNameTooLong")),{valid:e,customError:!e}}return t.valueMissing?(this.addFolderNameInput.validationMessage=get("data.FolderNameRequired"),{valid:t.valid,customError:!t.valid}):(this.addFolderNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:t.valid,customError:!t.valid})}}_refreshFolderList(){for(const e of this.folderLists)e.refreshFolderList()}async _checkFolderNameAlreadyExists(e,t=!1){const i=globalThis.backendaiclient.current_group_id(),o=(await globalThis.backendaiclient.vfolder.list(i)).map((e=>e.name));if(o.includes(e)){t&&(this.notification.text=get("import.FolderAlreadyExists"),this.notification.show());let i=1,r=e;for(;o.includes(r);)r=e+"_"+i,i++;e=r}return e}};__decorate([n({type:String})],BackendAIData.prototype,"apiMajorVersion",void 0),__decorate([n({type:Date})],BackendAIData.prototype,"folderListFetchKey",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"is_admin",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"enableStorageProxy",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"enableInferenceWorkload",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"authenticated",void 0),__decorate([n({type:String})],BackendAIData.prototype,"vhost",void 0),__decorate([n({type:String})],BackendAIData.prototype,"selectedVhost",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"vhosts",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"usageModes",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"permissions",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"allowedGroups",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"allowed_folder_type",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"notification",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"folderLists",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_status",void 0),__decorate([n({type:Boolean,reflect:!0})],BackendAIData.prototype,"active",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"_vfolderInnatePermissionSupport",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"storageInfo",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_activeTab",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescription",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescriptionTitle",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescriptionIcon",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"_helpDescriptionStorageProxyInfo",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"options",void 0),__decorate([n({type:Number})],BackendAIData.prototype,"capacity",void 0),__decorate([n({type:String})],BackendAIData.prototype,"cloneFolderName",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"quotaSupportStorageBackends",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"storageProxyInfo",void 0),__decorate([n({type:String})],BackendAIData.prototype,"folderType",void 0),__decorate([i("#add-folder-name")],BackendAIData.prototype,"addFolderNameInput",void 0),__decorate([i("#clone-folder-name")],BackendAIData.prototype,"cloneFolderNameInput",void 0),BackendAIData=__decorate([e$2("backend-ai-data-view")],BackendAIData); + `}firstUpdated(){var e;this.notification=globalThis.lablupNotification,this.folderLists=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelectorAll("backend-ai-storage-list"),fetch("resources/storage_metadata.json").then((e=>e.json())).then((e=>{const t=Object();for(const i in e.storageInfo)({}).hasOwnProperty.call(e.storageInfo,i)&&(t[i]={},"name"in e.storageInfo[i]&&(t[i].name=e.storageInfo[i].name),"description"in e.storageInfo[i]?t[i].description=e.storageInfo[i].description:t[i].description=get("data.NoStorageDescriptionFound"),"icon"in e.storageInfo[i]?t[i].icon=e.storageInfo[i].icon:t[i].icon="local.png","dialects"in e.storageInfo[i]&&e.storageInfo[i].dialects.forEach((e=>{t[e]=t[i]})));this.storageInfo=t})),this.options={responsive:!0,maintainAspectRatio:!0,legend:{display:!0,position:"bottom",align:"center",labels:{fontSize:20,boxWidth:10}}},void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(()=>{this._getStorageProxyInformation()}),!0):this._getStorageProxyInformation(),document.addEventListener("backend-ai-folder-list-changed",(()=>{this.folderListFetchKey=new Date})),document.addEventListener("backend-ai-vfolder-cloning",(e=>{if(e.detail){const t=e.detail;this.cloneFolderName=t.name,this._cloneFolderDialog()}}))}async _viewStateChanged(e){if(await this.updateComplete,!1===e)return;const t=()=>{this.is_admin=globalThis.backendaiclient.is_admin,this.authenticated=!0,this.enableStorageProxy=globalThis.backendaiclient.supports("storage-proxy"),this.enableInferenceWorkload=globalThis.backendaiclient.supports("inference-workload"),this.enableInferenceWorkload&&!this.usageModes.includes("Model")&&this.usageModes.push("Model"),this.apiMajorVersion=globalThis.backendaiclient.APIMajorVersion,this._getStorageProxyInformation(),globalThis.backendaiclient.isAPIVersionCompatibleWith("v4.20191215")&&(this._vfolderInnatePermissionSupport=!0),globalThis.backendaiclient.vfolder.list_allowed_types().then((e=>{this.allowed_folder_type=e}))};void 0===globalThis.backendaiclient||null===globalThis.backendaiclient||!1===globalThis.backendaiclient.ready?document.addEventListener("backend-ai-connected",(()=>{t()}),!0):t()}_toggleFolderTypeInput(){var e;this.folderType=(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#add-folder-type")).value}_showTab(e){var t,i;const o=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelectorAll(".tab-content");for(let e=0;e{var t;return null===(t=null==e?void 0:e.usage)||void 0===t?void 0:t.percentage})));return null!==(t=Object.keys(e.volume_info).find((t=>{var o,r;return(null===(r=null===(o=e.volume_info[t])||void 0===o?void 0:o.usage)||void 0===r?void 0:r.percentage)===i})))&&void 0!==t?t:e.default}_getAutoSelectedVhostInfo(e){var t;const i=Math.min(...Object.values(e.volume_info).map((e=>{var t;return null===(t=null==e?void 0:e.usage)||void 0===t?void 0:t.percentage})));return null!==(t=Object.values(e.volume_info).find((e=>{var t;return(null===(t=null==e?void 0:e.usage)||void 0===t?void 0:t.percentage)===i})))&&void 0!==t?t:e.volume_info[e.default]}async _getAutoSelectedVhostIncludedList(){const e=await globalThis.backendaiclient.vfolder.list_hosts();return e.allowed.length>1&&(e.allowed.unshift(`auto (${this._getAutoSelectedVhostName(e)})`),e.volume_info[`auto (${this._getAutoSelectedVhostName(e)})`]=this._getAutoSelectedVhostInfo(e)),e}async _cloneFolderDialog(){const e=await this._getAutoSelectedVhostIncludedList();if(this.addFolderNameInput.value="",this.vhosts=e.allowed,this.vhosts.length>1?this.vhost=this.selectedVhost=`auto (${this._getAutoSelectedVhostName(e)})`:this.vhost=this.selectedVhost=e.default,this.allowed_folder_type.includes("group")){const e=await globalThis.backendaiclient.group.list();this.allowedGroups=e.groups}this.cloneFolderNameInput.value=await this._checkFolderNameAlreadyExists(this.cloneFolderName),this.openDialog("clone-folder-dialog")}async _addFolderDialog(){const e=await this._getAutoSelectedVhostIncludedList();if(this.addFolderNameInput.value="",this.vhosts=e.allowed,this.vhosts.length>1?this.vhost=this.selectedVhost=`auto (${this._getAutoSelectedVhostName(e)})`:this.vhost=this.selectedVhost=e.default,this.allowed_folder_type.includes("group")){const e=await globalThis.backendaiclient.group.list();this.allowedGroups=e.groups}this.openDialog("add-folder-dialog")}async _getStorageProxyInformation(){const e=await this._getAutoSelectedVhostIncludedList();this.storageProxyInfo=e.volume_info||{}}openDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).show()}closeDialog(e){var t;(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#"+e)).hide()}_showStorageDescription(e,t){var i;e.stopPropagation(),t in this.storageInfo?(this._helpDescriptionTitle=this.storageInfo[t].name,this._helpDescriptionIcon=this.storageInfo[t].icon,this._helpDescription=this.storageInfo[t].description):(this._helpDescriptionTitle=t,this._helpDescriptionIcon="local.png",this._helpDescription=get("data.NoStorageDescriptionFound")),this._helpDescriptionStorageProxyInfo=this.storageProxyInfo[t];(null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("#help-description")).show()}_indexFrom1(e){return e+1}_addFolder(){var e,t,i,o,r,a;const n=this.addFolderNameInput.value;let s=(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#add-folder-host")).value;const l=s.match(/^auto \((.+)\)$/);l&&(s=l[1]);let d,c=(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#add-folder-type")).value;const u=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("#add-folder-usage-mode"),h=null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("#add-folder-permission"),p=null===(r=this.shadowRoot)||void 0===r?void 0:r.querySelector("#add-folder-cloneable");let m="",f="",g=!1;if(!1===["user","group"].includes(c)&&(c="user"),d="user"===c?"":this.is_admin?(null===(a=this.shadowRoot)||void 0===a?void 0:a.querySelector("#add-folder-group")).value:globalThis.backendaiclient.current_group,u&&(m=u.value,m=m.toLowerCase()),h)switch(f=h.value,f){case"Read-Write":default:f="rw";break;case"Read-Only":f="ro";break;case"Delete":f="wd"}if(p&&(g=p.selected),this.addFolderNameInput.reportValidity(),this.addFolderNameInput.checkValidity()){globalThis.backendaiclient.vfolder.create(n,s,d,m,f,g).then((()=>{this.notification.text=get("data.folders.FolderCreated"),this.notification.show(),this._refreshFolderList()})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message,this.notification.show(!0,e))})),this.closeDialog("add-folder-dialog")}}async _cloneFolder(){var e,t,i,o,r;const a=await this._checkFolderNameAlreadyExists(this.cloneFolderNameInput.value,!0);let n=(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#clone-folder-host")).value;const s=n.match(/^auto \((.+)\)$/);s&&(n=s[1]),(null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#clone-folder-type")).value;const l=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("#clone-folder-usage-mode"),d=null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("#clone-folder-permission"),c=null===(r=this.shadowRoot)||void 0===r?void 0:r.querySelector("#clone-folder-cloneable");let u="",h="",p=!1;if(l&&(u=l.value,u=u.toLowerCase()),d)switch(h=d.value,h){case"Read-Write":default:h="rw";break;case"Read-Only":h="ro";break;case"Delete":h="wd"}if(p=!!c&&c.selected,this.cloneFolderNameInput.reportValidity(),this.cloneFolderNameInput.checkValidity()){const e={cloneable:p,permission:h,target_host:n,target_name:a,usage_mode:u};globalThis.backendaiclient.vfolder.clone(e,this.cloneFolderName).then((()=>{this.notification.text=get("data.folders.FolderCloned"),this.notification.show(),this._refreshFolderList()})).catch((e=>{e&&e.message&&(this.notification.text=BackendAIPainKiller.relieve(e.message),this.notification.detail=e.message,this.notification.show(!0,e))})),this.closeDialog("clone-folder-dialog")}}_validateFolderName(){this.addFolderNameInput.validityTransform=(e,t)=>{if(t.valid){let e=!/[`~!@#$%^&*()|+=?;:'",<>{}[\]\\/\s]/gi.test(this.addFolderNameInput.value);return e||(this.addFolderNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot")),this.addFolderNameInput.value.length>64&&(e=!1,this.addFolderNameInput.validationMessage=get("data.FolderNameTooLong")),{valid:e,customError:!e}}return t.valueMissing?(this.addFolderNameInput.validationMessage=get("data.FolderNameRequired"),{valid:t.valid,customError:!t.valid}):(this.addFolderNameInput.validationMessage=get("data.Allowslettersnumbersand-_dot"),{valid:t.valid,customError:!t.valid})}}_refreshFolderList(){for(const e of this.folderLists)e.refreshFolderList()}async _checkFolderNameAlreadyExists(e,t=!1){const i=globalThis.backendaiclient.current_group_id(),o=(await globalThis.backendaiclient.vfolder.list(i)).map((e=>e.name));if(o.includes(e)){t&&(this.notification.text=get("import.FolderAlreadyExists"),this.notification.show());let i=1,r=e;for(;o.includes(r);)r=e+"_"+i,i++;e=r}return e}};__decorate([n({type:String})],BackendAIData.prototype,"apiMajorVersion",void 0),__decorate([n({type:Date})],BackendAIData.prototype,"folderListFetchKey",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"is_admin",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"enableStorageProxy",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"enableInferenceWorkload",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"authenticated",void 0),__decorate([n({type:String})],BackendAIData.prototype,"vhost",void 0),__decorate([n({type:String})],BackendAIData.prototype,"selectedVhost",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"vhosts",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"usageModes",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"permissions",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"allowedGroups",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"allowed_folder_type",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"notification",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"folderLists",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_status",void 0),__decorate([n({type:Boolean,reflect:!0})],BackendAIData.prototype,"active",void 0),__decorate([n({type:Boolean})],BackendAIData.prototype,"_vfolderInnatePermissionSupport",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"storageInfo",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_activeTab",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescription",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescriptionTitle",void 0),__decorate([n({type:String})],BackendAIData.prototype,"_helpDescriptionIcon",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"_helpDescriptionStorageProxyInfo",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"options",void 0),__decorate([n({type:Number})],BackendAIData.prototype,"capacity",void 0),__decorate([n({type:String})],BackendAIData.prototype,"cloneFolderName",void 0),__decorate([n({type:Array})],BackendAIData.prototype,"quotaSupportStorageBackends",void 0),__decorate([n({type:Object})],BackendAIData.prototype,"storageProxyInfo",void 0),__decorate([n({type:String})],BackendAIData.prototype,"folderType",void 0),__decorate([i("#add-folder-name")],BackendAIData.prototype,"addFolderNameInput",void 0),__decorate([i("#clone-folder-name")],BackendAIData.prototype,"cloneFolderNameInput",void 0),BackendAIData=__decorate([e$2("backend-ai-data-view")],BackendAIData); diff --git a/dist/components/backend-ai-edu-applauncher-57dee371.js b/dist/components/backend-ai-edu-applauncher-8acae0e5.js similarity index 99% rename from dist/components/backend-ai-edu-applauncher-57dee371.js rename to dist/components/backend-ai-edu-applauncher-8acae0e5.js index 85035bbf98..ca69b9dcd3 100644 --- a/dist/components/backend-ai-edu-applauncher-57dee371.js +++ b/dist/components/backend-ai-edu-applauncher-8acae0e5.js @@ -1,3 +1,3 @@ -import{_ as i,n as e,b as t,e as n,B as o,c as s,I as a,a as c,m as r,d as l,i as p,ar as h,as as u,g as d,f as g,x as f}from"./backend-ai-webui-a9940dc0.js";let b=class extends o{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.resources=Object()}static get styles(){return[s,a,c,r,l,p``]}firstUpdated(){this.notification=globalThis.lablupNotification}detectIE(){try{return!!!!document.documentMode||(navigator.userAgent.indexOf("MSIE")>0||navigator.userAgent.indexOf("WOW")>0||navigator.userAgent.indexOf(".NET")>0)}catch(i){const e=i.toString();return console.log(e),!1}}async prepareProjectInformation(){const i=`query { user{ ${["email","groups {name, id}"].join(" ")} } }`,e=await globalThis.backendaiclient.query(i,{});globalThis.backendaiclient.groups=e.user.groups.map((i=>i.name)).sort(),globalThis.backendaiclient.groupIds=e.user.groups.reduce(((i,e)=>(i[e.name]=e.id,i)),{});const t=globalThis.backendaiutils._readRecentProjectGroup();globalThis.backendaiclient.current_group=t||globalThis.backendaiclient.groups[0],globalThis.backendaiclient.current_group_id=()=>globalThis.backendaiclient.groupIds[globalThis.backendaiclient.current_group],console.log("current project:",t)}async launch(i){await this._initClient(i);const e=new URLSearchParams(window.location.search);this.resources={cpu:e.get("cpu"),mem:e.get("mem"),"cuda.shares":e.get("cuda-shares"),"cuda.device":e.get("cuda-device")};if(await this._token_login()){await this.prepareProjectInformation();const i=window.location.search,e=new URLSearchParams(i),t=e.get("session_id")||null;if(t){const i=e.get("app")||"jupyter";this._openServiceApp(t,i)}else await this._createEduSession()}}async _initClient(i){this.notification=globalThis.lablupNotification;const e=document.querySelector("#webui-shell");if(""===i){const e=localStorage.getItem("backendaiwebui.api_endpoint");null!=e&&(i=e.replace(/^"+|"+$/g,""))}i=i.trim(),this.clientConfig=new h("","",i,"SESSION"),globalThis.backendaiclient=new u(this.clientConfig,"Backend.AI Web UI.");await e._parseConfig("../../config.toml"),globalThis.backendaiclient._config._proxyURL=e.config.wsproxy.proxyURL,await globalThis.backendaiclient.get_manager_version(),globalThis.backendaiclient.ready=!0}async _token_login(){const i=window.location.search,e=new URLSearchParams(i),t=e.get("sToken")||e.get("stoken")||null;null!==t&&(document.cookie=`sToken=${t}; expires=Session; path=/`);const n={};for(const[i,t]of e.entries())"sToken"!==i&&"stoken"!==i&&(n[i]=t);try{if(await globalThis.backendaiclient.check_login())console.log("already logged-in session");else{console.log("logging with (cookie) token...");if(!await globalThis.backendaiclient.token_login(t,n))return this.notification.text=d("eduapi.CannotAuthorizeSessionByToken"),this.notification.show(!0),!1}return!0}catch(i){return this.notification.text=d("eduapi.CannotAuthorizeSessionByToken"),this.notification.show(!0,i),!1}}generateSessionId(){let i="";const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let t=0;t<8;t++)i+=e.charAt(Math.floor(62*Math.random()));return i+"-session"}async _createEduSession(){this.appLauncher.indicator=await globalThis.lablupIndicator.start();const i=["session_id","name","access_key","status","status_info","service_ports","mounts"];let e;e=globalThis.backendaiclient.supports("avoid-hol-blocking")?["RUNNING","RESTARTING","TERMINATING","PENDING","SCHEDULED","PREPARING","PULLING"].join(","):["RUNNING","RESTARTING","TERMINATING","PENDING","PREPARING","PULLING"].join(",");const t=globalThis.backendaiclient._config.accessKey;let n;try{this.appLauncher.indicator.set(20,d("eduapi.QueryingExisitingComputeSession")),n=await globalThis.backendaiclient.computeSession.list(i,e,t,30,0)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}const o=window.location.search;let s,a=new URLSearchParams(o).get("app")||"jupyter",c=!0;if(n.compute_session_list.total_count>0){console.log("Reusing an existing session ...");const i=n.compute_session_list.items[0].status;if("RUNNING"!==i)return this.notification.text=d("eduapi.sessionStatusIs")+` ${i}. `+d("eduapi.PleaseReload"),void this.notification.show(!0);let e=null;for(let i=0;ii.name)).includes(a)){e=t;break}}e?(c=!1,s="session_id"in e?e.session_id:null,this.appLauncher.indicator.set(50,d("eduapi.FoundExistingComputeSession"))):c=!0,s=null!==e&&"session_id"in e?e.session_id:null}if(c){let i;console.log("Creating a new session ..."),this.appLauncher.indicator.set(40,d("eduapi.FindingSessionTemplate"));try{i=await globalThis.backendaiclient.sessionTemplate.list(!1)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}if(i=i.filter((i=>i.name===a)),i.length<1)return this.notification.text=d("eduapi.NoSessionTemplate"),void this.notification.show(!0);const e=i[0].id;try{const i=await globalThis.backendaiclient.eduApp.get_mount_folders(),t=await globalThis.backendaiclient.eduApp.get_user_projects();if(!t)return this.notification.text=d("eduapi.EmptyProject"),void this.notification.show();const n=i?{mounts:i,...this.resources,group_name:t[0].name}:{...this.resources,group_name:t[0].name};let o;try{this.appLauncher.indicator.set(60,d("eduapi.CreatingComputeSession")),o=await globalThis.backendaiclient.createSessionFromTemplate(e,null,null,n,2e4)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}s=o.sessionId}catch(i){console.error(i),i&&i.message?("statusCode"in i&&408===i.statusCode?this.notification.text=d("eduapi.SessionStillPreparing"):i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i))}}this.appLauncher.indicator.set(100,d("eduapi.ComputeSessionPrepared")),s&&(a.startsWith("jupyter")&&!this.detectIE()&&(a="jupyterlab"),this._openServiceApp(s,a))}async _openServiceApp(i,e){this.appLauncher.indicator=await globalThis.lablupIndicator.start(),console.log(`launching ${e} from session ${i} ...`),this.appLauncher._open_wsproxy(i,e,null,null).then((async i=>{if(i.url){const e=await this.appLauncher._connectToProxyWorker(i.url,"");this.appLauncher.indicator.set(100,d("session.applauncher.Prepared")),setTimeout((()=>{globalThis.open(e||i.url,"_self")}))}}))}render(){return f` +import{_ as i,n as e,b as t,e as n,B as o,c as s,I as a,a as c,m as r,d as l,i as p,ar as h,as as u,g as d,f as g,x as f}from"./backend-ai-webui-75df15ed.js";let b=class extends o{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.resources=Object()}static get styles(){return[s,a,c,r,l,p``]}firstUpdated(){this.notification=globalThis.lablupNotification}detectIE(){try{return!!!!document.documentMode||(navigator.userAgent.indexOf("MSIE")>0||navigator.userAgent.indexOf("WOW")>0||navigator.userAgent.indexOf(".NET")>0)}catch(i){const e=i.toString();return console.log(e),!1}}async prepareProjectInformation(){const i=`query { user{ ${["email","groups {name, id}"].join(" ")} } }`,e=await globalThis.backendaiclient.query(i,{});globalThis.backendaiclient.groups=e.user.groups.map((i=>i.name)).sort(),globalThis.backendaiclient.groupIds=e.user.groups.reduce(((i,e)=>(i[e.name]=e.id,i)),{});const t=globalThis.backendaiutils._readRecentProjectGroup();globalThis.backendaiclient.current_group=t||globalThis.backendaiclient.groups[0],globalThis.backendaiclient.current_group_id=()=>globalThis.backendaiclient.groupIds[globalThis.backendaiclient.current_group],console.log("current project:",t)}async launch(i){await this._initClient(i);const e=new URLSearchParams(window.location.search);this.resources={cpu:e.get("cpu"),mem:e.get("mem"),"cuda.shares":e.get("cuda-shares"),"cuda.device":e.get("cuda-device")};if(await this._token_login()){await this.prepareProjectInformation();const i=window.location.search,e=new URLSearchParams(i),t=e.get("session_id")||null;if(t){const i=e.get("app")||"jupyter";this._openServiceApp(t,i)}else await this._createEduSession()}}async _initClient(i){this.notification=globalThis.lablupNotification;const e=document.querySelector("#webui-shell");if(""===i){const e=localStorage.getItem("backendaiwebui.api_endpoint");null!=e&&(i=e.replace(/^"+|"+$/g,""))}i=i.trim(),this.clientConfig=new h("","",i,"SESSION"),globalThis.backendaiclient=new u(this.clientConfig,"Backend.AI Web UI.");await e._parseConfig("../../config.toml"),globalThis.backendaiclient._config._proxyURL=e.config.wsproxy.proxyURL,await globalThis.backendaiclient.get_manager_version(),globalThis.backendaiclient.ready=!0}async _token_login(){const i=window.location.search,e=new URLSearchParams(i),t=e.get("sToken")||e.get("stoken")||null;null!==t&&(document.cookie=`sToken=${t}; expires=Session; path=/`);const n={};for(const[i,t]of e.entries())"sToken"!==i&&"stoken"!==i&&(n[i]=t);try{if(await globalThis.backendaiclient.check_login())console.log("already logged-in session");else{console.log("logging with (cookie) token...");if(!await globalThis.backendaiclient.token_login(t,n))return this.notification.text=d("eduapi.CannotAuthorizeSessionByToken"),this.notification.show(!0),!1}return!0}catch(i){return this.notification.text=d("eduapi.CannotAuthorizeSessionByToken"),this.notification.show(!0,i),!1}}generateSessionId(){let i="";const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let t=0;t<8;t++)i+=e.charAt(Math.floor(62*Math.random()));return i+"-session"}async _createEduSession(){this.appLauncher.indicator=await globalThis.lablupIndicator.start();const i=["session_id","name","access_key","status","status_info","service_ports","mounts"];let e;e=globalThis.backendaiclient.supports("avoid-hol-blocking")?["RUNNING","RESTARTING","TERMINATING","PENDING","SCHEDULED","PREPARING","PULLING"].join(","):["RUNNING","RESTARTING","TERMINATING","PENDING","PREPARING","PULLING"].join(",");const t=globalThis.backendaiclient._config.accessKey;let n;try{this.appLauncher.indicator.set(20,d("eduapi.QueryingExisitingComputeSession")),n=await globalThis.backendaiclient.computeSession.list(i,e,t,30,0)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}const o=window.location.search;let s,a=new URLSearchParams(o).get("app")||"jupyter",c=!0;if(n.compute_session_list.total_count>0){console.log("Reusing an existing session ...");const i=n.compute_session_list.items[0].status;if("RUNNING"!==i)return this.notification.text=d("eduapi.sessionStatusIs")+` ${i}. `+d("eduapi.PleaseReload"),void this.notification.show(!0);let e=null;for(let i=0;ii.name)).includes(a)){e=t;break}}e?(c=!1,s="session_id"in e?e.session_id:null,this.appLauncher.indicator.set(50,d("eduapi.FoundExistingComputeSession"))):c=!0,s=null!==e&&"session_id"in e?e.session_id:null}if(c){let i;console.log("Creating a new session ..."),this.appLauncher.indicator.set(40,d("eduapi.FindingSessionTemplate"));try{i=await globalThis.backendaiclient.sessionTemplate.list(!1)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}if(i=i.filter((i=>i.name===a)),i.length<1)return this.notification.text=d("eduapi.NoSessionTemplate"),void this.notification.show(!0);const e=i[0].id;try{const i=await globalThis.backendaiclient.eduApp.get_mount_folders(),t=await globalThis.backendaiclient.eduApp.get_user_projects();if(!t)return this.notification.text=d("eduapi.EmptyProject"),void this.notification.show();const n=i?{mounts:i,...this.resources,group_name:t[0].name}:{...this.resources,group_name:t[0].name};let o;try{this.appLauncher.indicator.set(60,d("eduapi.CreatingComputeSession")),o=await globalThis.backendaiclient.createSessionFromTemplate(e,null,null,n,2e4)}catch(i){return console.error(i),void(i&&i.message?(i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i)))}s=o.sessionId}catch(i){console.error(i),i&&i.message?("statusCode"in i&&408===i.statusCode?this.notification.text=d("eduapi.SessionStillPreparing"):i.description?this.notification.text=g.relieve(i.description):this.notification.text=g.relieve(i.message),this.notification.detail=i.message,this.notification.show(!0,i)):i&&i.title&&(this.notification.text=g.relieve(i.title),this.notification.show(!0,i))}}this.appLauncher.indicator.set(100,d("eduapi.ComputeSessionPrepared")),s&&(a.startsWith("jupyter")&&!this.detectIE()&&(a="jupyterlab"),this._openServiceApp(s,a))}async _openServiceApp(i,e){this.appLauncher.indicator=await globalThis.lablupIndicator.start(),console.log(`launching ${e} from session ${i} ...`),this.appLauncher._open_wsproxy(i,e,null,null).then((async i=>{if(i.url){const e=await this.appLauncher._connectToProxyWorker(i.url,"");this.appLauncher.indicator.set(100,d("session.applauncher.Prepared")),setTimeout((()=>{globalThis.open(e||i.url,"_self")}))}}))}render(){return f` `}};i([e({type:Object})],b.prototype,"webUIShell",void 0),i([e({type:Object})],b.prototype,"clientConfig",void 0),i([e({type:Object})],b.prototype,"client",void 0),i([e({type:Object})],b.prototype,"notification",void 0),i([e({type:String})],b.prototype,"resources",void 0),i([t("#app-launcher")],b.prototype,"appLauncher",void 0),b=i([n("backend-ai-edu-applauncher")],b); diff --git a/dist/components/backend-ai-email-verification-view-36a8105e.js b/dist/components/backend-ai-email-verification-view-f7125d4d.js similarity index 98% rename from dist/components/backend-ai-email-verification-view-36a8105e.js rename to dist/components/backend-ai-email-verification-view-f7125d4d.js index d81aeaf6c7..86fa35c771 100644 --- a/dist/components/backend-ai-email-verification-view-36a8105e.js +++ b/dist/components/backend-ai-email-verification-view-f7125d4d.js @@ -1,4 +1,4 @@ -import{_ as i,n as e,e as t,B as o,c as a,I as l,a as s,m as n,d as c,i as d,ar as r,as as h,g as f,x as g,t as u}from"./backend-ai-webui-a9940dc0.js";let v=class extends o{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.successDialog=Object(),this.failDialog=Object()}static get styles(){return[a,l,s,n,c,d` +import{_ as i,n as e,e as t,B as o,c as a,I as l,a as s,m as n,d as c,i as d,ar as r,as as h,g as f,x as g,t as u}from"./backend-ai-webui-75df15ed.js";let v=class extends o{constructor(){super(...arguments),this.webUIShell=Object(),this.clientConfig=Object(),this.client=Object(),this.notification=Object(),this.successDialog=Object(),this.failDialog=Object()}static get styles(){return[a,l,s,n,c,d` mwc-textfield { width: 100%; --mdc-text-field-fill-color: var(--general-menu-color); diff --git a/dist/components/backend-ai-environment-view-de8e7c4b.js b/dist/components/backend-ai-environment-view-0ed5b6b7.js similarity index 99% rename from dist/components/backend-ai-environment-view-de8e7c4b.js rename to dist/components/backend-ai-environment-view-0ed5b6b7.js index ee81d87372..0fee875da5 100644 --- a/dist/components/backend-ai-environment-view-de8e7c4b.js +++ b/dist/components/backend-ai-environment-view-0ed5b6b7.js @@ -1,4 +1,4 @@ -import{_ as e,n as t,b as i,e as a,B as s,c as o,I as r,a as n,m as l,d,i as c,g as m,f as u,t as p,l as h,x as g}from"./backend-ai-webui-a9940dc0.js";import"./lablup-grid-sort-filter-column-9fd9aaa5.js";import"./lablup-loading-spinner-8b3da9d1.js";import"./slider-b4cf5b64.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-filter-column-26a38357.js";import"./vaadin-grid-selection-column-3b7b0ad4.js";import"./vaadin-grid-sort-column-4f44c0ff.js";import"./mwc-switch-405e373b.js";import"./backend-ai-list-status-caaae261.js";import"./vaadin-item-a4241857.js";import"./lablup-activity-panel-d2e7b975.js";import"./mwc-tab-bar-f47ea595.js";import"./dir-utils-2ca2933c.js";import"./vaadin-item-mixin-88c89617.js";let v=class extends s{constructor(){super(),this.selectedIndex=0,this.selectedImages=[],this._cuda_gpu_disabled=!1,this._cuda_fgpu_disabled=!1,this._rocm_gpu_disabled=!1,this._tpu_disabled=!1,this._ipu_disabled=!1,this._atom_disabled=!1,this._warboy_disabled=!1,this.alias=Object(),this.indicator=Object(),this.deleteAppInfo=Object(),this.deleteAppRow=Object(),this.installImageResource=Object(),this.selectedCheckbox=Object(),this._grid=Object(),this.servicePortsMsg="",this._range={cpu:["1","2","3","4","5","6","7","8"],mem:["64MB","128MB","256MB","512MB","1GB","2GB","4GB","8GB","16GB","32GB","256GB","512GB"],"cuda-gpu":["0","1","2","3","4","5","6","7"],"cuda-fgpu":["0","0.1","0.2","0.5","1.0","2.0","4.0","8.0"],"rocm-gpu":["0","1","2","3","4","5","6","7"],tpu:["0","1","2","3","4"],ipu:["0","1","2","3","4"],atom:["0","1","2","3","4"],warboy:["0","1","2","3","4"]},this.cpuValue=0,this.listCondition="loading",this._boundRequirementsRenderer=this.requirementsRenderer.bind(this),this._boundControlsRenderer=this.controlsRenderer.bind(this),this._boundInstallRenderer=this.installRenderer.bind(this),this._boundBaseImageRenderer=this.baseImageRenderer.bind(this),this._boundConstraintRenderer=this.constraintRenderer.bind(this),this._boundDigestRenderer=this.digestRenderer.bind(this),this.installImageNameList=[],this.deleteImageNameList=[],this.images=[],this.allowed_registries=[],this.servicePorts=[]}static get styles(){return[o,r,n,l,d,c` +import{_ as e,n as t,b as i,e as a,B as s,c as o,I as r,a as n,m as l,d,i as c,g as m,f as u,t as p,l as h,x as g}from"./backend-ai-webui-75df15ed.js";import"./lablup-grid-sort-filter-column-54638b7b.js";import"./lablup-loading-spinner-02aea3b9.js";import"./slider-3f740add.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-filter-column-2b22f222.js";import"./vaadin-grid-selection-column-29a490b5.js";import"./vaadin-grid-sort-column-d722536e.js";import"./mwc-switch-13f7c132.js";import"./backend-ai-list-status-fa13c15b.js";import"./vaadin-item-19772d96.js";import"./lablup-activity-panel-86e1deef.js";import"./mwc-tab-bar-45ba859c.js";import"./dir-utils-f5050166.js";import"./vaadin-item-mixin-57783787.js";let v=class extends s{constructor(){super(),this.selectedIndex=0,this.selectedImages=[],this._cuda_gpu_disabled=!1,this._cuda_fgpu_disabled=!1,this._rocm_gpu_disabled=!1,this._tpu_disabled=!1,this._ipu_disabled=!1,this._atom_disabled=!1,this._warboy_disabled=!1,this.alias=Object(),this.indicator=Object(),this.deleteAppInfo=Object(),this.deleteAppRow=Object(),this.installImageResource=Object(),this.selectedCheckbox=Object(),this._grid=Object(),this.servicePortsMsg="",this._range={cpu:["1","2","3","4","5","6","7","8"],mem:["64MB","128MB","256MB","512MB","1GB","2GB","4GB","8GB","16GB","32GB","256GB","512GB"],"cuda-gpu":["0","1","2","3","4","5","6","7"],"cuda-fgpu":["0","0.1","0.2","0.5","1.0","2.0","4.0","8.0"],"rocm-gpu":["0","1","2","3","4","5","6","7"],tpu:["0","1","2","3","4"],ipu:["0","1","2","3","4"],atom:["0","1","2","3","4"],warboy:["0","1","2","3","4"]},this.cpuValue=0,this.listCondition="loading",this._boundRequirementsRenderer=this.requirementsRenderer.bind(this),this._boundControlsRenderer=this.controlsRenderer.bind(this),this._boundInstallRenderer=this.installRenderer.bind(this),this._boundBaseImageRenderer=this.baseImageRenderer.bind(this),this._boundConstraintRenderer=this.constraintRenderer.bind(this),this._boundDigestRenderer=this.digestRenderer.bind(this),this.installImageNameList=[],this.deleteImageNameList=[],this.images=[],this.allowed_registries=[],this.servicePorts=[]}static get styles(){return[o,r,n,l,d,c` vaadin-grid { border: 0; font-size: 14px; diff --git a/dist/components/backend-ai-error-view-0e8ee26a.js b/dist/components/backend-ai-error-view-e546570b.js similarity index 92% rename from dist/components/backend-ai-error-view-0e8ee26a.js rename to dist/components/backend-ai-error-view-e546570b.js index 4276d96e5e..3a0bf333e8 100644 --- a/dist/components/backend-ai-error-view-0e8ee26a.js +++ b/dist/components/backend-ai-error-view-e546570b.js @@ -1,4 +1,4 @@ -import{B as e,c as t,I as s,a as o,d as a,i as r,N as i,O as l,x as c,h as n,t as d,_ as m,n as u,e as h}from"./backend-ai-webui-a9940dc0.js";let v=class extends e{constructor(){super(...arguments),this.error_code=404}static get styles(){return[t,s,o,a,r` +import{B as e,c as t,I as s,a as o,d as a,i as r,p as i,q as l,x as c,h as n,t as d,_ as m,n as u,e as h}from"./backend-ai-webui-75df15ed.js";let v=class extends e{constructor(){super(...arguments),this.error_code=404}static get styles(){return[t,s,o,a,r` .title { font-size: 2em; font-weight: bolder; diff --git a/dist/components/backend-ai-import-view-06e22683.js b/dist/components/backend-ai-import-view-b7523da0.js similarity index 97% rename from dist/components/backend-ai-import-view-06e22683.js rename to dist/components/backend-ai-import-view-b7523da0.js index cde9d65134..350d46881f 100644 --- a/dist/components/backend-ai-import-view-06e22683.js +++ b/dist/components/backend-ai-import-view-b7523da0.js @@ -1,4 +1,4 @@ -import{_ as t,n as e,b as o,e as i,B as a,c as r,I as s,a as n,d as l,i as c,g as d,f as h,x as p,t as u}from"./backend-ai-webui-a9940dc0.js";import"./backend-ai-resource-monitor-2978fbc4.js";import"./backend-ai-session-launcher-a8a7a98f.js";import"./lablup-activity-panel-d2e7b975.js";import"./lablup-progress-bar-c7f68c65.js";import"./mwc-switch-405e373b.js";import"./lablup-codemirror-85098261.js";import"./slider-b4cf5b64.js";import"./mwc-check-list-item-d2338b83.js";import"./media-query-controller-7de4b65f.js";import"./dir-utils-2ca2933c.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-filter-column-26a38357.js";import"./vaadin-grid-selection-column-3b7b0ad4.js";let m=class extends a{constructor(){super(...arguments),this.condition="running",this.authenticated=!1,this.indicator=Object(),this.notification=Object(),this.requestURL="",this.queryString="",this.environment="python",this.importNotebookMessage="",this.importGithubMessage="",this.importGitlabMessage="",this.allowedGroups=[],this.allowed_folder_type=[],this.vhost="",this.vhosts=[],this.storageInfo=Object(),this._helpDescription="",this._helpDescriptionTitle="",this._helpDescriptionIcon=""}static get styles(){return[r,s,n,l,c` +import{_ as t,n as e,b as o,e as i,B as a,c as r,I as s,a as n,d as l,i as c,g as d,f as h,x as p,t as u}from"./backend-ai-webui-75df15ed.js";import"./backend-ai-resource-monitor-21ef3974.js";import"./backend-ai-session-launcher-676818a7.js";import"./lablup-activity-panel-86e1deef.js";import"./lablup-progress-bar-b230f3e3.js";import"./mwc-switch-13f7c132.js";import"./lablup-codemirror-59c15e56.js";import"./slider-3f740add.js";import"./mwc-check-list-item-5618f22b.js";import"./media-query-controller-bc25d693.js";import"./dir-utils-f5050166.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-filter-column-2b22f222.js";import"./vaadin-grid-selection-column-29a490b5.js";let m=class extends a{constructor(){super(...arguments),this.condition="running",this.authenticated=!1,this.indicator=Object(),this.notification=Object(),this.requestURL="",this.queryString="",this.environment="python",this.importNotebookMessage="",this.importGithubMessage="",this.importGitlabMessage="",this.allowedGroups=[],this.allowed_folder_type=[],this.vhost="",this.vhosts=[],this.storageInfo=Object(),this._helpDescription="",this._helpDescriptionTitle="",this._helpDescriptionIcon=""}static get styles(){return[r,s,n,l,c` div.description { font-size: 14px; color: var(--general-sidebar-color); diff --git a/dist/components/backend-ai-information-view-e387dfbf.js b/dist/components/backend-ai-information-view-7511523a.js similarity index 81% rename from dist/components/backend-ai-information-view-e387dfbf.js rename to dist/components/backend-ai-information-view-7511523a.js index c523682060..e274e4f1b8 100644 --- a/dist/components/backend-ai-information-view-e387dfbf.js +++ b/dist/components/backend-ai-information-view-7511523a.js @@ -1,3 +1,3 @@ -import{_ as a,e,B as t,c as i,I as n,a as s,i as r,x as c}from"./backend-ai-webui-a9940dc0.js";let o=class extends t{static get styles(){return[i,n,s,r``]}async _viewStateChanged(a){await this.updateComplete}render(){return c` +import{_ as a,e,B as t,c as i,I as n,a as s,i as r,x as c}from"./backend-ai-webui-75df15ed.js";let o=class extends t{static get styles(){return[i,n,s,r``]}async _viewStateChanged(a){await this.updateComplete}render(){return c` `}};o=a([e("backend-ai-information-view")],o); diff --git a/dist/components/backend-ai-list-status-caaae261.js b/dist/components/backend-ai-list-status-fa13c15b.js similarity index 98% rename from dist/components/backend-ai-list-status-caaae261.js rename to dist/components/backend-ai-list-status-fa13c15b.js index c94e0d66e1..46b478ca83 100644 --- a/dist/components/backend-ai-list-status-caaae261.js +++ b/dist/components/backend-ai-list-status-fa13c15b.js @@ -1,4 +1,4 @@ -import{_ as t,n as s,b as e,e as i,s as a,i as o,x as l,B as d,c as n,I as p,a as c}from"./backend-ai-webui-a9940dc0.js";let r=class extends a{constructor(){super(...arguments),this.active=!1}static get styles(){return[o` +import{_ as t,n as s,b as e,e as i,s as a,i as o,x as l,B as d,c as n,I as p,a as c}from"./backend-ai-webui-75df15ed.js";let r=class extends a{constructor(){super(...arguments),this.active=!1}static get styles(){return[o` .dots-box { width: 100px; background-color: transparent; diff --git a/dist/components/backend-ai-maintenance-view-8a93fcd4.js b/dist/components/backend-ai-maintenance-view-d24087a2.js similarity index 99% rename from dist/components/backend-ai-maintenance-view-8a93fcd4.js rename to dist/components/backend-ai-maintenance-view-d24087a2.js index 145ae59b17..29927e2102 100644 --- a/dist/components/backend-ai-maintenance-view-8a93fcd4.js +++ b/dist/components/backend-ai-maintenance-view-d24087a2.js @@ -1,4 +1,4 @@ -import{_ as e,n as a,b as t,e as i,B as n,c as s,I as c,a as l,m as o,d,i as r,x as g,t as m,h as u,g as b,f as h}from"./backend-ai-webui-a9940dc0.js";import"./lablup-activity-panel-d2e7b975.js";let p=class extends n{constructor(){super(...arguments),this.images=Object(),this.scanning=!1,this.recalculating=!1,this.notification=Object(),this.indicator=Object()}static get styles(){return[s,c,l,o,d,r` +import{_ as e,n as a,b as t,e as i,B as n,c as s,I as c,a as l,m as o,d,i as r,x as g,t as m,h as u,g as b,f as h}from"./backend-ai-webui-75df15ed.js";import"./lablup-activity-panel-86e1deef.js";let p=class extends n{constructor(){super(...arguments),this.images=Object(),this.scanning=!1,this.recalculating=!1,this.notification=Object(),this.indicator=Object()}static get styles(){return[s,c,l,o,d,r` div.indicator, span.indicator { font-size: 9px; diff --git a/dist/components/backend-ai-multi-select-d9f981f2.js b/dist/components/backend-ai-multi-select-1943e543.js similarity index 98% rename from dist/components/backend-ai-multi-select-d9f981f2.js rename to dist/components/backend-ai-multi-select-1943e543.js index a4c48e2ddd..40e64a6be7 100644 --- a/dist/components/backend-ai-multi-select-d9f981f2.js +++ b/dist/components/backend-ai-multi-select-1943e543.js @@ -1,4 +1,4 @@ -import{_ as e,b as t,n as i,u as o,e as s,s as a,c as l,I as r,a2 as d,a as c,m as n,d as m,i as p,x as h}from"./backend-ai-webui-a9940dc0.js";import"./mwc-check-list-item-d2338b83.js";var v;let u=v=class extends a{constructor(){super(),this.label="",this.validationMessage="",this.enableClearButton=!1,this.openUp=!1,this.required=!1,this._valid=!0,this.selectedItemList=[],this.items=[]}static get styles(){return[l,r,d,c,n,m,p` +import{_ as e,b as t,n as i,w as o,e as s,s as a,c as l,I as r,a2 as d,a as c,m as n,d as m,i as p,x as h}from"./backend-ai-webui-75df15ed.js";import"./mwc-check-list-item-5618f22b.js";var v;let u=v=class extends a{constructor(){super(),this.label="",this.validationMessage="",this.enableClearButton=!1,this.openUp=!1,this.required=!1,this._valid=!0,this.selectedItemList=[],this.items=[]}static get styles(){return[l,r,d,c,n,m,p` lablup-shields { margin: 1px; } diff --git a/dist/components/backend-ai-permission-denied-view-5d18811d.js b/dist/components/backend-ai-permission-denied-view-20b6fa23.js similarity index 94% rename from dist/components/backend-ai-permission-denied-view-5d18811d.js rename to dist/components/backend-ai-permission-denied-view-20b6fa23.js index 031ebf38aa..2387314bff 100644 --- a/dist/components/backend-ai-permission-denied-view-5d18811d.js +++ b/dist/components/backend-ai-permission-denied-view-20b6fa23.js @@ -1,4 +1,4 @@ -import{_ as e,n as i,e as t,B as a,c as o,I as s,a as r,d,i as n,N as c,O as l,x as m,h as u,t as p}from"./backend-ai-webui-a9940dc0.js";let g=class extends a{constructor(){super(...arguments),this.error_code=401}static get styles(){return[o,s,r,d,n` +import{_ as e,n as i,e as t,B as a,c as o,I as s,a as r,d,i as n,p as c,q as l,x as m,h as u,t as p}from"./backend-ai-webui-75df15ed.js";let g=class extends a{constructor(){super(...arguments),this.error_code=401}static get styles(){return[o,s,r,d,n` .title { font-size: 2em; font-weight: bolder; diff --git a/dist/components/backend-ai-resource-monitor-2978fbc4.js b/dist/components/backend-ai-resource-monitor-21ef3974.js similarity index 98% rename from dist/components/backend-ai-resource-monitor-2978fbc4.js rename to dist/components/backend-ai-resource-monitor-21ef3974.js index 95a4da3572..b1ed9b7da0 100644 --- a/dist/components/backend-ai-resource-monitor-2978fbc4.js +++ b/dist/components/backend-ai-resource-monitor-21ef3974.js @@ -1,4 +1,4 @@ -import{_ as e,n as t,b as s,e as r,B as i,c as o,I as a,a as c,m as l,d as n,i as p,g as d,f as u,x as _,t as h}from"./backend-ai-webui-a9940dc0.js";import"./lablup-progress-bar-c7f68c65.js";import"./backend-ai-session-launcher-a8a7a98f.js";import"./mwc-switch-405e373b.js";let g=class extends i{constructor(){super(),this.is_connected=!1,this.direction="horizontal",this.location="",this.aliases=Object(),this.aggregate_updating=!1,this.project_resource_monitor=!1,this.active=!1,this.resourceBroker=globalThis.resourceBroker,this.notification=globalThis.lablupNotification,this.init_resource()}static get is(){return"backend-ai-resource-monitor"}static get styles(){return[o,a,c,l,n,p` +import{_ as e,n as t,b as s,e as r,B as i,c as o,I as a,a as c,m as l,d as n,i as p,g as d,f as u,x as _,t as h}from"./backend-ai-webui-75df15ed.js";import"./lablup-progress-bar-b230f3e3.js";import"./backend-ai-session-launcher-676818a7.js";import"./mwc-switch-13f7c132.js";let g=class extends i{constructor(){super(),this.is_connected=!1,this.direction="horizontal",this.location="",this.aliases=Object(),this.aggregate_updating=!1,this.project_resource_monitor=!1,this.active=!1,this.resourceBroker=globalThis.resourceBroker,this.notification=globalThis.lablupNotification,this.init_resource()}static get is(){return"backend-ai-resource-monitor"}static get styles(){return[o,a,c,l,n,p` mwc-linear-progress { height: 5px; --mdc-theme-primary: #98be5a; @@ -434,9 +434,7 @@ import{_ as e,n as t,b as s,e as r,B as i,c as o,I as a,a as c,m as l,d as n,i a > TPU -
+
IPU
-
+
ATOM
-
+
Warboy
-
+
- `}};d=e([a("backend-ai-serving-list")],d); diff --git a/dist/components/backend-ai-serving-list-f5b0ed1e.js b/dist/components/backend-ai-serving-list-f5b0ed1e.js new file mode 100644 index 0000000000..859b08b666 --- /dev/null +++ b/dist/components/backend-ai-serving-list-f5b0ed1e.js @@ -0,0 +1,5 @@ +import{_ as a,e,B as t,c as s,I as i,a as r,i as n,x as d,p as c,q as l}from"./backend-ai-webui-75df15ed.js";let o=class extends t{static get styles(){return[s,i,r,n``]}async _viewStateChanged(a){await this.updateComplete}render(){return d` + + `}};o=a([e("backend-ai-serving-list")],o); diff --git a/dist/components/backend-ai-session-launcher-a8a7a98f.js b/dist/components/backend-ai-session-launcher-676818a7.js similarity index 79% rename from dist/components/backend-ai-session-launcher-a8a7a98f.js rename to dist/components/backend-ai-session-launcher-676818a7.js index d158ffeb36..9c451164bc 100644 --- a/dist/components/backend-ai-session-launcher-a8a7a98f.js +++ b/dist/components/backend-ai-session-launcher-676818a7.js @@ -1,4 +1,4 @@ -import{_ as e,n as t,b as i,e as s,s as o,c as a,I as r,a as n,m as l,d as c,i as d,x as h,r as u,aa as p,K as m,T as _,a0 as v,P as g,a1 as f,k as y,a9 as b,ab as x,ac as w,at as k,au as D,av as S,aw as P,ax as C,ay as T,az as I,aA as $,aB as M,aC as E,aD as O,aE as A,ao as R,aF as F,G as z,a6 as B,ak as N,aG as V,ad as q,D as L,ag as j,ah as G,aH as H,a3 as W,aI as Y,aJ as U,aK as K,aL as X,aM as J,aN as Q,aO as Z,a8 as ee,aP as te,aQ as ie,aR as se,aS as oe,aT as ae,aU as re,aV as ne,aW as le,aX as ce,aY as de,aZ as he,aj as ue,a_ as pe,B as me,g as _e,f as ve,l as ge,t as fe,o as ye}from"./backend-ai-webui-a9940dc0.js";import"./lablup-codemirror-85098261.js";import"./lablup-progress-bar-c7f68c65.js";import"./slider-b4cf5b64.js";import"./mwc-check-list-item-d2338b83.js";import{B as be,M as xe}from"./media-query-controller-7de4b65f.js";import{a as we,b as ke}from"./dir-utils-2ca2933c.js";import"./vaadin-grid-7aa99257.js";import"./vaadin-grid-filter-column-26a38357.js";import"./vaadin-grid-selection-column-3b7b0ad4.js";let De=class extends o{static get styles(){return[a,r,n,l,c,d` +import{_ as e,n as t,b as i,e as s,s as o,c as a,I as r,a as n,m as l,d as c,i as d,x as h,r as u,aa as p,N as m,T as _,a0 as v,P as g,a1 as f,k as y,a9 as b,ab as x,ac as w,at as k,au as D,av as S,aw as P,ax as C,ay as T,az as I,aA as $,aB as M,aC as E,aD as O,aE as A,ao as R,aF as F,J as z,a6 as B,ak as N,aG as V,ad as q,D as L,ag as j,ah as G,aH as H,a3 as W,aI as U,aJ as Y,aK as K,aL as X,aM as J,aN as Q,aO as Z,a8 as ee,aP as te,aQ as ie,aR as se,aS as oe,aT as ae,aU as re,aV as ne,aW as le,aX as ce,aY as de,aZ as he,aj as ue,a_ as pe,B as me,g as _e,f as ve,l as ge,t as fe,o as ye}from"./backend-ai-webui-75df15ed.js";import"./lablup-codemirror-59c15e56.js";import"./lablup-progress-bar-b230f3e3.js";import"./slider-3f740add.js";import"./mwc-check-list-item-5618f22b.js";import{B as be,M as xe}from"./media-query-controller-bc25d693.js";import{a as we,b as ke}from"./dir-utils-f5050166.js";import"./vaadin-grid-461d199a.js";import"./vaadin-grid-filter-column-2b22f222.js";import"./vaadin-grid-selection-column-29a490b5.js";let De=class extends o{static get styles(){return[a,r,n,l,c,d` mwc-textfield { width: var(--textfield-min-width, 65px); height: 40px; @@ -817,7 +817,7 @@ The complete set of contributors may be found at http://polymer.github.io/CONTRI Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -class We{constructor(){this._asyncModule=null,this._callback=null,this._timer=null}setConfig(e,t){this._asyncModule=e,this._callback=t,this._timer=this._asyncModule.run((()=>{this._timer=null,Ye.delete(this),this._callback()}))}cancel(){this.isActive()&&(this._cancelAsync(),Ye.delete(this))}_cancelAsync(){this.isActive()&&(this._asyncModule.cancel(this._timer),this._timer=null)}flush(){this.isActive()&&(this.cancel(),this._callback())}isActive(){return null!=this._timer}static debounce(e,t,i){return e instanceof We?e._cancelAsync():e=new We,e.setConfig(t,i),e}}let Ye=new Set;const Ue=function(){const e=Boolean(Ye.size);return Ye.forEach((e=>{try{e.flush()}catch(e){setTimeout((()=>{throw e}))}})),e},Ke=function(){let e,t;do{e=window.ShadyDOM&&ShadyDOM.flush(),window.ShadyCSS&&window.ShadyCSS.ScopingShim&&window.ShadyCSS.ScopingShim.flush(),t=Ue()}while(e||t)}; +class We{constructor(){this._asyncModule=null,this._callback=null,this._timer=null}setConfig(e,t){this._asyncModule=e,this._callback=t,this._timer=this._asyncModule.run((()=>{this._timer=null,Ue.delete(this),this._callback()}))}cancel(){this.isActive()&&(this._cancelAsync(),Ue.delete(this))}_cancelAsync(){this.isActive()&&(this._asyncModule.cancel(this._timer),this._timer=null)}flush(){this.isActive()&&(this.cancel(),this._callback())}isActive(){return null!=this._timer}static debounce(e,t,i){return e instanceof We?e._cancelAsync():e=new We,e.setConfig(t,i),e}}let Ue=new Set;const Ye=function(){const e=Boolean(Ue.size);return Ue.forEach((e=>{try{e.flush()}catch(e){setTimeout((()=>{throw e}))}})),e},Ke=function(){let e,t;do{e=window.ShadyDOM&&ShadyDOM.flush(),window.ShadyCSS&&window.ShadyCSS.ScopingShim&&window.ShadyCSS.ScopingShim.flush(),t=Ye()}while(e||t)}; /** @license Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -837,7 +837,7 @@ The complete set of contributors may be found at http://polymer.github.io/CONTRI Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -const Je=Ee(g);class Qe extends Je{static get is(){return"dom-repeat"}static get template(){return null}static get properties(){return{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},itemsIndexAs:{type:String,value:"itemsIndex"},sort:{type:Function,observer:"__sortChanged"},filter:{type:Function,observer:"__filterChanged"},observe:{type:String,observer:"__observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!$,readOnly:!0},initialCount:{type:Number},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"__computeFrameTime(targetFramerate)"},notifyDomChange:{type:Boolean},reuseChunkedInstances:{type:Boolean}}}static get observers(){return["__itemsChanged(items.*)"]}constructor(){super(),this.__instances=[],this.__renderDebouncer=null,this.__itemsIdxToInstIdx={},this.__chunkCount=null,this.__renderStartTime=null,this.__itemsArrayChanged=!1,this.__shouldMeasureChunk=!1,this.__shouldContinueChunking=!1,this.__chunkingId=0,this.__sortFn=null,this.__filterFn=null,this.__observePaths=null,this.__ctor=null,this.__isDetached=!0,this.template=null,this._templateInfo}disconnectedCallback(){super.disconnectedCallback(),this.__isDetached=!0;for(let e=0;e{if(!this.querySelector("template"))throw new Error("dom-repeat requires a