From 17a28a33e198c0aefa6b8cc465d4903086eadb2d Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 10 May 2026 08:21:33 -0400 Subject: [PATCH] CUB-119: Add docker-compose.yml + .env.example, remove legacy .NET backend and Angular frontend --- .env.example | 33 + backend/.gitignore | 21 - backend/Configurations/AgentConfiguration.cs | 88 - backend/ControlCenter.Api.csproj | 24 - backend/ControlCenter.Api.http | 6 - backend/ControlCenter/.gitignore | 18 - backend/ControlCenter/ControlCenter.csproj | 17 - .../Controllers/AgentsController.cs | 71 - .../Controllers/CommandController.cs | 122 - .../Controllers/LogsController.cs | 87 - backend/ControlCenter/Hubs/AgentStatusHub.cs | 211 - .../ControlCenter/Hubs/IAgentStatusClient.cs | 30 - .../Hubs/Models/AgentStatusModels.cs | 166 - .../Models/AgentMinionMapping.cs | 72 - backend/ControlCenter/Program.cs | 77 - .../Properties/launchSettings.json | 14 - .../Services/AgentMinionMapperService.cs | 193 - .../Services/GatewayEventBridgeService.cs | 523 -- .../appsettings.Development.json | 19 - backend/ControlCenter/appsettings.json | 22 - backend/Data/AppDbContext.cs | 29 - backend/Data/AppDbContextFactory.cs | 27 - backend/Dtos/AgentStatusUpdateDto.cs | 75 - backend/Entities/Agent.cs | 59 - backend/Entities/AgentStatus.cs | 13 - backend/Hubs/AgentStatusHub.cs | 155 - ...260426101703_CreateAgentsTable.Designer.cs | 94 - .../20260426101703_CreateAgentsTable.cs | 61 - .../Migrations/AppDbContextModelSnapshot.cs | 91 - backend/Models/AgentState.cs | 19 - backend/Program.cs | 42 - backend/Properties/launchSettings.json | 23 - backend/Repositories/AgentStateRepository.cs | 76 - backend/Repositories/IAgentStateRepository.cs | 27 - backend/appsettings.Development.json | 8 - backend/appsettings.json | 12 - backend/internal/models/models.go | 106 - docker-compose.yml | 88 + frontend-legacy/.dockerignore | 33 - frontend-legacy/.editorconfig | 17 - frontend-legacy/.gitignore | 44 - frontend-legacy/.prettierrc | 12 - frontend-legacy/.vscode/extensions.json | 4 - frontend-legacy/.vscode/launch.json | 20 - frontend-legacy/.vscode/mcp.json | 9 - frontend-legacy/.vscode/tasks.json | 42 - frontend-legacy/Dockerfile | 38 - frontend-legacy/README.md | 59 - frontend-legacy/angular.json | 103 - frontend-legacy/nginx.conf | 54 - frontend-legacy/package-lock.json | 8034 ----------------- frontend-legacy/package.json | 34 - frontend-legacy/public/favicon.ico | Bin 15086 -> 0 bytes frontend-legacy/src/app/app.config.ts | 13 - frontend-legacy/src/app/app.html | 1 - frontend-legacy/src/app/app.routes.ts | 22 - frontend-legacy/src/app/app.scss | 4 - frontend-legacy/src/app/app.ts | 16 - .../agent-card/agent-card.component.html | 100 - .../agent-card/agent-card.component.scss | 267 - .../agent-card/agent-card.component.ts | 183 - .../src/app/command-hub/components/index.ts | 1 - .../adaptive-navigation.component.html | 112 - .../adaptive-navigation.component.scss | 365 - .../adaptive-navigation.component.ts | 84 - .../components/adaptive-navigation/index.ts | 1 - .../agent-session-drawer.component.html | 140 - .../agent-session-drawer.component.scss | 500 - .../agent-session-drawer.component.ts | 268 - .../components/agent-session-drawer/index.ts | 2 - .../agent-status-badge.component.html | 8 - .../agent-status-badge.component.scss | 146 - .../agent-status-badge.component.ts | 54 - .../components/agent-status-badge/index.ts | 1 - .../global-action-modal.component.html | 31 - .../global-action-modal.component.scss | 198 - .../global-action-modal.component.ts | 87 - frontend-legacy/src/app/components/index.ts | 5 - .../quick-jump-button.component.html | 8 - .../quick-jump-button.component.scss | 68 - .../quick-jump-button.component.ts | 32 - .../app/components/quick-jump-drawer/index.ts | 1 - .../quick-jump-drawer.component.html | 109 - .../quick-jump-drawer.component.scss | 333 - .../quick-jump-drawer.component.ts | 215 - .../app/components/task-progress-bar/index.ts | 6 - .../task-progress-bar.component.html | 18 - .../task-progress-bar.component.scss | 77 - .../task-progress-bar.component.ts | 109 - frontend-legacy/src/app/design/index.ts | 11 - .../src/app/design/theme.service.ts | 151 - frontend-legacy/src/app/design/tokens.ts | 462 - frontend-legacy/src/app/directives/index.ts | 1 - .../app/directives/long-press.directive.ts | 89 - .../bottom-nav/bottom-nav.component.html | 24 - .../bottom-nav/bottom-nav.component.scss | 94 - .../layout/bottom-nav/bottom-nav.component.ts | 24 - .../header-bar/header-bar.component.html | 55 - .../header-bar/header-bar.component.scss | 126 - .../layout/header-bar/header-bar.component.ts | 28 - frontend-legacy/src/app/layout/index.ts | 4 - .../layout-shell/layout-shell.component.html | 27 - .../layout-shell/layout-shell.component.scss | 73 - .../layout-shell/layout-shell.component.ts | 85 - .../layout/nav-rail/nav-rail.component.html | 44 - .../layout/nav-rail/nav-rail.component.scss | 158 - .../app/layout/nav-rail/nav-rail.component.ts | 63 - frontend-legacy/src/app/models/agent.model.ts | 54 - frontend-legacy/src/app/models/index.ts | 2 - frontend-legacy/src/app/models/nav.model.ts | 19 - .../src/app/pages/hub/hub-page.component.html | 57 - .../src/app/pages/hub/hub-page.component.scss | 141 - .../src/app/pages/hub/hub-page.component.ts | 153 - .../src/app/pages/logs/logs-page.component.ts | 10 - .../pages/projects/projects-page.component.ts | 10 - .../pages/sessions/sessions-page.component.ts | 10 - .../pages/settings/settings-page.component.ts | 10 - .../src/app/services/agent-status.service.ts | 47 - frontend-legacy/src/index.html | 25 - frontend-legacy/src/main.ts | 6 - frontend-legacy/src/styles.scss | 285 - .../src/styles/_css-properties.scss | 115 - frontend-legacy/src/styles/_tokens.scss | 474 - frontend-legacy/src/styles/_utilities.scss | 170 - frontend-legacy/tsconfig.app.json | 15 - frontend-legacy/tsconfig.json | 30 - frontend-legacy/tsconfig.spec.json | 15 - .../migrations/001_initial_schema.down.sql | 0 .../migrations/001_initial_schema.up.sql | 0 .../migrations/002_add_indexes.down.sql | 0 .../migrations/002_add_indexes.up.sql | 0 131 files changed, 121 insertions(+), 17953 deletions(-) create mode 100644 .env.example delete mode 100644 backend/.gitignore delete mode 100644 backend/Configurations/AgentConfiguration.cs delete mode 100644 backend/ControlCenter.Api.csproj delete mode 100644 backend/ControlCenter.Api.http delete mode 100644 backend/ControlCenter/.gitignore delete mode 100644 backend/ControlCenter/ControlCenter.csproj delete mode 100644 backend/ControlCenter/Controllers/AgentsController.cs delete mode 100644 backend/ControlCenter/Controllers/CommandController.cs delete mode 100644 backend/ControlCenter/Controllers/LogsController.cs delete mode 100644 backend/ControlCenter/Hubs/AgentStatusHub.cs delete mode 100644 backend/ControlCenter/Hubs/IAgentStatusClient.cs delete mode 100644 backend/ControlCenter/Hubs/Models/AgentStatusModels.cs delete mode 100644 backend/ControlCenter/Models/AgentMinionMapping.cs delete mode 100644 backend/ControlCenter/Program.cs delete mode 100644 backend/ControlCenter/Properties/launchSettings.json delete mode 100644 backend/ControlCenter/Services/AgentMinionMapperService.cs delete mode 100644 backend/ControlCenter/Services/GatewayEventBridgeService.cs delete mode 100644 backend/ControlCenter/appsettings.Development.json delete mode 100644 backend/ControlCenter/appsettings.json delete mode 100644 backend/Data/AppDbContext.cs delete mode 100644 backend/Data/AppDbContextFactory.cs delete mode 100644 backend/Dtos/AgentStatusUpdateDto.cs delete mode 100644 backend/Entities/Agent.cs delete mode 100644 backend/Entities/AgentStatus.cs delete mode 100644 backend/Hubs/AgentStatusHub.cs delete mode 100644 backend/Migrations/20260426101703_CreateAgentsTable.Designer.cs delete mode 100644 backend/Migrations/20260426101703_CreateAgentsTable.cs delete mode 100644 backend/Migrations/AppDbContextModelSnapshot.cs delete mode 100644 backend/Models/AgentState.cs delete mode 100644 backend/Program.cs delete mode 100644 backend/Properties/launchSettings.json delete mode 100644 backend/Repositories/AgentStateRepository.cs delete mode 100644 backend/Repositories/IAgentStateRepository.cs delete mode 100644 backend/appsettings.Development.json delete mode 100644 backend/appsettings.json delete mode 100644 backend/internal/models/models.go create mode 100644 docker-compose.yml delete mode 100644 frontend-legacy/.dockerignore delete mode 100644 frontend-legacy/.editorconfig delete mode 100644 frontend-legacy/.gitignore delete mode 100644 frontend-legacy/.prettierrc delete mode 100644 frontend-legacy/.vscode/extensions.json delete mode 100644 frontend-legacy/.vscode/launch.json delete mode 100644 frontend-legacy/.vscode/mcp.json delete mode 100644 frontend-legacy/.vscode/tasks.json delete mode 100644 frontend-legacy/Dockerfile delete mode 100644 frontend-legacy/README.md delete mode 100644 frontend-legacy/angular.json delete mode 100644 frontend-legacy/nginx.conf delete mode 100644 frontend-legacy/package-lock.json delete mode 100644 frontend-legacy/package.json delete mode 100644 frontend-legacy/public/favicon.ico delete mode 100644 frontend-legacy/src/app/app.config.ts delete mode 100644 frontend-legacy/src/app/app.html delete mode 100644 frontend-legacy/src/app/app.routes.ts delete mode 100644 frontend-legacy/src/app/app.scss delete mode 100644 frontend-legacy/src/app/app.ts delete mode 100644 frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.html delete mode 100644 frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.scss delete mode 100644 frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.ts delete mode 100644 frontend-legacy/src/app/command-hub/components/index.ts delete mode 100644 frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.html delete mode 100644 frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.scss delete mode 100644 frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.ts delete mode 100644 frontend-legacy/src/app/components/adaptive-navigation/index.ts delete mode 100644 frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.html delete mode 100644 frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.scss delete mode 100644 frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.ts delete mode 100644 frontend-legacy/src/app/components/agent-session-drawer/index.ts delete mode 100644 frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.html delete mode 100644 frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.scss delete mode 100644 frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.ts delete mode 100644 frontend-legacy/src/app/components/agent-status-badge/index.ts delete mode 100644 frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.html delete mode 100644 frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.scss delete mode 100644 frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.ts delete mode 100644 frontend-legacy/src/app/components/index.ts delete mode 100644 frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.html delete mode 100644 frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.scss delete mode 100644 frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.ts delete mode 100644 frontend-legacy/src/app/components/quick-jump-drawer/index.ts delete mode 100644 frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.html delete mode 100644 frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.scss delete mode 100644 frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.ts delete mode 100644 frontend-legacy/src/app/components/task-progress-bar/index.ts delete mode 100644 frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.html delete mode 100644 frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.scss delete mode 100644 frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.ts delete mode 100644 frontend-legacy/src/app/design/index.ts delete mode 100644 frontend-legacy/src/app/design/theme.service.ts delete mode 100644 frontend-legacy/src/app/design/tokens.ts delete mode 100644 frontend-legacy/src/app/directives/index.ts delete mode 100644 frontend-legacy/src/app/directives/long-press.directive.ts delete mode 100644 frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.html delete mode 100644 frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.scss delete mode 100644 frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.ts delete mode 100644 frontend-legacy/src/app/layout/header-bar/header-bar.component.html delete mode 100644 frontend-legacy/src/app/layout/header-bar/header-bar.component.scss delete mode 100644 frontend-legacy/src/app/layout/header-bar/header-bar.component.ts delete mode 100644 frontend-legacy/src/app/layout/index.ts delete mode 100644 frontend-legacy/src/app/layout/layout-shell/layout-shell.component.html delete mode 100644 frontend-legacy/src/app/layout/layout-shell/layout-shell.component.scss delete mode 100644 frontend-legacy/src/app/layout/layout-shell/layout-shell.component.ts delete mode 100644 frontend-legacy/src/app/layout/nav-rail/nav-rail.component.html delete mode 100644 frontend-legacy/src/app/layout/nav-rail/nav-rail.component.scss delete mode 100644 frontend-legacy/src/app/layout/nav-rail/nav-rail.component.ts delete mode 100644 frontend-legacy/src/app/models/agent.model.ts delete mode 100644 frontend-legacy/src/app/models/index.ts delete mode 100644 frontend-legacy/src/app/models/nav.model.ts delete mode 100644 frontend-legacy/src/app/pages/hub/hub-page.component.html delete mode 100644 frontend-legacy/src/app/pages/hub/hub-page.component.scss delete mode 100644 frontend-legacy/src/app/pages/hub/hub-page.component.ts delete mode 100644 frontend-legacy/src/app/pages/logs/logs-page.component.ts delete mode 100644 frontend-legacy/src/app/pages/projects/projects-page.component.ts delete mode 100644 frontend-legacy/src/app/pages/sessions/sessions-page.component.ts delete mode 100644 frontend-legacy/src/app/pages/settings/settings-page.component.ts delete mode 100644 frontend-legacy/src/app/services/agent-status.service.ts delete mode 100644 frontend-legacy/src/index.html delete mode 100644 frontend-legacy/src/main.ts delete mode 100644 frontend-legacy/src/styles.scss delete mode 100644 frontend-legacy/src/styles/_css-properties.scss delete mode 100644 frontend-legacy/src/styles/_tokens.scss delete mode 100644 frontend-legacy/src/styles/_utilities.scss delete mode 100644 frontend-legacy/tsconfig.app.json delete mode 100644 frontend-legacy/tsconfig.json delete mode 100644 frontend-legacy/tsconfig.spec.json rename {backend => go-backend}/migrations/001_initial_schema.down.sql (100%) rename {backend => go-backend}/migrations/001_initial_schema.up.sql (100%) rename {backend => go-backend}/migrations/002_add_indexes.down.sql (100%) rename {backend => go-backend}/migrations/002_add_indexes.up.sql (100%) diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ab39c6c --- /dev/null +++ b/.env.example @@ -0,0 +1,33 @@ +# ============================================================================= +# Control Center — Environment Configuration Template +# ============================================================================= +# Copy this file to `.env` and fill in real values. +# Never commit `.env` — it is in .gitignore by default. +# ============================================================================= + +# ── Database ──────────────────────────────────────────────────────────────── +POSTGRES_DB=controlcenter +POSTGRES_USER=controlcenter +POSTGRES_PASSWORD=changeme +POSTGRES_PORT=5432 + +# ── Backend ─────────────────────────────────────────────────────────────────── +BACKEND_PORT=8080 +LOG_LEVEL=info +ENVIRONMENT=development + +# ── Frontend ──────────────────────────────────────────────────────────────── +FRONTEND_PORT=3000 + +# ── CORS ──────────────────────────────────────────────────────────────────── +# Comma-separated allowed origins. Use "*" for local dev. +CORS_ORIGIN=http://localhost:3000 + +# ── OpenClaw Gateway ────────────────────────────────────────────────────────── +# URL to the OpenClaw gateway agent status endpoint. +# In Docker Compose, use the container name or host.docker.internal for the +# gateway running outside Compose. +GATEWAY_URL=http://host.docker.internal:18789/api/agents + +# How often to poll the gateway for agent state updates. +GATEWAY_POLL_INTERVAL=5s diff --git a/backend/.gitignore b/backend/.gitignore deleted file mode 100644 index c2c0c5e..0000000 --- a/backend/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -## .NET -bin/ -obj/ -*.user -*.suo -*.cache -*.dll -*.pdb - -## IDE -.vs/ -.idea/ -*.swp -*~ - -## OS -.DS_Store -Thumbs.db - -## Environment -.env \ No newline at end of file diff --git a/backend/Configurations/AgentConfiguration.cs b/backend/Configurations/AgentConfiguration.cs deleted file mode 100644 index 0f9d304..0000000 --- a/backend/Configurations/AgentConfiguration.cs +++ /dev/null @@ -1,88 +0,0 @@ -using ControlCenter.Api.Entities; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace ControlCenter.Api.Configurations; - -/// -/// EF Core entity type configuration for the agents table. -/// Enforces snake_case naming, required fields, and index design. -/// -public class AgentConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - // Table name — snake_case - builder.ToTable("agents"); - - // Primary key - builder.HasKey(a => a.Id); - builder.Property(a => a.Id) - .HasColumnName("id") - .ValueGeneratedOnAdd(); - - // Status — stored as PostgreSQL enum via Npgsql - builder.Property(a => a.Status) - .HasColumnName("status") - .HasColumnType("agent_status") - .IsRequired(); - - // Task — nullable text - builder.Property(a => a.Task) - .HasColumnName("task") - .HasColumnType("text"); - - // Progress — nullable integer (0–100) - builder.Property(a => a.Progress) - .HasColumnName("progress"); - - // Session key — required, not null - builder.Property(a => a.SessionKey) - .HasColumnName("session_key") - .HasColumnType("text") - .IsRequired(); - - // Channel — required, not null - builder.Property(a => a.Channel) - .HasColumnName("channel") - .HasColumnType("text") - .IsRequired(); - - // Last activity — required, defaults to now() - builder.Property(a => a.LastActivity) - .HasColumnName("last_activity") - .HasColumnType("timestamptz") - .IsRequired(); - - // Created at — auto-set on insert - builder.Property(a => a.CreatedAt) - .HasColumnName("created_at") - .HasColumnType("timestamptz") - .IsRequired() - .HasDefaultValueSql("now()"); - - // Updated at — auto-set on insert and update - builder.Property(a => a.UpdatedAt) - .HasColumnName("updated_at") - .HasColumnType("timestamptz") - .IsRequired() - .HasDefaultValueSql("now()"); - - // Indexes - // Sessions are looked up by session_key frequently - builder.HasIndex(a => a.SessionKey) - .HasDatabaseName("ix_agents_session_key") - .IsUnique(); - - // Agents are filtered by channel for channel-specific queries - builder.HasIndex(a => a.Channel) - .HasDatabaseName("ix_agents_channel"); - - // Agents are filtered by status for fleet health monitoring - builder.HasIndex(a => a.Status) - .HasDatabaseName("ix_agents_status"); - - // Check constraint: progress must be 0–100 if present - builder.ToTable(t => t.HasCheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)")); - } -} \ No newline at end of file diff --git a/backend/ControlCenter.Api.csproj b/backend/ControlCenter.Api.csproj deleted file mode 100644 index a509f52..0000000 --- a/backend/ControlCenter.Api.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - net9.0 - enable - enable - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - diff --git a/backend/ControlCenter.Api.http b/backend/ControlCenter.Api.http deleted file mode 100644 index f621eb8..0000000 --- a/backend/ControlCenter.Api.http +++ /dev/null @@ -1,6 +0,0 @@ -@ControlCenter.Api_HostAddress = http://localhost:5178 - -GET {{ControlCenter.Api_HostAddress}}/weatherforecast/ -Accept: application/json - -### diff --git a/backend/ControlCenter/.gitignore b/backend/ControlCenter/.gitignore deleted file mode 100644 index 27e7e53..0000000 --- a/backend/ControlCenter/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -## .NET -bin/ -obj/ -*.user -*.suo -*.cache -*.dll -*.pdb -*.xml - -## IDE -.vs/ -.vscode/ -.idea/ - -## OS -.DS_Store -Thumbs.db \ No newline at end of file diff --git a/backend/ControlCenter/ControlCenter.csproj b/backend/ControlCenter/ControlCenter.csproj deleted file mode 100644 index 66ebc83..0000000 --- a/backend/ControlCenter/ControlCenter.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net9.0 - enable - enable - true - CS1591 - ControlCenter - ControlCenter - - - - - - - \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/AgentsController.cs b/backend/ControlCenter/Controllers/AgentsController.cs deleted file mode 100644 index 92da9b3..0000000 --- a/backend/ControlCenter/Controllers/AgentsController.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using ControlCenter.Services; - -namespace ControlCenter.Controllers; - -/// -/// REST API for querying agent fleet status. -/// Provides the initial data load for the Command Hub, -/// while real-time updates flow through the AgentStatus SignalR hub. -/// -/// API contract for Rex (Frontend): -/// -/// GET /api/agents — Returns all known agents with current status -/// GET /api/agents/{agentId} — Returns a specific agent's status -/// -/// -[ApiController] -[Route("api/[controller]")] -public class AgentsController : ControllerBase -{ - private readonly ILogger _logger; - private readonly GatewayEventBridgeService _bridgeService; - - public AgentsController( - ILogger logger, - GatewayEventBridgeService bridgeService) - { - _logger = logger; - _bridgeService = bridgeService; - } - - /// - /// Gets the current fleet status — all known agents with their latest state. - /// This is the initial load endpoint; subsequent updates arrive via SignalR. - /// - /// An array of agent card data for the entire fleet. - /// Returns the fleet snapshot. - [HttpGet] - [ProducesResponseType(typeof(AgentCardData[]), StatusCodes.Status200OK)] - public IActionResult GetAgents() - { - var snapshot = _bridgeService.GetFleetSnapshot(); - _logger.LogDebug("Fleet snapshot requested: {Count} agents", snapshot.Length); - return Ok(snapshot); - } - - /// - /// Gets the current status of a specific agent. - /// - /// The agent identifier, e.g. "otto", "dex". - /// The agent's current card data. - /// Returns the agent's status. - /// Agent not found in the fleet state. - [HttpGet("{agentId}")] - [ProducesResponseType(typeof(AgentCardData), StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult GetAgent(string agentId) - { - var snapshot = _bridgeService.GetFleetSnapshot(); - var agent = snapshot.FirstOrDefault(a => - a.Id.Equals(agentId, StringComparison.OrdinalIgnoreCase)); - - if (agent is null) - { - _logger.LogWarning("Agent not found: {AgentId}", agentId); - return NotFound(new { error = $"Agent '{agentId}' not found" }); - } - - return Ok(agent); - } -} \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/CommandController.cs b/backend/ControlCenter/Controllers/CommandController.cs deleted file mode 100644 index 0dc75bc..0000000 --- a/backend/ControlCenter/Controllers/CommandController.cs +++ /dev/null @@ -1,122 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace ControlCenter.Controllers; - -/// -/// REST API for sending control commands to agents. -/// Provides the Command Hub's action endpoints for agent lifecycle control. -/// -/// API contract for Rex (Frontend): -/// -/// POST /api/command/stop/{agentId} — Stop/abort an agent's active session -/// POST /api/command/restart/{agentId} — Restart an agent -/// POST /api/command/steer/{agentId} — Inject a message into an agent's session -/// -/// -/// Commands are forwarded to the OpenClaw Gateway via the -/// WebSocket bridge service. The Gateway handles the actual execution. -/// -[ApiController] -[Route("api/[controller]")] -public class CommandController : ControllerBase -{ - private readonly ILogger _logger; - - public CommandController(ILogger logger) - { - _logger = logger; - } - - /// - /// Stops (aborts) an agent's active session. - /// Sends an abort command to the OpenClaw Gateway. - /// - /// The agent identifier to stop. - /// Confirmation of the stop command. - /// Stop command sent successfully. - /// No active session found for the agent. - [HttpPost("stop/{agentId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult StopAgent(string agentId) - { - _logger.LogInformation("Stop command received for agent {AgentId}", agentId); - - // TODO: Forward to Gateway via bridge service - // await _bridgeService.SendRpcAsync("sessions.abort", new { sessionKey = ... }); - - return Ok(new - { - agentId, - command = "stop", - status = "sent", - timestamp = DateTime.UtcNow.ToString("o") - }); - } - - /// - /// Restarts an agent by aborting the current session and allowing - /// a new one to start on the next incoming message. - /// - /// The agent identifier to restart. - /// Confirmation of the restart command. - /// Restart command sent successfully. - [HttpPost("restart/{agentId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - public IActionResult RestartAgent(string agentId) - { - _logger.LogInformation("Restart command received for agent {AgentId}", agentId); - - // TODO: Forward to Gateway — abort current session + signal restart - - return Ok(new - { - agentId, - command = "restart", - status = "sent", - timestamp = DateTime.UtcNow.ToString("o") - }); - } - - /// - /// Steers (injects a message into) an agent's active session. - /// Used by operators to redirect an agent's task mid-execution. - /// - /// The agent identifier to steer. - /// The steering message to inject. - /// Confirmation of the steer command. - /// Steer command sent successfully. - /// Missing or empty message. - [HttpPost("steer/{agentId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - public IActionResult SteerAgent(string agentId, [FromBody] SteerRequest request) - { - if (string.IsNullOrWhiteSpace(request.Message)) - { - return BadRequest(new { error = "Message is required" }); - } - - _logger.LogInformation("Steer command received for agent {AgentId}: {Message}", - agentId, request.Message.Length > 100 - ? request.Message[..100] + "..." : request.Message); - - // TODO: Forward to Gateway via bridge service - // await _bridgeService.SendRpcAsync("sessions.steer", new { sessionKey = ..., message = request.Message }); - - return Ok(new - { - agentId, - command = "steer", - message = request.Message, - status = "sent", - timestamp = DateTime.UtcNow.ToString("o") - }); - } -} - -/// -/// Request body for the steer command. -/// -/// The message to inject into the agent's session. -public record SteerRequest(string Message); \ No newline at end of file diff --git a/backend/ControlCenter/Controllers/LogsController.cs b/backend/ControlCenter/Controllers/LogsController.cs deleted file mode 100644 index 238c345..0000000 --- a/backend/ControlCenter/Controllers/LogsController.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace ControlCenter.Controllers; - -/// -/// REST API for querying agent session logs. -/// Provides historical message and tool call logs for a specific agent. -/// -/// API contract for Rex (Frontend): -/// -/// GET /api/logs/{agentId} — Returns recent logs for an agent -/// GET /api/logs/{agentId}/tools — Returns recent tool calls for an agent -/// -/// -/// Log data is sourced from the OpenClaw Gateway's transcript files. -/// The Gateway's logs.tail RPC provides the raw data, and this -/// controller formats it for the frontend. -/// -[ApiController] -[Route("api/[controller]")] -public class LogsController : ControllerBase -{ - private readonly ILogger _logger; - - public LogsController(ILogger logger) - { - _logger = logger; - } - - /// - /// Gets recent session logs for a specific agent. - /// Returns the last N messages from the agent's active session transcript. - /// - /// The agent identifier, e.g. "otto", "dex". - /// Maximum number of log entries to return (default: 50, max: 200). - /// An array of log entries for the agent. - /// Returns the agent's recent logs. - /// No active session found for the agent. - [HttpGet("{agentId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult GetLogs(string agentId, [FromQuery] int limit = 50) - { - limit = Math.Clamp(limit, 1, 200); - - _logger.LogDebug("Logs requested for agent {AgentId}, limit {Limit}", agentId, limit); - - // TODO: Implement log retrieval by calling the Gateway's logs.tail RPC - // or reading transcript files. For now, return an empty array as the - // bridge service will provide this data when fully integrated. - return Ok(new - { - agentId, - logs = Array.Empty(), - count = 0, - hasMore = false - }); - } - - /// - /// Gets recent tool call logs for a specific agent. - /// Returns the last N tool invocations from the agent's session. - /// - /// The agent identifier. - /// Maximum number of tool entries to return (default: 20, max: 100). - /// An array of tool call entries for the agent. - /// Returns the agent's recent tool calls. - /// No active session found for the agent. - [HttpGet("{agentId}/tools")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - public IActionResult GetToolLogs(string agentId, [FromQuery] int limit = 20) - { - limit = Math.Clamp(limit, 1, 100); - - _logger.LogDebug("Tool logs requested for agent {AgentId}, limit {Limit}", agentId, limit); - - // TODO: Implement tool log retrieval. Return empty for now. - return Ok(new - { - agentId, - tools = Array.Empty(), - count = 0, - hasMore = false - }); - } -} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/AgentStatusHub.cs b/backend/ControlCenter/Hubs/AgentStatusHub.cs deleted file mode 100644 index c790b29..0000000 --- a/backend/ControlCenter/Hubs/AgentStatusHub.cs +++ /dev/null @@ -1,211 +0,0 @@ -using Microsoft.AspNetCore.SignalR; - -namespace ControlCenter.Hubs; - -/// -/// SignalR hub for real-time agent status updates in the Command Hub. -/// -/// Usage flow: -/// -/// Client connects to /hubs/agent-status -/// Client calls to subscribe to all agent updates -/// Client calls to subscribe to a specific agent -/// Server pushes -/// and events -/// Client calls for initial state on connect -/// -/// -/// Group naming: -/// -/// Fleet group: fleet — receives all agent updates -/// Agent group: agent:{agentId} — receives updates for one agent -/// -/// -/// Typed client: — all server-to-client -/// calls go through this interface for compile-time safety. -/// -/// Architecture note: This hub bridges OpenClaw Gateway WebSocket events -/// to SignalR clients. A background service () -/// subscribes to Gateway events and pushes them through this hub's extension methods. -/// -public class AgentStatusHub : Hub -{ - private readonly ILogger _logger; - - public AgentStatusHub(ILogger logger) - { - _logger = logger; - } - - /// - /// Broadcasts an agent status update to all connected clients. - /// - /// - /// Any connected client (or server-side caller) can invoke this method - /// to push a status update to every subscriber. The DTO is converted to - /// an record and relayed through the - /// callback. - /// - /// - /// The agent status update DTO to broadcast. - public async Task SendStatusUpdate(AgentStatusUpdateDto update) - { - _logger.LogInformation( - "Broadcasting status update for agent {AgentId}: {Status}", - update.AgentId, update.Status); - - var agentUpdate = update.ToUpdate(); - - // Broadcast to all connected clients - await Clients.All.AgentStatusChanged(agentUpdate); - - // Also push to the specific agent's group - var agentGroup = AgentGroupName(update.AgentId); - await Clients.Group(agentGroup).AgentStatusChanged(agentUpdate); - } - - /// - /// Adds the calling connection to the fleet group. - /// Once joined, the client will receive all agent status changes - /// and task progress updates across the entire fleet. - /// - public async Task JoinFleet() - { - await Groups.AddToGroupAsync(Context.ConnectionId, FleetGroupName); - _logger.LogDebug("Connection {ConnectionId} joined fleet group", Context.ConnectionId); - } - - /// - /// Removes the calling connection from the fleet group. - /// - public async Task LeaveFleet() - { - await Groups.RemoveFromGroupAsync(Context.ConnectionId, FleetGroupName); - _logger.LogDebug("Connection {ConnectionId} left fleet group", Context.ConnectionId); - } - - /// - /// Adds the calling connection to a specific agent's group. - /// Once joined, the client will receive updates only for that agent. - /// - /// The agent identifier, e.g. "otto", "dex". - /// Thrown if agentId is null or empty. - public async Task JoinAgentGroup(string agentId) - { - if (string.IsNullOrWhiteSpace(agentId)) - throw new HubException("agentId is required"); - - var groupName = AgentGroupName(agentId); - await Groups.AddToGroupAsync(Context.ConnectionId, groupName); - _logger.LogDebug("Connection {ConnectionId} joined agent group {GroupName}", - Context.ConnectionId, groupName); - } - - /// - /// Removes the calling connection from a specific agent's group. - /// - /// The agent identifier. - public async Task LeaveAgentGroup(string agentId) - { - if (string.IsNullOrWhiteSpace(agentId)) return; - - var groupName = AgentGroupName(agentId); - await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName); - } - - /// - /// Returns a snapshot of the current fleet state. - /// Called by clients on initial connection to get the full picture - /// before incremental updates begin arriving. - /// - /// An array of representing all known agents. - public Task GetFleetSnapshot() - { - // The fleet state is managed by the GatewayEventBridgeService. - // For now, return an empty array — the bridge service will push - // updates as they arrive from the Gateway. - _logger.LogDebug("Fleet snapshot requested by {ConnectionId}", Context.ConnectionId); - return Task.FromResult(Array.Empty()); - } - - /// - /// Overrides to perform cleanup. - /// SignalR automatically removes disconnected connections from all groups. - /// - /// Exception that caused the disconnection, if any. - public override Task OnDisconnectedAsync(Exception? exception) - { - _logger.LogDebug("Connection {ConnectionId} disconnected", Context.ConnectionId); - return base.OnDisconnectedAsync(exception); - } - - /// - /// The SignalR group name for the entire fleet (all agents). - /// - internal const string FleetGroupName = "fleet"; - - /// - /// Returns the SignalR group name for a specific agent. - /// Format: agent:{agentId} (lowercase for consistency). - /// - /// The agent identifier. - internal static string AgentGroupName(string agentId) => - $"agent:{agentId.ToLowerInvariant()}"; -} - -/// -/// Extension methods for pushing real-time agent updates through -/// the of . -/// -/// These methods are intended to be called from background services -/// (e.g., ) or other -/// server-side code that detects an agent state change. -/// -public static class AgentStatusHubExtensions -{ - /// - /// Pushes an agent status change to all clients subscribed to - /// the fleet group and the specific agent's group. - /// - /// Call this from any background service when an agent's - /// operational status changes (e.g., the Gateway reports a - /// session transition from "running" to "done"). - /// - /// The hub context injected via DI. - /// The agent status update payload. - /// A Task that completes when the message has been sent to all group members. - public static async Task PushAgentStatusAsync( - this IHubContext hubContext, - AgentStatusUpdate update) - { - // Broadcast to the fleet group (all subscribers) - await hubContext.Clients.Group(AgentStatusHub.FleetGroupName) - .AgentStatusChanged(update); - - // Also push to the specific agent's group - var agentGroup = AgentStatusHub.AgentGroupName(update.AgentId); - await hubContext.Clients.Group(agentGroup) - .AgentStatusChanged(update); - } - - /// - /// Pushes a task progress update to all clients subscribed to - /// the fleet group and the specific agent's group. - /// - /// The hub context injected via DI. - /// The task progress update payload. - /// A Task that completes when the message has been sent to all group members. - public static async Task PushTaskProgressAsync( - this IHubContext hubContext, - TaskProgressUpdate progress) - { - // Broadcast to the fleet group - await hubContext.Clients.Group(AgentStatusHub.FleetGroupName) - .AgentTaskProgress(progress); - - // Also push to the specific agent's group - var agentGroup = AgentStatusHub.AgentGroupName(progress.AgentId); - await hubContext.Clients.Group(agentGroup) - .AgentTaskProgress(progress); - } -} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/IAgentStatusClient.cs b/backend/ControlCenter/Hubs/IAgentStatusClient.cs deleted file mode 100644 index 4f3e1ea..0000000 --- a/backend/ControlCenter/Hubs/IAgentStatusClient.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace ControlCenter.Hubs; - -/// -/// Strongly-typed client interface for the AgentStatus SignalR hub. -/// Defines the methods the server can invoke on connected clients -/// to push real-time agent status and task progress updates. -/// -/// All server-to-client calls go through this interface for -/// compile-time safety — matching the pattern used by the -/// Extrudex PrinterHub. -/// -public interface IAgentStatusClient -{ - /// - /// Pushes an agent status change to all subscribed clients. - /// Fired whenever an agent's operational status changes - /// (e.g., idle → active, active → thinking, active → error). - /// - /// The full status update payload. - /// A Task that completes when the client has processed the update. - Task AgentStatusChanged(AgentStatusUpdate update); - - /// - /// Pushes a task progress update to all subscribed clients. - /// Fired when an agent reports progress on its current task. - /// - /// The task progress update payload. - /// A Task that completes when the client has processed the update. - Task AgentTaskProgress(TaskProgressUpdate progress); -} \ No newline at end of file diff --git a/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs b/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs deleted file mode 100644 index 3edb603..0000000 --- a/backend/ControlCenter/Hubs/Models/AgentStatusModels.cs +++ /dev/null @@ -1,166 +0,0 @@ -namespace ControlCenter; - -/// -/// Agent operational status derived from OpenClaw Gateway session activity. -/// Maps to the frontend AgentStatus type: 'active' | 'idle' | 'thinking' | 'error'. -/// -public enum AgentStatus -{ - /// Agent is currently processing a turn. - Active, - - /// Agent completed its last turn; no active work. - Idle, - - /// LLM call in flight; tokens streaming. - Thinking, - - /// Agent encountered an unhandled error. - Error -} - -/// -/// Extended lifecycle status including offline — not all agents have active sessions. -/// Used internally; clients only see (offline maps to idle). -/// -public enum AgentLifecycleStatus -{ - Active, - Idle, - Thinking, - Error, - Offline -} - -/// -/// Pushed to SignalR clients when an agent's status changes. -/// Matches the TypeScript AgentStatusUpdate interface from the design spec. -/// -/// Agent identifier, e.g. "otto", "dex". -/// Human-readable name, e.g. "Otto". -/// Role description, e.g. "Orchestrator Agent". -/// Current operational status. -/// Description of the current task, if any. -/// Full session key, e.g. "agent:otto:telegram:direct:8787451565". -/// Channel the agent is operating on, e.g. "telegram". -/// ISO 8601 timestamp of last activity. -/// Error message when status is 'error'. -public record AgentStatusUpdate( - string AgentId, - string DisplayName, - string Role, - string Status, - string? CurrentTask, - string SessionKey, - string Channel, - string LastActivity, - string? ErrorMessage = null -); - -/// -/// Pushed to SignalR clients when an agent's task progress updates. -/// Matches the TypeScript TaskProgressUpdate interface from the design spec. -/// -/// Agent identifier. -/// Description of the current task. -/// Task progress percentage (0–100), if trackable. -/// Elapsed time string, e.g. "04m 12s". -public record TaskProgressUpdate( - string AgentId, - string TaskDescription, - int? Progress, - string? Elapsed -); - -/// -/// Data transfer object for broadcasting agent status updates -/// to all connected SignalR clients via the hub's SendStatusUpdate method. -/// -/// This DTO provides a mutable, serialization-friendly alternative to -/// for callers that construct updates -/// from external data sources (e.g., HTTP API payloads). -/// -public class AgentStatusUpdateDto -{ - /// - /// Agent identifier, e.g. "otto", "dex", "rex". - /// - public string AgentId { get; set; } = string.Empty; - - /// - /// Human-readable display name, e.g. "Otto", "Dex". - /// - public string DisplayName { get; set; } = string.Empty; - - /// - /// Role description, e.g. "Orchestrator Agent", "Backend Specialist". - /// - public string Role { get; set; } = string.Empty; - - /// - /// Current operational status of the agent as lowercase string: - /// "active", "idle", "thinking", "error". - /// - public string Status { get; set; } = string.Empty; - - /// - /// Description of the agent's current task, if any. - /// - public string? CurrentTask { get; set; } - - /// - /// Full session key, e.g. "agent:otto:telegram:direct:8787451565". - /// - public string SessionKey { get; set; } = string.Empty; - - /// - /// Communication channel, e.g. "telegram", "discord", "slack". - /// - public string Channel { get; set; } = string.Empty; - - /// - /// ISO 8601 timestamp of the agent's last activity. - /// - public string LastActivity { get; set; } = string.Empty; - - /// - /// Error message when the agent status is "error". - /// - public string? ErrorMessage { get; set; } - - /// - /// Converts this DTO to an immutable record - /// for use with the typed SignalR client interface. - /// - /// An with equivalent field values. - public AgentStatusUpdate ToUpdate() => new( - AgentId, - DisplayName, - Role, - Status, - CurrentTask, - SessionKey, - Channel, - LastActivity, - ErrorMessage - ); -} - -/// -/// Snapshot of an agent's full card data, sent on initial connection -/// or when the fleet state is requested. -/// Matches the TypeScript AgentCardData interface from the design spec. -/// -public record AgentCardData( - string Id, - string DisplayName, - string Role, - string Status, - string? CurrentTask, - int? TaskProgress, - string? TaskElapsed, - string SessionKey, - string Channel, - string LastActivity, - string? ErrorMessage -); \ No newline at end of file diff --git a/backend/ControlCenter/Models/AgentMinionMapping.cs b/backend/ControlCenter/Models/AgentMinionMapping.cs deleted file mode 100644 index c9886dd..0000000 --- a/backend/ControlCenter/Models/AgentMinionMapping.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace ControlCenter.Models; - -/// -/// Defines which side of the Control Center dashboard a minion occupies. -/// -public enum MinionSide -{ - /// Development side — Rex, Dex, Hex. - Dev, - - /// Business side — Larry, Mel, Buzz. - Business -} - -/// -/// Visual state of a minion sprite, derived from the agent's -/// . Maps Active/Idle/Thinking/Error -/// to frontend animation states. -/// -public enum MinionState -{ - /// Agent is actively processing — minion shows working animation. - Active, - - /// Agent is idle — minion shows idle/patrolling animation. - Idle, - - /// Agent is thinking (LLM call in flight) — minion shows thinking animation. - Thinking, - - /// Agent encountered an error — minion shows error/distress animation. - Error -} - -/// -/// Static mapping entry that associates an agent ID with a minion's -/// display side and position index within that side. -/// -/// Position indices are zero-based within each side. The dev side -/// has Rex at 0, Dex at 1, and Hex at 2. The business side has -/// Larry at 0, Mel at 1, and Buzz at 2. -/// -/// Agent identifier, e.g. "rex", "dex". -/// Which side of the dashboard the minion occupies. -/// Zero-based position index within the side. -/// Human-readable name, e.g. "Rex". -public record AgentMinionMapping( - string AgentId, - MinionSide Side, - int PositionIndex, - string DisplayName -); - -/// -/// Real-time minion state update pushed to SignalR clients -/// when an agent's status changes. Combines the static mapping -/// (who/where) with the dynamic state (what the minion is doing). -/// -/// Agent identifier, e.g. "rex". -/// Human-readable minion name, e.g. "Rex". -/// Which side of the dashboard — Dev or Business. -/// Position within the side (0-based). -/// Current minion animation state. -/// ISO 8601 timestamp of the state change. -public record MinionStateUpdate( - string AgentId, - string DisplayName, - MinionSide Side, - int PositionIndex, - MinionState State, - string Timestamp -); \ No newline at end of file diff --git a/backend/ControlCenter/Program.cs b/backend/ControlCenter/Program.cs deleted file mode 100644 index 2b322ab..0000000 --- a/backend/ControlCenter/Program.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Reflection; -using ControlCenter.Hubs; -using ControlCenter.Services; - -var builder = WebApplication.CreateBuilder(args); - -// ── API Services ─────────────────────────────────────────── -builder.Services.AddControllers(); -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(c => -{ - c.SwaggerDoc("v1", new() - { - Title = "Control Center API", - Version = "v1", - Description = "OpenClaw Control Center — Command Hub backend with SignalR real-time updates" - }); - - // Include XML doc comments in Swagger output - var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; - var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - if (File.Exists(xmlPath)) - { - c.IncludeXmlComments(xmlPath); - } -}); - -// ── CORS (kiosk + remote browser) ───────────────────────── -// The Control Center frontend runs on a different origin than the backend. -// SignalR requires credentials for WebSocket transport, so we use -// specific origins rather than AllowAnyOrigin. -var corsOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins") - .Get() ?? new[] { "http://localhost:4200", "http://localhost:5000" }; - -builder.Services.AddCors(options => -{ - options.AddDefaultPolicy(policy => - { - policy.WithOrigins(corsOrigins) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); // Required for SignalR WebSocket - }); -}); - -// ── SignalR (real-time agent status updates) ─────────────── -builder.Services.AddSignalR(); - -// ── Gateway Bridge Service ──────────────────────────────── -// Background service that connects to the OpenClaw Gateway WebSocket -// and bridges events to the AgentStatus SignalR hub. -builder.Services.AddSingleton(); -builder.Services.AddHostedService(sp => sp.GetRequiredService()); - -// ── Agent-Minion Mapper Service ──────────────────────────── -// Maps agents to minion sprites/positions and publishes state -// updates through SignalR. -builder.Services.AddSingleton(); - -var app = builder.Build(); - -// ── Middleware ────────────────────────────────────────────── -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(); -} - -app.UseCors(); -app.UseAuthorization(); -app.MapControllers(); - -// ── Hub Endpoints ─────────────────────────────────────────── -// Agent status hub at /hubs/agent-status (matches the design spec) -app.MapHub("/hubs/agent-status"); - -app.Run(); \ No newline at end of file diff --git a/backend/ControlCenter/Properties/launchSettings.json b/backend/ControlCenter/Properties/launchSettings.json deleted file mode 100644 index 5596756..0000000 --- a/backend/ControlCenter/Properties/launchSettings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "applicationUrl": "http://localhost:5053", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/backend/ControlCenter/Services/AgentMinionMapperService.cs b/backend/ControlCenter/Services/AgentMinionMapperService.cs deleted file mode 100644 index 0dd82ef..0000000 --- a/backend/ControlCenter/Services/AgentMinionMapperService.cs +++ /dev/null @@ -1,193 +0,0 @@ -using ControlCenter.Hubs; -using ControlCenter.Models; -using Microsoft.AspNetCore.SignalR; - -namespace ControlCenter.Services; - -/// -/// Service that maps Linear agents to minion sprites and positions -/// in the Control Center dashboard. -/// -/// Static mappings define where each minion appears: -/// -/// Dev side: Rex (0), Dex (1), Hex (2) -/// Business side: Larry (0), Mel (1), Buzz (2) -/// -/// -/// Dynamic state is derived from the agent's : -/// -/// Active -/// Idle -/// Thinking -/// Error -/// -/// -/// State updates are published through the -/// SignalR hub so that connected clients can animate minion sprites -/// in real time. -/// -public class AgentMinionMapperService -{ - private readonly ILogger _logger; - private readonly IHubContext _hubContext; - - /// - /// Static agent-to-minion mapping table. Defines which side and position - /// each agent's minion occupies on the dashboard. - /// - private static readonly Dictionary Mappings = new() - { - // ── Dev Side ────────────────────────────────── - ["rex"] = new AgentMinionMapping("rex", MinionSide.Dev, 0, "Rex"), - ["dex"] = new AgentMinionMapping("dex", MinionSide.Dev, 1, "Dex"), - ["hex"] = new AgentMinionMapping("hex", MinionSide.Dev, 2, "Hex"), - - // ── Business Side ───────────────────────────── - ["larry"] = new AgentMinionMapping("larry", MinionSide.Business, 0, "Larry"), - ["mel"] = new AgentMinionMapping("mel", MinionSide.Business, 1, "Mel"), - ["buzz"] = new AgentMinionMapping("buzz", MinionSide.Business, 2, "Buzz"), - }; - - /// - /// Maps string values to . - /// - private static readonly Dictionary StatusToMinionState = new() - { - ["active"] = MinionState.Active, - ["idle"] = MinionState.Idle, - ["thinking"] = MinionState.Thinking, - ["error"] = MinionState.Error, - }; - - public AgentMinionMapperService( - ILogger logger, - IHubContext hubContext) - { - _logger = logger; - _hubContext = hubContext; - } - - /// - /// Gets the minion mapping for a given agent ID. - /// Returns null if the agent is not mapped to a minion position. - /// - /// The agent identifier, e.g. "rex", "dex". - /// The mapping record, or null if unmapped. - public AgentMinionMapping? GetMapping(string agentId) - { - return Mappings.GetValueOrDefault(agentId?.ToLowerInvariant() ?? string.Empty); - } - - /// - /// Gets all minion mappings, ordered by side then position index. - /// - /// All mappings, sorted for consistent display order. - public IReadOnlyList GetAllMappings() - { - return Mappings.Values - .OrderBy(m => m.Side) - .ThenBy(m => m.PositionIndex) - .ToList(); - } - - /// - /// Converts an agent status string to a . - /// Falls back to for unrecognized statuses. - /// - /// Agent status string: "active", "idle", "thinking", or "error". - /// The corresponding minion state. - public MinionState StatusToState(string status) - { - return StatusToMinionState.GetValueOrDefault( - status?.ToLowerInvariant() ?? string.Empty, - MinionState.Idle); - } - - /// - /// Publishes a minion state update through SignalR when an agent's - /// status changes. Only publishes for agents that have a minion mapping. - /// - /// This is the primary integration point: the - /// calls this method - /// whenever it detects a status change from the OpenClaw Gateway. - /// - /// The agent whose status changed, e.g. "dex". - /// The new status string: "active", "idle", "thinking", or "error". - /// A task that completes when the SignalR message has been sent. - public async Task PublishMinionStateUpdateAsync(string agentId, string status) - { - var mapping = GetMapping(agentId); - if (mapping is null) - { - _logger.LogDebug("No minion mapping for agent {AgentId}; skipping state update", agentId); - return; - } - - var minionState = StatusToState(status); - var update = new MinionStateUpdate( - AgentId: mapping.AgentId, - DisplayName: mapping.DisplayName, - Side: mapping.Side, - PositionIndex: mapping.PositionIndex, - State: minionState, - Timestamp: DateTime.UtcNow.ToString("o") - ); - - // Broadcast to the fleet group (all subscribers) - await _hubContext.Clients.Group(AgentStatusHub.FleetGroupName) - .AgentStatusChanged(ToAgentStatusUpdate(agentId, status)); - - // Also push to the specific agent's group - var agentGroup = AgentStatusHub.AgentGroupName(agentId); - await _hubContext.Clients.Group(agentGroup) - .AgentStatusChanged(ToAgentStatusUpdate(agentId, status)); - - _logger.LogInformation( - "Minion state update: {AgentId} → {State} (Side: {Side}, Position: {Index})", - agentId, minionState, mapping.Side, mapping.PositionIndex); - } - - /// - /// Gets the current minion state for all mapped agents, suitable - /// for building an initial fleet snapshot. - /// - /// All minion mappings with their current (idle) state. - public IReadOnlyList GetFullMinionState() - { - return Mappings.Values - .OrderBy(m => m.Side) - .ThenBy(m => m.PositionIndex) - .Select(m => new MinionStateUpdate( - AgentId: m.AgentId, - DisplayName: m.DisplayName, - Side: m.Side, - PositionIndex: m.PositionIndex, - State: MinionState.Idle, - Timestamp: DateTime.UtcNow.ToString("o"))) - .ToList(); - } - - /// - /// Converts a status string to an - /// for SignalR push. Uses the mapping table for display names and roles. - /// - private AgentStatusUpdate ToAgentStatusUpdate(string agentId, string status) - { - var mapping = GetMapping(agentId); - var displayName = mapping?.DisplayName ?? char.ToUpperInvariant(agentId[0]) + agentId[1..]; - - return new AgentStatusUpdate( - AgentId: agentId, - DisplayName: displayName, - Role: mapping is not null - ? $"{mapping.Side} Agent" - : "Agent", - Status: status, - CurrentTask: null, - SessionKey: string.Empty, - Channel: string.Empty, - LastActivity: DateTime.UtcNow.ToString("o"), - ErrorMessage: status == "error" ? "Agent encountered an error" : null - ); - } -} \ No newline at end of file diff --git a/backend/ControlCenter/Services/GatewayEventBridgeService.cs b/backend/ControlCenter/Services/GatewayEventBridgeService.cs deleted file mode 100644 index 0f37285..0000000 --- a/backend/ControlCenter/Services/GatewayEventBridgeService.cs +++ /dev/null @@ -1,523 +0,0 @@ -using System.Collections.Concurrent; -using System.Net.WebSockets; -using System.Text; -using System.Text.Json; -using ControlCenter.Hubs; -using Microsoft.AspNetCore.SignalR; - -namespace ControlCenter.Services; - -/// -/// Background service that connects to the OpenClaw Gateway WebSocket -/// and bridges Gateway events to the . -/// -/// Architecture: -/// -/// Connects to the Gateway WS endpoint (configurable via appsettings) -/// Handles the v3 protocol handshake (challenge → connect → hello-ok) -/// Subscribes to sessions.changed and related events -/// Translates session state changes into -/// and objects -/// Pushes updates through the SignalR hub -/// -/// -/// This is the server-side bridge that allows Angular clients to -/// receive real-time updates via SignalR instead of connecting directly -/// to the Gateway WebSocket. -/// -public class GatewayEventBridgeService : BackgroundService -{ - private readonly ILogger _logger; - private readonly IHubContext _hubContext; - private readonly IConfiguration _configuration; - - /// - /// In-memory fleet state — maps agent IDs to their latest card data. - /// Updated on every sessions.changed event from the Gateway. - /// - private readonly ConcurrentDictionary _fleetState = new(); - - /// - /// Known agent roles for display in the Command Hub. - /// Maps agent IDs to their functional descriptions. - /// - private static readonly Dictionary AgentRoles = new() - { - ["main"] = "Primary Assistant", - ["otto"] = "Orchestrator Agent", - ["dave"] = "Network Admin Agent", - ["bob"] = "Content Writer Agent", - ["stuart"] = "Image & Creative Agent", - ["phil"] = "Home Automation Agent", - ["carl"] = "Security Agent", - ["larry"] = "Business Agent", - ["mel"] = "E-Commerce Agent", - ["norbert"] = "Product Agent", - ["jerry"] = "Market Research Agent", - ["rex"] = "Frontend Dev Agent", - ["dex"] = "Backend Dev Agent", - ["hex"] = "Database Agent", - ["pip"] = "Raspberry Pi Agent", - ["nano"] = "ESP32/Firmware Agent", - ["axiom"] = "Utility Agent", - ["bonnie"] = "Music Agent", - ["sketch"] = "UI/UX Design Agent", - ["flip"] = "Mobile Dev Agent", - ["buzz"] = "SEO Agent", - ["aries"] = "Companion Agent" - }; - - /// - /// Maps OpenClaw session status to . - /// - private static string MapSessionStatus(string? sessionStatus) => sessionStatus switch - { - "running" => "active", - "streaming" => "thinking", - "error" or "aborted" => "error", - "done" => "idle", - _ => "idle" - }; - - public GatewayEventBridgeService( - ILogger logger, - IHubContext hubContext, - IConfiguration configuration) - { - _logger = logger; - _hubContext = hubContext; - _configuration = configuration; - } - - /// - /// Returns the current fleet state snapshot. - /// Used by the hub's GetFleetSnapshot method and by the - /// AgentsController REST endpoint. - /// - public AgentCardData[] GetFleetSnapshot() => - _fleetState.Values.ToArray(); - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - _logger.LogInformation("Gateway Event Bridge service starting"); - - while (!stoppingToken.IsCancellationRequested) - { - try - { - await ConnectAndListenAsync(stoppingToken); - } - catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) - { - _logger.LogInformation("Gateway Event Bridge service stopping"); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "Gateway connection lost, reconnecting in 5 seconds..."); - await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); - } - } - } - - /// - /// Connects to the OpenClaw Gateway WebSocket and processes events - /// until the connection is lost or cancellation is requested. - /// - private async Task ConnectAndListenAsync(CancellationToken stoppingToken) - { - var gatewayUrl = _configuration["Gateway:WebSocketUrl"] - ?? "ws://localhost:3271/ws"; - var authToken = _configuration["Gateway:AuthToken"] ?? string.Empty; - - _logger.LogInformation("Connecting to Gateway at {Url}", gatewayUrl); - - using var ws = new ClientWebSocket(); - - // Set auth header if available - if (!string.IsNullOrEmpty(authToken)) - { - ws.Options.SetRequestHeader("Authorization", $"Bearer {authToken}"); - } - - await ws.ConnectAsync(new Uri(gatewayUrl), stoppingToken); - _logger.LogInformation("Connected to Gateway WebSocket"); - - // Start receiving messages - await ReceiveMessagesAsync(ws, stoppingToken); - } - - /// - /// Receives and processes WebSocket messages from the Gateway. - /// Handles the v3 protocol handshake and dispatches events. - /// - private async Task ReceiveMessagesAsync(ClientWebSocket ws, CancellationToken stoppingToken) - { - var buffer = new byte[8192]; - var messageBuilder = new StringBuilder(); - - while (ws.State == WebSocketState.Open && !stoppingToken.IsCancellationRequested) - { - WebSocketReceiveResult result; - try - { - result = await ws.ReceiveAsync(buffer, stoppingToken); - } - catch (WebSocketException ex) - { - _logger.LogWarning(ex, "WebSocket receive error"); - break; - } - - if (result.MessageType == WebSocketMessageType.Close) - { - _logger.LogInformation("Gateway WebSocket closed by server"); - break; - } - - messageBuilder.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); - - if (result.EndOfMessage) - { - var message = messageBuilder.ToString(); - messageBuilder.Clear(); - await ProcessMessageAsync(ws, message, stoppingToken); - } - } - } - - /// - /// Processes a single WebSocket message from the Gateway. - /// Routes based on the message type: event, response, or challenge. - /// - private async Task ProcessMessageAsync( - ClientWebSocket ws, string message, CancellationToken stoppingToken) - { - try - { - using var doc = JsonDocument.Parse(message); - var root = doc.RootElement; - - var type = root.GetProperty("type").GetString(); - - switch (type) - { - case "event": - await HandleGatewayEventAsync(root); - break; - - case "res": - HandleGatewayResponse(root); - break; - } - - // Special handling for connect.challenge events - if (root.TryGetProperty("event", out var eventName) && - eventName.GetString() == "connect.challenge") - { - await HandleConnectChallengeAsync(ws, root, stoppingToken); - } - } - catch (JsonException ex) - { - _logger.LogWarning(ex, "Failed to parse Gateway message: {Message}", - message.Length > 200 ? message[..200] + "..." : message); - } - } - - /// - /// Handles the Gateway connect.challenge event by sending - /// a connect request with authentication credentials. - /// - private async Task HandleConnectChallengeAsync( - ClientWebSocket ws, JsonElement root, CancellationToken stoppingToken) - { - _logger.LogInformation("Received connect.challenge from Gateway"); - - var connectRequest = new - { - type = "req", - id = $"bridge-{Guid.NewGuid():N}", - method = "connect", - @params = new - { - minProtocol = 3, - maxProtocol = 3, - client = new - { - id = "control-center-backend", - version = "1.0.0", - platform = "server", - mode = "operator" - }, - role = "operator", - scopes = new[] { "operator.read", "operator.write" }, - auth = new - { - token = _configuration["Gateway:AuthToken"] ?? string.Empty - }, - locale = "en-US", - userAgent = "control-center-backend/1.0.0" - } - }; - - var json = JsonSerializer.Serialize(connectRequest); - var bytes = Encoding.UTF8.GetBytes(json); - await ws.SendAsync(bytes, WebSocketMessageType.Text, true, stoppingToken); - } - - /// - /// Handles a Gateway event message by dispatching to the - /// appropriate handler based on event name. - /// - private async Task HandleGatewayEventAsync(JsonElement root) - { - if (!root.TryGetProperty("event", out var eventProp)) return; - var eventName = eventProp.GetString(); - - _logger.LogDebug("Gateway event: {Event}", eventName); - - switch (eventName) - { - case "sessions.changed": - await HandleSessionsChangedAsync(root); - break; - - case "session.message": - HandleSessionMessage(root); - break; - - case "session.tool": - HandleSessionTool(root); - break; - - case "health": - HandleHealthEvent(root); - break; - } - } - - /// - /// Handles a sessions.changed event from the Gateway. - /// Updates the fleet state and pushes status changes through SignalR. - /// - private async Task HandleSessionsChangedAsync(JsonElement root) - { - if (!root.TryGetProperty("payload", out var payload)) return; - - // The payload may contain a snapshot of all sessions - if (payload.TryGetProperty("snapshot", out var snapshot) && - snapshot.ValueKind == JsonValueKind.Array) - { - foreach (var session in snapshot.EnumerateArray()) - { - var cardData = SessionToCardData(session); - if (cardData is null) continue; - - _fleetState[cardData.Id] = cardData; - - var update = new AgentStatusUpdate( - AgentId: cardData.Id, - DisplayName: cardData.DisplayName, - Role: cardData.Role, - Status: cardData.Status, - CurrentTask: cardData.CurrentTask, - SessionKey: cardData.SessionKey, - Channel: cardData.Channel, - LastActivity: cardData.LastActivity, - ErrorMessage: cardData.ErrorMessage - ); - - await _hubContext.PushAgentStatusAsync(update); - } - } - - // Handle individual updates/added/removed - if (payload.TryGetProperty("updated", out var updated) && - updated.ValueKind == JsonValueKind.Array) - { - foreach (var sessionKey in updated.EnumerateArray()) - { - _logger.LogDebug("Session updated: {Key}", sessionKey.GetString()); - } - } - } - - /// - /// Handles a session.message event. Updates the agent's last activity - /// and pushes a status update if the status changed. - /// - private void HandleSessionMessage(JsonElement root) - { - if (!root.TryGetProperty("payload", out var payload)) return; - if (!payload.TryGetProperty("sessionKey", out var sessionKeyProp)) return; - - var sessionKey = sessionKeyProp.GetString() ?? string.Empty; - var agentId = ExtractAgentId(sessionKey); - - if (string.IsNullOrEmpty(agentId)) return; - - // Update last activity timestamp - if (_fleetState.TryGetValue(agentId, out var existing)) - { - _fleetState[agentId] = existing with - { - LastActivity = DateTime.UtcNow.ToString("o"), - Status = "active" - }; - } - } - - /// - /// Handles a session.tool event. Extracts tool progress information - /// and pushes a through SignalR. - /// - private void HandleSessionTool(JsonElement root) - { - if (!root.TryGetProperty("payload", out var payload)) return; - if (!payload.TryGetProperty("sessionKey", out var sessionKeyProp)) return; - - var sessionKey = sessionKeyProp.GetString() ?? string.Empty; - var agentId = ExtractAgentId(sessionKey); - - if (string.IsNullOrEmpty(agentId)) return; - - var toolName = payload.TryGetProperty("toolName", out var tn) ? tn.GetString() : null; - var toolStatus = payload.TryGetProperty("status", out var ts) ? ts.GetString() : null; - - if (toolName is null || toolStatus is null) return; - - var progress = toolStatus switch - { - "started" => 0, - "completed" => 100, - _ => (int?)null - }; - - var update = new TaskProgressUpdate( - AgentId: agentId, - TaskDescription: $"{toolName} ({toolStatus})", - Progress: progress, - Elapsed: null - ); - - // Fire and forget — don't block the event loop - _ = _hubContext.PushTaskProgressAsync(update); - } - - /// - /// Handles a health event from the Gateway. - /// Logs the health status for diagnostics. - /// - private void HandleHealthEvent(JsonElement root) - { - if (!root.TryGetProperty("payload", out var payload)) return; - - var ok = payload.TryGetProperty("ok", out var okProp) && okProp.GetBoolean(); - var status = payload.TryGetProperty("status", out var s) ? s.GetString() : "unknown"; - - _logger.LogInformation("Gateway health: ok={Ok}, status={Status}", ok, status); - } - - /// - /// Handles a Gateway response message. Currently only logs for diagnostics. - /// - private void HandleGatewayResponse(JsonElement root) - { - if (root.TryGetProperty("ok", out var okProp) && okProp.GetBoolean()) - { - _logger.LogDebug("Gateway RPC response OK"); - - // Check for hello-ok after connect - if (root.TryGetProperty("payload", out var payload) && - payload.TryGetProperty("type", out var typeProp) && - typeProp.GetString() == "hello-ok") - { - _logger.LogInformation("Gateway handshake complete (hello-ok received)"); - } - } - else if (root.TryGetProperty("error", out var error)) - { - var errorMsg = error.TryGetProperty("message", out var msg) - ? msg.GetString() : "unknown error"; - _logger.LogWarning("Gateway RPC error: {Error}", errorMsg); - } - } - - /// - /// Converts a raw Gateway session JSON element into an - /// record. - /// - private AgentCardData? SessionToCardData(JsonElement session) - { - // Extract agent ID from session key or agentId field - string? agentId = null; - if (session.TryGetProperty("agentId", out var aid)) - agentId = aid.GetString(); - else if (session.TryGetProperty("key", out var key)) - agentId = ExtractAgentId(key.GetString() ?? string.Empty); - - if (string.IsNullOrEmpty(agentId)) return null; - - var sessionKey = session.TryGetProperty("key", out var sk) - ? sk.GetString() ?? string.Empty : string.Empty; - - var status = session.TryGetProperty("status", out var s) - ? MapSessionStatus(s.GetString()) : "idle"; - - var channel = ExtractChannel(session); - - var lastActivity = session.TryGetProperty("updatedAt", out var ua) - ? DateTimeOffset.FromUnixTimeMilliseconds(ua.GetInt64()).ToString("o") - : DateTime.UtcNow.ToString("o"); - - var displayName = char.ToUpperInvariant(agentId![0]) + agentId[1..]; - var role = AgentRoles.GetValueOrDefault(agentId!, "Agent"); - - return new AgentCardData( - Id: agentId!, - DisplayName: displayName, - Role: role, - Status: status, - CurrentTask: null, - TaskProgress: null, - TaskElapsed: null, - SessionKey: sessionKey, - Channel: channel, - LastActivity: lastActivity, - ErrorMessage: status == "error" ? "Agent encountered an error" : null - ); - } - - /// - /// Extracts the agent ID from a session key. - /// Session key format: "agent:{agentId}:{channel}:..." - /// - private static string? ExtractAgentId(string sessionKey) - { - if (string.IsNullOrEmpty(sessionKey)) return null; - - var parts = sessionKey.Split(':'); - if (parts.Length >= 2 && parts[0] == "agent") - return parts[1]; - - return null; - } - - /// - /// Extracts the channel from a session element. - /// - private static string ExtractChannel(JsonElement session) - { - // Try direct "channel" property - if (session.TryGetProperty("channel", out var ch)) - return ch.GetString() ?? "unknown"; - - // Try origin.provider - if (session.TryGetProperty("origin", out var origin) && - origin.TryGetProperty("provider", out var provider)) - return provider.GetString() ?? "unknown"; - - return "unknown"; - } -} \ No newline at end of file diff --git a/backend/ControlCenter/appsettings.Development.json b/backend/ControlCenter/appsettings.Development.json deleted file mode 100644 index 626b82e..0000000 --- a/backend/ControlCenter/appsettings.Development.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "Microsoft.AspNetCore": "Information", - "ControlCenter": "Debug" - } - }, - "Gateway": { - "WebSocketUrl": "ws://localhost:3271/ws", - "AuthToken": "" - }, - "Cors": { - "AllowedOrigins": [ - "http://localhost:4200", - "http://localhost:5000" - ] - } -} \ No newline at end of file diff --git a/backend/ControlCenter/appsettings.json b/backend/ControlCenter/appsettings.json deleted file mode 100644 index 60f801d..0000000 --- a/backend/ControlCenter/appsettings.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning", - "ControlCenter": "Debug" - } - }, - "AllowedHosts": "*", - - "Gateway": { - "WebSocketUrl": "ws://localhost:3271/ws", - "AuthToken": "" - }, - - "Cors": { - "AllowedOrigins": [ - "http://localhost:4200", - "http://localhost:5000" - ] - } -} \ No newline at end of file diff --git a/backend/Data/AppDbContext.cs b/backend/Data/AppDbContext.cs deleted file mode 100644 index 3277f00..0000000 --- a/backend/Data/AppDbContext.cs +++ /dev/null @@ -1,29 +0,0 @@ -using ControlCenter.Api.Configurations; -using ControlCenter.Api.Entities; -using Microsoft.EntityFrameworkCore; - -namespace ControlCenter.Api.Data; - -/// -/// EF Core DbContext for the Control Center database. -/// All table and column names use snake_case via explicit HasColumnName configuration. -/// -public class AppDbContext : DbContext -{ - public AppDbContext(DbContextOptions options) : base(options) { } - - public DbSet Agents => Set(); - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - // Apply all entity type configurations from the Configurations namespace - modelBuilder.ApplyConfigurationsFromAssembly(typeof(AgentConfiguration).Assembly); - - // Map the AgentStatus enum to a PostgreSQL enum type named "agent_status" - // This must be called after ApplyConfigurations to ensure the model is built - // before the enum mapping is applied. - modelBuilder.HasPostgresEnum(); - - base.OnModelCreating(modelBuilder); - } -} \ No newline at end of file diff --git a/backend/Data/AppDbContextFactory.cs b/backend/Data/AppDbContextFactory.cs deleted file mode 100644 index 7b82843..0000000 --- a/backend/Data/AppDbContextFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using ControlCenter.Api.Entities; - -namespace ControlCenter.Api.Data; - -/// -/// Design-time factory for AppDbContext, used by EF Core tools (dotnet ef) -/// to create migrations without requiring a running application. -/// -public class AppDbContextFactory : Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory -{ - public AppDbContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - - // Connection string for design-time operations (migrations). - // In production, this comes from appsettings / environment variables. - var connectionString = "Host=localhost;Database=control_center;Username=postgres;Password=postgres"; - - optionsBuilder.UseNpgsql(connectionString, npgsqlOptions => - { - npgsqlOptions.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName); - }); - - return new AppDbContext(optionsBuilder.Options); - } -} \ No newline at end of file diff --git a/backend/Dtos/AgentStatusUpdateDto.cs b/backend/Dtos/AgentStatusUpdateDto.cs deleted file mode 100644 index b67e74d..0000000 --- a/backend/Dtos/AgentStatusUpdateDto.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace ControlCenter.Api.Dtos; - -/// -/// Data transfer object for broadcasting agent status updates -/// to all connected SignalR clients. -/// -public class AgentStatusUpdateDto -{ - /// - /// Agent identifier, e.g. "otto", "dex", "rex". - /// Not null — every update must identify the agent it refers to. - /// - public string AgentId { get; set; } = string.Empty; - - /// - /// Human-readable display name, e.g. "Otto", "Dex". - /// Not null — used by clients to render agent cards. - /// - public string DisplayName { get; set; } = string.Empty; - - /// - /// Role description, e.g. "Orchestrator Agent", "Backend Specialist". - /// Not null — provides context for the agent's function. - /// - public string Role { get; set; } = string.Empty; - - /// - /// Current operational status of the agent. - /// Maps to values as lowercase strings: - /// "active", "idle", "thinking", "error". - /// - public string Status { get; set; } = string.Empty; - - /// - /// Description of the agent's current task, if any. - /// Null when the agent is idle with no active task. - /// - public string? CurrentTask { get; set; } - - /// - /// Task progress percentage (0–100). - /// Null when progress is not trackable for the current task. - /// - public int? TaskProgress { get; set; } - - /// - /// Elapsed time string for the current task, e.g. "04m 12s". - /// Null when no task is active. - /// - public string? TaskElapsed { get; set; } - - /// - /// Full session key, e.g. "agent:otto:telegram:direct:8787451565". - /// Not null — uniquely identifies the agent session. - /// - public string SessionKey { get; set; } = string.Empty; - - /// - /// Communication channel the agent is operating on, e.g. "telegram", "discord", "slack". - /// Not null — every agent session operates on exactly one channel. - /// - public string Channel { get; set; } = string.Empty; - - /// - /// ISO 8601 timestamp of the agent's last activity. - /// Not null — used by clients to detect stale connections. - /// - public string LastActivity { get; set; } = string.Empty; - - /// - /// Error message when the agent status is "error". - /// Null when the agent is not in an error state. - /// - public string? ErrorMessage { get; set; } -} \ No newline at end of file diff --git a/backend/Entities/Agent.cs b/backend/Entities/Agent.cs deleted file mode 100644 index 67be593..0000000 --- a/backend/Entities/Agent.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace ControlCenter.Api.Entities; - -/// -/// Represents an agent's current state in the Control Center. -/// Each row tracks one agent session's status, task, and activity. -/// -public class Agent -{ - /// - /// Primary key — UUID generated on insert. - /// - public Guid Id { get; set; } - - /// - /// Current operational status of the agent. - /// Stored as an enum in PostgreSQL via Npgsql. - /// - public AgentStatus Status { get; set; } = AgentStatus.Idle; - - /// - /// Description of the agent's current task, if any. - /// Nullable — not all agents have an active task. - /// - public string? Task { get; set; } - - /// - /// Task progress percentage (0–100). - /// Nullable — progress is only meaningful when an agent has a trackable task. - /// - public int? Progress { get; set; } - - /// - /// Full session key, e.g. "agent:otto:telegram:direct:8787451565". - /// Not null — every agent row must be associated with a session. - /// - public string SessionKey { get; set; } = string.Empty; - - /// - /// Communication channel the agent is operating on, e.g. "telegram", "discord", "slack". - /// Not null — every agent session operates on exactly one channel. - /// - public string Channel { get; set; } = string.Empty; - - /// - /// Timestamp of the agent's last activity. - /// Default: current UTC timestamp on insert. - /// - public DateTime LastActivity { get; set; } = DateTime.UtcNow; - - /// - /// Row creation timestamp. Set automatically on insert. - /// - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; - - /// - /// Row last-update timestamp. Updated automatically on any modification. - /// - public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; -} \ No newline at end of file diff --git a/backend/Entities/AgentStatus.cs b/backend/Entities/AgentStatus.cs deleted file mode 100644 index 3846fcc..0000000 --- a/backend/Entities/AgentStatus.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ControlCenter.Api.Entities; - -/// -/// Agent operational status enum. -/// Maps to the agent_status enum type in PostgreSQL. -/// -public enum AgentStatus -{ - Active = 0, - Idle = 1, - Thinking = 2, - Error = 3 -} \ No newline at end of file diff --git a/backend/Hubs/AgentStatusHub.cs b/backend/Hubs/AgentStatusHub.cs deleted file mode 100644 index 213804b..0000000 --- a/backend/Hubs/AgentStatusHub.cs +++ /dev/null @@ -1,155 +0,0 @@ -using ControlCenter.Api.Dtos; -using Microsoft.AspNetCore.SignalR; - -namespace ControlCenter.Api.Hubs; - -/// -/// SignalR hub for broadcasting agent status updates to connected clients. -/// -/// -/// Clients call to broadcast a status change, -/// and the hub relays it to all connected clients via the -/// callback. -/// -/// -/// -/// Server-side code should use -/// via IHubContext<AgentStatusHub, IAgentStatusClient> for background-service broadcasts. -/// -/// -/// -/// Architecture note: This hub bridges OpenClaw Gateway events to SignalR clients. -/// A background service subscribes to Gateway events and pushes them through -/// this hub's extension methods. -/// -/// -public class AgentStatusHub : Hub -{ - private readonly ILogger _logger; - - /// - /// Initializes a new instance of the class. - /// - /// Logger for diagnostic output. - public AgentStatusHub(ILogger logger) - { - _logger = logger; - } - - /// - /// Broadcasts an agent status update to all connected clients. - /// - /// - /// Any connected client (or server-side caller) can invoke this method - /// to push a status update to every subscriber. The update is relayed - /// through the callback. - /// - /// - /// The agent status update payload to broadcast. - public async Task SendStatusUpdate(AgentStatusUpdateDto update) - { - _logger.LogInformation( - "Broadcasting status update for agent {AgentId}: {Status}", - update.AgentId, update.Status); - - await Clients.All.AgentStatusChanged(update); - } - - /// - /// Adds the calling connection to the fleet group. - /// Once joined, the client will receive all agent status updates. - /// - public async Task JoinFleet() - { - await Groups.AddToGroupAsync(Context.ConnectionId, FleetGroupName); - _logger.LogDebug("Connection {ConnectionId} joined fleet group", Context.ConnectionId); - } - - /// - /// Removes the calling connection from the fleet group. - /// - public async Task LeaveFleet() - { - await Groups.RemoveFromGroupAsync(Context.ConnectionId, FleetGroupName); - _logger.LogDebug("Connection {ConnectionId} left fleet group", Context.ConnectionId); - } - - /// - /// Overrides to log disconnections. - /// SignalR automatically removes disconnected connections from all groups. - /// - /// Exception that caused the disconnection, if any. - public override Task OnDisconnectedAsync(Exception? exception) - { - _logger.LogDebug("Connection {ConnectionId} disconnected", Context.ConnectionId); - return base.OnDisconnectedAsync(exception); - } - - /// - /// The SignalR group name for the entire fleet (all agents). - /// - internal const string FleetGroupName = "fleet"; -} - -/// -/// Strongly-typed client interface for the AgentStatus SignalR hub. -/// Defines the methods the server can invoke on connected clients -/// to push real-time agent status updates. -/// -public interface IAgentStatusClient -{ - /// - /// Pushes an agent status change to all subscribed clients. - /// Fired whenever an agent's operational status changes - /// (e.g., idle → active, active → thinking, active → error). - /// - /// The full status update payload. - /// A Task that completes when the client has processed the update. - Task AgentStatusChanged(AgentStatusUpdateDto update); -} - -/// -/// Extension methods for pushing real-time agent updates through -/// the of . -/// -/// -/// These methods are intended to be called from background services -/// or other server-side code that detects an agent state change, -/// using the injected IHubContext<AgentStatusHub, IAgentStatusClient>. -/// -/// -public static class AgentStatusHubExtensions -{ - /// - /// Pushes an agent status update to all connected clients. - /// - /// - /// Call this from any background service when an agent's - /// operational status changes (e.g., the Gateway reports a - /// session transition from "running" to "done"). - /// - /// - /// The hub context injected via DI. - /// The agent status update payload. - /// A Task that completes when the message has been sent to all clients. - public static async Task PushStatusUpdateAsync( - this IHubContext hubContext, - AgentStatusUpdateDto update) - { - await hubContext.Clients.All.AgentStatusChanged(update); - } - - /// - /// Pushes an agent status update to clients subscribed to the fleet group. - /// - /// The hub context injected via DI. - /// The agent status update payload. - /// A Task that completes when the message has been sent to the fleet group. - public static async Task PushStatusUpdateToFleetAsync( - this IHubContext hubContext, - AgentStatusUpdateDto update) - { - await hubContext.Clients.Group(AgentStatusHub.FleetGroupName) - .AgentStatusChanged(update); - } -} \ No newline at end of file diff --git a/backend/Migrations/20260426101703_CreateAgentsTable.Designer.cs b/backend/Migrations/20260426101703_CreateAgentsTable.Designer.cs deleted file mode 100644 index 8b99837..0000000 --- a/backend/Migrations/20260426101703_CreateAgentsTable.Designer.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -using System; -using ControlCenter.Api.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace ControlCenter.Api.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260426101703_CreateAgentsTable")] - partial class CreateAgentsTable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "agent_status", new[] { "active", "idle", "thinking", "error" }); - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("ControlCenter.Api.Entities.Agent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("Channel") - .IsRequired() - .HasColumnType("text") - .HasColumnName("channel"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamptz") - .HasColumnName("created_at") - .HasDefaultValueSql("now()"); - - b.Property("LastActivity") - .HasColumnType("timestamptz") - .HasColumnName("last_activity"); - - b.Property("Progress") - .HasColumnType("integer") - .HasColumnName("progress"); - - b.Property("SessionKey") - .IsRequired() - .HasColumnType("text") - .HasColumnName("session_key"); - - b.Property("Status") - .HasColumnType("agent_status") - .HasColumnName("status"); - - b.Property("Task") - .HasColumnType("text") - .HasColumnName("task"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamptz") - .HasColumnName("updated_at") - .HasDefaultValueSql("now()"); - - b.HasKey("Id"); - - b.HasIndex("Channel") - .HasDatabaseName("ix_agents_channel"); - - b.HasIndex("SessionKey") - .IsUnique() - .HasDatabaseName("ix_agents_session_key"); - - b.HasIndex("Status") - .HasDatabaseName("ix_agents_status"); - - b.ToTable("agents", null, t => - { - t.HasCheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Migrations/20260426101703_CreateAgentsTable.cs b/backend/Migrations/20260426101703_CreateAgentsTable.cs deleted file mode 100644 index 4b38049..0000000 --- a/backend/Migrations/20260426101703_CreateAgentsTable.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace ControlCenter.Api.Migrations -{ - /// - public partial class CreateAgentsTable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("Npgsql:Enum:agent_status", "active,idle,thinking,error"); - - migrationBuilder.CreateTable( - name: "agents", - columns: table => new - { - id = table.Column(type: "uuid", nullable: false), - status = table.Column(type: "agent_status", nullable: false), - task = table.Column(type: "text", nullable: true), - progress = table.Column(type: "integer", nullable: true), - session_key = table.Column(type: "text", nullable: false), - channel = table.Column(type: "text", nullable: false), - last_activity = table.Column(type: "timestamptz", nullable: false), - created_at = table.Column(type: "timestamptz", nullable: false, defaultValueSql: "now()"), - updated_at = table.Column(type: "timestamptz", nullable: false, defaultValueSql: "now()") - }, - constraints: table => - { - table.PrimaryKey("PK_agents", x => x.id); - table.CheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)"); - }); - - migrationBuilder.CreateIndex( - name: "ix_agents_channel", - table: "agents", - column: "channel"); - - migrationBuilder.CreateIndex( - name: "ix_agents_session_key", - table: "agents", - column: "session_key", - unique: true); - - migrationBuilder.CreateIndex( - name: "ix_agents_status", - table: "agents", - column: "status"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "agents"); - } - } -} diff --git a/backend/Migrations/AppDbContextModelSnapshot.cs b/backend/Migrations/AppDbContextModelSnapshot.cs deleted file mode 100644 index c32b60a..0000000 --- a/backend/Migrations/AppDbContextModelSnapshot.cs +++ /dev/null @@ -1,91 +0,0 @@ -// -using System; -using ControlCenter.Api.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace ControlCenter.Api.Migrations -{ - [DbContext(typeof(AppDbContext))] - partial class AppDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.4") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "agent_status", new[] { "active", "idle", "thinking", "error" }); - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("ControlCenter.Api.Entities.Agent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("Channel") - .IsRequired() - .HasColumnType("text") - .HasColumnName("channel"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamptz") - .HasColumnName("created_at") - .HasDefaultValueSql("now()"); - - b.Property("LastActivity") - .HasColumnType("timestamptz") - .HasColumnName("last_activity"); - - b.Property("Progress") - .HasColumnType("integer") - .HasColumnName("progress"); - - b.Property("SessionKey") - .IsRequired() - .HasColumnType("text") - .HasColumnName("session_key"); - - b.Property("Status") - .HasColumnType("agent_status") - .HasColumnName("status"); - - b.Property("Task") - .HasColumnType("text") - .HasColumnName("task"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("timestamptz") - .HasColumnName("updated_at") - .HasDefaultValueSql("now()"); - - b.HasKey("Id"); - - b.HasIndex("Channel") - .HasDatabaseName("ix_agents_channel"); - - b.HasIndex("SessionKey") - .IsUnique() - .HasDatabaseName("ix_agents_session_key"); - - b.HasIndex("Status") - .HasDatabaseName("ix_agents_status"); - - b.ToTable("agents", null, t => - { - t.HasCheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)"); - }); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Models/AgentState.cs b/backend/Models/AgentState.cs deleted file mode 100644 index 7c5f4a6..0000000 --- a/backend/Models/AgentState.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace ControlCenter.Api.Models; - -/// -/// Read-only model representing an agent's current state. -/// Used as the return type from the Agent State Repository -/// to decouple consumers from the persistence layer. -/// -public class AgentState -{ - public Guid Id { get; set; } - public string Status { get; set; } = string.Empty; - public string? Task { get; set; } - public int? Progress { get; set; } - public string SessionKey { get; set; } = string.Empty; - public string Channel { get; set; } = string.Empty; - public DateTime LastActivity { get; set; } - public DateTime CreatedAt { get; set; } - public DateTime UpdatedAt { get; set; } -} \ No newline at end of file diff --git a/backend/Program.cs b/backend/Program.cs deleted file mode 100644 index d23abf3..0000000 --- a/backend/Program.cs +++ /dev/null @@ -1,42 +0,0 @@ -using ControlCenter.Api.Data; -using ControlCenter.Api.Hubs; -using ControlCenter.Api.Repositories; -using Microsoft.EntityFrameworkCore; - -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. -builder.Services.AddOpenApi(); - -// Register SignalR for real-time agent status updates -builder.Services.AddSignalR(); - -// Register Agent State Repository -builder.Services.AddScoped(); - -// Register DbContext with PostgreSQL -builder.Services.AddDbContext(options => -{ - var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") - ?? "Host=localhost;Database=control_center;Username=postgres;Password=postgres"; - - options.UseNpgsql(connectionString, npgsqlOptions => - { - npgsqlOptions.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName); - }); -}); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.MapOpenApi(); -} - -app.UseHttpsRedirection(); - -// Map SignalR hubs -app.MapHub("/hubs/agent-status"); - -app.Run(); \ No newline at end of file diff --git a/backend/Properties/launchSettings.json b/backend/Properties/launchSettings.json deleted file mode 100644 index 5a40284..0000000 --- a/backend/Properties/launchSettings.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "applicationUrl": "http://localhost:5178", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "applicationUrl": "https://localhost:7041;http://localhost:5178", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/backend/Repositories/AgentStateRepository.cs b/backend/Repositories/AgentStateRepository.cs deleted file mode 100644 index ca452ff..0000000 --- a/backend/Repositories/AgentStateRepository.cs +++ /dev/null @@ -1,76 +0,0 @@ -using ControlCenter.Api.Data; -using ControlCenter.Api.Entities; -using ControlCenter.Api.Models; -using Microsoft.EntityFrameworkCore; - -namespace ControlCenter.Api.Repositories; - -/// -/// EF Core implementation of the Agent State Repository. -/// Maps between the persisted entity and the -/// read-oriented model. -/// -public class AgentStateRepository : IAgentStateRepository -{ - private readonly AppDbContext _db; - - public AgentStateRepository(AppDbContext db) - { - _db = db; - } - - /// - public async Task> GetAllAsync(CancellationToken ct = default) - { - var agents = await _db.Agents - .AsNoTracking() - .OrderByDescending(a => a.LastActivity) - .ToListAsync(ct); - - return agents.Select(ToModel).ToList(); - } - - /// - public async Task GetBySessionKeyAsync(string sessionKey, CancellationToken ct = default) - { - var agent = await _db.Agents - .AsNoTracking() - .FirstOrDefaultAsync(a => a.SessionKey == sessionKey, ct); - - return agent is null ? null : ToModel(agent); - } - - /// - public async Task UpdateStatusAsync(Guid id, string status, CancellationToken ct = default) - { - if (!Enum.TryParse(status, ignoreCase: true, out var parsedStatus)) - return false; - - var agent = await _db.Agents.FindAsync([id], ct); - if (agent is null) - return false; - - agent.Status = parsedStatus; - agent.UpdatedAt = DateTime.UtcNow; - agent.LastActivity = DateTime.UtcNow; - - await _db.SaveChangesAsync(ct); - return true; - } - - /// - /// Maps a persisted entity to a model. - /// - private static AgentState ToModel(Agent agent) => new() - { - Id = agent.Id, - Status = agent.Status.ToString(), - Task = agent.Task, - Progress = agent.Progress, - SessionKey = agent.SessionKey, - Channel = agent.Channel, - LastActivity = agent.LastActivity, - CreatedAt = agent.CreatedAt, - UpdatedAt = agent.UpdatedAt, - }; -} \ No newline at end of file diff --git a/backend/Repositories/IAgentStateRepository.cs b/backend/Repositories/IAgentStateRepository.cs deleted file mode 100644 index 4c0c2b9..0000000 --- a/backend/Repositories/IAgentStateRepository.cs +++ /dev/null @@ -1,27 +0,0 @@ -using ControlCenter.Api.Models; - -namespace ControlCenter.Api.Repositories; - -/// -/// Repository interface for accessing and mutating Agent State. -/// Provides a clean abstraction over the EF Core data access layer. -/// -public interface IAgentStateRepository -{ - /// - /// Retrieve all agent states. - /// - Task> GetAllAsync(CancellationToken ct = default); - - /// - /// Retrieve a single agent state by its session key. - /// Returns null if no agent is found with the given session key. - /// - Task GetBySessionKeyAsync(string sessionKey, CancellationToken ct = default); - - /// - /// Update the status of an agent by its primary key. - /// Returns true if the agent was found and updated, false otherwise. - /// - Task UpdateStatusAsync(Guid id, string status, CancellationToken ct = default); -} \ No newline at end of file diff --git a/backend/appsettings.Development.json b/backend/appsettings.Development.json deleted file mode 100644 index ff66ba6..0000000 --- a/backend/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/backend/appsettings.json b/backend/appsettings.json deleted file mode 100644 index 0181f7d..0000000 --- a/backend/appsettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Database=control_center;Username=postgres;Password=postgres" - } -} diff --git a/backend/internal/models/models.go b/backend/internal/models/models.go deleted file mode 100644 index cd2186a..0000000 --- a/backend/internal/models/models.go +++ /dev/null @@ -1,106 +0,0 @@ -// Package models defines the database entities for the Control Center Go backend. -// Structs map 1:1 to the PostgreSQL schema defined in backend/migrations/. -package models - -import ( - "time" - - "github.com/jackc/pgx/v5/pgtype" -) - -// AgentStatus represents the possible lifecycle states of an agent. -type AgentStatus string - -const ( - AgentStatusActive AgentStatus = "active" - AgentStatusIdle AgentStatus = "idle" - AgentStatusThinking AgentStatus = "thinking" - AgentStatusError AgentStatus = "error" - AgentStatusOffline AgentStatus = "offline" -) - -// Agent represents a registered agent and its current state. -type Agent struct { - ID pgtype.UUID `db:"id" json:"id"` - Name string `db:"name" json:"name"` - Status AgentStatus `db:"status" json:"status"` - Task *string `db:"task" json:"task,omitempty"` - Progress int32 `db:"progress" json:"progress"` - SessionKey *string `db:"session_key" json:"session_key,omitempty"` - Channel *string `db:"channel" json:"channel,omitempty"` - LastActivity time.Time `db:"last_activity" json:"last_activity"` - CreatedAt time.Time `db:"created_at" json:"created_at"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` -} - -// SessionStatus represents the possible states of an agent session. -type SessionStatus string - -const ( - SessionStatusRunning SessionStatus = "running" - SessionStatusCompleted SessionStatus = "completed" - SessionStatusCrashed SessionStatus = "crashed" - SessionStatusTerminated SessionStatus = "terminated" -) - -// Session tracks an agent session over time. -type Session struct { - ID pgtype.UUID `db:"id" json:"id"` - AgentID pgtype.UUID `db:"agent_id" json:"agent_id"` - StartedAt time.Time `db:"started_at" json:"started_at"` - EndedAt *time.Time `db:"ended_at" json:"ended_at,omitempty"` - Status SessionStatus `db:"status" json:"status"` -} - -// TaskLogStatus represents the possible states of a task log entry. -type TaskLogStatus string - -const ( - TaskLogStatusPending TaskLogStatus = "pending" - TaskLogStatusRunning TaskLogStatus = "running" - TaskLogStatusCompleted TaskLogStatus = "completed" - TaskLogStatusFailed TaskLogStatus = "failed" - TaskLogStatusCancelled TaskLogStatus = "cancelled" -) - -// TaskLog records a historical task assigned to an agent. -type TaskLog struct { - ID pgtype.UUID `db:"id" json:"id"` - AgentID pgtype.UUID `db:"agent_id" json:"agent_id"` - Task string `db:"task" json:"task"` - Status TaskLogStatus `db:"status" json:"status"` - StartedAt time.Time `db:"started_at" json:"started_at"` - CompletedAt *time.Time `db:"completed_at" json:"completed_at,omitempty"` - ErrorMessage *string `db:"error_message" json:"error_message,omitempty"` -} - -// ProjectStatus represents the possible states of a project. -type ProjectStatus string - -const ( - ProjectStatusPlanned ProjectStatus = "planned" - ProjectStatusInProgress ProjectStatus = "in_progress" - ProjectStatusCompleted ProjectStatus = "completed" - ProjectStatusPaused ProjectStatus = "paused" - ProjectStatusCancelled ProjectStatus = "cancelled" -) - -// Project represents a project managed by the Control Center. -type Project struct { - ID pgtype.UUID `db:"id" json:"id"` - Name string `db:"name" json:"name"` - Description *string `db:"description" json:"description,omitempty"` - Status ProjectStatus `db:"status" json:"status"` - AgentID *pgtype.UUID `db:"agent_id" json:"agent_id,omitempty"` - CreatedAt time.Time `db:"created_at" json:"created_at"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` -} - -// AgentEvent represents an event in the agent lifecycle or telemetry stream. -type AgentEvent struct { - ID pgtype.UUID `db:"id" json:"id"` - AgentID pgtype.UUID `db:"agent_id" json:"agent_id"` - EventType string `db:"event_type" json:"event_type"` - Payload *map[string]interface{} `db:"payload" json:"payload,omitempty"` - CreatedAt time.Time `db:"created_at" json:"created_at"` -} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c676e14 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,88 @@ +# ============================================================================= +# Control Center — Full-Stack Docker Compose +# ============================================================================= +# Boot the entire stack: PostgreSQL + Go backend + React frontend. +# +# Usage: +# cp .env.example .env # fill in values +# docker compose up --build # first run (builds images) +# docker compose up # subsequent runs +# docker compose down -v # teardown including DB volume +# ============================================================================= + +name: control-center + +services: + # ── PostgreSQL ────────────────────────────────────────────────────────────── + postgres: + image: postgres:16-alpine + container_name: cc-postgres + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-controlcenter} + POSTGRES_USER: ${POSTGRES_USER:-controlcenter} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} + ports: + - "${POSTGRES_PORT:-5432}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./go-backend/migrations:/docker-entrypoint-initdb.d:ro + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-controlcenter} -d ${POSTGRES_DB:-controlcenter}"] + interval: 5s + timeout: 3s + retries: 5 + networks: + - cc-network + + # ── Go Backend ────────────────────────────────────────────────────────────── + backend: + build: + context: ./go-backend + dockerfile: Dockerfile + container_name: cc-backend + restart: unless-stopped + ports: + - "${BACKEND_PORT:-8080}:8080" + environment: + PORT: "8080" + DATABASE_URL: postgres://${POSTGRES_USER:-controlcenter}:${POSTGRES_PASSWORD:-changeme}@postgres:5432/${POSTGRES_DB:-controlcenter}?sslmode=disable + CORS_ORIGIN: "${CORS_ORIGIN:-http://localhost:3000}" + LOG_LEVEL: ${LOG_LEVEL:-info} + ENVIRONMENT: ${ENVIRONMENT:-development} + GATEWAY_URL: ${GATEWAY_URL:-http://openclaw-gateway:18789/api/agents} + GATEWAY_POLL_INTERVAL: ${GATEWAY_POLL_INTERVAL:-5s} + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"] + interval: 10s + timeout: 3s + retries: 3 + start_period: 5s + networks: + - cc-network + + # ── React Frontend (nginx) ────────────────────────────────────────────────── + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + container_name: cc-frontend + restart: unless-stopped + ports: + - "${FRONTEND_PORT:-3000}:80" + depends_on: + backend: + condition: service_healthy + networks: + - cc-network + +volumes: + postgres_data: + driver: local + +networks: + cc-network: + driver: bridge diff --git a/frontend-legacy/.dockerignore b/frontend-legacy/.dockerignore deleted file mode 100644 index 1625b0d..0000000 --- a/frontend-legacy/.dockerignore +++ /dev/null @@ -1,33 +0,0 @@ -# Dependencies -node_modules/ -npm-debug.log* -yarn-error.log - -# Build output (rebuilt in container) -dist/ -out-tsc/ - -# Angular cache -.angular/cache/ - -# IDE -.idea/ -.vscode/ -*.sublime-workspace - -# OS files -.DS_Store -Thumbs.db - -# Git -.git/ -.gitignore - -# Docker -Dockerfile -.dockerignore - -# Misc -coverage/ -tmp/ -*.log \ No newline at end of file diff --git a/frontend-legacy/.editorconfig b/frontend-legacy/.editorconfig deleted file mode 100644 index f166060..0000000 --- a/frontend-legacy/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single -ij_typescript_use_double_quotes = false - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/frontend-legacy/.gitignore b/frontend-legacy/.gitignore deleted file mode 100644 index 854acd5..0000000 --- a/frontend-legacy/.gitignore +++ /dev/null @@ -1,44 +0,0 @@ -# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -!.vscode/mcp.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings -__screenshots__/ - -# System files -.DS_Store -Thumbs.db diff --git a/frontend-legacy/.prettierrc b/frontend-legacy/.prettierrc deleted file mode 100644 index d6c16d7..0000000 --- a/frontend-legacy/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "printWidth": 100, - "singleQuote": true, - "overrides": [ - { - "files": "*.html", - "options": { - "parser": "angular" - } - } - ] -} diff --git a/frontend-legacy/.vscode/extensions.json b/frontend-legacy/.vscode/extensions.json deleted file mode 100644 index 77b3745..0000000 --- a/frontend-legacy/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] -} diff --git a/frontend-legacy/.vscode/launch.json b/frontend-legacy/.vscode/launch.json deleted file mode 100644 index 925af83..0000000 --- a/frontend-legacy/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/frontend-legacy/.vscode/mcp.json b/frontend-legacy/.vscode/mcp.json deleted file mode 100644 index 956af8c..0000000 --- a/frontend-legacy/.vscode/mcp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - // For more information, visit: https://angular.dev/ai/mcp - "servers": { - "angular-cli": { - "command": "npx", - "args": ["-y", "@angular/cli", "mcp"] - } - } -} diff --git a/frontend-legacy/.vscode/tasks.json b/frontend-legacy/.vscode/tasks.json deleted file mode 100644 index 244306f..0000000 --- a/frontend-legacy/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "Changes detected" - }, - "endsPattern": { - "regexp": "bundle generation (complete|failed)" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "Changes detected" - }, - "endsPattern": { - "regexp": "bundle generation (complete|failed)" - } - } - } - } - ] -} diff --git a/frontend-legacy/Dockerfile b/frontend-legacy/Dockerfile deleted file mode 100644 index 4ef33cf..0000000 --- a/frontend-legacy/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -# ============================================================ -# Control Center Frontend — Multi-stage Docker Build -# Angular 21 + nginx for static serving + API proxy -# ============================================================ - -# --- Build Stage --- -FROM node:22-slim AS builder - -WORKDIR /app - -# Install dependencies first (layer caching) -COPY package.json package-lock.json ./ -RUN npm ci - -# Copy source and build production bundle -COPY . . -RUN npm run build - -# --- Runtime Stage --- -FROM nginx:1.27-alpine AS runtime - -# Remove default nginx config -RUN rm /etc/nginx/conf.d/default.conf - -# Copy custom nginx config -COPY nginx.conf /etc/nginx/conf.d/default.conf - -# Copy built Angular app from builder stage -COPY --from=builder /app/dist/frontend/browser /usr/share/nginx/html - -# Expose HTTP port -EXPOSE 80 - -# Health check — confirm nginx is serving -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget -qO- http://localhost/ || exit 1 - -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend-legacy/README.md b/frontend-legacy/README.md deleted file mode 100644 index fcca214..0000000 --- a/frontend-legacy/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Frontend - -This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.8. - -## Development server - -To start a local development server, run: - -```bash -ng serve -``` - -Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files. - -## Code scaffolding - -Angular CLI includes powerful code scaffolding tools. To generate a new component, run: - -```bash -ng generate component component-name -``` - -For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run: - -```bash -ng generate --help -``` - -## Building - -To build the project run: - -```bash -ng build -``` - -This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed. - -## Running unit tests - -To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command: - -```bash -ng test -``` - -## Running end-to-end tests - -For end-to-end (e2e) testing, run: - -```bash -ng e2e -``` - -Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs. - -## Additional Resources - -For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. diff --git a/frontend-legacy/angular.json b/frontend-legacy/angular.json deleted file mode 100644 index 7285303..0000000 --- a/frontend-legacy/angular.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "cli": { - "packageManager": "npm" - }, - "newProjectRoot": "projects", - "projects": { - "frontend": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss", - "skipTests": true - }, - "@schematics/angular:class": { - "skipTests": true - }, - "@schematics/angular:directive": { - "skipTests": true - }, - "@schematics/angular:guard": { - "skipTests": true - }, - "@schematics/angular:interceptor": { - "skipTests": true - }, - "@schematics/angular:pipe": { - "skipTests": true - }, - "@schematics/angular:resolver": { - "skipTests": true - }, - "@schematics/angular:service": { - "skipTests": true - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular/build:application", - "options": { - "browser": "src/main.ts", - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - { - "glob": "**/*", - "input": "public" - } - ], - "styles": [ - "src/styles.scss" - ], - "stylePreprocessorOptions": { - "includePaths": [ -"src", - "src/styles" - ] - } - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kB", - "maximumError": "1MB" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "4kB", - "maximumError": "8kB" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular/build:dev-server", - "configurations": { - "production": { - "buildTarget": "frontend:build:production" - }, - "development": { - "buildTarget": "frontend:build:development" - } - }, - "defaultConfiguration": "development" - } - } - } - } -} diff --git a/frontend-legacy/nginx.conf b/frontend-legacy/nginx.conf deleted file mode 100644 index e36d2d7..0000000 --- a/frontend-legacy/nginx.conf +++ /dev/null @@ -1,54 +0,0 @@ -server { - listen 80; - server_name _; - - root /usr/share/nginx/html; - index index.html; - - # Gzip compression - gzip on; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; - - # Cache static assets (Angular uses content hashes) - location /assets/ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Cache hashed JS/CSS bundles - location ~* \.(js|css)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Proxy API requests to backend - location /api/ { - proxy_pass http://backend:8080/api/; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # Proxy SignalR WebSocket connections to backend - location /hubs/ { - proxy_pass http://backend:8080/hubs/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 86400; - } - - # Angular SPA — all other routes fall back to index.html - location / { - try_files $uri $uri/ /index.html; - } -} \ No newline at end of file diff --git a/frontend-legacy/package-lock.json b/frontend-legacy/package-lock.json deleted file mode 100644 index 13eff9a..0000000 --- a/frontend-legacy/package-lock.json +++ /dev/null @@ -1,8034 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@angular/animations": "^21.2.10", - "@angular/cdk": "^21.2.8", - "@angular/common": "^21.2.0", - "@angular/compiler": "^21.2.0", - "@angular/core": "^21.2.0", - "@angular/forms": "^21.2.0", - "@angular/material": "^21.2.8", - "@angular/platform-browser": "^21.2.0", - "@angular/router": "^21.2.0", - "@microsoft/signalr": "^10.0.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0" - }, - "devDependencies": { - "@angular/build": "^21.2.8", - "@angular/cli": "^21.2.8", - "@angular/compiler-cli": "^21.2.0", - "prettier": "^3.8.1", - "typescript": "~5.9.2" - } - }, - "node_modules/@algolia/abtesting": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.14.1.tgz", - "integrity": "sha512-Dkj0BgPiLAaim9sbQ97UKDFHJE/880wgStAM18U++NaJ/2Cws34J5731ovJifr6E3Pv4T2CqvMXf8qLCC417Ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-abtesting": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.48.1.tgz", - "integrity": "sha512-LV5qCJdj+/m9I+Aj91o+glYszrzd7CX6NgKaYdTOj4+tUYfbS62pwYgUfZprYNayhkQpVFcrW8x8ZlIHpS23Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-analytics": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.48.1.tgz", - "integrity": "sha512-/AVoMqHhPm14CcHq7mwB+bUJbfCv+jrxlNvRjXAuO+TQa+V37N8k1b0ijaRBPdmSjULMd8KtJbQyUyabXOu6Kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-common": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.48.1.tgz", - "integrity": "sha512-VXO+qu2Ep6ota28ktvBm3sG53wUHS2n7bgLWmce5jTskdlCD0/JrV4tnBm1l7qpla1CeoQb8D7ShFhad+UoSOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-insights": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.48.1.tgz", - "integrity": "sha512-zl+Qyb0nLg+Y5YvKp1Ij+u9OaPaKg2/EPzTwKNiVyOHnQJlFxmXyUZL1EInczAZsEY8hVpPCLtNfhMhfxluXKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-personalization": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.48.1.tgz", - "integrity": "sha512-r89Qf9Oo9mKWQXumRu/1LtvVJAmEDpn8mHZMc485pRfQUMAwSSrsnaw1tQ3sszqzEgAr1c7rw6fjBI+zrAXTOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-query-suggestions": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.48.1.tgz", - "integrity": "sha512-TPKNPKfghKG/bMSc7mQYD9HxHRUkBZA4q1PEmHgICaSeHQscGqL4wBrKkhfPlDV1uYBKW02pbFMUhsOt7p4ZpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-search": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.1.tgz", - "integrity": "sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/ingestion": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.48.1.tgz", - "integrity": "sha512-/RFq3TqtXDUUawwic/A9xylA2P3LDMO8dNhphHAUOU51b1ZLHrmZ6YYJm3df1APz7xLY1aht6okCQf+/vmrV9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/monitoring": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.48.1.tgz", - "integrity": "sha512-Of0jTeAZRyRhC7XzDSjJef0aBkgRcvRAaw0ooYRlOw57APii7lZdq+layuNdeL72BRq1snaJhoMMwkmLIpJScw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/recommend": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.48.1.tgz", - "integrity": "sha512-bE7JcpFXzxF5zHwj/vkl2eiCBvyR1zQ7aoUdO+GDXxGp0DGw7nI0p8Xj6u8VmRQ+RDuPcICFQcCwRIJT5tDJFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-browser-xhr": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.48.1.tgz", - "integrity": "sha512-MK3wZ2koLDnvH/AmqIF1EKbJlhRS5j74OZGkLpxI4rYvNi9Jn/C7vb5DytBnQ4KUWts7QsmbdwHkxY5txQHXVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-fetch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.48.1.tgz", - "integrity": "sha512-2oDT43Y5HWRSIQMPQI4tA/W+TN/N2tjggZCUsqQV440kxzzoPGsvv9QP1GhQ4CoDa+yn6ygUsGp6Dr+a9sPPSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-node-http": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.48.1.tgz", - "integrity": "sha512-xcaCqbhupVWhuBP1nwbk1XNvwrGljozutEiLx06mvqDf3o8cHyEgQSHS4fKJM+UAggaWVnnFW+Nne5aQ8SUJXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular-devkit/architect": { - "version": "0.2102.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2102.8.tgz", - "integrity": "sha512-b7su7AHIO5F2I6InEu/Bx/oXvGjdCP7kos2tGX73he/lPrTuizooils62OgAzgJ2UeKscyRNUjBPieFCy6XvHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.2.8", - "rxjs": "7.8.2" - }, - "bin": { - "architect": "bin/cli.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/core": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.2.8.tgz", - "integrity": "sha512-DyxCILaaic/hfcfiBjAC/SdKE1ybSQIrU62/K5Msn3gZtThZj/T7cG0VHfbmpEFcgYkrQ9caUt6MCg8OoOVDzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/schematics": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.2.8.tgz", - "integrity": "sha512-UTEMM1JXzzxufLsTGDsWth2E7+8e9PaFT7nbjUvJ2qevltACkiqAbHEpiD2ISzrSRIO3OirJ+cZtnzXO0FyoBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.2.8", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.21", - "ora": "9.3.0", - "rxjs": "7.8.2" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/animations": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.2.10.tgz", - "integrity": "sha512-sIzAcxwtRCJ/fu0tK4mo1ooiEaDxJ+Nl6s9nK1D1NP1em12VX03Jx8CMixp/kVtgh4mZnm1x6psBB0FUz3U3Ug==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/core": "21.2.10" - } - }, - "node_modules/@angular/build": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.2.8.tgz", - "integrity": "sha512-t0PHT7ONDMLwcjC9GaClNF+gsUKN78ofBikw4huiu6np5Rwmxp8KKCrdoRx20lOiibSolXgjZ2Ny0xxjNdNdQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2102.8", - "@babel/core": "7.29.0", - "@babel/helper-annotate-as-pure": "7.27.3", - "@babel/helper-split-export-declaration": "7.24.7", - "@inquirer/confirm": "5.1.21", - "@vitejs/plugin-basic-ssl": "2.1.4", - "beasties": "0.4.1", - "browserslist": "^4.26.0", - "esbuild": "0.27.3", - "https-proxy-agent": "7.0.6", - "istanbul-lib-instrument": "6.0.3", - "jsonc-parser": "3.3.1", - "listr2": "9.0.5", - "magic-string": "0.30.21", - "mrmime": "2.0.1", - "parse5-html-rewriting-stream": "8.0.0", - "picomatch": "4.0.4", - "piscina": "5.1.4", - "rolldown": "1.0.0-rc.4", - "sass": "1.97.3", - "semver": "7.7.4", - "source-map-support": "0.5.21", - "tinyglobby": "0.2.15", - "undici": "7.24.4", - "vite": "7.3.2", - "watchpack": "2.5.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "optionalDependencies": { - "lmdb": "3.5.1" - }, - "peerDependencies": { - "@angular/compiler": "^21.0.0", - "@angular/compiler-cli": "^21.0.0", - "@angular/core": "^21.0.0", - "@angular/localize": "^21.0.0", - "@angular/platform-browser": "^21.0.0", - "@angular/platform-server": "^21.0.0", - "@angular/service-worker": "^21.0.0", - "@angular/ssr": "^21.2.8", - "karma": "^6.4.0", - "less": "^4.2.0", - "ng-packagr": "^21.0.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "tslib": "^2.3.0", - "typescript": ">=5.9 <6.0", - "vitest": "^4.0.8" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - }, - "@angular/localize": { - "optional": true - }, - "@angular/platform-browser": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "@angular/ssr": { - "optional": true - }, - "karma": { - "optional": true - }, - "less": { - "optional": true - }, - "ng-packagr": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/@angular/cdk": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-21.2.8.tgz", - "integrity": "sha512-WdvMLpuFcRgDWLDyin3sw5a65PQYdI0Y+4BxiMxOkesoZ2RZTBAlLKIfQ9Nz5CY3LamUTO3Qel2T8ZhJ+Cqfuw==", - "license": "MIT", - "dependencies": { - "parse5": "^8.0.0", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/cli": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.2.8.tgz", - "integrity": "sha512-Y+/US12o+7X2774oeKPsEfHeeYM2SxwnyoXfcaLR8vrMn0zxUrhHebmlz9h83th4EJEuex1Qk0JtF7j5vcwrqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/architect": "0.2102.8", - "@angular-devkit/core": "21.2.8", - "@angular-devkit/schematics": "21.2.8", - "@inquirer/prompts": "7.10.1", - "@listr2/prompt-adapter-inquirer": "3.0.5", - "@modelcontextprotocol/sdk": "1.26.0", - "@schematics/angular": "21.2.8", - "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.48.1", - "ini": "6.0.0", - "jsonc-parser": "3.3.1", - "listr2": "9.0.5", - "npm-package-arg": "13.0.2", - "pacote": "21.3.1", - "parse5-html-rewriting-stream": "8.0.0", - "semver": "7.7.4", - "yargs": "18.0.0", - "zod": "4.3.6" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/common": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.2.10.tgz", - "integrity": "sha512-WLyi/CRLtgALg2mmaqIuKuPnE4i+8PGt/uuz26pVqx+ASh28/TWr5KSCAMomgxEc8kt4OE7lopoQsTihrQCfEw==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/core": "21.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/compiler": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.2.10.tgz", - "integrity": "sha512-IrgdFuzzD7NTK3WQaSfowjAPxPbnTqsgR92NsOs5ZaWu3RgLl21dHThNc0BK1KwVwppLUSWmD4qePbcLW71VzQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/@angular/compiler-cli": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.2.10.tgz", - "integrity": "sha512-FDcnj3ogRmnTca4m2GbKP2khFOCtoVvWDZyfw2ZCPAf+zsQlKTyscKvx4GpTFo+KHrYXpawUpDIWHORFpuqFEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "7.29.0", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^5.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^18.0.0" - }, - "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/compiler": "21.2.10", - "typescript": ">=5.9 <6.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@angular/core": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.2.10.tgz", - "integrity": "sha512-uxH+mbPiCE7rInWKYOPe9Ytas97+mFM6FhFORoN234yBK3b8he+iDuxX6dsbhEFCxhRmfS6hLxe7BdLY6U6kIA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/compiler": "21.2.10", - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0 || ~0.16.0" - }, - "peerDependenciesMeta": { - "@angular/compiler": { - "optional": true - }, - "zone.js": { - "optional": true - } - } - }, - "node_modules/@angular/forms": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.2.10.tgz", - "integrity": "sha512-XOo9qkuBqCLzSBXmyga9ke2tSulxWl+E7Y9Uwqgz8sJtQUlyP/0GYJfu60jiC3NAYobk9K/6h6MsU8zftQKdaA==", - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/common": "21.2.10", - "@angular/core": "21.2.10", - "@angular/platform-browser": "21.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/material": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-21.2.8.tgz", - "integrity": "sha512-+hLSDa5uKPd4JESM+X15QsRNkNf2OTT3gu+sTN44vBBzbc3j0OPRtf9sAkzWbYeDAwvyu8LC7kXI8GuX1eaXHg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/cdk": "21.2.8", - "@angular/common": "^21.0.0 || ^22.0.0", - "@angular/core": "^21.0.0 || ^22.0.0", - "@angular/forms": "^21.0.0 || ^22.0.0", - "@angular/platform-browser": "^21.0.0 || ^22.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/platform-browser": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.2.10.tgz", - "integrity": "sha512-5WMoHGU8BOV3eO9h3vGMIUDPf+3SHis7+X2dHKMtKfFBUtiO8m/lq2x3PzkkKj1782i7KYt92EqPHuADd/eWOw==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/animations": "21.2.10", - "@angular/common": "21.2.10", - "@angular/core": "21.2.10" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } - } - }, - "node_modules/@angular/router": { - "version": "21.2.10", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.2.10.tgz", - "integrity": "sha512-4cHHwewIhFEAAaRgJ80371EOtNlydFHbjj/UENLZitjU0azal0mfFCBdkaEdVehd7+mH5xO7MRjy6eFTcTYR5Q==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@angular/common": "21.2.10", - "@angular/core": "21.2.10", - "@angular/platform-browser": "21.2.10", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@gar/promise-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", - "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@harperfast/extended-iterable": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz", - "integrity": "sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", - "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", - "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8", - "listr2": "9.0.5" - } - }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.1.tgz", - "integrity": "sha512-tpfN4kKrrMpQ+If1l8bhmoNkECJi0iOu6AEdrTJvWVC+32sLxTARX5Rsu579mPImRP9YFWfWgeRQ5oav7zApQQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.1.tgz", - "integrity": "sha512-+a2tTfc3rmWhLAolFUWRgJtpSuu+Fw/yjn4rF406NMxhfjbMuiOUTDRvRlMFV+DzyjkwnokisskHbCWkS3Ly5w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.1.tgz", - "integrity": "sha512-0EgcE6reYr8InjD7V37EgXcYrloqpxVPINy3ig1MwDSbl6LF/vXTYRH9OE1Ti1D8YZnB35ZH9aTcdfSb5lql2A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.1.tgz", - "integrity": "sha512-aoERa5B6ywXdyFeYGQ1gbQpkMkDbEo45qVoXE5QpIRavqjnyPwjOulMkmkypkmsbJ5z4Wi0TBztON8agCTG0Vg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.1.tgz", - "integrity": "sha512-SqNDY1+vpji7bh0sFH5wlWyFTOzjbDOl0/kB5RLLYDAFyd/uw3n7wyrmas3rYPpAW7z18lMOi1yKlTPv967E3g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.1.tgz", - "integrity": "sha512-50v0O1Lt37cwrmR9vWZK5hRW0Aw+KEmxJJ75fge/zIYdvNKB/0bSMSVR5Uc2OV9JhosIUyklOmrEvavwNJ8D6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.1.tgz", - "integrity": "sha512-qwosvPyl+zpUlp3gRb7UcJ3H8S28XHCzkv0Y0EgQToXjQP91ZD67EHSCDmaLjtKhe+GVIW5om1KUpzVLA0l6pg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@microsoft/signalr": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-10.0.0.tgz", - "integrity": "sha512-0BRqz/uCx3JdrOqiqgFhih/+hfTERaUfCZXFB52uMaZJrKaPRzHzMuqVsJC/V3pt7NozcNXGspjKiQEK+X7P2w==", - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "eventsource": "^2.0.2", - "fetch-cookie": "^2.0.3", - "node-fetch": "^2.6.7", - "ws": "^7.5.10" - } - }, - "node_modules/@microsoft/signalr/node_modules/eventsource": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", - "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@napi-rs/nice": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", - "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.1.1", - "@napi-rs/nice-android-arm64": "1.1.1", - "@napi-rs/nice-darwin-arm64": "1.1.1", - "@napi-rs/nice-darwin-x64": "1.1.1", - "@napi-rs/nice-freebsd-x64": "1.1.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", - "@napi-rs/nice-linux-arm64-gnu": "1.1.1", - "@napi-rs/nice-linux-arm64-musl": "1.1.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", - "@napi-rs/nice-linux-s390x-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-musl": "1.1.1", - "@napi-rs/nice-openharmony-arm64": "1.1.1", - "@napi-rs/nice-win32-arm64-msvc": "1.1.1", - "@napi-rs/nice-win32-ia32-msvc": "1.1.1", - "@napi-rs/nice-win32-x64-msvc": "1.1.1" - } - }, - "node_modules/@napi-rs/nice-android-arm-eabi": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", - "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-android-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", - "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", - "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", - "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-freebsd-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", - "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", - "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", - "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", - "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-ppc64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", - "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-riscv64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", - "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-s390x-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", - "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", - "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", - "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-openharmony-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", - "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-arm64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", - "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-ia32-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", - "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-x64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", - "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@npmcli/agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", - "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", - "dev": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^11.2.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/fs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", - "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", - "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promise-retry": "^1.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "ini": "^6.0.0", - "lru-cache": "^11.2.1", - "npm-pick-manifest": "^11.0.1", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/installed-package-contents": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", - "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^5.0.0", - "npm-normalize-package-bin": "^5.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", - "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", - "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "glob": "^13.0.0", - "hosted-git-info": "^9.0.0", - "json-parse-even-better-errors": "^5.0.0", - "proc-log": "^6.0.0", - "semver": "^7.5.3", - "spdx-expression-parse": "^4.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/promise-spawn": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", - "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/redact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", - "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/run-script": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", - "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^5.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "node-gyp": "^12.1.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.113.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.113.0.tgz", - "integrity": "sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", - "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", - "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", - "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.4.tgz", - "integrity": "sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.4.tgz", - "integrity": "sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.4.tgz", - "integrity": "sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.4.tgz", - "integrity": "sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.4.tgz", - "integrity": "sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.4.tgz", - "integrity": "sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.4.tgz", - "integrity": "sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.4.tgz", - "integrity": "sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", - "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", - "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", - "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", - "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", - "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", - "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", - "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", - "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", - "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", - "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", - "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", - "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", - "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", - "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", - "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", - "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", - "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", - "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", - "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", - "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", - "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", - "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", - "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", - "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@schematics/angular": { - "version": "21.2.8", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.2.8.tgz", - "integrity": "sha512-Kx3PmuZIXhwQqAqoERAXqDCORHFbKTMd+eflXwZfpKkrbWJTVPqKpL4R9RVdEr2E6/VEXDFrdL1whIvGd1xmDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.2.8", - "@angular-devkit/schematics": "21.2.8", - "jsonc-parser": "3.3.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@sigstore/bundle": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", - "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", - "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.1.tgz", - "integrity": "sha512-/ScWUhhoFasJsSRGTVBwId1loQjjnjAfE4djL6ZhrXRpNCmPTnUKF5Jokd58ILseOMjzET3UrMOtJPS9sYeI0g==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", - "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@gar/promise-retry": "^1.0.2", - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.2.0", - "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.4", - "proc-log": "^6.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/tuf": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", - "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0", - "tuf-js": "^4.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/verify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", - "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "license": "MIT" - }, - "node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", - "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^10.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitejs/plugin-basic-ssl": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.4.tgz", - "integrity": "sha512-HXciTXN/sDBYWgeAD4V4s0DN0g72x5mlxQhHxtYu3Tt8BLa6MzcJZUyDVFCdtjNs3bfENVHVzOsmooTVuNgAAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/abbrev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", - "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/algoliasearch": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.1.tgz", - "integrity": "sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/abtesting": "1.14.1", - "@algolia/client-abtesting": "5.48.1", - "@algolia/client-analytics": "5.48.1", - "@algolia/client-common": "5.48.1", - "@algolia/client-insights": "5.48.1", - "@algolia/client-personalization": "5.48.1", - "@algolia/client-query-suggestions": "5.48.1", - "@algolia/client-search": "5.48.1", - "@algolia/ingestion": "1.48.1", - "@algolia/monitoring": "1.48.1", - "@algolia/recommend": "5.48.1", - "@algolia/requester-browser-xhr": "5.48.1", - "@algolia/requester-fetch": "5.48.1", - "@algolia/requester-node-http": "5.48.1" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.21", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz", - "integrity": "sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/beasties": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.4.1.tgz", - "integrity": "sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "css-select": "^6.0.0", - "css-what": "^7.0.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "htmlparser2": "^10.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.49", - "postcss-media-query-parser": "^0.2.3", - "postcss-safe-parser": "^7.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" - }, - "node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacache": { - "version": "20.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.4.tgz", - "integrity": "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^5.0.0", - "fs-minipass": "^3.0.0", - "glob": "^13.0.0", - "lru-cache": "^11.1.0", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001790", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz", - "integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz", - "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz", - "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^7.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "nth-check": "^2.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", - "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.344", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.344.tgz", - "integrity": "sha512-4MxfbmNDm+KPh066EZy+eUnkcDPcZ35wNmOWzFuh/ijvHsve6kbLTLURy88uCNK5FbpN+yk2nQY6BYh1GEt+wg==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz", - "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.4.0.tgz", - "integrity": "sha512-gDK8yiqKxrGta+3WtON59arrrw6GLmadA1qoFgYXzdcch8fmKDID2XqO8itsi3f1wufXYPT51387dN6cvVBS3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "10.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fetch-cookie": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz", - "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==", - "license": "Unlicense", - "dependencies": { - "set-cookie-parser": "^2.4.8", - "tough-cookie": "^4.0.0" - } - }, - "node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hono": { - "version": "4.12.14", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz", - "integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/hosted-git-info": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", - "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^11.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/ignore-walk": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", - "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minimatch": "^10.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/immutable": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", - "dev": true, - "license": "MIT" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", - "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jose": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.2.tgz", - "integrity": "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", - "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^5.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/lmdb": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.5.1.tgz", - "integrity": "sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@harperfast/extended-iterable": "^1.0.3", - "msgpackr": "^1.11.2", - "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.5.3", - "weak-lru-cache": "^1.2.2" - }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.5.1", - "@lmdb/lmdb-darwin-x64": "3.5.1", - "@lmdb/lmdb-linux-arm": "3.5.1", - "@lmdb/lmdb-linux-arm64": "3.5.1", - "@lmdb/lmdb-linux-x64": "3.5.1", - "@lmdb/lmdb-win32-arm64": "3.5.1", - "@lmdb/lmdb-win32-x64": "3.5.1" - } - }, - "node_modules/log-symbols": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", - "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/make-fetch-happen": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", - "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promise-retry": "^1.0.0", - "@npmcli/agent": "^4.0.0", - "@npmcli/redact": "^4.0.0", - "cacache": "^20.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^6.0.0", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-fetch": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", - "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^2.0.0", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - }, - "optionalDependencies": { - "iconv-lite": "^0.7.2" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", - "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-sized": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", - "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/msgpackr": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz", - "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==", - "dev": true, - "license": "MIT", - "optional": true, - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" - } - }, - "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.2.2" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" - } - }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.3.0.tgz", - "integrity": "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "nopt": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "tar": "^7.5.4", - "tinyglobby": "^0.2.12", - "undici": "^6.25.0", - "which": "^6.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/node-gyp/node_modules/undici": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", - "integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", - "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^4.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-bundled": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", - "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^5.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-install-checks": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", - "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-package-arg": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", - "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", - "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^7.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-packlist": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", - "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", - "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^8.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", - "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "npm-package-arg": "^13.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-registry-fetch": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", - "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^4.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^15.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^13.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.3.0.tgz", - "integrity": "sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.6.2", - "cli-cursor": "^5.0.0", - "cli-spinners": "^3.2.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.1.0", - "log-symbols": "^7.0.1", - "stdin-discarder": "^0.3.1", - "string-width": "^8.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ordered-binary": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", - "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pacote": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.1.tgz", - "integrity": "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "@npmcli/installed-package-contents": "^4.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "@npmcli/run-script": "^10.0.0", - "cacache": "^20.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^13.0.0", - "npm-packlist": "^10.0.1", - "npm-pick-manifest": "^11.0.1", - "npm-registry-fetch": "^19.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^4.0.0", - "ssri": "^13.0.0", - "tar": "^7.4.3" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", - "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", - "license": "MIT", - "dependencies": { - "entities": "^8.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", - "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0", - "parse5": "^8.0.0", - "parse5-sax-parser": "^8.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parse5-sax-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", - "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^8.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", - "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/path-to-regexp": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", - "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/piscina": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.4.tgz", - "integrity": "sha512-7uU4ZnKeQq22t9AsmHGD2w4OYQGonwFnTypDypaWi7Qr2EvQIFVtG8J5D/3bE7W123Wdc9+v4CZDu5hJXVCtBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.x" - }, - "optionalDependencies": { - "@napi-rs/nice": "^1.0.4" - } - }, - "node_modules/pkce-challenge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/postcss": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", - "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": ">=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/prettier": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", - "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/proc-log": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", - "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", - "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT" - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" - }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rolldown": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.4.tgz", - "integrity": "sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.113.0", - "@rolldown/pluginutils": "1.0.0-rc.4" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.4", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.4", - "@rolldown/binding-darwin-x64": "1.0.0-rc.4", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.4", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.4", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.4", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.4", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.4", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.4", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.4", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.4", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.4", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.4" - } - }, - "node_modules/rollup": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", - "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.2", - "@rollup/rollup-android-arm64": "4.60.2", - "@rollup/rollup-darwin-arm64": "4.60.2", - "@rollup/rollup-darwin-x64": "4.60.2", - "@rollup/rollup-freebsd-arm64": "4.60.2", - "@rollup/rollup-freebsd-x64": "4.60.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", - "@rollup/rollup-linux-arm-musleabihf": "4.60.2", - "@rollup/rollup-linux-arm64-gnu": "4.60.2", - "@rollup/rollup-linux-arm64-musl": "4.60.2", - "@rollup/rollup-linux-loong64-gnu": "4.60.2", - "@rollup/rollup-linux-loong64-musl": "4.60.2", - "@rollup/rollup-linux-ppc64-gnu": "4.60.2", - "@rollup/rollup-linux-ppc64-musl": "4.60.2", - "@rollup/rollup-linux-riscv64-gnu": "4.60.2", - "@rollup/rollup-linux-riscv64-musl": "4.60.2", - "@rollup/rollup-linux-s390x-gnu": "4.60.2", - "@rollup/rollup-linux-x64-gnu": "4.60.2", - "@rollup/rollup-linux-x64-musl": "4.60.2", - "@rollup/rollup-openbsd-x64": "4.60.2", - "@rollup/rollup-openharmony-arm64": "4.60.2", - "@rollup/rollup-win32-arm64-msvc": "4.60.2", - "@rollup/rollup-win32-ia32-msvc": "4.60.2", - "@rollup/rollup-win32-x64-gnu": "4.60.2", - "@rollup/rollup-win32-x64-msvc": "4.60.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/sass": { - "version": "1.97.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", - "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", - "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/ssri": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", - "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stdin-discarder": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.3.2.tgz", - "integrity": "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", - "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/tar": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", - "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tuf-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", - "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "4.1.0", - "debug": "^4.4.3", - "make-fetch-happen": "^15.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.4.tgz", - "integrity": "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", - "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", - "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/weak-lru-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", - "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", - "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "zod": "^3.25.28 || ^4" - } - } - } -} diff --git a/frontend-legacy/package.json b/frontend-legacy/package.json deleted file mode 100644 index 01ddd7b..0000000 --- a/frontend-legacy/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "private": true, - "packageManager": "npm@11.11.0", - "dependencies": { - "@angular/animations": "^21.2.10", - "@angular/cdk": "^21.2.8", - "@angular/common": "^21.2.0", - "@angular/compiler": "^21.2.0", - "@angular/core": "^21.2.0", - "@angular/forms": "^21.2.0", - "@angular/material": "^21.2.8", - "@angular/platform-browser": "^21.2.0", - "@angular/router": "^21.2.0", - "@microsoft/signalr": "^10.0.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0" - }, - "devDependencies": { - "@angular/build": "^21.2.8", - "@angular/cli": "^21.2.8", - "@angular/compiler-cli": "^21.2.0", - "prettier": "^3.8.1", - "typescript": "~5.9.2" - } -} diff --git a/frontend-legacy/public/favicon.ico b/frontend-legacy/public/favicon.ico deleted file mode 100644 index 57614f9c967596fad0a3989bec2b1deff33034f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmd^G33O9Omi+`8$@{|M-I6TH3wzF-p5CV8o}7f~KxR60LK+ApEFB<$bcciv%@SmA zV{n>g85YMFFeU*Uvl=i4v)C*qgnb;$GQ=3XTe9{Y%c`mO%su)noNCCQ*@t1WXn|B(hQ7i~ zrUK8|pUkD6#lNo!bt$6)jR!&C?`P5G(`e((P($RaLeq+o0Vd~f11;qB05kdbAOm?r zXv~GYr_sibQO9NGTCdT;+G(!{4Xs@4fPak8#L8PjgJwcs-Mm#nR_Z0s&u?nDX5^~@ z+A6?}g0|=4e_LoE69pPFO`yCD@BCjgKpzMH0O4Xs{Ahc?K3HC5;l=f zg>}alhBXX&);z$E-wai+9TTRtBX-bWYY@cl$@YN#gMd~tM_5lj6W%8ah4;uZ;jP@Q zVbuel1rPA?2@x9Y+u?e`l{Z4ngfG5q5BLH5QsEu4GVpt{KIp1?U)=3+KQ;%7ec8l* zdV=zZgN5>O3G(3L2fqj3;oBbZZw$Ij@`Juz@?+yy#OPw)>#wsTewVgTK9BGt5AbZ&?K&B3GVF&yu?@(Xj3fR3n+ZP0%+wo)D9_xp>Z$`A4 zfV>}NWjO#3lqumR0`gvnffd9Ka}JJMuHS&|55-*mCD#8e^anA<+sFZVaJe7{=p*oX zE_Uv?1>e~ga=seYzh{9P+n5<+7&9}&(kwqSaz;1aD|YM3HBiy<))4~QJSIryyqp| z8nGc(8>3(_nEI4n)n7j(&d4idW1tVLjZ7QbNLXg;LB ziHsS5pXHEjGJZb59KcvS~wv;uZR-+4qEqow`;JCfB*+b^UL^3!?;-^F%yt=VjU|v z39SSqKcRu_NVvz!zJzL0CceJaS6%!(eMshPv_0U5G`~!a#I$qI5Ic(>IONej@aH=f z)($TAT#1I{iCS4f{D2+ApS=$3E7}5=+y(rA9mM#;Cky%b*Gi0KfFA`ofKTzu`AV-9 znW|y@19rrZ*!N2AvDi<_ZeR3O2R{#dh1#3-d%$k${Rx42h+i&GZo5!C^dSL34*AKp z27mTd>k>?V&X;Nl%GZ(>0s`1UN~Hfyj>KPjtnc|)xM@{H_B9rNr~LuH`Gr5_am&Ep zTjZA8hljNj5H1Ipm-uD9rC}U{-vR!eay5&6x6FkfupdpT*84MVwGpdd(}ib)zZ3Ky z7C$pnjc82(W_y_F{PhYj?o!@3__UUvpX)v69aBSzYj3 zdi}YQkKs^SyXyFG2LTRz9{(w}y~!`{EuAaUr6G1M{*%c+kP1olW9z23dSH!G4_HSK zzae-DF$OGR{ofP*!$a(r^5Go>I3SObVI6FLY)N@o<*gl0&kLo-OT{Tl*7nCz>Iq=? zcigIDHtj|H;6sR?or8Wd_a4996GI*CXGU}o;D9`^FM!AT1pBY~?|4h^61BY#_yIfO zKO?E0 zJ{Pc`9rVEI&$xxXu`<5E)&+m(7zX^v0rqofLs&bnQT(1baQkAr^kEsk)15vlzAZ-l z@OO9RF<+IiJ*O@HE256gCt!bF=NM*vh|WVWmjVawcNoksRTMvR03H{p@cjwKh(CL4 z7_PB(dM=kO)!s4fW!1p0f93YN@?ZSG` z$B!JaAJCtW$B97}HNO9(x-t30&E}Mo1UPi@Av%uHj~?T|!4JLwV;KCx8xO#b9IlUW zI6+{a@Wj|<2Y=U;a@vXbxqZNngH8^}LleE_4*0&O7#3iGxfJ%Id>+sb;7{L=aIic8 z|EW|{{S)J-wr@;3PmlxRXU8!e2gm_%s|ReH!reFcY8%$Hl4M5>;6^UDUUae?kOy#h zk~6Ee_@ZAn48Bab__^bNmQ~+k=02jz)e0d9Z3>G?RGG!65?d1>9}7iG17?P*=GUV-#SbLRw)Hu{zx*azHxWkGNTWl@HeWjA?39Ia|sCi{e;!^`1Oec zb>Z|b65OM*;eC=ZLSy?_fg$&^2xI>qSLA2G*$nA3GEnp3$N-)46`|36m*sc#4%C|h zBN<2U;7k>&G_wL4=Ve5z`ubVD&*Hxi)r@{4RCDw7U_D`lbC(9&pG5C*z#W>8>HU)h z!h3g?2UL&sS!oY5$3?VlA0Me9W5e~V;2jds*fz^updz#AJ%G8w2V}AEE?E^=MK%Xt z__Bx1cr7+DQmuHmzn*|hh%~eEc9@m05@clWfpEFcr+06%0&dZJH&@8^&@*$qR@}o3 z@Tuuh2FsLz^zH+dN&T&?0G3I?MpmYJ;GP$J!EzjeM#YLJ!W$}MVNb0^HfOA>5Fe~UNn%Zk(PT@~9}1dt)1UQ zU*B5K?Dl#G74qmg|2>^>0WtLX#Jz{lO4NT`NYB*(L#D|5IpXr9v&7a@YsGp3vLR7L zHYGHZg7{ie6n~2p$6Yz>=^cEg7tEgk-1YRl%-s7^cbqFb(U7&Dp78+&ut5!Tn(hER z|Gp4Ed@CnOPeAe|N>U(dB;SZ?NU^AzoD^UAH_vamp6Ws}{|mSq`^+VP1g~2B{%N-!mWz<`)G)>V-<`9`L4?3dM%Qh6<@kba+m`JS{Ya@9Fq*m6$$ zA1%Ogc~VRH33|S9l%CNb4zM%k^EIpqY}@h{w(aBcJ9c05oiZx#SK9t->5lSI`=&l~ z+-Ic)a{FbBhXV$Xt!WRd`R#Jk-$+_Z52rS>?Vpt2IK<84|E-SBEoIw>cs=a{BlQ7O z-?{Fy_M&84&9|KM5wt~)*!~i~E=(6m8(uCO)I=)M?)&sRbzH$9Rovzd?ZEY}GqX+~ zFbEbLz`BZ49=2Yh-|<`waK-_4!7`ro@zlC|r&I4fc4oyb+m=|c8)8%tZ-z5FwhzDt zL5kB@u53`d@%nHl0Sp)Dw`(QU&>vujEn?GPEXUW!Wi<+4e%BORl&BIH+SwRcbS}X@ z01Pk|vA%OdJKAs17zSXtO55k!;%m9>1eW9LnyAX4uj7@${O6cfii`49qTNItzny5J zH&Gj`e}o}?xjQ}r?LrI%FjUd@xflT3|7LA|ka%Q3i}a8gVm<`HIWoJGH=$EGClX^C0lysQJ>UO(q&;`T#8txuoQ_{l^kEV9CAdXuU1Ghg8 zN_6hHFuy&1x24q5-(Z7;!poYdt*`UTdrQOIQ!2O7_+AHV2hgXaEz7)>$LEdG z<8vE^Tw$|YwZHZDPM!SNOAWG$?J)MdmEk{U!!$M#fp7*Wo}jJ$Q(=8>R`Ats?e|VU?Zt7Cdh%AdnfyN3MBWw{ z$OnREvPf7%z6`#2##_7id|H%Y{vV^vWXb?5d5?a_y&t3@p9t$ncHj-NBdo&X{wrfJ zamN)VMYROYh_SvjJ=Xd!Ga?PY_$;*L=SxFte!4O6%0HEh%iZ4=gvns7IWIyJHa|hT z2;1+e)`TvbNb3-0z&DD_)Jomsg-7p_Uh`wjGnU1urmv1_oVqRg#=C?e?!7DgtqojU zWoAB($&53;TsXu^@2;8M`#z{=rPy?JqgYM0CDf4v@z=ZD|ItJ&8%_7A#K?S{wjxgd z?xA6JdJojrWpB7fr2p_MSsU4(R7=XGS0+Eg#xR=j>`H@R9{XjwBmqAiOxOL` zt?XK-iTEOWV}f>Pz3H-s*>W z4~8C&Xq25UQ^xH6H9kY_RM1$ch+%YLF72AA7^b{~VNTG}Tj#qZltz5Q=qxR`&oIlW Nr__JTFzvMr^FKp4S3v*( diff --git a/frontend-legacy/src/app/app.config.ts b/frontend-legacy/src/app/app.config.ts deleted file mode 100644 index 6bee550..0000000 --- a/frontend-legacy/src/app/app.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core'; -import { provideRouter } from '@angular/router'; -import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; - -import { routes } from './app.routes'; - -export const appConfig: ApplicationConfig = { - providers: [ - provideBrowserGlobalErrorListeners(), - provideRouter(routes), - provideAnimationsAsync(), - ], -}; \ No newline at end of file diff --git a/frontend-legacy/src/app/app.html b/frontend-legacy/src/app/app.html deleted file mode 100644 index 12b5d24..0000000 --- a/frontend-legacy/src/app/app.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend-legacy/src/app/app.routes.ts b/frontend-legacy/src/app/app.routes.ts deleted file mode 100644 index b3066bd..0000000 --- a/frontend-legacy/src/app/app.routes.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Routes } from '@angular/router'; -import { LayoutShellComponent } from './layout/layout-shell/layout-shell.component'; -import { HubPageComponent } from './pages/hub/hub-page.component'; -import { ProjectsPageComponent } from './pages/projects/projects-page.component'; -import { SessionsPageComponent } from './pages/sessions/sessions-page.component'; -import { LogsPageComponent } from './pages/logs/logs-page.component'; -import { SettingsPageComponent } from './pages/settings/settings-page.component'; - -export const routes: Routes = [ - { - path: '', - component: LayoutShellComponent, - children: [ - { path: '', redirectTo: 'hub', pathMatch: 'full' }, - { path: 'hub', component: HubPageComponent }, - { path: 'projects', component: ProjectsPageComponent }, - { path: 'sessions', component: SessionsPageComponent }, - { path: 'logs', component: LogsPageComponent }, - { path: 'settings', component: SettingsPageComponent }, - ], - }, -]; \ No newline at end of file diff --git a/frontend-legacy/src/app/app.scss b/frontend-legacy/src/app/app.scss deleted file mode 100644 index 7f5064e..0000000 --- a/frontend-legacy/src/app/app.scss +++ /dev/null @@ -1,4 +0,0 @@ -:host { - display: block; - min-height: 100vh; -} \ No newline at end of file diff --git a/frontend-legacy/src/app/app.ts b/frontend-legacy/src/app/app.ts deleted file mode 100644 index d514aa5..0000000 --- a/frontend-legacy/src/app/app.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [RouterOutlet], - template: '', - styles: [` - :host { - display: block; - min-height: 100vh; - } - `], -}) -export class App {} \ No newline at end of file diff --git a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.html b/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.html deleted file mode 100644 index 42be39a..0000000 --- a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - -
- - -
-
- - {{ statusLabel() }} -
- -
- {{ displayName || agentId }} - {{ role }} -
-
- - -
-

- {{ isError() ? errorMessage || task : task }} -

-
- - -
- - {{ progress }}% -
- - -
- - {{ taskElapsed }} -
- - - -
\ No newline at end of file diff --git a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.scss b/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.scss deleted file mode 100644 index d651f4b..0000000 --- a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.scss +++ /dev/null @@ -1,267 +0,0 @@ -// ============================================================================ -// AgentCard — M3 tactical dark styling -// Per spec Section 7.3: left‑border accent, status‑aware coloring, -// responsive card layout with 320px min‑width. -// Enhanced: data-status selectors, elapsed time, design token imports. -// ============================================================================ - -@use 'tokens' as tokens; - -.agent-card { - display: flex; - flex-direction: column; - min-width: tokens.$cc-card-min-width; - padding: tokens.$cc-card-padding; - background-color: var(--cc-surface-container); - border-radius: tokens.$cc-card-border-radius; - border-left: 4px solid var(--status-offline); // default; overridden by [style] - border-top: 1px solid var(--cc-outline); - border-right: 1px solid var(--cc-outline); - border-bottom: 1px solid var(--cc-outline); - gap: 16px; - transition: border-left-color 0.3s ease, box-shadow 0.2s ease; - cursor: default; - - &:hover { - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); - } - - // CUB-26: Card is now clickable for session drawer - cursor: pointer; - - &:focus-visible { - outline: 2px solid var(--color-primary); - outline-offset: 2px; - } - - &:focus-within { - outline: 2px solid var(--status-active); - outline-offset: 2px; - } -} - -// ── Header ── -.agent-card__header { - display: flex; - align-items: center; - gap: 12px; -} - -.agent-card__badge { - display: flex; - align-items: center; - gap: 6px; - padding: 4px 10px; - border-radius: 12px; - background-color: var(--status-active-bg); // overridden per status below - font-size: 12px; - font-weight: 500; - letter-spacing: 0.02em; - text-transform: uppercase; - color: var(--cc-on-surface); -} - -.agent-card__status-label { - font-size: 12px; - font-weight: 500; - text-transform: uppercase; - letter-spacing: 0.04em; - color: var(--cc-on-surface-variant); -} - -.agent-card__identity { - display: flex; - flex-direction: column; - gap: 2px; -} - -.agent-card__name { - font-size: 16px; - font-weight: 600; - color: var(--cc-on-surface); - line-height: 1.2; -} - -.agent-card__role { - font-size: 12px; - font-weight: 400; - color: var(--cc-on-surface-variant); -} - -// ── Body ── -.agent-card__body { - padding: 4px 0; -} - -.agent-card__task { - margin: 0; - font-size: 14px; - font-weight: 400; - color: var(--cc-on-surface); - line-height: 1.4; - - &--error { - color: var(--status-error); - } -} - -// ── Progress Bar ── -.agent-card__progress { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 0; -} - -.agent-card__progress-label { - font-family: var(--cc-font-mono); - font-size: 12px; - font-weight: 500; - color: var(--cc-on-surface-variant); - white-space: nowrap; - min-width: 36px; -} - -// Override mat-progress-bar to match tactical dark theme -.agent-card__progress ::ng-deep .mat-mdc-progress-bar { - height: 4px; - border-radius: 2px; - - .mdc-linear-progress__bar-inner { - background-color: var(--status-active); - } - - .mdc-linear-progress__track { - background-color: var(--cc-outline); - } -} - -// ── Elapsed Time ── -.agent-card__elapsed { - display: flex; - align-items: center; - gap: 4px; - font-size: 12px; - color: var(--cc-on-surface-variant); - padding: 2px 0; -} - -.agent-card__elapsed-icon { - font-size: 14px; - width: 14px; - height: 14px; - color: var(--status-thinking); -} - -// ── Footer ── -.agent-card__footer { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-top: auto; // push footer to bottom -} - -.agent-card__meta { - display: flex; - align-items: center; - gap: 12px; -} - -.agent-card__channel { - display: inline-flex; - align-items: center; - gap: 4px; - font-size: 12px; - color: var(--cc-on-surface-variant); -} - -.agent-card__channel .mat-icon { - font-size: 14px; - width: 14px; - height: 14px; -} - -.agent-card__last-activity { - font-size: 12px; - color: var(--cc-on-surface-variant); -} - -// ── Quick‑Jump Button ── -.agent-card__jump { - flex-shrink: 0; - - .mat-mdc-button { - min-width: 36px; - padding: 0 8px; - color: var(--status-active); - } - - .mat-icon { - font-size: 18px; - width: 18px; - height: 18px; - } -} - -// ── Status‑specific background tints for badge ── -// Using data-status attribute selectors for clean styling. - -.agent-card[data-status="active"] .agent-card__badge { - background-color: var(--status-active-bg); -} - -.agent-card[data-status="idle"] .agent-card__badge { - background-color: var(--status-idle-bg); -} - -.agent-card[data-status="thinking"] .agent-card__badge { - background-color: var(--status-thinking-bg); -} - -.agent-card[data-status="error"] .agent-card__badge { - background-color: var(--status-error-bg); -} - -.agent-card[data-status="offline"] .agent-card__badge { - background-color: var(--cc-surface-container-high); -} - -// ── Active‑like pulse on card border ── -.agent-card[data-status="active"], -.agent-card[data-status="thinking"] { - border-left-width: 4px; -} - -.agent-card[data-status="error"] { - border-left-color: var(--status-error); -} - -// ── Responsive ── -@media (max-width: tokens.$cc-breakpoint-mobile) { - .agent-card { - min-width: unset; - padding: 16px; - } - - .agent-card__header { - flex-wrap: wrap; - gap: 8px; - } - - .agent-card__footer { - flex-wrap: wrap; - gap: 8px; - } - - .agent-card__meta { - gap: 8px; - } -} - -// ── Accessibility: reduced motion ── -@media (prefers-reduced-motion: reduce) { - .agent-card { - transition: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.ts b/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.ts deleted file mode 100644 index 05e5b01..0000000 --- a/frontend-legacy/src/app/command-hub/components/agent-card/agent-card.component.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - OnDestroy, - Output, - computed, - effect, - inject, - signal, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; -import { MatIconModule } from '@angular/material/icon'; -import { MatButtonModule } from '@angular/material/button'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; -import { MatTooltipModule } from '@angular/material/tooltip'; -import { AgentStatus } from '../../../models/agent.model'; -import { LongPressDirective } from '../../../directives/long-press.directive'; -import { - STATUS_COLORS, - STATUS_LABELS, - CHANNEL_ICONS, -} from '../../../design/tokens'; - -// ============================================================================ -// AgentCard Component -// Per spec Section 7.3: Composes Agent Status Badge, Task Progress Bar, -// and Quick‑Jump Button into a card with left‑border status accent. -// CUB-26: Emits cardClick and cardLongPress for drawer/modal integration. -// Enhanced with data-status attribute, elapsed time, and design tokens. -// ============================================================================ - -@Component({ - selector: 'app-agent-card', - standalone: true, - imports: [ - CommonModule, - RouterModule, - MatIconModule, - MatButtonModule, - MatProgressBarModule, - MatTooltipModule, - LongPressDirective, - ], - templateUrl: './agent-card.component.html', - styleUrl: './agent-card.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AgentCardComponent implements OnDestroy { - // --- Six required inputs per spec --- - - /** Agent status — drives badge color and left‑border accent */ - @Input({ required: true }) status!: AgentStatus; - - /** Current task description, e.g. "Reviewing PR #42" */ - @Input() task = ''; - - /** Task progress percentage 0–100 */ - @Input() progress = 0; - - /** Full session key for quick‑jump navigation */ - @Input({ required: true }) sessionKey = ''; - - /** Communication channel, e.g. "telegram" */ - @Input({ required: true }) channel = ''; - - /** Timestamp of last agent activity */ - @Input({ required: true }) lastActivity!: Date; - - // --- Additional display inputs --- - - /** Short agent ID, e.g. "otto" */ - @Input() agentId = ''; - - /** Display name, e.g. "Otto" */ - @Input() displayName = ''; - - /** Role description, e.g. "Orchestrator Agent" */ - @Input() role = ''; - - /** Error message (shown only when status is 'error') */ - @Input() errorMessage = ''; - - /** Elapsed time string, e.g. "04m 12s" */ - @Input() taskElapsed = ''; - - // --- CUB-26: Outputs for drawer/modal integration --- - - /** Emitted when the card is clicked — opens the session drawer. */ - @Output() readonly cardClick = new EventEmitter(); - - /** Emitted when the card is long-pressed — bypasses drawer, opens session log directly. */ - @Output() readonly cardLongPress = new EventEmitter(); - - // --- Internal state --- - - /** Timer for refreshing relative-time label */ - private _timer: ReturnType | null = null; - - /** Internal signal to trigger relative-time recomputation */ - private readonly _tick = signal(0); - - // --- Computed values using design tokens --- - - /** Map status → CSS custom property for the left‑border accent */ - readonly statusBorderColor = computed(() => { - const map: Record = { - active: 'var(--status-active)', - idle: 'var(--status-idle)', - thinking: 'var(--status-thinking)', - error: 'var(--status-error)', - offline: 'var(--status-offline)', - }; - return map[this.status] ?? 'var(--status-offline)'; - }); - - /** Human‑readable status label (from design tokens) */ - readonly statusLabel = computed(() => STATUS_LABELS[this.status] ?? this.status); - - /** CSS class suffix for the status badge dot */ - readonly statusDotClass = computed(() => `status-dot--${this.status}`); - - /** Material icon name for the channel (from design tokens) */ - readonly channelIcon = computed(() => CHANNEL_ICONS[this.channel] ?? 'chat'); - - /** Relative time string for lastActivity, refreshed every 30s */ - readonly lastActivityLabel = computed(() => { - // Read tick to create dependency that forces recomputation - this._tick(); - return this._relativeTime(this.lastActivity); - }); - - /** Quick‑jump route derived from sessionKey */ - readonly jumpRoute = computed(() => `/sessions/${this.sessionKey}`); - - /** Whether progress bar should show */ - readonly showProgress = computed(() => this.progress > 0 && this.status !== 'error'); - - /** Whether error state is active */ - readonly isError = computed(() => this.status === 'error'); - - /** Whether card is in an active-like state (active or thinking) */ - readonly isActiveLike = computed(() => this.status === 'active' || this.status === 'thinking'); - - constructor() { - // Start the relative-time refresh timer - this._startTimer(); - } - - ngOnDestroy(): void { - this._stopTimer(); - } - - // --- Private helpers --- - - private _relativeTime(date: Date | null | undefined): string { - if (!date) return ''; - const now = Date.now(); - const then = date.getTime(); - const diffSec = Math.max(0, Math.floor((now - then) / 1000)); - if (diffSec < 60) return 'just now'; - if (diffSec < 3600) return `${Math.floor(diffSec / 60)}m ago`; - if (diffSec < 86400) return `${Math.floor(diffSec / 3600)}h ago`; - return `${Math.floor(diffSec / 86400)}d ago`; - } - - private _startTimer(): void { - this._stopTimer(); - this._timer = setInterval(() => { - // Increment tick to force lastActivityLabel recomputation - this._tick.update(v => v + 1); - }, 30_000); - } - - private _stopTimer(): void { - if (this._timer) { - clearInterval(this._timer); - this._timer = null; - } - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/command-hub/components/index.ts b/frontend-legacy/src/app/command-hub/components/index.ts deleted file mode 100644 index 39f0d45..0000000 --- a/frontend-legacy/src/app/command-hub/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './agent-card/agent-card.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.html b/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.html deleted file mode 100644 index c51fffa..0000000 --- a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - -@if (mobileMenuOpen()) { - - -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.scss b/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.scss deleted file mode 100644 index 6428d77..0000000 --- a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.scss +++ /dev/null @@ -1,365 +0,0 @@ -// ============================================================================ -// Adaptive Navigation — Desktop sidebar / Mobile header -// Per CUB-27 spec breakpoints: -// Compact (0–599px): Mobile header + hamburger + drawer -// Medium (600–1023px): Collapsed sidebar (icon-only, 72px) -// Expanded (≥1024px): Full sidebar with labels (72px collapsed, 256px expanded) -// ============================================================================ - -// --------------------------------------------------------------------------- -// Desktop Sidebar (visible ≥600px) -// --------------------------------------------------------------------------- -.adaptive-nav__sidebar { - display: none; // Hidden by default (mobile-first) - flex-direction: column; - width: var(--cc-nav-rail-collapsed-width, 72px); - min-height: 100vh; - background-color: var(--cc-surface-container-high); - border-right: 1px solid var(--cc-outline); - z-index: 10; -} - -.adaptive-nav__sidebar-header { - display: flex; - align-items: center; - justify-content: center; - height: 64px; - border-bottom: 1px solid var(--cc-outline); -} - -.adaptive-nav__brand { - font-size: 18px; - font-weight: 700; - color: var(--status-active); - letter-spacing: 0.04em; -} - -.adaptive-nav__sidebar-nav { - flex: 1; - padding-top: 8px; -} - -.adaptive-nav__sidebar-item { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - min-height: 56px; - padding: 8px 0; - margin: 2px 8px; - border-radius: 28px; - color: var(--cc-on-surface-variant); - text-decoration: none; - transition: background-color 150ms ease, color 150ms ease; - - &:hover { - background-color: rgba(255, 255, 255, 0.08); - color: var(--cc-on-surface); - } - - &--active { - background-color: var(--status-active-bg); - color: var(--status-active); - - .adaptive-nav__sidebar-label { - font-weight: 500; - } - } -} - -.adaptive-nav__sidebar-label { - font-size: 11px; - font-weight: 400; - letter-spacing: 0.02em; - white-space: nowrap; -} - -// --------------------------------------------------------------------------- -// Sidebar Footer — LIVE indicator + action buttons -// --------------------------------------------------------------------------- -.adaptive-nav__sidebar-footer { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - padding: 12px 0 20px; - border-top: 1px solid var(--cc-outline); -} - -.adaptive-nav__sidebar-actions { - display: flex; - gap: 4px; - - .mat-mdc-icon-button { - color: var(--cc-on-surface-variant) !important; - --mdc-icon-button-icon-size: 20px; - - &:hover { - color: var(--cc-on-surface) !important; - } - } -} - -// --------------------------------------------------------------------------- -// LIVE Status Indicator -// --------------------------------------------------------------------------- -.adaptive-nav__live { - display: flex; - align-items: center; - gap: 6px; - padding: 4px 8px; - border-radius: 16px; - transition: background-color 200ms ease; - - &--connected { - background-color: var(--status-active-bg); - } -} - -.adaptive-nav__live-dot { - display: inline-block; - width: 8px; - height: 8px; - min-width: 8px; - border-radius: 50%; - background-color: var(--status-error); - transition: background-color 200ms ease; - - &--connected { - background-color: var(--status-active); - animation: pulse-active 2s ease-in-out infinite; - } -} - -.adaptive-nav__live-chip { - font-size: 11px !important; - font-weight: 600 !important; - letter-spacing: 0.06em; - height: 24px !important; - min-height: 24px !important; - padding: 0 8px !important; - color: var(--status-active) !important; - --mdc-chip-elevated-container-color: transparent; - background: transparent !important; - border: none !important; - box-shadow: none !important; -} - -.adaptive-nav__live-text { - font-size: 12px; - font-weight: 600; - letter-spacing: 0.06em; - color: var(--status-active); -} - -// --------------------------------------------------------------------------- -// Mobile Header (visible <600px only) -// --------------------------------------------------------------------------- -.adaptive-nav__mobile-header { - display: none; // Hidden on desktop, shown on mobile via media query - align-items: center; - height: var(--cc-header-height-compact, 56px); - padding: 0 12px; - background-color: var(--cc-surface-container-high); - border-bottom: 1px solid var(--cc-outline); - z-index: 20; - gap: 8px; -} - -.adaptive-nav__hamburger { - color: var(--cc-on-surface-variant) !important; - min-width: 48px; - min-height: 48px; - - &:hover { - color: var(--cc-on-surface) !important; - } -} - -.adaptive-nav__mobile-title { - flex: 1; - font-size: 20px; - font-weight: 500; - color: var(--cc-on-surface); - margin: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.adaptive-nav__live--mobile { - padding: 4px 10px; - border-radius: 16px; - - .adaptive-nav__live-text { - font-size: 11px; - font-weight: 700; - } -} - -.adaptive-nav__mobile-action { - color: var(--cc-on-surface-variant) !important; - min-width: 48px; - min-height: 48px; - - &:hover { - color: var(--cc-on-surface) !important; - } -} - -// --------------------------------------------------------------------------- -// Mobile Drawer -// --------------------------------------------------------------------------- -.adaptive-nav__overlay { - position: fixed; - inset: 0; - background-color: rgba(0, 0, 0, 0.5); - z-index: 40; -} - -.adaptive-nav__mobile-drawer { - position: fixed; - top: var(--cc-header-height-compact, 56px); // Below header - left: 0; - bottom: 0; - width: 280px; - max-width: 80vw; - background-color: var(--cc-surface-container); - border-right: 1px solid var(--cc-outline); - z-index: 50; - padding: 12px 0; - overflow-y: auto; - animation: slide-in-left 200ms cubic-bezier(0.4, 0, 0.2, 1); -} - -.adaptive-nav__drawer-item { - display: flex; - align-items: center; - gap: 16px; - min-height: 48px; - padding: 0 20px; - color: var(--cc-on-surface-variant); - text-decoration: none; - transition: background-color 150ms ease, color 150ms ease; - - &:hover { - background-color: rgba(255, 255, 255, 0.08); - color: var(--cc-on-surface); - } - - &--active { - background-color: var(--status-active-bg); - color: var(--status-active); - - .adaptive-nav__drawer-label { - font-weight: 500; - } - } -} - -.adaptive-nav__drawer-label { - font-size: 14px; - font-weight: 400; - white-space: nowrap; -} - -// --------------------------------------------------------------------------- -// Drawer slide-in animation -// --------------------------------------------------------------------------- -@keyframes slide-in-left { - from { - transform: translateX(-100%); - } - to { - transform: translateX(0); - } -} - -// --------------------------------------------------------------------------- -// Media Queries — Layout Switch (CUB-27 breakpoints) -// --------------------------------------------------------------------------- - -// Compact (0–599px): Show mobile header, hide sidebar -@media (max-width: 599px) { - .adaptive-nav__sidebar { - display: none; - } - - .adaptive-nav__mobile-header { - display: flex; - } - - // Hide mobile drawer and overlay on desktop - .adaptive-nav__overlay, - .adaptive-nav__mobile-drawer { - // These are conditional via @if in template, no display:none needed - } -} - -// Medium (600–1023px): Show collapsed sidebar (icon-only), hide mobile -@media (min-width: 600px) and (max-width: 1023px) { - .adaptive-nav__sidebar { - display: flex; - width: var(--cc-nav-rail-collapsed-width, 72px); - } - - // Hide labels on medium (collapsed) - .adaptive-nav__sidebar-label, - .adaptive-nav__brand { - display: none; - } - - .adaptive-nav__sidebar-header { - justify-content: center; - } - - .adaptive-nav__sidebar-item { - flex-direction: column; - justify-content: center; - } - - .adaptive-nav__mobile-header { - display: none; - } - - .adaptive-nav__overlay, - .adaptive-nav__mobile-drawer { - display: none; - } -} - -// Expanded (≥1024px): Show sidebar with labels -@media (min-width: 1024px) { - .adaptive-nav__sidebar { - display: flex; - width: var(--cc-nav-rail-collapsed-width, 72px); - transition: width 200ms cubic-bezier(0.4, 0, 0.2, 1); - } - - .adaptive-nav__mobile-header { - display: none; - } - - .adaptive-nav__overlay, - .adaptive-nav__mobile-drawer { - display: none; - } -} - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .adaptive-nav__live-dot--connected { - animation: none; - } - - .adaptive-nav__mobile-drawer { - animation: none; - } - - .adaptive-nav__sidebar { - transition: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.ts b/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.ts deleted file mode 100644 index 8163821..0000000 --- a/frontend-legacy/src/app/components/adaptive-navigation/adaptive-navigation.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { ChangeDetectionStrategy, Component, signal, HostListener, OnDestroy, OnInit } from '@angular/core'; -import { RouterLink, RouterLinkActive } from '@angular/router'; -import { MatIconModule } from '@angular/material/icon'; -import { MatButtonModule } from '@angular/material/button'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatBadgeModule } from '@angular/material/badge'; -import { NAV_DESTINATIONS } from '../../models/nav.model'; - -/** - * Adaptive Navigation Component — switches between desktop sidebar - * and mobile header layouts using CSS media queries + JS breakpoint sync. - * - * Per CUB-27 spec breakpoints: - * Compact (0–599px): Mobile header + hamburger + bottom nav - * Medium (600–1023px): Collapsed sidebar (icon-only) - * Expanded (≥1024px): Expandable sidebar (hover/click) - * - * The LIVE status indicator is visible in all layouts. - */ -@Component({ - selector: 'app-adaptive-navigation', - standalone: true, - imports: [ - RouterLink, - RouterLinkActive, - MatIconModule, - MatButtonModule, - MatChipsModule, - MatBadgeModule, - ], - templateUrl: './adaptive-navigation.component.html', - styleUrl: './adaptive-navigation.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AdaptiveNavigationComponent implements OnInit, OnDestroy { - /** Navigation destinations shared with other nav components */ - protected readonly destinations = NAV_DESTINATIONS; - - /** Whether the mobile drawer is open */ - protected readonly mobileMenuOpen = signal(false); - - /** Live connection status */ - protected readonly isConnected = signal(true); - - /** Responsive breakpoint state */ - protected readonly isMedium = signal(false); - protected readonly isExpanded = signal(false); - - private readonly COMPACT_MAX = 599; - private readonly MEDIUM_MAX = 1023; - - ngOnInit(): void { - this.updateBreakpoint(); - } - - @HostListener('window:resize') - onResize(): void { - this.updateBreakpoint(); - } - - /** Toggle mobile menu */ - toggleMobileMenu(): void { - this.mobileMenuOpen.update((v) => !v); - } - - /** Close mobile menu (e.g. on nav) */ - closeMobileMenu(): void { - this.mobileMenuOpen.set(false); - } - - private updateBreakpoint(): void { - const w = window.innerWidth; - this.isMedium.set(w >= this.COMPACT_MAX + 1 && w <= this.MEDIUM_MAX); - this.isExpanded.set(w > this.MEDIUM_MAX); - // Close mobile menu when switching to desktop - if (w > this.COMPACT_MAX) { - this.mobileMenuOpen.set(false); - } - } - - ngOnDestroy(): void { - // HostListener auto-unsubscribes - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/adaptive-navigation/index.ts b/frontend-legacy/src/app/components/adaptive-navigation/index.ts deleted file mode 100644 index c154a5e..0000000 --- a/frontend-legacy/src/app/components/adaptive-navigation/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './adaptive-navigation.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.html b/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.html deleted file mode 100644 index 9b343e2..0000000 --- a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.html +++ /dev/null @@ -1,140 +0,0 @@ - - - -@if (isOpen()) { -
-} - - - \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.scss b/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.scss deleted file mode 100644 index b98dc62..0000000 --- a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.scss +++ /dev/null @@ -1,500 +0,0 @@ -// ============================================================================ -// Agent Session Drawer — CUB-26 -// Desktop: 480px side drawer slides from right with modal overlay. -// Mobile: Bottom sheet slides up from bottom. -// Uses Control Center design tokens from CUB-21. -// ============================================================================ - -// --------------------------------------------------------------------------- -// Backdrop -// --------------------------------------------------------------------------- -.session-drawer-backdrop { - position: fixed; - inset: 0; - background-color: rgba(0, 0, 0, 0.6); - backdrop-filter: blur(4px); - z-index: 998; - opacity: 0; - transition: opacity 200ms ease-out; - - &--visible { - opacity: 1; - } -} - -// --------------------------------------------------------------------------- -// Drawer Panel — Desktop: Side drawer from right -// --------------------------------------------------------------------------- -.session-drawer { - position: fixed; - top: 0; - right: 0; - bottom: 0; - width: 480px; - max-width: 100vw; - background-color: var(--cc-surface-container); - border-left: 1px solid var(--cc-outline); - z-index: 999; - display: flex; - flex-direction: column; - transform: translateX(100%); - transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: -4px 0 32px rgba(0, 0, 0, 0.4); - overflow: hidden; - - &--open { - transform: translateX(0); - } - - // --------------------------------------------------------------------------- - // Mobile: Bottom Sheet — slides up from bottom - // --------------------------------------------------------------------------- - &--mobile { - top: auto; - right: 0; - bottom: 0; - left: 0; - width: 100%; - max-width: 100vw; - max-height: 85vh; - border-left: none; - border-top: 1px solid var(--cc-outline); - border-radius: 20px 20px 0 0; - transform: translateY(100%); - box-shadow: 0 -4px 32px rgba(0, 0, 0, 0.4); - - &.session-drawer--open { - transform: translateY(0); - } - - // Drag handle for mobile bottom sheet - &::before { - content: ''; - display: block; - width: 32px; - height: 4px; - border-radius: 2px; - background: var(--cc-on-surface-variant); - opacity: 0.4; - margin: 8px auto 4px; - } - } -} - -// --------------------------------------------------------------------------- -// Header -// --------------------------------------------------------------------------- -.session-drawer__header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px 24px 16px; - border-bottom: 1px solid var(--cc-outline); - flex-shrink: 0; -} - -.session-drawer__header-identity { - display: flex; - align-items: center; - gap: 12px; - min-width: 0; - flex: 1; -} - -.session-drawer__header-text { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} - -.session-drawer__title { - font-size: 20px; - font-weight: 600; - color: var(--cc-on-surface); - margin: 0; - letter-spacing: -0.01em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.session-drawer__role { - font-size: 13px; - color: var(--cc-on-surface-variant); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.session-drawer__close-btn { - --mat-icon-button-state-layer-color: transparent; - color: var(--cc-on-surface-variant); - flex-shrink: 0; - - &:hover { - color: var(--cc-on-surface); - } - - &:focus-visible { - outline: 2px solid var(--color-primary); - outline-offset: 2px; - } -} - -// --------------------------------------------------------------------------- -// Content — scrollable area -// --------------------------------------------------------------------------- -.session-drawer__content { - flex: 1; - overflow-y: auto; - padding: 0 24px 16px; -} - -// --------------------------------------------------------------------------- -// Sections -// --------------------------------------------------------------------------- -.session-drawer__section { - padding: 16px 0; - border-bottom: 1px solid var(--cc-outline); - - &:last-child { - border-bottom: none; - } -} - -.session-drawer__section-title { - font-size: 13px; - font-weight: 600; - color: var(--cc-on-surface-variant); - text-transform: uppercase; - letter-spacing: 0.08em; - margin: 0 0 12px; -} - -// --------------------------------------------------------------------------- -// Meta Row — Status + Channel -// --------------------------------------------------------------------------- -.session-drawer__meta-row { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 12px; -} - -.session-drawer__status-chip { - display: inline-flex; - align-items: center; - padding: 4px 12px; - border-radius: 8px; - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.04em; - - &.status-chip--active { - background-color: var(--status-active-bg); - color: var(--status-active); - } - - &.status-chip--idle { - background-color: var(--status-idle-bg); - color: var(--status-idle); - } - - &.status-chip--thinking { - background-color: var(--status-thinking-bg); - color: var(--status-thinking); - } - - &.status-chip--error { - background-color: var(--status-error-bg); - color: var(--status-error); - } - - &.status-chip--offline { - background-color: rgba(100, 116, 139, 0.12); - color: var(--status-offline); - } -} - -.session-drawer__channel-badge { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 4px 10px; - border-radius: 8px; - background: var(--cc-surface-container-high); - font-size: 12px; - color: var(--cc-on-surface-variant); -} - -.session-drawer__channel-icon { - font-size: 14px; - width: 14px; - height: 14px; -} - -// --------------------------------------------------------------------------- -// Session Key -// --------------------------------------------------------------------------- -.session-drawer__session-key { - margin-bottom: 12px; -} - -.session-drawer__label { - display: block; - font-size: 11px; - font-weight: 500; - color: var(--cc-on-surface-variant); - text-transform: uppercase; - letter-spacing: 0.06em; - margin-bottom: 4px; -} - -.session-drawer__key-value { - display: block; - font-family: var(--cc-font-mono); - font-size: 12px; - color: var(--color-secondary); - background: var(--cc-surface); - padding: 8px 12px; - border-radius: 8px; - border: 1px solid var(--cc-outline); - word-break: break-all; - line-height: 1.5; - user-select: all; -} - -// --------------------------------------------------------------------------- -// Task Info -// --------------------------------------------------------------------------- -.session-drawer__task-info { - margin-bottom: 12px; -} - -.session-drawer__task-text { - font-size: 14px; - color: var(--cc-on-surface); - line-height: 1.4; -} - -// --------------------------------------------------------------------------- -// Last Activity -// --------------------------------------------------------------------------- -.session-drawer__last-activity { - margin-bottom: 0; -} - -.session-drawer__activity-time { - font-size: 14px; - color: var(--cc-on-surface); -} - -// --------------------------------------------------------------------------- -// Recent Messages -// --------------------------------------------------------------------------- -.session-drawer__messages { - display: flex; - flex-direction: column; - gap: 10px; -} - -.session-drawer__message { - padding: 10px 14px; - border-radius: 12px; - max-width: 100%; - - &--agent { - background: var(--cc-surface-container-high); - border: 1px solid var(--cc-outline); - } - - &--user { - background: rgba(56, 189, 248, 0.08); - border: 1px solid rgba(56, 189, 248, 0.15); - } -} - -.session-drawer__message-sender { - display: block; - font-size: 12px; - font-weight: 600; - color: var(--cc-on-surface-variant); - margin-bottom: 4px; -} - -.session-drawer__message-text { - font-size: 14px; - color: var(--cc-on-surface); - margin: 0; - line-height: 1.5; - word-wrap: break-word; -} - -.session-drawer__message-time { - display: block; - font-size: 11px; - color: var(--cc-on-surface-variant); - margin-top: 4px; - font-family: var(--cc-font-mono); -} - -// --------------------------------------------------------------------------- -// Live Log Container -// --------------------------------------------------------------------------- -.session-drawer__log-container { - background: var(--cc-surface); - border: 1px solid var(--cc-outline); - border-radius: 10px; - padding: 10px 12px; - max-height: 260px; - overflow-y: auto; - font-family: var(--cc-font-mono); - font-size: 12px; - line-height: 1.7; -} - -.session-drawer__log-line { - display: flex; - gap: 8px; - padding: 1px 0; - white-space: nowrap; - - &--info { - color: var(--cc-on-surface); - } - - &--warn { - color: #FBBF24; - } - - &--error { - color: var(--status-error); - } - - &--debug { - color: var(--cc-on-surface-variant); - } -} - -.session-drawer__log-time { - color: var(--cc-on-surface-variant); - flex-shrink: 0; - opacity: 0.7; -} - -.session-drawer__log-level { - width: 48px; - flex-shrink: 0; - font-weight: 600; - font-size: 11px; - letter-spacing: 0.02em; -} - -.session-drawer__log-message { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: inherit; -} - -// --------------------------------------------------------------------------- -// Empty State -// --------------------------------------------------------------------------- -.session-drawer__empty-state { - font-size: 13px; - color: var(--cc-on-surface-variant); - text-align: center; - padding: 16px 0; - margin: 0; -} - -// --------------------------------------------------------------------------- -// Action Buttons — Sticky Footer -// --------------------------------------------------------------------------- -.session-drawer__actions { - display: flex; - align-items: center; - gap: 12px; - padding: 16px 24px 20px; - border-top: 1px solid var(--cc-outline); - background-color: var(--cc-surface-container); - flex-shrink: 0; -} - -.session-drawer__action-btn { - display: inline-flex; - align-items: center; - gap: 8px; - font-weight: 500; - - .mat-icon { - width: 18px; - height: 18px; - font-size: 18px; - } - - &--primary { - flex: 1; - } - - &--secondary { - flex-shrink: 0; - } - - &:focus-visible { - outline: 2px solid var(--color-primary); - outline-offset: 2px; - } -} - -// --------------------------------------------------------------------------- -// Mobile Adjustments -// --------------------------------------------------------------------------- -.session-drawer--mobile { - .session-drawer__header { - padding: 12px 20px 12px; - } - - .session-drawer__content { - padding: 0 20px 12px; - } - - .session-drawer__actions { - padding: 12px 20px 16px; - flex-direction: column; - - .session-drawer__action-btn { - width: 100%; - justify-content: center; - } - } - - .session-drawer__log-container { - max-height: 200px; - } -} - -// --------------------------------------------------------------------------- -// Responsive — wider viewports keep 480px, narrow go full-width -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .session-drawer:not(.session-drawer--mobile) { - width: 100%; - max-width: 100vw; - } -} - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .session-drawer { - transition: none; - } - - .session-drawer-backdrop { - transition: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.ts b/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.ts deleted file mode 100644 index 2442e48..0000000 --- a/frontend-legacy/src/app/components/agent-session-drawer/agent-session-drawer.component.ts +++ /dev/null @@ -1,268 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - ElementRef, - EventEmitter, - HostListener, - Input, - OnDestroy, - Output, - signal, - ViewChild, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatChipsModule } from '@angular/material/chips'; -import { AgentCardData, AgentStatus } from '../../models/agent.model'; - -// ============================================================================ -// Agent Session Drawer — Per CUB-26 -// Desktop: 480px side drawer slides from right with modal overlay. -// Mobile: Bottom sheet slides up from bottom. -// Shows: Agent name, status badge, session key, live log tail, -// recent messages, and action buttons. -// ============================================================================ - -export interface SessionLogLine { - timestamp: Date; - level: 'info' | 'warn' | 'error' | 'debug'; - message: string; -} - -export interface SessionMessage { - id: string; - sender: 'agent' | 'user'; - content: string; - timestamp: Date; -} - -@Component({ - selector: 'app-agent-session-drawer', - standalone: true, - imports: [CommonModule, MatButtonModule, MatIconModule, MatChipsModule], - templateUrl: './agent-session-drawer.component.html', - styleUrl: './agent-session-drawer.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AgentSessionDrawerComponent implements OnDestroy { - // --------------------------------------------------------------------------- - // Inputs - // --------------------------------------------------------------------------- - - /** The agent whose session details are displayed. */ - @Input() set agent(value: AgentCardData | null) { - this._agent = value; - if (value) { - this.isOpen.set(true); - this.loadSessionData(value); - } - } - get agent(): AgentCardData | null { - return this._agent; - } - private _agent: AgentCardData | null = null; - - /** Whether this is mobile viewport (bottom sheet mode). */ - @Input() isMobile = false; - - // --------------------------------------------------------------------------- - // Outputs - // --------------------------------------------------------------------------- - - /** Emitted when the user clicks "Open Full Session". Payload is the session key. */ - @Output() readonly openSession = new EventEmitter(); - - /** Emitted when the user clicks "Pin to Dashboard". Payload is the session key. */ - @Output() readonly pinToDashboard = new EventEmitter(); - - /** Emitted when the drawer closes. */ - @Output() readonly drawerClose = new EventEmitter(); - - // --------------------------------------------------------------------------- - // Signals - // --------------------------------------------------------------------------- - - readonly isOpen = signal(false); - readonly logLines = signal([]); - readonly recentMessages = signal([]); - - // --------------------------------------------------------------------------- - // View Children - // --------------------------------------------------------------------------- - - @ViewChild('drawerPanel') drawerPanel!: ElementRef; - - // --------------------------------------------------------------------------- - // Status Helpers - // --------------------------------------------------------------------------- - - getStatusClass(status: string): string { - return `status-dot--${status}`; - } - - getStatusLabel(status: AgentStatus): string { - const labels: Record = { - active: 'Active', - idle: 'Idle', - thinking: 'Thinking…', - error: 'Error', - offline: 'Offline', - }; - return labels[status] ?? status; - } - - getStatusChipColor(status: AgentStatus): string { - const map: Record = { - active: 'status-chip--active', - idle: 'status-chip--idle', - thinking: 'status-chip--thinking', - error: 'status-chip--error', - offline: 'status-chip--offline', - }; - return map[status] ?? ''; - } - - getLogLevelClass(level: SessionLogLine['level']): string { - return `log-line--${level}`; - } - - /** Format a date to a short time string. */ - formatTime(date: Date): string { - return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); - } - - /** Format a date to a relative time string. */ - formatRelativeTime(date: Date): string { - const now = Date.now(); - const then = date.getTime(); - const diffSec = Math.max(0, Math.floor((now - then) / 1000)); - if (diffSec < 60) return 'just now'; - if (diffSec < 3600) return `${Math.floor(diffSec / 60)}m ago`; - if (diffSec < 86400) return `${Math.floor(diffSec / 3600)}h ago`; - return `${Math.floor(diffSec / 86400)}d ago`; - } - - // --------------------------------------------------------------------------- - // Public API - // --------------------------------------------------------------------------- - - /** Open the drawer for a specific agent. */ - open(agentData: AgentCardData): void { - this._agent = agentData; - this.isOpen.set(true); - this.loadSessionData(agentData); - } - - /** Close the drawer. */ - close(): void { - this.isOpen.set(false); - this.drawerClose.emit(); - } - - // --------------------------------------------------------------------------- - // Keyboard Handling - // --------------------------------------------------------------------------- - - @HostListener('document:keydown.escape') - onEscapeKey(): void { - if (this.isOpen()) { - this.close(); - } - } - - /** Handle keyboard navigation within the drawer. */ - onDrawerKeydown(event: KeyboardEvent): void { - if (event.key === 'Escape') { - this.close(); - return; - } - // Tab through actions — browser default Tab behavior is fine, - // we just trap focus within the drawer - } - - // --------------------------------------------------------------------------- - // Outside Click - // --------------------------------------------------------------------------- - - onBackdropClick(): void { - this.close(); - } - - // --------------------------------------------------------------------------- - // Actions - // --------------------------------------------------------------------------- - - onOpenSession(): void { - if (this._agent) { - this.openSession.emit(this._agent.sessionKey); - } - this.close(); - } - - onPinToDashboard(): void { - if (this._agent) { - this.pinToDashboard.emit(this._agent.sessionKey); - } - // Don't close — user may want to keep viewing - } - - // --------------------------------------------------------------------------- - // Lifecycle - // --------------------------------------------------------------------------- - - ngOnDestroy(): void { - // Clean up any subscriptions when needed - } - - // --------------------------------------------------------------------------- - // Private - // --------------------------------------------------------------------------- - - /** Load mock session data for the agent (TODO: wire to real data service). */ - private loadSessionData(agentData: AgentCardData): void { - // TODO: Replace with real session data service when available. - // For now, generate placeholder log lines and messages. - const now = new Date(); - const logLines: SessionLogLine[] = []; - for (let i = 19; i >= 0; i--) { - const ts = new Date(now.getTime() - i * 5000); - const levels: SessionLogLine['level'][] = ['info', 'info', 'info', 'debug', 'warn']; - const messages = [ - `Processing task queue for ${agentData.displayName}`, - `SignalR heartbeat OK`, - `Session state: active`, - `Checking for pending commands…`, - `Updating task progress: ${Math.floor(Math.random() * 100)}%`, - ]; - logLines.push({ - timestamp: ts, - level: levels[i % levels.length], - message: messages[i % messages.length], - }); - } - this.logLines.set(logLines); - - const recentMessages: SessionMessage[] = [ - { - id: '1', - sender: 'user', - content: `Hey ${agentData.displayName}, how's the current task going?`, - timestamp: new Date(now.getTime() - 120000), - }, - { - id: '2', - sender: 'agent', - content: agentData.currentTask ?? 'Working on it — progress is steady.', - timestamp: new Date(now.getTime() - 115000), - }, - { - id: '3', - sender: 'user', - content: 'Great, let me know if you hit any blockers.', - timestamp: new Date(now.getTime() - 110000), - }, - ]; - this.recentMessages.set(recentMessages); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-session-drawer/index.ts b/frontend-legacy/src/app/components/agent-session-drawer/index.ts deleted file mode 100644 index 56d96ee..0000000 --- a/frontend-legacy/src/app/components/agent-session-drawer/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { AgentSessionDrawerComponent } from './agent-session-drawer.component'; -export type { SessionLogLine, SessionMessage } from './agent-session-drawer.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.html b/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.html deleted file mode 100644 index e88ea86..0000000 --- a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.html +++ /dev/null @@ -1,8 +0,0 @@ - - - {{ displayLabel }} - \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.scss b/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.scss deleted file mode 100644 index 331d6f9..0000000 --- a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.scss +++ /dev/null @@ -1,146 +0,0 @@ -// ============================================================================ -// Agent Status Badge — per spec Section 7.3 -// Colored pill with dot indicator and optional pulse animation. -// ============================================================================ - -$badge-height: 24px; -$dot-size: 8px; -$border-radius: 12px; -$font-size: 12px; -$font-weight: 500; -$padding-x: 8px; -$gap: 6px; - -@use 'sass:color'; - -// Status color palette -$color-active: #22c55e; // green-500 -$color-idle: #9ca3af; // gray-400 -$color-thinking: #3b82f6; // blue-500 -$color-error: #ef4444; // red-500 -$color-offline: #9ca3af; // gray-400 - -// Background tints (12% opacity for soft pill background) -$bg-active: rgba($color-active, 0.12); -$bg-idle: rgba($color-idle, 0.12); -$bg-thinking: rgba($color-thinking, 0.12); -$bg-error: rgba($color-error, 0.12); -$bg-offline: rgba($color-offline, 0.12); - -// --------------------------------------------------------------------------- -// Base pill -// --------------------------------------------------------------------------- -.badge { - display: inline-flex; - align-items: center; - height: $badge-height; - padding: 0 $padding-x; - border-radius: $border-radius; - gap: $gap; - font-size: $font-size; - font-weight: $font-weight; - line-height: 1; - white-space: nowrap; - user-select: none; -} - -// --------------------------------------------------------------------------- -// Dot indicator -// --------------------------------------------------------------------------- -.badge__dot { - width: $dot-size; - height: $dot-size; - border-radius: 50%; - flex-shrink: 0; -} - -// --------------------------------------------------------------------------- -// Label text -// --------------------------------------------------------------------------- -.badge__label { - line-height: 1; -} - -// --------------------------------------------------------------------------- -// Status color variants -// --------------------------------------------------------------------------- -.badge--active { - background: $bg-active; - color: color.adjust($color-active, $lightness: -10%); - - .badge__dot { - background: $color-active; - } -} - -.badge--idle { - background: $bg-idle; - color: color.adjust($color-idle, $lightness: -15%); - - .badge__dot { - background: $color-idle; - } -} - -.badge--thinking { - background: $bg-thinking; - color: color.adjust($color-thinking, $lightness: -10%); - - .badge__dot { - background: $color-thinking; - } -} - -.badge--error { - background: $bg-error; - color: color.adjust($color-error, $lightness: -10%); - - .badge__dot { - background: $color-error; - } -} - -.badge--offline { - background: $bg-offline; - color: color.adjust($color-offline, $lightness: -15%); - - .badge__dot { - background: $color-offline; - } -} - -// --------------------------------------------------------------------------- -// Pulse animation — applied when status is active, thinking, or error -// --------------------------------------------------------------------------- -.badge--pulse { - .badge__dot { - animation: pulse-dot 2s ease-in-out infinite; - } -} - -// Active: 2s pulse -.badge--active.badge--pulse .badge__dot { - animation-duration: 2s; -} - -// Thinking: 3s pulse -.badge--thinking.badge--pulse .badge__dot { - animation-duration: 3s; -} - -// Error: 0.8s pulse (fast, urgent) -.badge--error.badge--pulse .badge__dot { - animation-duration: 0.8s; -} - -@keyframes pulse-dot { - 0%, - 100% { - opacity: 1; - transform: scale(1); - } - 50% { - opacity: 0.4; - transform: scale(1.5); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.ts b/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.ts deleted file mode 100644 index a246d63..0000000 --- a/frontend-legacy/src/app/components/agent-status-badge/agent-status-badge.component.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { ChangeDetectionStrategy, Component, input } from '@angular/core'; -import { AgentStatus } from '../../models/agent.model'; - -/** - * Agent Status Badge component. - * Displays a colored pill with a pulse animation indicating the agent's current status. - * Per spec Section 7.3: Agent Card Component Interface — status indicator. - * - * Color mapping: - * - Active → green - * - Idle → gray - * - Thinking → blue - * - Error → red - * - Offline → gray (no pulse) - * - * Pulse animations: - * - Active → 2s - * - Error → 0.8s - * - Thinking → 3s - * - Idle / Offline → no pulse - */ -@Component({ - selector: 'app-agent-status-badge', - standalone: true, - imports: [], - templateUrl: './agent-status-badge.component.html', - styleUrl: './agent-status-badge.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AgentStatusBadgeComponent { - /** Current agent status — binds to the AgentStatus type from the model. */ - readonly status = input.required(); - - /** Label text shown inside the badge. Defaults to title-cased status. */ - readonly label = input(); - - get displayLabel(): string { - return this.label() ?? this.titleCase(this.status()); - } - - /** CSS class driven by the current status value. */ - get statusClass(): string { - return `badge--${this.status()}`; - } - - /** Whether the pulse animation should be active for the current status. */ - get hasPulse(): boolean { - return this.status() === 'active' || this.status() === 'thinking' || this.status() === 'error'; - } - - private titleCase(value: string): string { - return value.charAt(0).toUpperCase() + value.slice(1); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/agent-status-badge/index.ts b/frontend-legacy/src/app/components/agent-status-badge/index.ts deleted file mode 100644 index e531d31..0000000 --- a/frontend-legacy/src/app/components/agent-status-badge/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AgentStatusBadgeComponent } from './agent-status-badge.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.html b/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.html deleted file mode 100644 index 47eb934..0000000 --- a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.html +++ /dev/null @@ -1,31 +0,0 @@ - -
- - - \ No newline at end of file diff --git a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.scss b/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.scss deleted file mode 100644 index fce6731..0000000 --- a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.scss +++ /dev/null @@ -1,198 +0,0 @@ -// ============================================================================ -// Global Action Modal — Tactical Dark Mode Styling -// Uses Control Center design tokens from styles.scss -// ============================================================================ - -// --------------------------------------------------------------------------- -// Backdrop -// --------------------------------------------------------------------------- -:host { - display: block; - position: fixed; - inset: 0; - z-index: 1000; -} - -.global-action-modal__backdrop { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.6); - backdrop-filter: blur(4px); -} - -// --------------------------------------------------------------------------- -// Modal Panel -// --------------------------------------------------------------------------- -.global-action-modal__panel { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: min(560px, calc(100vw - 48px)); - background: var(--cc-surface-container); - border: 1px solid var(--cc-outline); - border-radius: var(--cc-card-border-radius); - box-shadow: 0 24px 48px rgba(0, 0, 0, 0.5); - overflow: hidden; -} - -// --------------------------------------------------------------------------- -// Header -// --------------------------------------------------------------------------- -.global-action-modal__header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px 24px 12px; -} - -.global-action-modal__title { - margin: 0; - font-size: 20px; - font-weight: 600; - color: var(--cc-on-surface); - letter-spacing: 0.01em; -} - -.global-action-modal__close { - --mat-icon-button-state-layer-color: transparent; - color: var(--cc-on-surface-variant); - - &:hover { - color: var(--cc-on-surface); - } -} - -// --------------------------------------------------------------------------- -// Action Grid -// --------------------------------------------------------------------------- -.global-action-modal__actions { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 12px; - padding: 12px 24px 24px; -} - -// --------------------------------------------------------------------------- -// Action Button -// --------------------------------------------------------------------------- -.global-action-modal__action-btn { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - padding: 20px 16px; - border: 1px solid var(--cc-outline); - border-radius: 12px; - background: var(--cc-surface); - color: var(--cc-on-surface); - cursor: pointer; - transition: background 150ms ease, border-color 150ms ease, transform 100ms ease; - font-family: inherit; - text-align: center; - - &:hover { - background: var(--cc-surface-container-high); - border-color: var(--cc-on-surface-variant); - transform: translateY(-1px); - } - - &:active { - transform: translateY(0); - } - - &:focus-visible { - outline: 2px solid var(--mat-sys-primary, #38BDF8); - outline-offset: 2px; - } -} - -// Action icon wrapper -.global-action-modal__action-icon { - width: 48px; - height: 48px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 12px; - - .mat-icon { - width: 28px; - height: 28px; - font-size: 28px; - } -} - -// Action label -.global-action-modal__action-label { - font-size: 15px; - font-weight: 600; - letter-spacing: 0.01em; -} - -// Action description -.global-action-modal__action-desc { - font-size: 12px; - color: var(--cc-on-surface-variant); - line-height: 1.4; -} - -// --------------------------------------------------------------------------- -// Color Variants — per-action accent colors -// --------------------------------------------------------------------------- -.global-action-modal__action-btn--deploy { - .global-action-modal__action-icon { - background: var(--status-active-bg); - color: var(--status-active); - } - - &:hover { - border-color: var(--status-active); - } -} - -.global-action-modal__action-btn--pause { - .global-action-modal__action-icon { - background: var(--status-idle-bg); - color: var(--status-idle); - } - - &:hover { - border-color: var(--status-idle); - } -} - -.global-action-modal__action-btn--emergency { - .global-action-modal__action-icon { - background: var(--status-error-bg); - color: var(--status-error); - } - - &:hover { - border-color: var(--status-error); - } - - .global-action-modal__action-label { - color: var(--status-error); - } -} - -.global-action-modal__action-btn--add { - .global-action-modal__action-icon { - background: var(--status-thinking-bg); - color: var(--status-thinking); - } - - &:hover { - border-color: var(--status-thinking); - } -} - -// --------------------------------------------------------------------------- -// Responsive — stack single column on narrow viewports -// --------------------------------------------------------------------------- -@media (max-width: 400px) { - .global-action-modal__actions { - grid-template-columns: 1fr; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.ts b/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.ts deleted file mode 100644 index dc36fa2..0000000 --- a/frontend-legacy/src/app/components/global-action-modal/global-action-modal.component.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core'; -import { MatIconModule } from '@angular/material/icon'; -import { MatButtonModule } from '@angular/material/button'; - -/** - * Global Action Modal — overlay for fleet-wide commands. - * - * Four main actions: Deploy All, Pause All, Emergency Stop, Add Agent. - * Tactical Dark Mode styling using Control Center design tokens. - * Dismisses on backdrop click or close button. - */ -@Component({ - selector: 'app-global-action-modal', - standalone: true, - imports: [MatIconModule, MatButtonModule], - templateUrl: './global-action-modal.component.html', - styleUrl: './global-action-modal.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class GlobalActionModalComponent { - /** Emitted when any action button is clicked. Payload is the action key. */ - @Output() readonly actionSelected = new EventEmitter(); - - /** Emitted when the modal is dismissed (backdrop click or close button). */ - @Output() readonly dismissed = new EventEmitter(); - - @ViewChild('backdrop') backdropEl!: ElementRef; - - /** All available global actions. */ - readonly actions: GlobalActionDef[] = [ - { - key: 'deploy-all', - label: 'Deploy All', - description: 'Deploy all agents in the fleet', - icon: 'rocket_launch', - color: 'deploy', - }, - { - key: 'pause-all', - label: 'Pause All', - description: 'Pause all running agents', - icon: 'pause_circle', - color: 'pause', - }, - { - key: 'emergency-stop', - label: 'Emergency Stop', - description: 'Immediately halt all agents', - icon: 'emergency', - color: 'emergency', - }, - { - key: 'add-agent', - label: 'Add Agent', - description: 'Register a new agent to the fleet', - icon: 'person_add', - color: 'add', - }, - ]; - - onBackdropClick(): void { - this.dismissed.emit(); - } - - onModalClick(event: Event): void { - // Prevent clicks inside the modal panel from closing it - event.stopPropagation(); - } - - onClose(): void { - this.dismissed.emit(); - } - - onAction(action: GlobalActionDef): void { - this.actionSelected.emit(action.key); - } -} - -export type GlobalAction = 'deploy-all' | 'pause-all' | 'emergency-stop' | 'add-agent'; - -export interface GlobalActionDef { - key: GlobalAction; - label: string; - description: string; - icon: string; - color: 'deploy' | 'pause' | 'emergency' | 'add'; -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/index.ts b/frontend-legacy/src/app/components/index.ts deleted file mode 100644 index 84852cc..0000000 --- a/frontend-legacy/src/app/components/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './quick-jump-button/quick-jump-button.component'; -export { AgentStatusBadgeComponent } from './agent-status-badge/agent-status-badge.component'; -export { QuickJumpDrawerComponent } from './quick-jump-drawer/index'; -export { AgentSessionDrawerComponent } from './agent-session-drawer/index'; -export type { SessionLogLine, SessionMessage } from './agent-session-drawer/index'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.html b/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.html deleted file mode 100644 index 3aa3c3c..0000000 --- a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.html +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.scss b/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.scss deleted file mode 100644 index 718b441..0000000 --- a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.scss +++ /dev/null @@ -1,68 +0,0 @@ -// ============================================================================ -// Quick-Jump Button — M3 FilledTonalIconButton -// Per spec Section 7.3: Agent Card Quick-Jump action -// M3 spec: FilledTonalIconButton uses secondary container color -// with 8% state layer overlay for hover/focus. -// ============================================================================ - -.quick-jump-button { - // M3 FilledTonalIconButton: secondary-container background - // Angular Material mat-icon-button sets up the base shape (40x40, round). - // We override the color tokens to match FilledTonal style. - --mdc-icon-button-icon-color: var(--mat-sys-on-secondary-container); - background-color: var(--mat-sys-secondary-container); - border-radius: 50%; - transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1); - - // M3 State Layer: 8% overlay on hover - &:hover { - background-color: var(--mat-sys-secondary-container); - // State layer overlay using a pseudo-element for precise 8% opacity - &::after { - content: ''; - position: absolute; - inset: 0; - border-radius: 50%; - background-color: var(--mat-sys-on-secondary-container); - opacity: 0.08; - pointer-events: none; - } - } - - // M3 State Layer: 12% overlay on focus-visible (slightly stronger for accessibility) - &:focus-visible { - background-color: var(--mat-sys-secondary-container); - outline: 3px solid var(--status-active); - outline-offset: 2px; - - &::after { - content: ''; - position: absolute; - inset: 0; - border-radius: 50%; - background-color: var(--mat-sys-on-secondary-container); - opacity: 0.12; - pointer-events: none; - } - } - - // M3 State Layer: 12% overlay on active/pressed - &:active { - background-color: var(--mat-sys-secondary-container); - - &::after { - content: ''; - position: absolute; - inset: 0; - border-radius: 50%; - background-color: var(--mat-sys-on-secondary-container); - opacity: 0.12; - pointer-events: none; - } - } - - // Icon color stays on-secondary-container across all states - .mat-icon { - color: var(--mat-sys-on-secondary-container); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.ts b/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.ts deleted file mode 100644 index 899fc1d..0000000 --- a/frontend-legacy/src/app/components/quick-jump-button/quick-jump-button.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core'; -import { MatIconButton } from '@angular/material/button'; -import { MatIcon } from '@angular/material/icon'; - -/** - * Quick-Jump Button — M3 FilledTonalIconButton - * - * An icon button that emits a navigation event for jumping to an agent session. - * Uses the Material Design 3 FilledTonalIconButton style with 8% state layer - * overlay on hover and focus. - * - * Per spec Section 7.3: Agent Card Component Interface - */ -@Component({ - selector: 'app-quick-jump-button', - standalone: true, - imports: [MatIconButton, MatIcon], - templateUrl: './quick-jump-button.component.html', - styleUrl: './quick-jump-button.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class QuickJumpButtonComponent { - /** Emitted when the button is clicked, carrying the session key for navigation. */ - @Output() jumpClick = new EventEmitter(); - - /** The session key to navigate to. Set by the parent agent card. */ - sessionKey = ''; - - onJumpClick(): void { - this.jumpClick.emit(this.sessionKey); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-drawer/index.ts b/frontend-legacy/src/app/components/quick-jump-drawer/index.ts deleted file mode 100644 index f559c65..0000000 --- a/frontend-legacy/src/app/components/quick-jump-drawer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { QuickJumpDrawerComponent } from './quick-jump-drawer.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.html b/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.html deleted file mode 100644 index d9dc4d2..0000000 --- a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.html +++ /dev/null @@ -1,109 +0,0 @@ - - - -@if (isOpen()) { -
-} - - - \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.scss b/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.scss deleted file mode 100644 index 1a9362c..0000000 --- a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.scss +++ /dev/null @@ -1,333 +0,0 @@ -// ============================================================================ -// Quick-Jump Drawer — Slide-out panel for fast agent switching -// Per CUB-51: slides from right, agent list with status badges, -// search/filter input, closes via ESC or outside click. -// ============================================================================ - -// --------------------------------------------------------------------------- -// Backdrop -// --------------------------------------------------------------------------- -.quick-jump-backdrop { - position: fixed; - inset: 0; - background-color: rgba(0, 0, 0, 0.5); - z-index: 998; - opacity: 0; - transition: opacity 200ms ease-out; - - &.backdrop-visible { - opacity: 1; - } -} - -// --------------------------------------------------------------------------- -// Drawer Panel -// --------------------------------------------------------------------------- -.quick-jump-drawer { - position: fixed; - top: 0; - right: 0; - bottom: 0; - width: 380px; - max-width: 90vw; - background-color: var(--cc-surface-container); - border-left: 1px solid var(--cc-outline); - z-index: 999; - display: flex; - flex-direction: column; - transform: translateX(100%); - transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: -4px 0 24px rgba(0, 0, 0, 0.3); - - &--open { - transform: translateX(0); - } -} - -// --------------------------------------------------------------------------- -// Header -// --------------------------------------------------------------------------- -.quick-jump-drawer__header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px 24px 12px; - border-bottom: 1px solid var(--cc-outline); -} - -.quick-jump-drawer__title { - font-size: 20px; - font-weight: 500; - color: var(--cc-on-surface); - margin: 0; - letter-spacing: -0.01em; -} - -.quick-jump-drawer__close-btn { - display: flex; - align-items: center; - justify-content: center; - width: 36px; - height: 36px; - border: none; - border-radius: 8px; - background: transparent; - color: var(--cc-on-surface-variant); - font-size: 18px; - cursor: pointer; - transition: background-color 150ms ease, color 150ms ease; - - &:hover { - background-color: var(--cc-surface-container-high); - color: var(--cc-on-surface); - } - - &:focus-visible { - outline: 2px solid var(--status-active); - outline-offset: 2px; - } -} - -// --------------------------------------------------------------------------- -// Search -// --------------------------------------------------------------------------- -.quick-jump-drawer__search { - position: relative; - display: flex; - align-items: center; - margin: 16px 24px 8px; - border: 1px solid var(--cc-outline); - border-radius: 12px; - background-color: var(--cc-surface-container-high); - transition: border-color 150ms ease; - - &:focus-within { - border-color: var(--status-active); - } -} - -.quick-jump-drawer__search-icon { - display: flex; - align-items: center; - justify-content: center; - padding-left: 12px; - font-family: 'Material Icons'; - font-size: 20px; - color: var(--cc-on-surface-variant); - pointer-events: none; - user-select: none; - - // Use a simple "search" text since icon font may not be loaded inside - // the drawer — rely on Material icon font from the parent app - &::before { - content: 'search'; - font-family: 'Material Icons'; - } -} - -.quick-jump-drawer__search-input { - flex: 1; - border: none; - outline: none; - background: transparent; - padding: 12px 8px; - font-size: 15px; - font-family: 'Inter', 'Roboto', sans-serif; - color: var(--cc-on-surface); - - &::placeholder { - color: var(--cc-on-surface-variant); - opacity: 0.7; - } -} - -.quick-jump-drawer__search-clear { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - margin-right: 4px; - border: none; - border-radius: 8px; - background: transparent; - color: var(--cc-on-surface-variant); - font-size: 14px; - cursor: pointer; - transition: background-color 150ms ease, color 150ms ease; - - &:hover { - background-color: var(--cc-surface-container); - color: var(--cc-on-surface); - } - - &:focus-visible { - outline: 2px solid var(--status-active); - outline-offset: 2px; - } -} - -// --------------------------------------------------------------------------- -// Agent List -// --------------------------------------------------------------------------- -.quick-jump-drawer__agent-list { - list-style: none; - margin: 0; - padding: 8px 12px; - overflow-y: auto; - flex: 1; -} - -.quick-jump-drawer__agent-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - border-radius: 12px; - cursor: pointer; - transition: background-color 150ms ease; - - &:hover, - &--highlighted { - background-color: var(--cc-surface-container-high); - } - - &--highlighted { - outline: 2px solid var(--status-active); - outline-offset: -2px; - } - - &:focus-visible { - outline: 2px solid var(--status-active); - outline-offset: 2px; - } -} - -.quick-jump-drawer__agent-info { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; // Allow text truncation - flex: 1; -} - -.quick-jump-drawer__agent-name { - font-size: 15px; - font-weight: 500; - color: var(--cc-on-surface); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.quick-jump-drawer__agent-role { - font-size: 12px; - color: var(--cc-on-surface-variant); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.quick-jump-drawer__agent-status-label { - font-size: 11px; - font-weight: 500; - text-transform: uppercase; - letter-spacing: 0.05em; - padding: 3px 8px; - border-radius: 6px; - white-space: nowrap; - - &.status-label--active { - color: var(--status-active); - background-color: var(--status-active-bg); - } - - &.status-label--idle { - color: var(--status-idle); - background-color: var(--status-idle-bg); - } - - &.status-label--thinking { - color: var(--status-thinking); - background-color: var(--status-thinking-bg); - } - - &.status-label--error { - color: var(--status-error); - background-color: var(--status-error-bg); - } - - &.status-label--offline { - color: var(--status-offline); - background-color: rgba(100, 116, 139, 0.12); - } -} - -// --------------------------------------------------------------------------- -// Empty State -// --------------------------------------------------------------------------- -.quick-jump-drawer__empty { - display: flex; - align-items: center; - justify-content: center; - padding: 48px 24px; - color: var(--cc-on-surface-variant); - font-size: 14px; - text-align: center; -} - -// --------------------------------------------------------------------------- -// Footer -// --------------------------------------------------------------------------- -.quick-jump-drawer__footer { - padding: 12px 24px 16px; - border-top: 1px solid var(--cc-outline); -} - -.quick-jump-drawer__footer-hint { - display: flex; - align-items: center; - justify-content: center; - gap: 4px; - font-size: 11px; - color: var(--cc-on-surface-variant); - opacity: 0.7; - - kbd { - display: inline-block; - padding: 2px 6px; - font-size: 11px; - font-family: var(--cc-font-mono); - background-color: var(--cc-surface-container-high); - border: 1px solid var(--cc-outline); - border-radius: 4px; - color: var(--cc-on-surface-variant); - line-height: 1.4; - } -} - -// --------------------------------------------------------------------------- -// Mobile Adjustments -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .quick-jump-drawer { - width: 100%; - max-width: 100vw; - } - - .quick-jump-drawer__header { - padding: 16px 16px 10px; - } - - .quick-jump-drawer__search { - margin: 12px 16px 8px; - } - - .quick-jump-drawer__agent-list { - padding: 4px 8px; - } - - .quick-jump-drawer__footer { - padding: 10px 16px 14px; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.ts b/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.ts deleted file mode 100644 index 983348f..0000000 --- a/frontend-legacy/src/app/components/quick-jump-drawer/quick-jump-drawer.component.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - ElementRef, - EventEmitter, - HostListener, - OnDestroy, - Output, - signal, - ViewChild, -} from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { Subject, takeUntil } from 'rxjs'; -import { AgentCardData } from '../../models/agent.model'; -import { AgentStatusService } from '../../services/agent-status.service'; - -@Component({ - selector: 'app-quick-jump-drawer', - standalone: true, - imports: [ReactiveFormsModule], - templateUrl: './quick-jump-drawer.component.html', - styleUrl: './quick-jump-drawer.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class QuickJumpDrawerComponent implements OnDestroy { - /** Emits when the drawer should close (ESC, outside click, or item select). */ - @Output() readonly drawerClose = new EventEmitter(); - - /** Whether the drawer is visible. */ - readonly isOpen = signal(false); - - /** Search/filter input control. */ - readonly searchControl = new FormControl('', { nonNullable: true }); - - /** Filtered agent list based on search. */ - readonly filteredAgents = signal([]); - - /** Track which agent row is highlighted via keyboard navigation. */ - readonly highlightedIndex = signal(-1); - - @ViewChild('searchInput') searchInput!: ElementRef; - @ViewChild('drawerPanel') drawerPanel!: ElementRef; - - private readonly destroy$ = new Subject(); - - constructor(private readonly agentStatusService: AgentStatusService) { - // Reactively filter agents as the search input changes - this.searchControl.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe((query) => this.filterAgents(query)); - - // Initial load - this.filterAgents(''); - } - - // --------------------------------------------------------------------------- - // Public API - // --------------------------------------------------------------------------- - - /** Open the drawer and focus the search input. */ - open(): void { - this.isOpen.set(true); - this.searchControl.setValue('', { emitEvent: false }); - this.highlightedIndex.set(-1); - // Focus search input after animation frame (drawer needs to render first) - requestAnimationFrame(() => { - this.searchInput?.nativeElement?.focus(); - }); - } - - /** Close the drawer. */ - close(): void { - this.isOpen.set(false); - this.searchControl.setValue('', { emitEvent: false }); - this.highlightedIndex.set(-1); - this.drawerClose.emit(); - } - - /** Toggle the drawer open/close. */ - toggle(): void { - if (this.isOpen()) { - this.close(); - } else { - this.open(); - } - } - - // --------------------------------------------------------------------------- - // Keyboard Handling - // --------------------------------------------------------------------------- - - @HostListener('document:keydown.escape') - onEscapeKey(): void { - if (this.isOpen()) { - this.close(); - } - } - - /** Handle keyboard navigation within the drawer panel. */ - onDrawerKeydown(event: KeyboardEvent): void { - const agents = this.filteredAgents(); - if (!agents.length) return; - - switch (event.key) { - case 'ArrowDown': { - event.preventDefault(); - this.highlightedIndex.update((i) => - i < agents.length - 1 ? i + 1 : 0 - ); - this.scrollIntoView(); - break; - } - case 'ArrowUp': { - event.preventDefault(); - this.highlightedIndex.update((i) => - i > 0 ? i - 1 : agents.length - 1 - ); - this.scrollIntoView(); - break; - } - case 'Enter': { - const idx = this.highlightedIndex(); - if (idx >= 0 && idx < agents.length) { - this.selectAgent(agents[idx]); - } - break; - } - } - } - - // --------------------------------------------------------------------------- - // Outside Click - // --------------------------------------------------------------------------- - - /** Close when clicking on the backdrop (outside the panel). */ - onBackdropClick(event: MouseEvent): void { - if ( - this.drawerPanel?.nativeElement && - !this.drawerPanel.nativeElement.contains(event.target as Node) - ) { - this.close(); - } - } - - // --------------------------------------------------------------------------- - // Agent Selection - // --------------------------------------------------------------------------- - - /** Select an agent — navigates or focuses the agent card. */ - selectAgent(agent: AgentCardData): void { - // TODO: Wire up navigation to the selected agent's detail view - // For now, emit close after selection - console.log('[QuickJump] Selected agent:', agent.id); - this.close(); - } - - // --------------------------------------------------------------------------- - // Status Helpers - // --------------------------------------------------------------------------- - - /** Get the CSS class for a given agent status. */ - getStatusClass(status: string): string { - return `status-dot--${status}`; - } - - /** Get a human-readable label for an agent status. */ - getStatusLabel(status: string): string { - const labels: Record = { - active: 'Active', - idle: 'Idle', - thinking: 'Thinking', - error: 'Error', - offline: 'Offline', - }; - return labels[status] ?? status; - } - - // --------------------------------------------------------------------------- - // Lifecycle - // --------------------------------------------------------------------------- - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - - // --------------------------------------------------------------------------- - // Private - // --------------------------------------------------------------------------- - - private filterAgents(query: string): void { - const allAgents = this.agentStatusService.agents(); - const lowerQuery = query.toLowerCase().trim(); - - if (!lowerQuery) { - this.filteredAgents.set(allAgents); - return; - } - - const filtered = allAgents.filter( - (agent) => - agent.displayName.toLowerCase().includes(lowerQuery) || - agent.id.toLowerCase().includes(lowerQuery) || - agent.role.toLowerCase().includes(lowerQuery) - ); - this.filteredAgents.set(filtered); - this.highlightedIndex.set(-1); - } - - private scrollIntoView(): void { - const idx = this.highlightedIndex(); - const el = document.getElementById(`quick-jump-agent-${idx}`); - el?.scrollIntoView({ block: 'nearest', behavior: 'smooth' }); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/task-progress-bar/index.ts b/frontend-legacy/src/app/components/task-progress-bar/index.ts deleted file mode 100644 index 67414db..0000000 --- a/frontend-legacy/src/app/components/task-progress-bar/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// ============================================================================ -// Task Progress Bar — Barrel Export -// CUB-44 -// ============================================================================ - -export { TaskProgressBarComponent } from './task-progress-bar.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.html b/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.html deleted file mode 100644 index f8d8a7d..0000000 --- a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.html +++ /dev/null @@ -1,18 +0,0 @@ - -
- -
- {{ clampedProgress }}% - - {{ elapsedText }} - -
- - - -
\ No newline at end of file diff --git a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.scss b/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.scss deleted file mode 100644 index bb467a2..0000000 --- a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.scss +++ /dev/null @@ -1,77 +0,0 @@ -// ============================================================================ -// Task Progress Bar — Tactical Dark Theme Styling -// Per CUB-44: Uses --color-primary for bar fill and --color-surface-light -// for track background, mapped to the Control Center's M3 dark tokens. -// ============================================================================ - -// --------------------------------------------------------------------------- -// Container -// --------------------------------------------------------------------------- -.task-progress-bar { - display: flex; - flex-direction: column; - gap: 6px; - width: 100%; -} - -// --------------------------------------------------------------------------- -// Info row: percentage label + elapsed time -// --------------------------------------------------------------------------- -.task-progress-bar__info { - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 8px; -} - -.task-progress-bar__percent { - font-family: var(--cc-font-mono, 'Roboto Mono', monospace); - font-size: 14px; - font-weight: 600; - color: var(--cc-on-surface, #E2E8F0); - letter-spacing: 0.02em; -} - -.task-progress-bar__elapsed { - font-family: var(--cc-font-mono, 'Roboto Mono', monospace); - font-size: 12px; - font-weight: 400; - color: var(--cc-on-surface-variant, #8A9BB0); - letter-spacing: 0.01em; -} - -// --------------------------------------------------------------------------- -// Material Progress Bar Overrides -// --------------------------------------------------------------------------- -// Map the spec's --color-primary and --color-surface-light to the Control -// Center's actual theme tokens. This ensures the bar uses the tactical dark -// palette while respecting the spec's variable naming. -// --------------------------------------------------------------------------- - -.task-progress-bar__bar { - // Override the track (background) to use the surface container - --mat-progress-bar-track-height: 6px; - --mat-progress-bar-active-indicator-height: 6px; - - // Bar fill color: primary (cyan/sky blue per tactical dark theme) - --mat-progress-bar-active-indicator-color: var(--color-primary, var(--mat-sys-primary, #38BDF8)); - - // Track background: surface container (dark slate) - --mat-progress-bar-track-color: var(--color-surface-light, var(--cc-surface-container, #1C2027)); - - // Border radius for a softer bar - border-radius: 3px; - - // Smooth transition on value changes - transition: none; -} - -// Rounded ends on the progress bar fill -:host ::ng-deep .mdc-linear-progress__bar-inner { - border-radius: 3px; -} - -// Rounded track background -:host ::ng-deep .mdc-linear-progress__track { - border-radius: 3px; -} \ No newline at end of file diff --git a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.ts b/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.ts deleted file mode 100644 index a380566..0000000 --- a/frontend-legacy/src/app/components/task-progress-bar/task-progress-bar.component.ts +++ /dev/null @@ -1,109 +0,0 @@ -// ============================================================================ -// Task Progress Bar Component -// Per CUB-44: Determinate progress bar with optional elapsed time display. -// Uses Angular Material mat-progress-bar in determinate mode with tactical -// dark theme styling via CSS custom properties. -// ============================================================================ - -import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - Input, - OnDestroy, - OnInit, -} from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; - -/** - * Displays a determinate progress bar with an optional elapsed time indicator. - * - * Usage: - * ```html - * - * - * ``` - */ -@Component({ - selector: 'app-task-progress-bar', - standalone: true, - imports: [CommonModule, MatProgressBarModule], - templateUrl: './task-progress-bar.component.html', - styleUrl: './task-progress-bar.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class TaskProgressBarComponent implements OnInit, OnDestroy { - // --------------------------------------------------------------------------- - // Inputs - // --------------------------------------------------------------------------- - - /** Current progress percentage (0–100). Required. */ - @Input({ required: true }) - progress!: number; - - /** Whether to show elapsed time next to the percentage. Defaults to false. */ - @Input() - showElapsed = false; - - // --------------------------------------------------------------------------- - // Internal state - // --------------------------------------------------------------------------- - - /** Timestamp when the component initialized — used for elapsed calculation. */ - startTime = Date.now(); - - /** Formatted elapsed time string, e.g. "2m 15s ago". */ - elapsedText = ''; - - /** Interval timer for updating the elapsed display. */ - private timer: ReturnType | null = null; - - constructor(private cdr: ChangeDetectorRef) {} - - // --------------------------------------------------------------------------- - // Lifecycle - // --------------------------------------------------------------------------- - - ngOnInit(): void { - this.updateElapsed(); - - if (this.showElapsed) { - // Update elapsed time every second - this.timer = setInterval(() => { - this.updateElapsed(); - this.cdr.markForCheck(); - }, 1000); - } - } - - ngOnDestroy(): void { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - } - - // --------------------------------------------------------------------------- - // Helpers - // --------------------------------------------------------------------------- - - /** Clamp progress to 0–100 for safety. */ - get clampedProgress(): number { - return Math.max(0, Math.min(100, this.progress ?? 0)); - } - - /** Recalculate the elapsed time string. */ - private updateElapsed(): void { - const elapsedMs = Date.now() - this.startTime; - const totalSeconds = Math.floor(elapsedMs / 1000); - const minutes = Math.floor(totalSeconds / 60); - const seconds = totalSeconds % 60; - - if (minutes > 0) { - this.elapsedText = `${minutes}m ${seconds}s ago`; - } else { - this.elapsedText = `${seconds}s ago`; - } - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/design/index.ts b/frontend-legacy/src/app/design/index.ts deleted file mode 100644 index 3c94005..0000000 --- a/frontend-legacy/src/app/design/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — Design System Barrel Export -// ============================================================================ -// Import everything from '@app/design' for convenient access. -// -// Usage: -// import { CcTokens, CcThemeService, CcCssProps } from '@app/design'; -// ============================================================================ - -export * from './tokens'; -export * from './theme.service'; \ No newline at end of file diff --git a/frontend-legacy/src/app/design/theme.service.ts b/frontend-legacy/src/app/design/theme.service.ts deleted file mode 100644 index 3fe1ae3..0000000 --- a/frontend-legacy/src/app/design/theme.service.ts +++ /dev/null @@ -1,151 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — Theme Service -// ============================================================================ -// Angular service providing programmatic access to design tokens, theme -// mode switching (dark/light), and runtime CSS custom property manipulation. -// -// Usage: -// constructor(private theme: CcThemeService) {} -// -// // Read a token -// const primary = this.theme.getToken('--cc-color-primary'); -// -// // Set a token at runtime -// this.theme.setToken('--cc-color-primary', '#00ff00'); -// -// // Toggle theme -// this.theme.setMode('light'); -// ============================================================================ - -import { Injectable, signal, computed, effect } from '@angular/core'; -import { CcCssProps, getStatusColor, setCssToken, getCssToken } from './tokens'; - -// --------------------------------------------------------------------------- -// Theme Mode Types -// --------------------------------------------------------------------------- -export type ThemeMode = 'dark' | 'light'; - -// --------------------------------------------------------------------------- -// Light theme overrides (future use) -// --------------------------------------------------------------------------- -const LIGHT_THEME_OVERRIDES: Record = { - // Surface tokens - '--cc-surface-darkest': '#F8FAFC', - '--cc-surface-dark': '#FFFFFF', - '--cc-surface-medium': '#F1F5F9', - '--cc-surface-light': '#E2E8F0', - '--cc-surface-lighter': '#CBD5E1', - - // On-surface tokens - '--cc-on-surface': '#0F172A', - '--cc-on-surface-variant': '#475569', - '--cc-on-surface-muted': '#94A3B8', - - // Border - '--cc-surface-lighter-alt': '#E2E8F0', - - // M3 system overrides for light - '--mat-sys-surface': '#FFFFFF', - '--mat-sys-surface-container': '#F1F5F9', - '--mat-sys-surface-container-high': '#E2E8F0', - '--mat-sys-on-surface': '#0F172A', - '--mat-sys-on-surface-variant': '#475569', - '--mat-sys-outline': '#CBD5E1', - '--mat-sys-background': '#F8FAFC', -}; - -// --------------------------------------------------------------------------- -// Dark theme (matches the SCSS defaults) -// --------------------------------------------------------------------------- -const DARK_THEME_OVERRIDES: Record = { - '--cc-surface-darkest': '#0D0F12', - '--cc-surface-dark': '#13161A', - '--cc-surface-medium': '#1C2027', - '--cc-surface-light': '#252B33', - '--cc-surface-lighter': '#2D3748', - - '--cc-on-surface': '#E2E8F0', - '--cc-on-surface-variant': '#8A9BB0', - '--cc-on-surface-muted': '#64748B', - - '--mat-sys-surface': '#13161A', - '--mat-sys-surface-container': '#1C2027', - '--mat-sys-surface-container-high': '#252B33', - '--mat-sys-on-surface': '#E2E8F0', - '--mat-sys-on-surface-variant': '#8A9BB0', - '--mat-sys-outline': '#2D3748', - '--mat-sys-background': '#0D0F12', -}; - -@Injectable({ providedIn: 'root' }) -export class CcThemeService { - // --------------------------------------------------------------------------- - // Signals for reactive theme state - // --------------------------------------------------------------------------- - private readonly _mode = signal( - (localStorage.getItem('cc-theme') as ThemeMode) ?? 'dark' - ); - - /** Current theme mode */ - readonly mode = this._mode.asReadonly(); - - /** Computed: is the current mode dark? */ - readonly isDark = computed(() => this._mode() === 'dark'); - - /** Computed: is the current mode light? */ - readonly isLight = computed(() => this._mode() === 'light'); - - constructor() { - // Apply theme on init and whenever mode changes - effect(() => { - this.applyTheme(this._mode()); - }); - } - - // --------------------------------------------------------------------------- - // Public API - // --------------------------------------------------------------------------- - - /** Set the theme mode and persist to localStorage */ - setMode(mode: ThemeMode): void { - this._mode.set(mode); - localStorage.setItem('cc-theme', mode); - } - - /** Toggle between dark and light mode */ - toggle(): void { - this.setMode(this._mode() === 'dark' ? 'light' : 'dark'); - } - - /** Read a CSS custom property from the document root */ - getToken(property: string): string { - return getCssToken(property); - } - - /** Set a CSS custom property on the document root */ - setToken(property: string, value: string): void { - setCssToken(property, value); - } - - /** Get status color set by agent status */ - getStatusColors(status: string): { fg: string; bg: string; border: string } { - return getStatusColor(status); - } - - // --------------------------------------------------------------------------- - // Internal - // --------------------------------------------------------------------------- - - /** Apply a theme mode by setting all CSS custom properties */ - private applyTheme(mode: ThemeMode): void { - const overrides = mode === 'dark' ? DARK_THEME_OVERRIDES : LIGHT_THEME_OVERRIDES; - - // Set color-scheme for native form controls - document.documentElement.style.setProperty('color-scheme', mode); - - // Apply all overrides - for (const [prop, value] of Object.entries(overrides)) { - document.documentElement.style.setProperty(prop, value); - } - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/design/tokens.ts b/frontend-legacy/src/app/design/tokens.ts deleted file mode 100644 index b2633b2..0000000 --- a/frontend-legacy/src/app/design/tokens.ts +++ /dev/null @@ -1,462 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — Design Tokens (TypeScript) -// ============================================================================ -// Typed representation of the design system tokens for programmatic access. -// These mirror the SCSS tokens in styles/_tokens.scss and the CSS custom -// properties emitted by styles/_css-properties.scss. -// -// Usage: -// import { CcTokens } from '@app/design/tokens'; -// const primary = CcTokens.color.primary; -// const surface = CcTokens.surface.dark; -// ============================================================================ - -// --------------------------------------------------------------------------- -// Color Palette -// --------------------------------------------------------------------------- -export const CcColors = { - primary: { - 50: '#ecfeff', - 100: '#cffafe', - 200: '#a5f3fc', - 300: '#67e8f9', - 400: '#22d3ee', - 500: '#38bdf8', - 600: '#0ea5e9', - 700: '#0284c7', - 800: '#0369a1', - 900: '#075985', - }, - secondary: { - 50: '#f0fdfa', - 100: '#ccfbf1', - 200: '#99f6e4', - 300: '#5eead4', - 400: '#2dd4bf', - 500: '#14b8a6', - 600: '#0d9488', - 700: '#0f766e', - 800: '#115e59', - 900: '#134e4a', - }, - accent: { - 50: '#f5f3ff', - 100: '#ede9fe', - 200: '#ddd6fe', - 300: '#c4b5fd', - 400: '#a78bfa', - 500: '#8b5cf6', - 600: '#7c3aed', - 700: '#6d28d9', - 800: '#5b21b6', - 900: '#4c1d95', - }, - danger: { - 50: '#fef2f2', - 100: '#fee2e2', - 200: '#fecaca', - 300: '#fca5a5', - 400: '#f87171', - 500: '#ef4444', - 600: '#dc2626', - 700: '#b91c1c', - 800: '#991b1b', - 900: '#7f1d1d', - }, -} as const; - -// --------------------------------------------------------------------------- -// Semantic Colors (Tactical Dark) -// --------------------------------------------------------------------------- -export const CcSemanticColors = { - surface: { - darkest: '#0D0F12', - dark: '#13161A', - medium: '#1C2027', - light: '#252B33', - lighter: '#2D3748', - }, - onSurface: { - primary: '#E2E8F0', - variant: '#8A9BB0', - muted: '#64748B', - }, -} as const; - -// --------------------------------------------------------------------------- -// Status Colors -// --------------------------------------------------------------------------- -export const CcStatusColors = { - active: { fg: '#38bdf8', bg: 'rgba(56, 189, 248, 0.12)', border: 'rgba(56, 189, 248, 0.40)' }, - idle: { fg: '#2dd4bf', bg: 'rgba(45, 212, 191, 0.12)', border: 'rgba(45, 212, 191, 0.40)' }, - thinking: { fg: '#a78bfa', bg: 'rgba(167, 139, 250, 0.12)', border: 'rgba(167, 139, 250, 0.40)' }, - error: { fg: '#f87171', bg: 'rgba(248, 113, 113, 0.12)', border: 'rgba(248, 113, 113, 0.40)' }, - offline: { fg: '#64748b', bg: 'rgba(100, 116, 139, 0.12)', border: 'rgba(100, 116, 139, 0.40)' }, -} as const; - -// --------------------------------------------------------------------------- -// Convenience exports for component usage (CUB-20) -// --------------------------------------------------------------------------- -/** Status colors — maps AgentStatus to hex values */ -export const STATUS_COLORS: Record = { - active: '#38BDF8', - idle: '#2DD4BF', - thinking: '#A78BFA', - error: '#F87171', - offline: '#64748B', -}; - -/** Status background tints (12% opacity) */ -export const STATUS_BG_COLORS: Record = { - active: 'rgba(56, 189, 248, 0.12)', - idle: 'rgba(45, 212, 191, 0.12)', - thinking: 'rgba(167, 139, 250, 0.12)', - error: 'rgba(248, 113, 113, 0.12)', - offline: 'rgba(100, 116, 139, 0.12)', -}; - -/** Surface overrides (CUB-20 convenience) */ -export const SURFACE = { - background: '#0D0F12', - surface: '#13161A', - container: '#1C2027', - containerHigh: '#252B33', - onSurface: '#E2E8F0', - onSurfaceVariant: '#8A9BB0', - outline: '#2D3748', -} as const; - -/** Tactical Dark Mode color palette (CUB-20 convenience) */ -export const COLORS = { - surface: '#0F172A', - surfaceLight: '#1E293B', - primary: '#38BDF8', - secondary: '#2DD4BF', - accent: '#A78BFA', - danger: '#F87171', - textPrimary: '#FFFFFF', - textSecondary: '#94A3B8', - border: '#334155', -} as const; - -/** Layout constants (CUB-20 convenience) */ -export const LAYOUT = { - navRailCollapsedWidth: 72, - navRailExpandedWidth: 256, - headerHeight: 64, - bottomNavHeight: 80, - cardBorderRadius: 16, - cardMinWidth: 320, - cardGap: 16, - cardPadding: 20, - sectionPadding: 24, - spacingUnit: 8, -} as const; - -/** Breakpoints (px) (CUB-20 convenience) */ -export const BREAKPOINTS = { - mobile: 599, - tablet: 1023, - desktop: 1024, -} as const; - -/** Channel icon mapping (CUB-20) */ -export const CHANNEL_ICONS: Record = { - telegram: 'telegram', - slack: 'chat', - discord: 'forum', - whatsapp: 'chat', - webchat: 'language', - email: 'email', - mqtt: 'sensors', -}; - -/** Human-readable status labels (CUB-20) */ -export const STATUS_LABELS: Record = { - active: 'Active', - idle: 'Idle', - thinking: 'Thinking…', - error: 'Error', - offline: 'Offline', -}; - -// --------------------------------------------------------------------------- -// Typography -// --------------------------------------------------------------------------- -export const CcTypography = { - fontFamily: { - brand: "'Inter, Roboto, sans-serif'", - body: "'Inter, Roboto, sans-serif'", - mono: "'Roboto Mono, Cascadia Code, Fira Code, monospace'", - }, - size: { - displayLarge: '57px', - displayMedium: '45px', - displaySmall: '36px', - headlineLarge: '32px', - headlineMedium: '28px', - headlineSmall: '24px', - titleLarge: '22px', - titleMedium: '16px', - titleSmall: '14px', - bodyLarge: '16px', - bodyMedium: '14px', - bodySmall: '12px', - labelLarge: '14px', - labelMedium: '12px', - labelSmall: '11px', - }, - weight: { - regular: 400, - medium: 500, - bold: 600, - heavy: 700, - }, - lineHeight: { - tight: '1.2', - normal: '1.5', - relaxed: '1.6', - }, - letterSpacing: { - tight: '-0.01em', - normal: '0em', - wide: '0.02em', - mono: '0.05em', - }, -} as const; - -// --------------------------------------------------------------------------- -// Spacing (4px grid) -// --------------------------------------------------------------------------- -export const CcSpacing = { - 0: '0px', - 1: '4px', - 2: '8px', - 3: '12px', - 4: '16px', - 5: '20px', - 6: '24px', - 7: '28px', - 8: '32px', - 9: '36px', - 10: '40px', - 12: '48px', - 14: '56px', - 16: '64px', - 20: '80px', -} as const; - -// --------------------------------------------------------------------------- -// Layout -// --------------------------------------------------------------------------- -export const CcLayout = { - navRailCollapsedWidth: '72px', - navRailExpandedWidth: '256px', - headerHeight: '64px', - bottomNavHeight: '80px', - cardBorderRadius: '16px', - cardMinWidth: '320px', - badgeHeight: '24px', - badgeBorderRadius: '12px', - statusDotSize: '10px', -} as const; - -// --------------------------------------------------------------------------- -// Breakpoints (M3 canonical) -// --------------------------------------------------------------------------- -export const CcBreakpoints = { - compact: 599, - medium: 767, - expanded: 1023, - large: 1439, -} as const; - -// --------------------------------------------------------------------------- -// Border Radius -// --------------------------------------------------------------------------- -export const CcRadius = { - none: '0px', - xs: '4px', - sm: '8px', - md: '12px', - lg: '16px', - xl: '24px', - full: '9999px', -} as const; - -// --------------------------------------------------------------------------- -// Shadows (M3 elevation) -// --------------------------------------------------------------------------- -export const CcShadows = { - level0: 'none', - level1: '0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.3)', - level2: '0 2px 6px 0 rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.3)', - level3: '0 4px 12px 0 rgba(0, 0, 0, 0.3), 0 4px 8px -4px rgba(0, 0, 0, 0.3)', - level4: '0 8px 24px 0 rgba(0, 0, 0, 0.3), 0 8px 16px -8px rgba(0, 0, 0, 0.3)', -} as const; - -// --------------------------------------------------------------------------- -// Motion -// --------------------------------------------------------------------------- -export const CcMotion = { - duration: { - instant: 0, - fast: 100, - short: 150, - medium: 200, - standard: 300, - long: 500, - }, - easing: { - standard: 'cubic-bezier(0.4, 0, 0.2, 1)', - decelerate: 'cubic-bezier(0, 0, 0.2, 1)', - accelerate: 'cubic-bezier(0.4, 0, 1, 1)', - sharp: 'cubic-bezier(0.4, 0, 0.6, 1)', - }, -} as const; - -// --------------------------------------------------------------------------- -// Accessibility -// --------------------------------------------------------------------------- -export const CcA11y = { - focusRing: { - width: '2px', - offset: '2px', - color: '#38bdf8', - style: 'solid', - }, - minTouchTarget: 48, - minBodyFont: 16, -} as const; - -// --------------------------------------------------------------------------- -// Aggregate token object for convenient access -// --------------------------------------------------------------------------- -export const CcTokens = { - color: CcColors, - semantic: CcSemanticColors, - status: CcStatusColors, - typography: CcTypography, - spacing: CcSpacing, - layout: CcLayout, - breakpoints: CcBreakpoints, - radius: CcRadius, - shadows: CcShadows, - motion: CcMotion, - a11y: CcA11y, -} as const; - -// --------------------------------------------------------------------------- -// CSS Custom Property Names -// --------------------------------------------------------------------------- -export const CcCssProps = { - // Color - colorPrimary: '--cc-color-primary', - colorSecondary: '--cc-color-secondary', - colorAccent: '--cc-color-accent', - colorDanger: '--cc-color-danger', - - // Surface - surfaceDarkest: '--cc-surface-darkest', - surfaceDark: '--cc-surface-dark', - surfaceMedium: '--cc-surface-medium', - surfaceLight: '--cc-surface-light', - surfaceLighter: '--cc-surface-lighter', - - // On-surface - onSurface: '--cc-on-surface', - onSurfaceVariant: '--cc-on-surface-variant', - onSurfaceMuted: '--cc-on-surface-muted', - - // Status - statusActive: '--cc-status-active', - statusIdle: '--cc-status-idle', - statusThinking: '--cc-status-thinking', - statusError: '--cc-status-error', - statusOffline: '--cc-status-offline', - statusActiveBg: '--cc-status-active-bg', - statusIdleBg: '--cc-status-idle-bg', - statusThinkingBg: '--cc-status-thinking-bg', - statusErrorBg: '--cc-status-error-bg', - statusOfflineBg: '--cc-status-offline-bg', - statusActiveBorder: '--cc-status-active-border', - statusIdleBorder: '--cc-status-idle-border', - statusThinkingBorder: '--cc-status-thinking-border', - statusErrorBorder: '--cc-status-error-border', - statusOfflineBorder: '--cc-status-offline-border', - - // Typography - fontBrand: '--cc-font-brand', - fontBody: '--cc-font-body', - fontMono: '--cc-font-mono', - - // Spacing - spacing2: '--cc-spacing-2', - spacing4: '--cc-spacing-4', - spacing6: '--cc-spacing-6', - spacing8: '--cc-spacing-8', - spacing12: '--cc-spacing-12', - spacing16: '--cc-spacing-16', - - // Layout - navRailCollapsed: '--cc-nav-rail-collapsed', - navRailExpanded: '--cc-nav-rail-expanded', - headerHeight: '--cc-header-height', - bottomNavHeight: '--cc-bottom-nav-height', - cardRadius: '--cc-card-radius', - cardMinWidth: '--cc-card-min-width', - - // Radius - radiusNone: '--cc-radius-none', - radiusXs: '--cc-radius-xs', - radiusSm: '--cc-radius-sm', - radiusMd: '--cc-radius-md', - radiusLg: '--cc-radius-lg', - radiusXl: '--cc-radius-xl', - radiusFull: '--cc-radius-full', - - // Shadows - shadow0: '--cc-shadow-0', - shadow1: '--cc-shadow-1', - shadow2: '--cc-shadow-2', - shadow3: '--cc-shadow-3', - shadow4: '--cc-shadow-4', - - // Motion - durationFast: '--cc-duration-fast', - durationShort: '--cc-duration-short', - durationMedium: '--cc-duration-medium', - durationStandard: '--cc-duration-standard', - durationLong: '--cc-duration-long', - easingStandard: '--cc-easing-standard', - easingDecelerate: '--cc-easing-decelerate', - easingAccelerate: '--cc-easing-accelerate', - - // Accessibility - focusWidth: '--cc-focus-width', - focusOffset: '--cc-focus-offset', - focusColor: '--cc-focus-color', - touchMin: '--cc-touch-min', -} as const; - -// --------------------------------------------------------------------------- -// Utility: Read a CSS custom property from the document -// --------------------------------------------------------------------------- -export function getCssToken(propertyName: string): string { - return getComputedStyle(document.documentElement).getPropertyValue(propertyName).trim(); -} - -// --------------------------------------------------------------------------- -// Utility: Set a CSS custom property on the document root -// --------------------------------------------------------------------------- -export function setCssToken(propertyName: string, value: string): void { - document.documentElement.style.setProperty(propertyName, value); -} - -// --------------------------------------------------------------------------- -// Utility: Get status color by agent status type -// --------------------------------------------------------------------------- -export function getStatusColor(status: string): { fg: string; bg: string; border: string } { - const statusMap: Record = CcStatusColors; - return statusMap[status] ?? CcStatusColors.offline; -} \ No newline at end of file diff --git a/frontend-legacy/src/app/directives/index.ts b/frontend-legacy/src/app/directives/index.ts deleted file mode 100644 index f01d552..0000000 --- a/frontend-legacy/src/app/directives/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { LongPressDirective } from './long-press.directive'; \ No newline at end of file diff --git a/frontend-legacy/src/app/directives/long-press.directive.ts b/frontend-legacy/src/app/directives/long-press.directive.ts deleted file mode 100644 index f4025b1..0000000 --- a/frontend-legacy/src/app/directives/long-press.directive.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - Directive, - ElementRef, - EventEmitter, - OnDestroy, - Output, - Input, -} from '@angular/core'; - -// ============================================================================ -// Long-Press Directive — CUB-26 -// Emits after a sustained press (500ms default). -// Used on agent cards to bypass the drawer and open Session Log directly. -// ============================================================================ - -@Directive({ - selector: '[appLongPress]', - standalone: true, - host: { - '(mousedown)': 'onMouseDown($event)', - '(mouseup)': 'onMouseUp()', - '(mouseleave)': 'onMouseLeave()', - '(touchstart)': 'onTouchStart($event)', - '(touchend)': 'onTouchEnd()', - '(touchmove)': 'onTouchMove()', - '(contextmenu)': 'onContextMenu($event)', - }, -}) -export class LongPressDirective implements OnDestroy { - /** Duration in ms before a press counts as a long press. */ - @Input() appLongPressDuration = 500; - - /** Emits when a long press is detected. Payload is the original event. */ - @Output() readonly appLongPress = new EventEmitter(); - - private timer: ReturnType | null = null; - private isLongPress = false; - - onMouseDown(event: MouseEvent): void { - this.isLongPress = false; - this.timer = setTimeout(() => { - this.isLongPress = true; - this.appLongPress.emit(event); - }, this.appLongPressDuration); - } - - onMouseUp(): void { - this.clearTimer(); - } - - onMouseLeave(): void { - this.clearTimer(); - } - - onTouchStart(event: TouchEvent): void { - this.isLongPress = false; - this.timer = setTimeout(() => { - this.isLongPress = true; - this.appLongPress.emit(event); - }, this.appLongPressDuration); - } - - onTouchEnd(): void { - this.clearTimer(); - } - - onTouchMove(): void { - // Cancel on touch move (finger moved) - this.clearTimer(); - } - - onContextMenu(event: MouseEvent): void { - // Prevent native context menu on long press - if (this.isLongPress) { - event.preventDefault(); - } - } - - ngOnDestroy(): void { - this.clearTimer(); - } - - private clearTimer(): void { - if (this.timer !== null) { - clearTimeout(this.timer); - this.timer = null; - } - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.html b/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.html deleted file mode 100644 index 6fe14fb..0000000 --- a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.html +++ /dev/null @@ -1,24 +0,0 @@ - \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.scss b/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.scss deleted file mode 100644 index 3194735..0000000 --- a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.scss +++ /dev/null @@ -1,94 +0,0 @@ -// ============================================================================ -// Bottom Navigation Bar — Mobile Navigation -// Per CUB-27 spec breakpoints: -// Compact (0–599px): Visible — M3 NavigationBar pattern -// Medium+ (≥600px): Hidden — nav rail takes over -// ============================================================================ - -.bottom-nav { - display: none; // Hidden on desktop, shown on mobile via media query - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: var(--cc-bottom-nav-height); - background-color: var(--cc-surface-container-high); - border-top: 1px solid var(--cc-outline); - z-index: 50; - align-items: center; - justify-content: space-around; - padding: 0 8px; - // Safe area inset for notched devices - padding-bottom: env(safe-area-inset-bottom, 0px); -} - -.bottom-nav__item { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - min-width: 48px; - min-height: 48px; - padding: 8px 0; - text-decoration: none; - color: var(--cc-on-surface-variant); - border-radius: 16px; - transition: color 150ms ease, background-color 150ms ease; - - &:hover { - color: var(--cc-on-surface); - background-color: rgba(255, 255, 255, 0.06); - } - - &--active { - color: var(--status-active); - background-color: var(--status-active-bg); - - .bottom-nav__label { - font-weight: 500; - } - } -} - -.bottom-nav__icon-wrapper { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - border-radius: 16px; - - .bottom-nav__item--active & { - background-color: var(--status-active-bg); - } -} - -.bottom-nav__label { - font-size: 12px; - font-weight: 400; - letter-spacing: 0.02em; - white-space: nowrap; -} - -// --------------------------------------------------------------------------- -// Compact (0–599px): Show bottom nav -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .bottom-nav { - display: flex; - } -} - -// --------------------------------------------------------------------------- -// Medium+ (≥600px): Hidden — nav rail takes over -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .bottom-nav__item { - transition: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.ts b/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.ts deleted file mode 100644 index cf7cd14..0000000 --- a/frontend-legacy/src/app/layout/bottom-nav/bottom-nav.component.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { RouterLink, RouterLinkActive } from '@angular/router'; -import { MatIconModule } from '@angular/material/icon'; -import { MatBadgeModule } from '@angular/material/badge'; -import { NAV_DESTINATIONS } from '../../models/nav.model'; - -/** - * Bottom Navigation Bar for mobile (compact breakpoint). - * Per spec Section 3.2: M3 NavigationBar, 3–5 destinations, - * active destination uses M3 indicator pill. - * Visible only on compact (< 600px) breakpoint. - */ -@Component({ - selector: 'app-bottom-nav', - standalone: true, - imports: [RouterLink, RouterLinkActive, MatIconModule, MatBadgeModule], - templateUrl: './bottom-nav.component.html', - styleUrl: './bottom-nav.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class BottomNavComponent { - /** Show only first 5 destinations on bottom nav */ - protected readonly destinations = NAV_DESTINATIONS.slice(0, 5); -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/header-bar/header-bar.component.html b/frontend-legacy/src/app/layout/header-bar/header-bar.component.html deleted file mode 100644 index fd04dcd..0000000 --- a/frontend-legacy/src/app/layout/header-bar/header-bar.component.html +++ /dev/null @@ -1,55 +0,0 @@ - \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/header-bar/header-bar.component.scss b/frontend-legacy/src/app/layout/header-bar/header-bar.component.scss deleted file mode 100644 index e7086ba..0000000 --- a/frontend-legacy/src/app/layout/header-bar/header-bar.component.scss +++ /dev/null @@ -1,126 +0,0 @@ -// ============================================================================ -// Header Bar — Top App Bar -// Per CUB-27 spec breakpoints: -// Compact (0–599px): SmallTopAppBar — 56px height, compact title, hidden labels -// Medium (600–1023px): Medium top bar — 64px height -// Expanded (≥1024px): MediumTopAppBar — 64px height, full actions -// ============================================================================ - -.header-bar { - display: flex; - align-items: center; - justify-content: space-between; - height: var(--cc-header-height-compact); // Compact by default (mobile-first) - padding: 0 var(--cc-section-padding-compact); - background-color: var(--cc-surface-container-high); - border-bottom: 1px solid var(--cc-outline); - z-index: 20; -} - -.header-bar__title { - font-size: 20px; - font-weight: 500; - color: var(--cc-on-surface); - margin: 0; - letter-spacing: -0.01em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.header-bar__actions { - display: flex; - align-items: center; - gap: 4px; -} - -.header-bar__action-btn { - color: var(--cc-on-surface-variant) !important; - min-width: 48px; - min-height: 48px; - - &:hover { - color: var(--cc-on-surface) !important; - } -} - -.header-bar__live-dot { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 50%; - margin-right: 6px; - background-color: var(--status-error); - vertical-align: middle; - - &--connected { - background-color: var(--status-active); - animation: pulse-active 2s ease-in-out infinite; - } -} - -.header-bar__live-label { - font-size: 13px; - font-weight: 500; - color: var(--cc-on-surface-variant); - vertical-align: middle; -} - -// --------------------------------------------------------------------------- -// Compact (0–599px): SmallTopAppBar — hide live label, tighter spacing -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .header-bar__live-label { - display: none; // Space saving on compact — dot alone is enough - } - - .header-bar__actions { - gap: 0; - } -} - -// --------------------------------------------------------------------------- -// Medium (600–1023px): Medium top bar -// --------------------------------------------------------------------------- -@media (min-width: 600px) and (max-width: 1023px) { - .header-bar { - height: var(--cc-header-height); - padding: 0 var(--cc-section-padding); - } - - .header-bar__title { - font-size: 24px; - } - - .header-bar__actions { - gap: 4px; - } -} - -// --------------------------------------------------------------------------- -// Expanded (≥1024px): Full top bar -// --------------------------------------------------------------------------- -@media (min-width: 1024px) { - .header-bar { - height: var(--cc-header-height); - padding: 0 var(--cc-section-padding); - } - - .header-bar__title { - font-size: 28px; - font-weight: 400; - } - - .header-bar__actions { - gap: 8px; - } -} - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .header-bar__live-dot--connected { - animation: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/header-bar/header-bar.component.ts b/frontend-legacy/src/app/layout/header-bar/header-bar.component.ts deleted file mode 100644 index e2405ad..0000000 --- a/frontend-legacy/src/app/layout/header-bar/header-bar.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Output, signal } from '@angular/core'; -import { MatIconModule } from '@angular/material/icon'; -import { MatButtonModule } from '@angular/material/button'; -import { MatBadgeModule } from '@angular/material/badge'; - -/** - * Header Bar component for the Command Hub. - * Per spec Section 3.1: 64px tall, app title + live indicator + notification bell + settings. - * Uses M3 top app bar pattern. - */ -@Component({ - selector: 'app-header-bar', - standalone: true, - imports: [MatIconModule, MatButtonModule, MatBadgeModule], - templateUrl: './header-bar.component.html', - styleUrl: './header-bar.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class HeaderBarComponent { - /** Emits when the user requests the Quick-Jump drawer. */ - @Output() readonly openQuickJump = new EventEmitter(); - - protected readonly notificationCount = signal(3); - protected readonly isConnected = signal(true); - - // TODO: Wire up notification panel (spec Section 2: Notifications Panel) - // TODO: Wire up settings navigation -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/index.ts b/frontend-legacy/src/app/layout/index.ts deleted file mode 100644 index aaea114..0000000 --- a/frontend-legacy/src/app/layout/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './nav-rail/nav-rail.component'; -export * from './bottom-nav/bottom-nav.component'; -export * from './header-bar/header-bar.component'; -export * from './layout-shell/layout-shell.component'; \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.html b/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.html deleted file mode 100644 index 0fbb6d9..0000000 --- a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.html +++ /dev/null @@ -1,27 +0,0 @@ -
- - - -
- - - - -
- -
-
- - - -
- - - - - - \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.scss b/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.scss deleted file mode 100644 index 2905da4..0000000 --- a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.scss +++ /dev/null @@ -1,73 +0,0 @@ -// ============================================================================ -// Layout Shell — Adaptive layout container -// Per CUB-27 spec breakpoints: -// Compact (0–599px): Header + Content + Bottom Nav (stacked) -// Medium (600–1023px): Collapsed Nav Rail + Header + Content -// Expanded (≥1024px): Expandable Nav Rail + Header + Content -// ============================================================================ - -.layout-shell { - display: flex; - min-height: 100vh; - background-color: var(--cc-background); -} - -.layout-shell__nav-rail { - flex-shrink: 0; -} - -.layout-shell__main { - flex: 1; - display: flex; - flex-direction: column; - min-width: 0; // Prevent flex overflow - overflow: hidden; -} - -.layout-shell__header { - flex-shrink: 0; -} - -.layout-shell__content { - flex: 1; - overflow-y: auto; - overflow-x: hidden; - padding: var(--cc-section-padding); -} - -.layout-shell__bottom-nav { - flex-shrink: 0; -} - -// --------------------------------------------------------------------------- -// Compact (0–599px): Stack layout vertically, bottom nav visible -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .layout-shell { - flex-direction: column; - } - - .layout-shell__content { - padding: var(--cc-section-padding-compact); - // Account for bottom nav bar height - padding-bottom: calc(var(--cc-bottom-nav-height) + 16px); - } -} - -// --------------------------------------------------------------------------- -// Medium (600–1023px): Sidebar + content, collapsed nav rail -// --------------------------------------------------------------------------- -@media (min-width: 600px) and (max-width: 1023px) { - .layout-shell__content { - padding: 20px; - } -} - -// --------------------------------------------------------------------------- -// Expanded (≥1024px): Full nav rail with expandable behavior -// --------------------------------------------------------------------------- -@media (min-width: 1024px) { - .layout-shell__content { - padding: var(--cc-section-padding); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.ts b/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.ts deleted file mode 100644 index 5fb15ad..0000000 --- a/frontend-legacy/src/app/layout/layout-shell/layout-shell.component.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { ChangeDetectionStrategy, Component, HostListener, OnDestroy, signal, ViewChild } from '@angular/core'; -import { Router, RouterOutlet } from '@angular/router'; -import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; -import { Subscription } from 'rxjs'; -import { NavRailComponent } from '../nav-rail/nav-rail.component'; -import { BottomNavComponent } from '../bottom-nav/bottom-nav.component'; -import { HeaderBarComponent } from '../header-bar/header-bar.component'; -import { QuickJumpDrawerComponent } from '../../components/quick-jump-drawer/index'; -import { AgentSessionDrawerComponent } from '../../components/agent-session-drawer/index'; -import { AgentCardData } from '../../models/agent.model'; - -/** - * Layout Shell — wraps the main content area with adaptive navigation. - * Desktop/Kiosk: Nav Rail (left) + Header + Content - * Mobile: Header + Content + Bottom Nav - * Per spec Section 3.1 (kiosk) and 3.2 (mobile). - * CUB-26: Hosts the Agent Session Drawer for quick-jump navigation. - */ -@Component({ - selector: 'app-layout-shell', - standalone: true, - imports: [RouterOutlet, NavRailComponent, BottomNavComponent, HeaderBarComponent, QuickJumpDrawerComponent, AgentSessionDrawerComponent], - templateUrl: './layout-shell.component.html', - styleUrl: './layout-shell.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class LayoutShellComponent implements OnDestroy { - @ViewChild(QuickJumpDrawerComponent) quickJumpDrawer!: QuickJumpDrawerComponent; - @ViewChild(AgentSessionDrawerComponent) sessionDrawer!: AgentSessionDrawerComponent; - - /** Whether the viewport is mobile-sized. */ - readonly isMobile = signal(false); - - private readonly breakpointSub: Subscription; - - constructor( - private readonly breakpointObserver: BreakpointObserver, - private readonly router: Router, - ) { - this.breakpointSub = this.breakpointObserver - .observe([Breakpoints.Handset, Breakpoints.Small]) - .subscribe((result) => { - this.isMobile.set(result.matches); - }); - } - - /** Open the quick-jump drawer from anywhere in the layout. */ - openQuickJump(): void { - this.quickJumpDrawer?.open(); - } - - /** Open the session drawer for a specific agent. */ - openSessionDrawer(agent: AgentCardData): void { - this.sessionDrawer?.open(agent); - } - - /** Open the session log page directly (long-press bypass). */ - openSessionLog(sessionKey: string): void { - this.router.navigate(['/sessions'], { queryParams: { key: sessionKey } }); - } - - /** Handle "Open Full Session" action from session drawer. */ - onOpenSession(sessionKey: string): void { - this.router.navigate(['/sessions'], { queryParams: { key: sessionKey } }); - } - - /** Handle "Pin to Dashboard" action from session drawer. */ - onPinToDashboard(sessionKey: string): void { - // TODO: Implement pin-to-dashboard logic - console.log('[LayoutShell] Pin to dashboard:', sessionKey); - } - - /** Global keyboard shortcut: Ctrl+K or Cmd+K opens the quick-jump drawer. */ - @HostListener('document:keydown', ['$event']) - onGlobalKeydown(event: KeyboardEvent): void { - if ((event.ctrlKey || event.metaKey) && event.key === 'k') { - event.preventDefault(); - this.quickJumpDrawer?.toggle(); - } - } - - ngOnDestroy(): void { - this.breakpointSub.unsubscribe(); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.html b/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.html deleted file mode 100644 index f11b38c..0000000 --- a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.html +++ /dev/null @@ -1,44 +0,0 @@ - \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.scss b/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.scss deleted file mode 100644 index 0f31592..0000000 --- a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.scss +++ /dev/null @@ -1,158 +0,0 @@ -// ============================================================================ -// Nav Rail — Desktop/Kiosk Navigation -// Per CUB-27 spec breakpoints: -// Compact (0–599px): Hidden — bottom nav takes over -// Medium (600–1023px): Collapsed (72px), icon-only -// Expanded (≥1024px): Expandable (72px collapsed / 256px expanded on hover) -// Section 5.4: Spacing & Grid -// ============================================================================ - -.nav-rail { - display: none; // Hidden by default (mobile-first) - flex-direction: column; - width: var(--cc-nav-rail-collapsed-width); - min-height: 100vh; - background-color: var(--cc-surface-container-high); - border-right: 1px solid var(--cc-outline); - transition: width 200ms cubic-bezier(0.4, 0, 0.2, 1); - overflow: hidden; - z-index: 10; - - &--expanded { - width: var(--cc-nav-rail-expanded-width); - } -} - -.nav-rail__header { - display: flex; - align-items: center; - gap: 12px; - padding: 16px 12px; - min-height: 64px; - border-bottom: 1px solid var(--cc-outline); -} - -.nav-rail__toggle { - display: flex; - align-items: center; - justify-content: center; - width: 48px; - height: 48px; - min-width: 48px; - border: none; - border-radius: 50%; - background: transparent; - color: var(--cc-on-surface); - cursor: pointer; - transition: background-color 150ms ease; - - &:hover { - background-color: rgba(255, 255, 255, 0.08); - } - - &:focus-visible { - outline: 3px solid var(--status-active); - outline-offset: 2px; - } -} - -.nav-rail__brand { - font-size: 18px; - font-weight: 600; - color: var(--status-active); - white-space: nowrap; - letter-spacing: 0.02em; -} - -.nav-rail__nav { - flex: 1; - padding-top: 8px; - - // Override Angular Material list item styles for compact nav rail items - --mat-list-list-item-one-line-vertical-gap: 4px; -} - -.nav-rail__item { - display: flex; - align-items: center; - gap: 16px; - min-height: 56px; - padding: 0 12px; - border-radius: 28px; - margin: 2px 12px; - color: var(--cc-on-surface-variant); - text-decoration: none; - transition: background-color 150ms ease, color 150ms ease; - - &:hover { - background-color: rgba(255, 255, 255, 0.08); - color: var(--cc-on-surface); - } - - &--active { - background-color: var(--status-active-bg); - color: var(--status-active); - - .nav-rail__label { - font-weight: 500; - } - } -} - -.nav-rail__label { - font-size: 14px; - font-weight: 400; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -// --------------------------------------------------------------------------- -// Medium (600–1023px): Show collapsed nav rail (icon-only) -// --------------------------------------------------------------------------- -@media (min-width: 600px) and (max-width: 1023px) { - .nav-rail { - display: flex; - width: var(--cc-nav-rail-collapsed-width); - } - - // Always collapsed on medium — hide labels - .nav-rail__brand, - .nav-rail__label { - display: none; - } - - .nav-rail__header { - justify-content: center; - padding: 16px 0; - } - - .nav-rail__item { - justify-content: center; - padding: 0; - margin: 2px 8px; - } - - // Disable expand on medium - .nav-rail--expanded { - width: var(--cc-nav-rail-collapsed-width); - } -} - -// --------------------------------------------------------------------------- -// Expanded (≥1024px): Full expandable nav rail -// --------------------------------------------------------------------------- -@media (min-width: 1024px) { - .nav-rail { - display: flex; - } -} - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .nav-rail { - transition: none; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.ts b/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.ts deleted file mode 100644 index 78258e2..0000000 --- a/frontend-legacy/src/app/layout/nav-rail/nav-rail.component.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { ChangeDetectionStrategy, Component, HostListener, signal, OnDestroy, OnInit } from '@angular/core'; -import { RouterLink, RouterLinkActive } from '@angular/router'; -import { MatIconModule } from '@angular/material/icon'; -import { MatBadgeModule } from '@angular/material/badge'; -import { NAV_DESTINATIONS } from '../../models/nav.model'; - -@Component({ - selector: 'app-nav-rail', - standalone: true, - imports: [RouterLink, RouterLinkActive, MatIconModule, MatBadgeModule], - templateUrl: './nav-rail.component.html', - styleUrl: './nav-rail.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class NavRailComponent implements OnInit, OnDestroy { - protected readonly destinations = NAV_DESTINATIONS; - protected readonly expanded = signal(false); - protected readonly isExpandedBreakpoint = signal(false); - - private readonly EXPANDED_BP = 1024; - - ngOnInit(): void { - this.updateBreakpoint(); - } - - @HostListener('window:resize') - onResize(): void { - this.updateBreakpoint(); - } - - @HostListener('mouseenter') - onHoverIn(): void { - if (this.isExpandedBreakpoint()) { - this.expanded.set(true); - } - } - - @HostListener('mouseleave') - onHoverOut(): void { - if (this.isExpandedBreakpoint()) { - this.expanded.set(false); - } - } - - toggleExpand(): void { - if (this.isExpandedBreakpoint()) { - this.expanded.update(v => !v); - } - } - - private updateBreakpoint(): void { - const isExpanded = window.innerWidth >= this.EXPANDED_BP; - this.isExpandedBreakpoint.set(isExpanded); - // Collapse when leaving expanded breakpoint - if (!isExpanded) { - this.expanded.set(false); - } - } - - ngOnDestroy(): void { - // Cleanup is handled by HostListener auto-unsubscribe - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/models/agent.model.ts b/frontend-legacy/src/app/models/agent.model.ts deleted file mode 100644 index c090801..0000000 --- a/frontend-legacy/src/app/models/agent.model.ts +++ /dev/null @@ -1,54 +0,0 @@ -// ============================================================================ -// Agent Status Types -// Per spec Section 7.3: Agent Card Component Interface -// ============================================================================ - -export type AgentStatus = 'active' | 'idle' | 'thinking' | 'error' | 'offline'; - -export interface AgentCardData { - /** Short agent ID, e.g., "otto" */ - id: string; - - /** Display name, e.g., "Otto" */ - displayName: string; - - /** Role description, e.g., "Orchestrator Agent" */ - role: string; - - /** Current agent status */ - status: AgentStatus; - - /** Current task description, e.g., "Reviewing PR #42" */ - currentTask?: string; - - /** Task progress percentage 0–100 */ - taskProgress?: number; - - /** Elapsed time string, e.g., "04m 12s" */ - taskElapsed?: string; - - /** Full session key, e.g., "agent:otto:telegram:direct:8787..." */ - sessionKey: string; - - /** Communication channel, e.g., "telegram" */ - channel: string; - - /** Timestamp of last activity */ - lastActivity: Date; - - /** Error message (populated only on error status) */ - errorMessage?: string; -} - -export interface AgentStatusUpdate { - agentId: string; - status: AgentStatus; - timestamp: Date; -} - -export interface TaskProgressUpdate { - agentId: string; - taskName?: string; - progress: number; - elapsed?: string; -} \ No newline at end of file diff --git a/frontend-legacy/src/app/models/index.ts b/frontend-legacy/src/app/models/index.ts deleted file mode 100644 index da487dc..0000000 --- a/frontend-legacy/src/app/models/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './agent.model'; -export * from './nav.model'; \ No newline at end of file diff --git a/frontend-legacy/src/app/models/nav.model.ts b/frontend-legacy/src/app/models/nav.model.ts deleted file mode 100644 index 015e9ef..0000000 --- a/frontend-legacy/src/app/models/nav.model.ts +++ /dev/null @@ -1,19 +0,0 @@ -// ============================================================================ -// Navigation Model -// Per spec Section 3.5: Global Navigation Structure -// ============================================================================ - -export interface NavDestination { - label: string; - icon: string; - route: string; - badge?: number; -} - -export const NAV_DESTINATIONS: NavDestination[] = [ - { label: 'Command Hub', icon: 'bolt', route: '/hub' }, - { label: 'Projects', icon: 'assignment', route: '/projects' }, - { label: 'Sessions', icon: 'folder_open', route: '/sessions' }, - { label: 'Logs', icon: 'bar_chart', route: '/logs' }, - { label: 'Settings', icon: 'settings', route: '/settings' }, -]; \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/hub/hub-page.component.html b/frontend-legacy/src/app/pages/hub/hub-page.component.html deleted file mode 100644 index 73b6a4e..0000000 --- a/frontend-legacy/src/app/pages/hub/hub-page.component.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - -
-

Command Hub

- - -
- @for (filter of filters; track filter.value) { - - } -
- - -
- @for (agent of filteredAgents(); track agent.id) { - - } @empty { -

No agents online

- } -
-
- - - \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/hub/hub-page.component.scss b/frontend-legacy/src/app/pages/hub/hub-page.component.scss deleted file mode 100644 index 9371319..0000000 --- a/frontend-legacy/src/app/pages/hub/hub-page.component.scss +++ /dev/null @@ -1,141 +0,0 @@ -// ============================================================================ -// Hub Page — Responsive AgentCard Grid with Filter Chips -// Per CUB-27 spec breakpoints: -// Compact (0–599px): Single-column cards, horizontal-scroll filter chips -// Medium (600–1023px): 2-column grid -// Expanded (≥1024px): 3+ column auto-fill grid -// ============================================================================ - -.hub-page { - display: flex; - flex-direction: column; - gap: 16px; - min-height: 400px; - overflow-x: hidden; - padding: var(--cc-section-padding); -} - -.hub-page__title { - grid-column: 1 / -1; - font-size: 24px; - font-weight: 600; - color: var(--cc-on-surface); - margin: 0 0 8px; -} - -// --------------------------------------------------------------------------- -// Filter Chip Group -// --------------------------------------------------------------------------- -.hub-page__filters { - display: flex; - gap: 8px; - padding: 4px 0; - overflow-x: auto; - -webkit-overflow-scrolling: touch; - scrollbar-width: none; // Firefox - - &::-webkit-scrollbar { - display: none; // Chrome/Safari - } -} - -.hub-page__filter-chip { - display: inline-flex; - align-items: center; - justify-content: center; - min-height: 36px; - min-width: 48px; // Touch target - padding: 6px 16px; - border: 1px solid var(--cc-outline); - border-radius: 20px; - background-color: transparent; - color: var(--cc-on-surface-variant); - font-size: 13px; - font-weight: 500; - letter-spacing: 0.02em; - cursor: pointer; - white-space: nowrap; - transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease; - flex-shrink: 0; // Prevent shrinking in scroll container - - &:hover { - background-color: rgba(255, 255, 255, 0.06); - color: var(--cc-on-surface); - } - - &:focus-visible { - outline: 2px solid var(--status-active); - outline-offset: 2px; - } - - &--active { - background-color: var(--status-active-bg); - color: var(--status-active); - border-color: var(--status-active); - } -} - -// --------------------------------------------------------------------------- -// Agent Card Grid -// --------------------------------------------------------------------------- -.hub-page__grid { - display: grid; - grid-template-columns: 1fr; - gap: var(--cc-card-gap); -} - -// --------------------------------------------------------------------------- -// Empty State -// --------------------------------------------------------------------------- -.hub-page__placeholder, -.hub-page__empty { - display: flex; - align-items: center; - justify-content: center; - padding: 48px 24px; - color: var(--cc-on-surface-variant); - font-size: 16px; - text-align: center; -} - -// --------------------------------------------------------------------------- -// Compact (0–599px): Single-column cards -// --------------------------------------------------------------------------- -@media (max-width: 599px) { - .hub-page { - padding: 0; - } - - .hub-page__grid { - grid-template-columns: 1fr; - gap: 12px; - } - - .hub-page__filters { - padding: 4px 0 8px; - // Ensure horizontal scroll on mobile - margin: 0 -8px; - padding-left: 8px; - padding-right: 8px; - } -} - -// --------------------------------------------------------------------------- -// Medium (600–1023px): 2-column grid -// --------------------------------------------------------------------------- -@media (min-width: 600px) and (max-width: 1023px) { - .hub-page__grid { - grid-template-columns: repeat(2, 1fr); - gap: var(--cc-card-gap); - } -} - -// --------------------------------------------------------------------------- -// Expanded (≥1024px): 3+ column auto-fill grid -// --------------------------------------------------------------------------- -@media (min-width: 1024px) { - .hub-page__grid { - grid-template-columns: repeat(auto-fill, minmax(var(--cc-card-min-width), 1fr)); - gap: var(--cc-card-gap); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/hub/hub-page.component.ts b/frontend-legacy/src/app/pages/hub/hub-page.component.ts deleted file mode 100644 index c52b02e..0000000 --- a/frontend-legacy/src/app/pages/hub/hub-page.component.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { ChangeDetectionStrategy, Component, signal, computed, ViewChild } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { MatChipsModule } from '@angular/material/chips'; -import { AgentCardComponent } from '../../command-hub/components/agent-card/agent-card.component'; -import { AgentSessionDrawerComponent } from '../../components/agent-session-drawer/index'; -import { AgentCardData } from '../../models/agent.model'; -import { AgentStatus } from '../../models/agent.model'; - -/** - * Filter options for the hub page agent card grid. - * Per CUB-27: "Filter chip group (All, Active, Error, etc.) with horizontal scroll on mobile" - */ -export type AgentFilter = 'all' | AgentStatus; - -@Component({ - selector: 'app-hub-page', - standalone: true, - imports: [CommonModule, MatChipsModule, AgentCardComponent, AgentSessionDrawerComponent], - templateUrl: './hub-page.component.html', - styleUrl: './hub-page.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class HubPageComponent { - @ViewChild(AgentSessionDrawerComponent) sessionDrawer!: AgentSessionDrawerComponent; - - readonly isMobile = signal(false); - - protected readonly filters: { label: string; value: AgentFilter }[] = [ - { label: 'All', value: 'all' }, - { label: 'Active', value: 'active' }, - { label: 'Idle', value: 'idle' }, - { label: 'Thinking', value: 'thinking' }, - { label: 'Error', value: 'error' }, - { label: 'Offline', value: 'offline' }, - ]; - - protected readonly activeFilter = signal('all'); - - /** Stub agent data (TODO: wire to AgentStatusService / SignalR). */ - readonly agents = signal([ - { - id: 'otto', - displayName: 'Otto', - role: 'Orchestrator Agent', - status: 'active', - currentTask: 'Reviewing PR #42', - taskProgress: 67, - taskElapsed: '04m 12s', - sessionKey: 'agent:otto:slack:CUB-42:abc123', - channel: 'slack', - lastActivity: new Date(), - }, - { - id: 'rex', - displayName: 'Rex', - role: 'Frontend Agent', - status: 'thinking', - currentTask: 'Building responsive layout', - taskProgress: 40, - taskElapsed: '02m 30s', - sessionKey: 'agent:rex:telegram:CUB-27:def456', - channel: 'telegram', - lastActivity: new Date(Date.now() - 30000), - }, - { - id: 'dex', - displayName: 'Dex', - role: 'Backend Agent', - status: 'idle', - currentTask: undefined, - taskProgress: undefined, - taskElapsed: undefined, - sessionKey: 'agent:dex:slack:CUB-53:ghi789', - channel: 'slack', - lastActivity: new Date(Date.now() - 300000), - }, - { - id: 'hex', - displayName: 'Hex', - role: 'Database Agent', - status: 'error', - currentTask: 'Migration failed — rollback initiated', - taskProgress: 0, - taskElapsed: '00m 45s', - sessionKey: 'agent:hex:slack:CUB-56:jkl012', - channel: 'slack', - lastActivity: new Date(Date.now() - 60000), - errorMessage: 'Connection timeout to database server', - }, - { - id: 'nano', - displayName: 'Nano', - role: 'ESP32 Agent', - status: 'offline', - currentTask: undefined, - taskProgress: undefined, - taskElapsed: undefined, - sessionKey: 'agent:nano:mqtt:CUB-48:mno345', - channel: 'mqtt', - lastActivity: new Date(Date.now() - 86400000), - }, - ]); - - protected readonly filteredAgents = computed(() => { - const filter = this.activeFilter(); - if (filter === 'all') return this.agents(); - return this.agents().filter(a => a.status === filter); - }); - - constructor() { - // Detect mobile viewport - if (typeof window !== 'undefined') { - const mql = window.matchMedia('(max-width: 599px)'); - this.isMobile.set(mql.matches); - mql.addEventListener('change', (e) => this.isMobile.set(e.matches)); - } - } - - protected selectFilter(filter: AgentFilter): void { - this.activeFilter.set(filter); - } - - /** Card click → open session drawer with agent details. */ - onCardClick(sessionKey: string): void { - const agent = this.agents().find((a) => a.sessionKey === sessionKey); - if (agent) { - this.sessionDrawer?.open(agent); - } - } - - /** Long-press on card → bypass drawer, go directly to session log. */ - onCardLongPress(sessionKey: string): void { - console.log('[Hub] Long press — navigate to session log:', sessionKey); - // TODO: Navigate directly to session log page when sessions route is implemented - } - - /** Open full session from drawer action button. */ - onOpenSession(sessionKey: string): void { - console.log('[Hub] Open full session:', sessionKey); - // TODO: Navigate to full session view - } - - /** Pin agent to dashboard from drawer action button. */ - onPinToDashboard(sessionKey: string): void { - console.log('[Hub] Pin to dashboard:', sessionKey); - // TODO: Implement pin-to-dashboard - } - - /** Drawer closed. */ - onDrawerClose(): void { - // No-op for now — drawer is self-managing - } -} \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/logs/logs-page.component.ts b/frontend-legacy/src/app/pages/logs/logs-page.component.ts deleted file mode 100644 index 8992104..0000000 --- a/frontend-legacy/src/app/pages/logs/logs-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; - -@Component({ - selector: 'app-logs-page', - standalone: true, - imports: [], - template: `

Logs page — coming soon

`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class LogsPageComponent {} \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/projects/projects-page.component.ts b/frontend-legacy/src/app/pages/projects/projects-page.component.ts deleted file mode 100644 index 8506ee3..0000000 --- a/frontend-legacy/src/app/pages/projects/projects-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; - -@Component({ - selector: 'app-projects-page', - standalone: true, - imports: [], - template: `

Projects page — coming soon

`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ProjectsPageComponent {} \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/sessions/sessions-page.component.ts b/frontend-legacy/src/app/pages/sessions/sessions-page.component.ts deleted file mode 100644 index 2e2917d..0000000 --- a/frontend-legacy/src/app/pages/sessions/sessions-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; - -@Component({ - selector: 'app-sessions-page', - standalone: true, - imports: [], - template: `

Sessions page — coming soon

`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class SessionsPageComponent {} \ No newline at end of file diff --git a/frontend-legacy/src/app/pages/settings/settings-page.component.ts b/frontend-legacy/src/app/pages/settings/settings-page.component.ts deleted file mode 100644 index e9f3eb9..0000000 --- a/frontend-legacy/src/app/pages/settings/settings-page.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; - -@Component({ - selector: 'app-settings-page', - standalone: true, - imports: [], - template: `

Settings page — coming soon

`, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class SettingsPageComponent {} \ No newline at end of file diff --git a/frontend-legacy/src/app/services/agent-status.service.ts b/frontend-legacy/src/app/services/agent-status.service.ts deleted file mode 100644 index ed7fd96..0000000 --- a/frontend-legacy/src/app/services/agent-status.service.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable, signal } from '@angular/core'; -import { AgentCardData, AgentStatus, AgentStatusUpdate, TaskProgressUpdate } from '../models/agent.model'; - -/** - * Agent Status Service — stub for future SignalR integration. - * Per spec Section 7.4: Connects to /hubs/agent-status for real-time updates. - * - * TODO: Implement SignalR hub connection when backend is ready. - * TODO: Wire up NgRx store or signals for reactive state management. - */ -@Injectable({ providedIn: 'root' }) -export class AgentStatusService { - /** Stub: list of agents (will come from SignalR) */ - private readonly _agents = signal([]); - - readonly agents = this._agents.asReadonly(); - - /** Stub: update an agent's status */ - updateStatus(update: AgentStatusUpdate): void { - this._agents.update(agents => - agents.map(agent => - agent.id === update.agentId - ? { ...agent, status: update.status } - : agent - ) - ); - } - - /** Stub: update an agent's task progress */ - updateTaskProgress(progress: TaskProgressUpdate): void { - this._agents.update(agents => - agents.map(agent => - agent.id === progress.agentId - ? { - ...agent, - taskProgress: progress.progress, - ...(progress.taskName ? { currentTask: progress.taskName } : {}), - ...(progress.elapsed ? { taskElapsed: progress.elapsed } : {}), - } - : agent - ) - ); - } - - // TODO: connect() — Initialize SignalR connection - // TODO: disconnect() — Clean up SignalR connection -} \ No newline at end of file diff --git a/frontend-legacy/src/index.html b/frontend-legacy/src/index.html deleted file mode 100644 index 0005819..0000000 --- a/frontend-legacy/src/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - OpenClaw Control Center - - - - - - - - - - - - - - \ No newline at end of file diff --git a/frontend-legacy/src/main.ts b/frontend-legacy/src/main.ts deleted file mode 100644 index 5df75f9..0000000 --- a/frontend-legacy/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { App } from './app/app'; - -bootstrapApplication(App, appConfig) - .catch((err) => console.error(err)); diff --git a/frontend-legacy/src/styles.scss b/frontend-legacy/src/styles.scss deleted file mode 100644 index 2035f40..0000000 --- a/frontend-legacy/src/styles.scss +++ /dev/null @@ -1,285 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — M3 Tactical Dark Theme -// ============================================================================ -// Main global stylesheet. Imports the design system token modules and -// applies the M3 dark theme. All tokens are defined once in -// styles/_tokens.scss — SCSS variables and mixins -// styles/_css-properties.scss — CSS custom property output -// styles/_utilities.scss — utility mixins for components -// -// Components should @use these modules rather than hardcoding values. -// ============================================================================ - -@use 'styles/tokens' as tokens; -@use 'styles/css-properties' as css-props; -@use 'styles/utilities' as utils; -@use '@angular/material' as mat; - -// --------------------------------------------------------------------------- -// M3 Theme Definition -// --------------------------------------------------------------------------- -// Using mat.define-theme() with custom color tokens to match the tactical -// dark palette. Angular Material 19+ uses the new theming API. -// --------------------------------------------------------------------------- - -$dark-theme: mat.define-theme(( - color: ( - theme-type: dark, - primary: mat.$cyan-palette, - tertiary: mat.$violet-palette, - ), - typography: ( - brand-family: tokens.$font-family-brand, - plain-family: tokens.$font-family-body, - bold-weight: tokens.$font-weight-bold, - medium-weight: tokens.$font-weight-medium, - regular-weight: tokens.$font-weight-regular, - ), - density: ( - scale: 0, - ), -)); - -// --------------------------------------------------------------------------- -// Apply theme to :root -// --------------------------------------------------------------------------- -html { - height: 100%; - @include mat.theme($dark-theme); - color-scheme: dark; -} - -// --------------------------------------------------------------------------- -// Emit Design System CSS Custom Properties -// --------------------------------------------------------------------------- -@include css-props.emit-custom-properties; - -// --------------------------------------------------------------------------- -// Per spec Section 5.1 "Status Colors (Semantic — outside M3 tonal system)" -// These are NOT part of the M3 tonal palette; they are semantic overrides. -// --------------------------------------------------------------------------- -:root { - // --- Tactical Dark Mode color palette (CUB-47) --- - --color-surface: #0F172A; - --color-surface-light: #1E293B; - --color-primary: #38BDF8; - --color-secondary: #2DD4BF; - --color-accent: #A78BFA; - --color-danger: #F87171; - --color-text-primary: #FFFFFF; - --color-text-secondary: #94A3B8; - --color-border: #334155; - - // --- Status colors --- - --status-active: #38BDF8; - --status-idle: #2DD4BF; - --status-thinking: #A78BFA; - --status-error: #F87171; - --status-offline: #64748B; - - // --- Status background tints (12% opacity) --- - --status-active-bg: rgba(56, 189, 248, 0.12); - --status-idle-bg: rgba(45, 212, 191, 0.12); - --status-thinking-bg: rgba(167, 139, 250, 0.12); - --status-error-bg: rgba(248, 113, 113, 0.12); - - // --- Surface overrides (tactical dark palette) --- - --cc-background: #0D0F12; - --cc-surface: #13161A; - --cc-surface-container: #1C2027; - --cc-surface-container-high: #252B33; - --cc-on-surface: #E2E8F0; - --cc-on-surface-variant: #8A9BB0; - --cc-outline: #2D3748; - - // --- Mono font stack --- - --cc-font-mono: 'Roboto Mono', 'Cascadia Code', 'Fira Code', monospace; - - // --- Layout constants --- - --cc-nav-rail-collapsed-width: 72px; - --cc-nav-rail-expanded-width: 256px; - --cc-header-height: 64px; - --cc-header-height-compact: 56px; - --cc-bottom-nav-height: 80px; - --cc-card-border-radius: 16px; - --cc-card-min-width: 280px; - --cc-card-gap: 16px; - --cc-card-padding: 20px; - --cc-section-padding: 24px; - --cc-section-padding-compact: 16px; - --cc-spacing-unit: 8px; - - // --- Responsive breakpoints (CUB-27) --- - --cc-breakpoint-compact: 599px; // 0-599px: phone / compact - --cc-breakpoint-medium: 600px; // 600-1023px: tablet / medium - --cc-breakpoint-expanded: 1024px; // ≥1024px: desktop/kiosk / expanded -} - -// --------------------------------------------------------------------------- -// Global Body Styles -// --------------------------------------------------------------------------- -body { - background-color: var(--cc-surface-darkest); - color: var(--cc-on-surface); - font-family: var(--cc-font-body); - margin: 0; - height: 100%; - min-height: 100vh; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -// --------------------------------------------------------------------------- -// Typography Helpers -// --------------------------------------------------------------------------- -.text-mono { - font-family: var(--cc-font-mono); - font-size: tokens.$font-size-body-medium; - font-weight: tokens.$font-weight-regular; - letter-spacing: tokens.$letter-spacing-mono; -} - -.text-display-large { - font-size: tokens.$font-size-display-large; - font-weight: tokens.$font-weight-heavy; - line-height: tokens.$line-height-tight; - letter-spacing: tokens.$letter-spacing-tight; -} - -.text-headline-medium { - font-size: tokens.$font-size-headline-medium; - font-weight: tokens.$font-weight-bold; - line-height: tokens.$line-height-tight; -} - -.text-title-large { - font-size: tokens.$font-size-title-large; - font-weight: tokens.$font-weight-bold; -} - -.text-title-medium { - font-size: tokens.$font-size-title-medium; - font-weight: tokens.$font-weight-medium; -} - -.text-body-large { - font-size: tokens.$font-size-body-large; - font-weight: tokens.$font-weight-regular; - line-height: tokens.$line-height-normal; -} - -.text-body-medium { - font-size: tokens.$font-size-body-medium; - font-weight: tokens.$font-weight-regular; - line-height: tokens.$line-height-normal; -} - -.text-label-medium { - font-size: tokens.$font-size-label-medium; - font-weight: tokens.$font-weight-medium; - letter-spacing: tokens.$letter-spacing-wide; -} - -// --------------------------------------------------------------------------- -// Status Dot Pulse Animations -// --------------------------------------------------------------------------- -@keyframes pulse-active { - 0%, 100% { opacity: 1; transform: scale(1); } - 50% { opacity: 0.7; transform: scale(1.15); } -} - -@keyframes pulse-error { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.4; } -} - -@keyframes pulse-thinking { - 0%, 100% { opacity: 0.8; } - 50% { opacity: 0.4; } -} - -// --------------------------------------------------------------------------- -// Status Dot Utility Classes -// --------------------------------------------------------------------------- -.status-dot { - width: tokens.$status-dot-size; - height: tokens.$status-dot-size; - border-radius: tokens.$radius-full; - display: inline-block; - - &--active { - background-color: var(--cc-status-active); - animation: pulse-active tokens.$duration-standard tokens.$easing-standard infinite; - } - - &--idle { - background-color: var(--cc-status-idle); - } - - &--thinking { - background-color: var(--cc-status-thinking); - animation: pulse-thinking 3s tokens.$easing-standard infinite; - } - - &--error { - background-color: var(--cc-status-error); - animation: pulse-error tokens.$duration-fast tokens.$easing-standard infinite; - } - - &--offline { - background-color: var(--cc-status-offline); - } -} - -// --------------------------------------------------------------------------- -// Accessibility: Reduced Motion -// --------------------------------------------------------------------------- -@media (prefers-reduced-motion: reduce) { - .status-dot--active, - .status-dot--error, - .status-dot--thinking { - animation: none; - } -} - -// --------------------------------------------------------------------------- -// Screen-reader-only utility -// --------------------------------------------------------------------------- -.sr-only { - @include tokens.sr-only; -} - -// --------------------------------------------------------------------------- -// Truncate utility -// --------------------------------------------------------------------------- -.truncate { - @include tokens.truncate; -} - -// --------------------------------------------------------------------------- -// Focus ring utility -// --------------------------------------------------------------------------- -.focus-ring { - @include tokens.focus-ring; -} - -// --------------------------------------------------------------------------- -// Scrollbar Styling (Tactical Dark) -// --------------------------------------------------------------------------- -::-webkit-scrollbar { - width: 6px; - height: 6px; -} - -::-webkit-scrollbar-track { - background: var(--cc-surface-dark); -} - -::-webkit-scrollbar-thumb { - background: var(--cc-surface-lighter); - border-radius: 3px; - - &:hover { - background: var(--cc-on-surface-variant); - } -} \ No newline at end of file diff --git a/frontend-legacy/src/styles/_css-properties.scss b/frontend-legacy/src/styles/_css-properties.scss deleted file mode 100644 index d067500..0000000 --- a/frontend-legacy/src/styles/_css-properties.scss +++ /dev/null @@ -1,115 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — CSS Custom Property Output -// ============================================================================ -// This module emits ALL design tokens as CSS custom properties on :root. -// Import this in styles.scss to make tokens available to all components. -// -// Tokens are namespaced with --cc- (Control Center) to avoid collisions -// with Angular Material's --mat- variables. -// ============================================================================ - -@use 'tokens' as *; - -// --------------------------------------------------------------------------- -// Emit all CSS custom properties -// --------------------------------------------------------------------------- -@mixin emit-custom-properties { - :root { - // --- Color tokens --- - --cc-color-primary: #{$color-primary-500}; - --cc-color-secondary: #{$color-secondary-400}; - --cc-color-accent: #{$color-accent-400}; - --cc-color-danger: #{$color-danger-400}; - - // --- Surface tokens --- - --cc-surface-darkest: #{$color-surface-darkest}; - --cc-surface-dark: #{$color-surface-dark}; - --cc-surface-medium: #{$color-surface-medium}; - --cc-surface-light: #{$color-surface-light}; - --cc-surface-lighter: #{$color-surface-lighter}; - - // --- On-surface tokens --- - --cc-on-surface: #{$color-on-surface}; - --cc-on-surface-variant: #{$color-on-surface-variant}; - --cc-on-surface-muted: #{$color-on-surface-muted}; - - // --- Status tokens --- - --cc-status-active: #{$status-active}; - --cc-status-idle: #{$status-idle}; - --cc-status-thinking: #{$status-thinking}; - --cc-status-error: #{$status-error}; - --cc-status-offline: #{$status-offline}; - - --cc-status-active-bg: #{$status-active-bg}; - --cc-status-idle-bg: #{$status-idle-bg}; - --cc-status-thinking-bg: #{$status-thinking-bg}; - --cc-status-error-bg: #{$status-error-bg}; - --cc-status-offline-bg: #{$status-offline-bg}; - - --cc-status-active-border: #{$status-active-border}; - --cc-status-idle-border: #{$status-idle-border}; - --cc-status-thinking-border: #{$status-thinking-border}; - --cc-status-error-border: #{$status-error-border}; - --cc-status-offline-border: #{$status-offline-border}; - - // --- Typography tokens --- - --cc-font-brand: #{$font-family-brand}; - --cc-font-body: #{$font-family-body}; - --cc-font-mono: #{$font-family-mono}; - - // --- Spacing tokens --- - --cc-spacing-0: #{$spacing-0}; - --cc-spacing-1: #{$spacing-1}; - --cc-spacing-2: #{$spacing-2}; - --cc-spacing-3: #{$spacing-3}; - --cc-spacing-4: #{$spacing-4}; - --cc-spacing-5: #{$spacing-5}; - --cc-spacing-6: #{$spacing-6}; - --cc-spacing-7: #{$spacing-7}; - --cc-spacing-8: #{$spacing-8}; - --cc-spacing-10: #{$spacing-10}; - --cc-spacing-12: #{$spacing-12}; - --cc-spacing-16: #{$spacing-16}; - - // --- Layout tokens --- - --cc-nav-rail-collapsed: #{$nav-rail-collapsed-width}; - --cc-nav-rail-expanded: #{$nav-rail-expanded-width}; - --cc-header-height: #{$header-height}; - --cc-bottom-nav-height: #{$bottom-nav-height}; - --cc-card-radius: #{$card-border-radius}; - --cc-card-min-width: #{$card-min-width}; - - // --- Radius tokens --- - --cc-radius-none: #{$radius-none}; - --cc-radius-xs: #{$radius-xs}; - --cc-radius-sm: #{$radius-sm}; - --cc-radius-md: #{$radius-md}; - --cc-radius-lg: #{$radius-lg}; - --cc-radius-xl: #{$radius-xl}; - --cc-radius-full: #{$radius-full}; - - // --- Shadow tokens --- - --cc-shadow-0: #{$shadow-level-0}; - --cc-shadow-1: #{$shadow-level-1}; - --cc-shadow-2: #{$shadow-level-2}; - --cc-shadow-3: #{$shadow-level-3}; - --cc-shadow-4: #{$shadow-level-4}; - - // --- Motion tokens --- - --cc-duration-fast: #{$duration-fast}; - --cc-duration-short: #{$duration-short}; - --cc-duration-medium: #{$duration-medium}; - --cc-duration-standard: #{$duration-standard}; - --cc-duration-long: #{$duration-long}; - - --cc-easing-standard: #{$easing-standard}; - --cc-easing-decelerate: #{$easing-decelerate}; - --cc-easing-accelerate: #{$easing-accelerate}; - - // --- Accessibility tokens --- - --cc-focus-width: #{$focus-ring-width}; - --cc-focus-offset: #{$focus-ring-offset}; - --cc-focus-color: #{$focus-ring-color}; - --cc-touch-min: #{$min-touch-target}; - } -} \ No newline at end of file diff --git a/frontend-legacy/src/styles/_tokens.scss b/frontend-legacy/src/styles/_tokens.scss deleted file mode 100644 index 6f14453..0000000 --- a/frontend-legacy/src/styles/_tokens.scss +++ /dev/null @@ -1,474 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — M3 Design Tokens -// ============================================================================ -// Single source of truth for all design tokens. -// Components should @use this module and reference tokens via variables or -// the theme() mixin rather than hardcoding values. -// -// Token structure: -// 1. Color tokens — palette, semantic, status, surface -// 2. Typography — families, sizes, weights, line-heights -// 3. Spacing — 4px base grid, named steps -// 4. Layout — dimensions, breakpoints, radii, shadows -// 5. Motion — durations, easing curves -// 6. Accessibility — focus, reduced-motion -// ============================================================================ - -@use 'sass:map'; -@use 'sass:meta'; - -// ============================================================================ -// 1. COLOR TOKENS -// ============================================================================ - -// --------------------------------------------------------------------------- -// 1a. Primary Palette (M3 cyan-based) -// --------------------------------------------------------------------------- -$color-primary-50: #ecfeff; -$color-primary-100: #cffafe; -$color-primary-200: #a5f3fc; -$color-primary-300: #67e8f9; -$color-primary-400: #22d3ee; -$color-primary-500: #38bdf8; // Brand primary -$color-primary-600: #0ea5e9; -$color-primary-700: #0284c7; -$color-primary-800: #0369a1; -$color-primary-900: #075985; - -// --------------------------------------------------------------------------- -// 1b. Secondary Palette (M3 teal-based) -// --------------------------------------------------------------------------- -$color-secondary-50: #f0fdfa; -$color-secondary-100: #ccfbf1; -$color-secondary-200: #99f6e4; -$color-secondary-300: #5eead4; -$color-secondary-400: #2dd4bf; // Brand secondary -$color-secondary-500: #14b8a6; -$color-secondary-600: #0d9488; -$color-secondary-700: #0f766e; -$color-secondary-800: #115e59; -$color-secondary-900: #134e4a; - -// --------------------------------------------------------------------------- -// 1c. Accent / Tertiary Palette (M3 violet-based) -// --------------------------------------------------------------------------- -$color-accent-50: #f5f3ff; -$color-accent-100: #ede9fe; -$color-accent-200: #ddd6fe; -$color-accent-300: #c4b5fd; -$color-accent-400: #a78bfa; // Brand accent -$color-accent-500: #8b5cf6; -$color-accent-600: #7c3aed; -$color-accent-700: #6d28d9; -$color-accent-800: #5b21b6; -$color-accent-900: #4c1d95; - -// --------------------------------------------------------------------------- -// 1d. Danger / Error Palette -// --------------------------------------------------------------------------- -$color-danger-50: #fef2f2; -$color-danger-100: #fee2e2; -$color-danger-200: #fecaca; -$color-danger-300: #fca5a5; -$color-danger-400: #f87171; // Brand danger -$color-danger-500: #ef4444; -$color-danger-600: #dc2626; -$color-danger-700: #b91c1c; -$color-danger-800: #991b1b; -$color-danger-900: #7f1d1d; - -// --------------------------------------------------------------------------- -// 1e. Semantic Surface Tokens (Tactical Dark) -// --------------------------------------------------------------------------- -$color-surface-darkest: #0D0F12; // Page background -$color-surface-dark: #13161A; // Card / container surface -$color-surface-medium: #1C2027; // Container-elevated -$color-surface-light: #252B33; // Container-high / hover -$color-surface-lighter: #2D3748; // Border / divider zone - -$color-on-surface: #E2E8F0; // Primary text on dark surfaces -$color-on-surface-variant: #8A9BB0; // Secondary / muted text -$color-on-surface-muted: #64748B; // Disabled / hint text - -// --------------------------------------------------------------------------- -// 1f. Status Colors (Semantic — outside M3 tonal system) -// --------------------------------------------------------------------------- -$status-active: #38bdf8; -$status-idle: #2dd4bf; -$status-thinking: #a78bfa; -$status-error: #f87171; -$status-offline: #64748b; - -// Status background tints (12% opacity for badges, pills, backgrounds) -$status-active-bg: rgba(56, 189, 248, 0.12); -$status-idle-bg: rgba(45, 212, 191, 0.12); -$status-thinking-bg: rgba(167, 139, 250, 0.12); -$status-error-bg: rgba(248, 113, 113, 0.12); -$status-offline-bg: rgba(100, 116, 139, 0.12); - -// Status border colors (40% opacity) -$status-active-border: rgba(56, 189, 248, 0.40); -$status-idle-border: rgba(45, 212, 191, 0.40); -$status-thinking-border: rgba(167, 139, 250, 0.40); -$status-error-border: rgba(248, 113, 113, 0.40); -$status-offline-border: rgba(100, 116, 139, 0.40); - -// Map for iteration -$status-colors: ( - 'active': ('fg': $status-active, 'bg': $status-active-bg, 'border': $status-active-border), - 'idle': ('fg': $status-idle, 'bg': $status-idle-bg, 'border': $status-idle-border), - 'thinking': ('fg': $status-thinking, 'bg': $status-thinking-bg, 'border': $status-thinking-border), - 'error': ('fg': $status-error, 'bg': $status-error-bg, 'border': $status-error-border), - 'offline': ('fg': $status-offline, 'bg': $status-offline-bg, 'border': $status-offline-border), -); - -// --------------------------------------------------------------------------- -// 1g. Full color map for programmatic access -// --------------------------------------------------------------------------- -$colors: ( - 'primary': $color-primary-500, - 'secondary': $color-secondary-400, - 'accent': $color-accent-400, - 'danger': $color-danger-400, - 'surface': $color-surface-dark, - 'surface-light': $color-surface-light, - 'on-surface': $color-on-surface, - 'on-surface-variant': $color-on-surface-variant, - 'border': $color-surface-lighter, -); - -// ============================================================================ -// 2. TYPOGRAPHY TOKENS -// ============================================================================ - -// --------------------------------------------------------------------------- -// 2a. Font Families -// --------------------------------------------------------------------------- -$font-family-brand: 'Inter, Roboto, sans-serif'; -$font-family-body: 'Inter, Roboto, sans-serif'; -$font-family-mono: 'Roboto Mono, Cascadia Code, Fira Code, monospace'; - -// --------------------------------------------------------------------------- -// 2b. Font Sizes (M3 type scale) -// --------------------------------------------------------------------------- -$font-size-display-large: 57px; -$font-size-display-medium: 45px; -$font-size-display-small: 36px; -$font-size-headline-large: 32px; -$font-size-headline-medium: 28px; -$font-size-headline-small: 24px; -$font-size-title-large: 22px; -$font-size-title-medium: 16px; -$font-size-title-small: 14px; -$font-size-body-large: 16px; -$font-size-body-medium: 14px; -$font-size-body-small: 12px; -$font-size-label-large: 14px; -$font-size-label-medium: 12px; -$font-size-label-small: 11px; - -// --------------------------------------------------------------------------- -// 2c. Font Weights -// --------------------------------------------------------------------------- -$font-weight-regular: 400; -$font-weight-medium: 500; -$font-weight-bold: 600; -$font-weight-heavy: 700; - -// --------------------------------------------------------------------------- -// 2d. Line Heights -// --------------------------------------------------------------------------- -$line-height-tight: 1.2; -$line-height-normal: 1.5; -$line-height-relaxed: 1.6; - -// --------------------------------------------------------------------------- -// 2e. Letter Spacing -// --------------------------------------------------------------------------- -$letter-spacing-tight: -0.01em; -$letter-spacing-normal: 0em; -$letter-spacing-wide: 0.02em; -$letter-spacing-mono: 0.05em; - -// --------------------------------------------------------------------------- -// 2f. Typography map -// --------------------------------------------------------------------------- -$typography: ( - 'font-family-brand': $font-family-brand, - 'font-family-body': $font-family-body, - 'font-family-mono': $font-family-mono, - 'size-display-large': $font-size-display-large, - 'size-headline-medium': $font-size-headline-medium, - 'size-title-large': $font-size-title-large, - 'size-title-medium': $font-size-title-medium, - 'size-body-large': $font-size-body-large, - 'size-body-medium': $font-size-body-medium, - 'size-body-small': $font-size-body-small, - 'size-label-large': $font-size-label-large, - 'size-label-medium': $font-size-label-medium, - 'weight-regular': $font-weight-regular, - 'weight-medium': $font-weight-medium, - 'weight-bold': $font-weight-bold, -); - -// ============================================================================ -// 3. SPACING TOKENS (4px grid) -// ============================================================================ - -$spacing-0: 0px; -$spacing-1: 4px; -$spacing-2: 8px; -$spacing-3: 12px; -$spacing-4: 16px; -$spacing-5: 20px; -$spacing-6: 24px; -$spacing-7: 28px; -$spacing-8: 32px; -$spacing-9: 36px; -$spacing-10: 40px; -$spacing-12: 48px; -$spacing-14: 56px; -$spacing-16: 64px; -$spacing-20: 80px; - -// Named semantic spacing -$spacing-unit: $spacing-2; // 8px — base grid unit -$spacing-card-gap: $spacing-4; // 16px -$spacing-card-pad: $spacing-5; // 20px -$spacing-section: $spacing-6; // 24px - -// ============================================================================ -// 4. LAYOUT TOKENS -// ============================================================================ - -// --------------------------------------------------------------------------- -// 4a. Dimensions -// --------------------------------------------------------------------------- -$nav-rail-collapsed-width: 72px; -$nav-rail-expanded-width: 256px; -$header-height: 64px; -$bottom-nav-height: 80px; -$card-border-radius: 16px; -$card-min-width: 320px; -$badge-height: 24px; -$badge-border-radius: 12px; -$status-dot-size: 10px; - -// --------------------------------------------------------------------------- -// 4b. Breakpoints (M3 canonical) -// --------------------------------------------------------------------------- -$breakpoint-compact: 599px; // Mobile phone -$breakpoint-medium: 767px; // Tablet portrait -$breakpoint-expanded: 1023px; // Tablet landscape -$breakpoint-large: 1439px; // Desktop - -// Named breakpoint map for @media mixins -$breakpoints: ( - 'compact': $breakpoint-compact, - 'medium': $breakpoint-medium, - 'expanded': $breakpoint-expanded, - 'large': $breakpoint-large, -); - -// --------------------------------------------------------------------------- -// 4c. Border Radius -// --------------------------------------------------------------------------- -$radius-none: 0px; -$radius-xs: 4px; -$radius-sm: 8px; -$radius-md: 12px; -$radius-lg: 16px; -$radius-xl: 24px; -$radius-full: 9999px; - -// --------------------------------------------------------------------------- -// 4d. Shadows (M3 elevation) -// --------------------------------------------------------------------------- -$shadow-level-0: none; -$shadow-level-1: 0 1px 3px 0 rgba(0, 0, 0, 0.3), 0 1px 2px -1px rgba(0, 0, 0, 0.3); -$shadow-level-2: 0 2px 6px 0 rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.3); -$shadow-level-3: 0 4px 12px 0 rgba(0, 0, 0, 0.3), 0 4px 8px -4px rgba(0, 0, 0, 0.3); -$shadow-level-4: 0 8px 24px 0 rgba(0, 0, 0, 0.3), 0 8px 16px -8px rgba(0, 0, 0, 0.3); - -// ============================================================================ -// 5. MOTION TOKENS -// ============================================================================ - -$duration-instant: 0ms; // No animation (reduced motion fallback) -$duration-fast: 100ms; -$duration-short: 150ms; -$duration-medium: 200ms; -$duration-standard: 300ms; -$duration-long: 500ms; - -$easing-standard: cubic-bezier(0.4, 0, 0.2, 1); // M3 standard -$easing-decelerate: cubic-bezier(0, 0, 0.2, 1); // M3 decelerate (entering) -$easing-accelerate: cubic-bezier(0.4, 0, 1, 1); // M3 accelerate (exiting) -$easing-sharp: cubic-bezier(0.4, 0, 0.6, 1); // M3 sharp - -// ============================================================================ -// 6. ACCESSIBILITY TOKENS -// ============================================================================ - -$focus-ring-width: 2px; -$focus-ring-offset: 2px; -$focus-ring-color: $status-active; -$focus-ring-style: solid; - -$min-touch-target: 48px; -$min-body-font: 16px; - -// ============================================================================ -// MIXINS -// ============================================================================ - -// --------------------------------------------------------------------------- -// Responsive breakpoint mixin -// Usage: @include tokens.respond-to('expanded') { ... } -// --------------------------------------------------------------------------- -@mixin respond-to($breakpoint) { - $value: map.get($breakpoints, $breakpoint); - @if $value { - @media (min-width: $value + 1) { - @content; - } - } @else { - @error "Unknown breakpoint: `#{$breakpoint}`. Valid: compact, medium, expanded, large"; - } -} - -// --------------------------------------------------------------------------- -// Below-breakpoint mixin (max-width) -// Usage: @include tokens.below('expanded') { ... } -// --------------------------------------------------------------------------- -@mixin below($breakpoint) { - $value: map.get($breakpoints, $breakpoint); - @if $value { - @media (max-width: $value) { - @content; - } - } @else { - @error "Unknown breakpoint: `#{$breakpoint}`. Valid: compact, medium, expanded, large"; - } -} - -// --------------------------------------------------------------------------- -// Focus ring mixin -// --------------------------------------------------------------------------- -@mixin focus-ring($color: $focus-ring-color) { - &:focus-visible { - outline: $focus-ring-width $focus-ring-style $color; - outline-offset: $focus-ring-offset; - } -} - -// --------------------------------------------------------------------------- -// Card surface mixin -// --------------------------------------------------------------------------- -@mixin card-surface { - background-color: $color-surface-medium; - border-radius: $card-border-radius; - border: 1px solid $color-surface-lighter; -} - -// --------------------------------------------------------------------------- -// Mono text mixin -// --------------------------------------------------------------------------- -@mixin mono-text($size: $font-size-body-medium) { - font-family: $font-family-mono; - font-size: $size; - letter-spacing: $letter-spacing-mono; -} - -// --------------------------------------------------------------------------- -// Status dot mixin -// --------------------------------------------------------------------------- -@mixin status-dot($status) { - $colors: map.get($status-colors, $status); - @if not $colors { - @error "Unknown status: `#{$status}`. Valid: active, idle, thinking, error, offline"; - } - $fg: map.get($colors, 'fg'); - - width: $status-dot-size; - height: $status-dot-size; - border-radius: $radius-full; - background-color: $fg; - - @if $status == 'active' { - animation: pulse-active $duration-standard $easing-standard infinite; - } @else if $status == 'thinking' { - animation: pulse-thinking 3s $easing-standard infinite; - } @else if $status == 'error' { - animation: pulse-error $duration-fast $easing-standard infinite; - } -} - -// --------------------------------------------------------------------------- -// Truncate text mixin (single line) -// --------------------------------------------------------------------------- -@mixin truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -// --------------------------------------------------------------------------- -// Screen-reader-only mixin -// --------------------------------------------------------------------------- -@mixin sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; -} - -// --------------------------------------------------------------------------- -// Touch target mixin — ensures minimum 48px touch area -// --------------------------------------------------------------------------- -@mixin touch-target($min-size: $min-touch-target) { - min-width: $min-size; - min-height: $min-size; -} -// ============================================================================ -// CUB-20 / CUB-27 CONVENIENCE ALIASES -// ============================================================================ -// Short aliases used by agent-card, hub-page, and other components. -// These map to the canonical M3 tokens above. - -$cc-background: $color-surface-darkest; -$cc-surface: $color-surface-dark; -$cc-surface-container: $color-surface-medium; -$cc-surface-container-high: $color-surface-light; -$cc-on-surface: $color-on-surface; -$cc-on-surface-variant: $color-on-surface-variant; -$cc-outline: $color-surface-lighter; - -$cc-font-mono: $font-family-mono; -$cc-font-family: $font-family-brand; - -$cc-nav-rail-collapsed-width: $nav-rail-collapsed-width; -$cc-nav-rail-expanded-width: $nav-rail-expanded-width; -$cc-header-height: $header-height; -$cc-bottom-nav-height: $bottom-nav-height; -$cc-card-border-radius: $card-border-radius; -$cc-card-min-width: $card-min-width; -$cc-card-gap: $spacing-card-gap; -$cc-card-padding: $spacing-card-pad; -$cc-section-padding: $spacing-section; -$cc-spacing-unit: $spacing-unit; - -$cc-breakpoint-mobile: $breakpoint-compact; -$cc-breakpoint-tablet: $breakpoint-medium; -$cc-breakpoint-desktop: $breakpoint-expanded; - -$cc-surface-darkest: $color-surface-darkest; -$cc-surface-dark: $color-surface-dark; -$cc-surface-medium: $color-surface-medium; -$cc-surface-light: $color-surface-light; -$cc-surface-lighter: $color-surface-lighter; diff --git a/frontend-legacy/src/styles/_utilities.scss b/frontend-legacy/src/styles/_utilities.scss deleted file mode 100644 index 9901928..0000000 --- a/frontend-legacy/src/styles/_utilities.scss +++ /dev/null @@ -1,170 +0,0 @@ -// ============================================================================ -// OpenClaw Control Center — Utility Mixins -// ============================================================================ -// Reusable patterns that enforce design-system consistency. -// Components should @use this module and include mixins rather than -// writing repetitive CSS blocks. -// ============================================================================ - -@use 'tokens' as *; - -// --------------------------------------------------------------------------- -// Elevation / Surface Card -// Applies consistent card styling using design tokens. -// Usage: @include utils.card-surface(); -// --------------------------------------------------------------------------- -@mixin card-surface($elevation: 1) { - background-color: var(--cc-surface-medium); - border-radius: var(--cc-card-radius); - border: 1px solid var(--cc-surface-lighter); - box-shadow: var(--cc-shadow-#{$elevation}); - transition: box-shadow var(--cc-duration-short) var(--cc-easing-standard); -} - -// --------------------------------------------------------------------------- -// Elevated card on hover -// --------------------------------------------------------------------------- -@mixin card-hover($elevation: 2) { - &:hover { - box-shadow: var(--cc-shadow-#{$elevation}); - } -} - -// --------------------------------------------------------------------------- -// Status-aware left border -// Applies colored left border based on agent status. -// Usage: @include utils.status-border('active'); -// --------------------------------------------------------------------------- -@mixin status-border($status) { - $status-map: ( - 'active': var(--cc-status-active), - 'idle': var(--cc-status-idle), - 'thinking': var(--cc-status-thinking), - 'error': var(--cc-status-error), - 'offline': var(--cc-status-offline), - ); - $color: map-get($status-map, $status); - @if not $color { - $color: var(--cc-status-offline); - } - border-left: 4px solid $color; -} - -// --------------------------------------------------------------------------- -// Status badge / pill -// --------------------------------------------------------------------------- -@mixin status-badge($status) { - $fg-map: ( - 'active': var(--cc-status-active), - 'idle': var(--cc-status-idle), - 'thinking': var(--cc-status-thinking), - 'error': var(--cc-status-error), - 'offline': var(--cc-status-offline), - ); - $bg-map: ( - 'active': var(--cc-status-active-bg), - 'idle': var(--cc-status-idle-bg), - 'thinking': var(--cc-status-thinking-bg), - 'error': var(--cc-status-error-bg), - 'offline': var(--cc-status-offline-bg), - ); - - display: inline-flex; - align-items: center; - gap: 6px; - height: $badge-height; - padding: 0 8px; - border-radius: $badge-border-radius; - background-color: map-get($bg-map, $status); - color: map-get($fg-map, $status); - font-size: $font-size-label-medium; - font-weight: $font-weight-medium; - white-space: nowrap; -} - -// --------------------------------------------------------------------------- -// Glass surface (frosted glass effect) -// --------------------------------------------------------------------------- -@mixin glass-surface { - background-color: rgba(19, 22, 26, 0.8); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); - border: 1px solid var(--cc-surface-lighter); -} - -// --------------------------------------------------------------------------- -// Responsive grid -// Creates a responsive grid that adapts from 1-col to 2-col. -// --------------------------------------------------------------------------- -@mixin responsive-grid($min-col-width: $card-min-width, $gap: $spacing-card-gap) { - display: grid; - grid-template-columns: repeat(auto-fill, minmax($min-col-width, 1fr)); - gap: $gap; -} - -// --------------------------------------------------------------------------- -// Scroll container -// --------------------------------------------------------------------------- -@mixin scroll-container($direction: 'y') { - @if $direction == 'y' { - overflow-y: auto; - overflow-x: hidden; - } @else { - overflow-x: auto; - overflow-y: hidden; - } - -webkit-overflow-scrolling: touch; - - // Custom scrollbar (tactical dark) - &::-webkit-scrollbar { - width: 6px; - height: 6px; - } - &::-webkit-scrollbar-track { - background: var(--cc-surface-dark); - } - &::-webkit-scrollbar-thumb { - background: var(--cc-surface-lighter); - border-radius: 3px; - &:hover { - background: var(--cc-on-surface-variant); - } - } -} - -// --------------------------------------------------------------------------- -// Page container -// Standard page padding and layout -// --------------------------------------------------------------------------- -@mixin page-container { - padding: $spacing-section; - min-height: 400px; - overflow-x: hidden; -} - -// --------------------------------------------------------------------------- -// Transition helpers -// --------------------------------------------------------------------------- -@mixin transition-colors($duration: $duration-short) { - transition: color #{$duration} $easing-standard, - background-color #{$duration} $easing-standard, - border-color #{$duration} $easing-standard; -} - -@mixin transition-transform($duration: $duration-medium) { - transition: transform #{$duration} $easing-standard; -} - -@mixin transition-opacity($duration: $duration-short) { - transition: opacity #{$duration} $easing-standard; -} - -// --------------------------------------------------------------------------- -// Reduced motion -// Wraps content in a reduced-motion media query. -// --------------------------------------------------------------------------- -@mixin reduced-motion { - @media (prefers-reduced-motion: reduce) { - @content; - } -} \ No newline at end of file diff --git a/frontend-legacy/tsconfig.app.json b/frontend-legacy/tsconfig.app.json deleted file mode 100644 index 264f459..0000000 --- a/frontend-legacy/tsconfig.app.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "src/**/*.spec.ts" - ] -} diff --git a/frontend-legacy/tsconfig.json b/frontend-legacy/tsconfig.json deleted file mode 100644 index ad457fa..0000000 --- a/frontend-legacy/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "compileOnSave": false, - "compilerOptions": { - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - "isolatedModules": true, - "experimentalDecorators": true, - "importHelpers": true, - "target": "ES2022", - "module": "preserve" - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - }, - "files": [], - "references": [ - { - "path": "./tsconfig.app.json" - } - ] -} diff --git a/frontend-legacy/tsconfig.spec.json b/frontend-legacy/tsconfig.spec.json deleted file mode 100644 index d383706..0000000 --- a/frontend-legacy/tsconfig.spec.json +++ /dev/null @@ -1,15 +0,0 @@ -/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ -/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": [ - "vitest/globals" - ] - }, - "include": [ - "src/**/*.d.ts", - "src/**/*.spec.ts" - ] -} diff --git a/backend/migrations/001_initial_schema.down.sql b/go-backend/migrations/001_initial_schema.down.sql similarity index 100% rename from backend/migrations/001_initial_schema.down.sql rename to go-backend/migrations/001_initial_schema.down.sql diff --git a/backend/migrations/001_initial_schema.up.sql b/go-backend/migrations/001_initial_schema.up.sql similarity index 100% rename from backend/migrations/001_initial_schema.up.sql rename to go-backend/migrations/001_initial_schema.up.sql diff --git a/backend/migrations/002_add_indexes.down.sql b/go-backend/migrations/002_add_indexes.down.sql similarity index 100% rename from backend/migrations/002_add_indexes.down.sql rename to go-backend/migrations/002_add_indexes.down.sql diff --git a/backend/migrations/002_add_indexes.up.sql b/go-backend/migrations/002_add_indexes.up.sql similarity index 100% rename from backend/migrations/002_add_indexes.up.sql rename to go-backend/migrations/002_add_indexes.up.sql