diff --git a/.ai-dev/project.json b/.ai-dev/project.json new file mode 100644 index 0000000..985233e --- /dev/null +++ b/.ai-dev/project.json @@ -0,0 +1,4 @@ +{ + "projectSlug": "ai-dev", + "apiPort": 5191 +} diff --git a/.gitignore b/.gitignore index 209fa5b..3b78691 100644 --- a/.gitignore +++ b/.gitignore @@ -407,6 +407,11 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd +# VS Code extension — generated backend binaries (produced by npm run package:*) +ai-dev-vscode/bin/ +# *.vsix build artefacts +ai-dev-vscode/*.vsix + # VS Code files for those working on multiple tools .vscode/* !.vscode/settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json index c6f376d..db8c102 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -26,6 +26,33 @@ "type": "dotnet", "request": "launch", "projectPath": "${workspaceFolder}/ai-dev-net.AppHost/ai-dev-net.AppHost.csproj" + }, + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}/ai-dev-vscode", + "${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/ai-dev-vscode/dist/**/*.js" + ], + "preLaunchTask": "build-extension" + }, + { + "name": "ai-dev.api", + "type": "dotnet", + "request": "launch", + "projectPath": "${workspaceFolder}/ai-dev.api/ai-dev.api.csproj", + "launchSettingsProfile": "http" + } + ], + "compounds": [ + { + "name": "API + Extension", + "configurations": ["ai-dev.api", "Run Extension"], + "stopAll": true } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 467b586..7afc499 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,5 +2,16 @@ "chat.tools.terminal.autoApprove": { "dotnet test": true, "dotnet list": true + }, + "files.watcherExclude": { + "**/node_modules/**": true, + "**/dist/**": true + }, + "files.exclude": { + "**/node_modules": true + }, + "search.exclude": { + "**/node_modules": true, + "**/dist": true } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 8da4512..b79cbb2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -29,6 +29,16 @@ ], "problemMatcher": "$msCompile", "group": "build" + }, + { + "label": "build-extension", + "type": "shell", + "command": "npm run build", + "options": { + "cwd": "${workspaceFolder}/ai-dev-vscode" + }, + "problemMatcher": ["$tsc"], + "group": "build" } ] } diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9ff1184 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,123 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +### .NET (run from repo root) + +```bash +# Build solution +dotnet build ai-dev-net.slnx + +# Run all unit tests +dotnet test ai-dev-net.tests.unit/ai-dev-net.tests.unit.csproj + +# Run a single test class or method +dotnet test ai-dev-net.tests.unit/ai-dev-net.tests.unit.csproj --filter "FullyQualifiedName~AgentSlugTests" + +# Run integration tests +dotnet test ai-dev-net.tests.integration/ai-dev-net.tests.integration.csproj + +# Run the Aspire host (starts all services) +dotnet run --project ai-dev-net.AppHost + +# Run just the API +dotnet run --project ai-dev.api + +# Run the WinUI desktop app (requires Windows, x64) +dotnet run --project ai-dev.ui.winui -p:Platform=x64 +``` + +### VS Code Extension (run from `ai-dev-vscode/`) + +```bash +npm run build # one-shot bundle +npm run watch # incremental rebuild +npm test # Jest unit tests +npm run package # produce .vsix for sideloading +``` + +### CI mirrors + +CI runs `dotnet restore ai-dev-net.slnx`, then `dotnet build` with `-c Release -p:Platform=x64`, then the unit tests. `Directory.Build.props` sets `TreatWarningsAsErrors=true` globally — the build will fail on any warning. + +--- + +## Architecture + +This is a multi-agent AI orchestration platform. The .NET backend manages projects, agents, tasks (a Kanban board), decisions, and planning sessions. A WinUI 3 desktop app and an ASP.NET Core web app provide UI. A VS Code extension surfaces agent activity in the editor sidebar. + +### Layer map + +``` +ai-dev-net.AppHost Aspire orchestration host — entry point for dev/deploy +ai-dev.api ASP.NET Core Minimal API + SignalR hub; consumed by the VS Code extension +ai-dev.ui.winui WinUI 3 desktop app (Windows App SDK 1.8), x86/x64/ARM64 +ai-dev.core Domain: entities, value types, service contracts, domain events +ai-dev.core.local Local orchestration: planning sessions, transcript compaction, progressive context discovery +ai-dev.mcp Model Context Protocol server — workspace tools (file I/O, git, journal) exposed to LLMs +ai-dev.executor.* Six pluggable LLM backends (Anthropic, Claude CLI, Ollama, LM Studio, GitHub Models, Copilot CLI) +ai-dev-net.ServiceDefaults Shared DI/service configuration used by all host projects +ai-dev-vscode VS Code extension: React 19 webviews, SignalR client, backend process manager +``` + +### How the pieces connect + +- **Executors** implement a common contract in `ai-dev.core` and are registered via their own `Add*Executor()` extension methods. The `ModelResolver` and `AgentRunnerService` in `ai-dev.core` select and invoke them. +- **`ai-dev.core.local`** sits above `ai-dev.core` and handles the stateful session lifecycle: building prompts (`AgentPromptBuilder`), compacting transcripts (`RuleBasedContextCompactor`), running progressive discovery (`ProgressiveDiscoveryEngine`), and routing tool calls (`LocalToolBroker`). +- **`ai-dev.mcp`** exposes workspace tools (file reads, git ops, journal writes) as MCP tools. Executors that support MCP (Anthropic, Claude CLI) call these tools; the responses are routed back through the session. +- **`ai-dev.api`** is a thin HTTP layer over `ai-dev.core` services. It also hosts a SignalR hub (`ProjectStateHub`) that pushes `ProjectStateChangedEvent` domain events to connected clients (the VS Code extension). +- **`ai-dev.ui.winui`** uses the same `ai-dev.core` services directly (in-process) via DI. View models are MVVM Community Toolkit `ObservableObject` partials. +- **`ai-dev-vscode`** connects to `ai-dev.api` via REST + SignalR. `WorkspaceDetector` discovers projects by watching for `.ai-dev/project.json` files across open workspace folders; `BackendProcessManager` spawns the API process from the bundled binaries. + +### Workspace layout on disk + +``` +/ + .ai-dev/ + workspaces.json project registry (slug → name) + studio-settings.json + / + project.json project metadata (codebasePath, codebaseInitialized, …) + agents/ + board/ + decisions/ + kb/ + playbooks/ + sessions/ +``` + +`WorkspacePaths` in `ai-dev.core` is the single source of truth for all path resolution. Every service resolves paths through it — never string-concatenate paths directly. + +The VS Code extension discovers a project via `/.ai-dev/project.json` (fields: `projectSlug`, `apiPort`). This file is separate from the studio workspace storage above. + +### Domain model + +See `docs/UBIQUITOUS_LANGUAGE.md` for the canonical glossary. Key terms: + +- **Agent** — an autonomous LLM worker with a slug, executor, and inbox. Runs one session at a time. +- **Task / BoardTask** — a Kanban card. Assigned to an agent via `TaskAssigned` domain event. +- **Decision** — a pending question surfaced by an agent; resolved by a human or another agent. +- **Planning Session** — a multi-turn LLM conversation that produces a structured plan before execution. +- **Executor** — the runtime backend that sends prompts to an LLM and streams tool calls back. + +### Value types + +All domain identifiers are strongly-typed immutable records (`AgentSlug`, `ProjectSlug`, `TaskId`, `ColumnId`, `DecisionId`, …) defined in `ai-dev.core/Models/Types/`. Each has: +- Constructor validation (throws `ArgumentException` on bad input) +- A companion `*JsonConverter` registered at the serializer level +- `TryParse()` for safe deserialization + +Do not use raw `string` for any domain identifier. Add a new value type if one is missing. + +### Result pattern + +`Result` (in `ai-dev.core/Models/Result.cs`) is used instead of exceptions for recoverable errors. Use `Result.Ok(value)` / `Result.Fail(reason)` and the extension methods in `ResultExtensions`. Do not throw from service methods that can legitimately fail. + +### Testing conventions + +- Framework: xUnit 3, Shouldly assertions, NSubstitute mocks. +- All global usings are declared in `GlobalUsings.cs` — no per-file `using` for the standard set. +- Tests use temp directories (`Path.GetTempPath() + Guid`) for any file I/O — never relative paths. +- Value type tests follow the pattern in `AgentSlugTests.cs`: constructor validation, round-trip serialisation, equality, `TryParse`. diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..80f498a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + true + + diff --git a/ai-dev-net.AppHost/AppHost.cs b/ai-dev-net.AppHost/AppHost.cs index 1a5661e..843477b 100644 --- a/ai-dev-net.AppHost/AppHost.cs +++ b/ai-dev-net.AppHost/AppHost.cs @@ -1,16 +1,18 @@ var builder = DistributedApplication.CreateBuilder(args); -var workspaceRoot = Path.GetFullPath(Path.Combine( - AppContext.BaseDirectory, - "..", - "..", - "..", - "..", - "workspaces")); +// WORKSPACE_ROOT must be set in the developer's environment to the managed project directory +// (e.g. M:\ai-dev-net). The API and MCP will walk up from there to find .ai-dev/project.json. +var workspaceRoot = Environment.GetEnvironmentVariable("WORKSPACE_ROOT") + ?? throw new InvalidOperationException( + "WORKSPACE_ROOT environment variable is not set. " + + "Set it to the managed project directory (e.g. M:\\ai-dev-net)."); builder.AddProject("ai-dev-mcp") .WithEnvironment("WORKSPACE_ROOT", workspaceRoot); +builder.AddProject("ai-dev-api") + .WithEnvironment("WORKSPACE_ROOT", workspaceRoot); + builder.AddProject("ai-dev-winui"); builder.Build().Run(); diff --git a/ai-dev-net.AppHost/ai-dev-net.AppHost.csproj b/ai-dev-net.AppHost/ai-dev-net.AppHost.csproj index 3da5450..93f4494 100644 --- a/ai-dev-net.AppHost/ai-dev-net.AppHost.csproj +++ b/ai-dev-net.AppHost/ai-dev-net.AppHost.csproj @@ -11,6 +11,7 @@ + diff --git a/ai-dev-net.slnx b/ai-dev-net.slnx index ab36d8a..c4eeb29 100644 --- a/ai-dev-net.slnx +++ b/ai-dev-net.slnx @@ -40,6 +40,7 @@ + diff --git a/ai-dev-net.tests.integration/ConsistencyUiAndDetectionIntegrationTests.cs b/ai-dev-net.tests.integration/ConsistencyUiAndDetectionIntegrationTests.cs index d63182e..2433584 100644 --- a/ai-dev-net.tests.integration/ConsistencyUiAndDetectionIntegrationTests.cs +++ b/ai-dev-net.tests.integration/ConsistencyUiAndDetectionIntegrationTests.cs @@ -12,6 +12,7 @@ namespace AiDevNet.Tests.Integration; public class ConsistencyUiAndDetectionIntegrationTests : IDisposable { private readonly string _rootPath; + private readonly ActiveWorkspaceHolder _holder; private readonly WorkspacePaths _paths; private readonly AtomicFileWriter _fileWriter = new(); private readonly ProjectMutationCoordinator _coordinator = new(); @@ -20,7 +21,9 @@ public ConsistencyUiAndDetectionIntegrationTests() { _rootPath = Path.Combine(Path.GetTempPath(), $"consistency-ui-{Guid.NewGuid():N}"); Directory.CreateDirectory(_rootPath); - _paths = new WorkspacePaths(new RootDir(_rootPath)); + _holder = new ActiveWorkspaceHolder(); + _holder.Activate(_rootPath); + _paths = _holder.Paths; } public void Dispose() @@ -32,8 +35,8 @@ public void Dispose() [Fact] public async Task CheckProjectAsync_WhenRawBoardHasDuplicateTaskReference_ReportsRawFinding() { - var workspaceService = new WorkspaceService(_paths, _fileWriter); - workspaceService.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); + var workspaceService = new WorkspaceService(_holder, _fileWriter); + workspaceService.CreateProject(_rootPath, "demo-project", "Demo Project", null).ShouldBeOfType>(); var projectSlug = new ProjectSlug("demo-project"); var boardPath = _paths.BoardPath(projectSlug); _fileWriter.WriteAllText(boardPath, "{\"columns\":[{\"id\":\"backlog\",\"title\":\"Backlog\",\"taskIds\":[\"task-1\"]},{\"id\":\"review\",\"title\":\"Review\",\"taskIds\":[\"task-1\"]}],\"tasks\":{\"task-1\":{\"id\":\"task-1\",\"title\":\"Investigate failure\",\"priority\":\"normal\"}}}"); diff --git a/ai-dev-net.tests.integration/ProductionReadinessIntegrationTests.cs b/ai-dev-net.tests.integration/ProductionReadinessIntegrationTests.cs index 7e61ce2..08f57ac 100644 --- a/ai-dev-net.tests.integration/ProductionReadinessIntegrationTests.cs +++ b/ai-dev-net.tests.integration/ProductionReadinessIntegrationTests.cs @@ -17,21 +17,28 @@ namespace AiDevNet.Tests.Integration; public class ProductionReadinessIntegrationTests : IDisposable { private readonly string _rootPath; + private readonly ActiveWorkspaceHolder _holder; private readonly WorkspacePaths _paths; private readonly AtomicFileWriter _fileWriter = new(); private readonly ProjectMutationCoordinator _coordinator = new(); + private readonly string _templatesDir; public ProductionReadinessIntegrationTests() { _rootPath = Path.Combine(Path.GetTempPath(), $"prod-ready-{Guid.NewGuid():N}"); Directory.CreateDirectory(_rootPath); - _paths = new WorkspacePaths(new RootDir(_rootPath)); + _holder = new ActiveWorkspaceHolder(); + _holder.Activate(_rootPath); + _paths = _holder.Paths; + _templatesDir = Path.Combine(Path.GetTempPath(), $"templates-{Guid.NewGuid():N}"); } public void Dispose() { if (Directory.Exists(_rootPath)) Directory.Delete(_rootPath, recursive: true); + if (Directory.Exists(_templatesDir)) + Directory.Delete(_templatesDir, recursive: true); } [Fact] @@ -135,14 +142,14 @@ public void AtomicFileWriter_WhenOverwritingFile_ReplacesContent() [Fact] public void WorkspaceService_CreateProject_UsesAtomicWritesForArtifacts() { - var service = new WorkspaceService(_paths, _fileWriter); + var service = new WorkspaceService(_holder, _fileWriter); - var result = service.CreateProject("demo-project", "Demo Project", "Main app"); + var result = service.CreateProject(_rootPath, "demo-project", "Demo Project", "Main app"); result.ShouldBeOfType>(); File.Exists(_paths.ProjectJsonPath(new ProjectSlug("demo-project"))).ShouldBeTrue(); File.Exists(_paths.BoardPath(new ProjectSlug("demo-project"))).ShouldBeTrue(); - File.Exists(_paths.RegistryPath).ShouldBeTrue(); + File.Exists(GlobalPaths.RegistryFile).ShouldBeTrue(); } [Fact] @@ -153,20 +160,19 @@ public void AgentService_CreateAgent_WritesFilesAtomically() modelRegistry.GetModelsForExecutor(Arg.Any()).Returns([]); var service = new AgentService( _paths, - new AgentTemplatesService(_paths), + new AgentTemplatesService(_templatesDir), _fileWriter, _coordinator, modelRegistry, NullLogger.Instance); var projectSlug = new ProjectSlug("demo-project"); - var workspaceService = new WorkspaceService(_paths, _fileWriter); - workspaceService.CreateProject(projectSlug.Value, "Demo Project", null).ShouldBeOfType>(); + var workspaceService = new WorkspaceService(_holder, _fileWriter); + workspaceService.CreateProject(_rootPath, projectSlug.Value, "Demo Project", null).ShouldBeOfType>(); - var templateJsonPath = _paths.SafeTemplatePath("generic-standard", ".json")!; - var templateMdPath = _paths.SafeTemplatePath("generic-standard", ".md")!; - Directory.CreateDirectory(Path.GetDirectoryName(templateJsonPath.Value)!); - File.WriteAllText(templateJsonPath.Value, "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); - File.WriteAllText(templateMdPath.Value, "# Generic\n\nYou build features."); + Directory.CreateDirectory(_templatesDir); + File.WriteAllText(Path.Combine(_templatesDir, "generic-standard.json"), + "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); + File.WriteAllText(Path.Combine(_templatesDir, "generic-standard.md"), "# Generic\n\nYou build features."); var result = service.CreateAgent(projectSlug, "backend-dev", "Backend Dev", "generic-standard"); @@ -179,8 +185,8 @@ public void AgentService_CreateAgent_WritesFilesAtomically() public void KbAndPlaybookServices_SaveAtomically() { var projectSlug = new ProjectSlug("demo-project"); - var workspaceService = new WorkspaceService(_paths, _fileWriter); - workspaceService.CreateProject(projectSlug.Value, "Demo Project", null).ShouldBeOfType>(); + var workspaceService = new WorkspaceService(_holder, _fileWriter); + workspaceService.CreateProject(_rootPath, projectSlug.Value, "Demo Project", null).ShouldBeOfType>(); var kbService = new KbService(_paths, _fileWriter, _coordinator); var playbookService = new PlaybookService(_paths, _fileWriter, _coordinator); diff --git a/ai-dev-net.tests.integration/ProjectStateHubTests.cs b/ai-dev-net.tests.integration/ProjectStateHubTests.cs new file mode 100644 index 0000000..d039c45 --- /dev/null +++ b/ai-dev-net.tests.integration/ProjectStateHubTests.cs @@ -0,0 +1,93 @@ +using AiDev; +using AiDev.Api.Hubs; +using AiDev.Models; +using AiDev.Models.Types; +using AiDev.Services; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.Extensions.DependencyInjection; + +namespace AiDevNet.Tests.Integration; + +public class ProjectStateHubTests : IAsyncLifetime +{ + private WebApplicationFactory _factory = null!; + private string _workspaceRoot = null!; + + public ValueTask InitializeAsync() + { + _workspaceRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(_workspaceRoot); + + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + builder.UseSetting("WORKSPACE_ROOT", _workspaceRoot)); + + return ValueTask.CompletedTask; + } + + public async ValueTask DisposeAsync() + { + await _factory.DisposeAsync(); + try { Directory.Delete(_workspaceRoot, recursive: true); } catch { } + } + + [Fact] + public async Task StateChanged_WhenNotifierFires_ClientReceivesMessage() + { + var projectSlug = "test-project"; + var received = new TaskCompletionSource<(string slug, string[] kinds)>( + TaskCreationOptions.RunContinuationsAsynchronously); + + var hubUrl = new UriBuilder(_factory.Server.BaseAddress) { Path = "/hubs/project" }.Uri; + var connection = new HubConnectionBuilder() + .WithUrl(hubUrl, o => o.HttpMessageHandlerFactory = _ => _factory.Server.CreateHandler()) + .Build(); + + connection.On("StateChanged", msg => + received.TrySetResult((msg.ProjectSlug, msg.Kinds))); + + await connection.StartAsync(TestContext.Current.CancellationToken); + await connection.InvokeAsync("JoinProject", projectSlug, TestContext.Current.CancellationToken); + + // Fire the notifier directly via DI + var notifier = _factory.Services.GetRequiredService(); + notifier.Notify(new ProjectSlug(projectSlug), ProjectStateChangeKind.Agents | ProjectStateChangeKind.Messages); + + var timeout = Task.Delay(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); + var completed = await Task.WhenAny(received.Task, timeout); + completed.ShouldBe(received.Task, "Timed out waiting for StateChanged message"); + + var (slug, kinds) = await received.Task; + slug.ShouldBe(projectSlug); + kinds.ShouldContain("Agents"); + kinds.ShouldContain("Messages"); + + await connection.StopAsync(TestContext.Current.CancellationToken); + } + + [Fact] + public async Task StateChanged_WhenClientNotInGroup_DoesNotReceiveMessage() + { + var received = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + var hubUrl = new UriBuilder(_factory.Server.BaseAddress) { Path = "/hubs/project" }.Uri; + var connection = new HubConnectionBuilder() + .WithUrl(hubUrl, o => o.HttpMessageHandlerFactory = _ => _factory.Server.CreateHandler()) + .Build(); + + connection.On("StateChanged", _ => received.TrySetResult(true)); + + await connection.StartAsync(TestContext.Current.CancellationToken); + // Deliberately do NOT join any project group + + var notifier = _factory.Services.GetRequiredService(); + notifier.Notify(new ProjectSlug("other-project"), ProjectStateChangeKind.Board); + + var timeout = Task.Delay(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken); + var completed = await Task.WhenAny(received.Task, timeout); + completed.ShouldBe(timeout, "Client not in group should not receive message"); + + await connection.StopAsync(TestContext.Current.CancellationToken); + } +} diff --git a/ai-dev-net.tests.integration/ai-dev-net.tests.integration.csproj b/ai-dev-net.tests.integration/ai-dev-net.tests.integration.csproj index 1b04e24..fb54051 100644 --- a/ai-dev-net.tests.integration/ai-dev-net.tests.integration.csproj +++ b/ai-dev-net.tests.integration/ai-dev-net.tests.integration.csproj @@ -10,12 +10,16 @@ - + + + + + + - @@ -23,6 +27,7 @@ + diff --git a/ai-dev-net.tests.unit/ActiveWorkspaceHolderTests.cs b/ai-dev-net.tests.unit/ActiveWorkspaceHolderTests.cs new file mode 100644 index 0000000..28f047a --- /dev/null +++ b/ai-dev-net.tests.unit/ActiveWorkspaceHolderTests.cs @@ -0,0 +1,57 @@ +namespace AiDevNet.Tests.Unit; + +public class ActiveWorkspaceHolderTests +{ + [Fact] + public void HasActiveProject_WhenNotActivated_ReturnsFalse() + { + var holder = new ActiveWorkspaceHolder(); + + holder.HasActiveProject.ShouldBeFalse(); + holder.ActiveCodebasePath.ShouldBeNull(); + } + + [Fact] + public void Paths_WhenNotActivated_Throws() + { + var holder = new ActiveWorkspaceHolder(); + + Should.Throw(() => _ = holder.Paths); + } + + [Fact] + public void Activate_SetsPathsAndCodebasePath() + { + var holder = new ActiveWorkspaceHolder(); + var codebasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + + holder.Activate(codebasePath); + + holder.HasActiveProject.ShouldBeTrue(); + holder.ActiveCodebasePath.ShouldBe(Path.GetFullPath(codebasePath)); + holder.Paths.Root.Value.ShouldBe(Path.Combine(Path.GetFullPath(codebasePath), ".ai-dev")); + } + + [Fact] + public void Deactivate_ClearsState() + { + var holder = new ActiveWorkspaceHolder(); + holder.Activate(Path.GetTempPath()); + + holder.Deactivate(); + + holder.HasActiveProject.ShouldBeFalse(); + holder.ActiveCodebasePath.ShouldBeNull(); + } + + [Fact] + public void Activate_NormalizesRelativePath() + { + var holder = new ActiveWorkspaceHolder(); + var dir = Path.GetTempPath(); + + holder.Activate(dir); + + holder.ActiveCodebasePath.ShouldBe(Path.GetFullPath(dir)); + } +} diff --git a/ai-dev-net.tests.unit/AgentRunnerServiceTests.cs b/ai-dev-net.tests.unit/AgentRunnerServiceTests.cs index 25b51e3..7432af4 100644 --- a/ai-dev-net.tests.unit/AgentRunnerServiceTests.cs +++ b/ai-dev-net.tests.unit/AgentRunnerServiceTests.cs @@ -111,7 +111,7 @@ private static AgentRunnerService CreateRunner(WorkspacePaths paths, AtomicFileW new AgentStatusWriter(NullLogger.Instance), [executor], modelRegistry, - new AgentService(paths, new AgentTemplatesService(paths), fileWriter, new ProjectMutationCoordinator(), modelRegistry, NullLogger.Instance), + new AgentService(paths, new AgentTemplatesService(), fileWriter, new ProjectMutationCoordinator(), modelRegistry, NullLogger.Instance), new AgentPromptBuilder(new KbService(paths, fileWriter, new ProjectMutationCoordinator()), new PlaybookService(paths, fileWriter, new ProjectMutationCoordinator()), NullLogger.Instance), new SessionCompletionProcessor(paths, new BoardService(paths, dispatcher, fileWriter, new ProjectMutationCoordinator(), NullLogger.Instance, projectStateNotifier), new InsightsService([], settings, NullLogger.Instance), projectStateNotifier, NullLogger.Instance), new SecretsService(paths, fileWriter), diff --git a/ai-dev-net.tests.unit/AgentServiceTests.cs b/ai-dev-net.tests.unit/AgentServiceTests.cs index c9294e7..624a7be 100644 --- a/ai-dev-net.tests.unit/AgentServiceTests.cs +++ b/ai-dev-net.tests.unit/AgentServiceTests.cs @@ -7,7 +7,7 @@ public class AgentServiceTests [Fact] public void CreateAgent_WhenTemplateMissing_ReturnsError() { - var service = CreateService(out _); + var service = CreateService(out _, out _); var result = service.CreateAgent(new ProjectSlug("demo-project"), "backend-dev", "Backend Dev", "missing-template"); @@ -17,7 +17,7 @@ public void CreateAgent_WhenTemplateMissing_ReturnsError() [Fact] public void SaveAgentMeta_WhenAgentMissing_ReturnsError() { - var service = CreateService(out _); + var service = CreateService(out _, out _); var result = service.SaveAgentMeta(new ProjectSlug("demo-project"), new AgentSlug("backend-dev"), "Backend Dev", "Builds APIs", "sonnet", AgentExecutorName.Default); @@ -27,13 +27,9 @@ public void SaveAgentMeta_WhenAgentMissing_ReturnsError() [Fact] public void CreateAgent_WhenTemplateExists_ReturnsOk() { - var service = CreateService(out var paths); + var service = CreateService(out var paths, out var templatesDir); var projectSlug = new ProjectSlug("demo-project"); - var templateJsonPath = paths.SafeTemplatePath("generic-standard", ".json")!; - var templateMdPath = paths.SafeTemplatePath("generic-standard", ".md")!; - Directory.CreateDirectory(Path.GetDirectoryName(templateJsonPath.Value)!); - File.WriteAllText(templateJsonPath.Value, "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); - File.WriteAllText(templateMdPath.Value, "# Generic\n\nYou build features."); + WriteTemplate(templatesDir, "generic-standard"); var result = service.CreateAgent(projectSlug, "backend-dev", "Backend Dev", "generic-standard"); @@ -44,7 +40,7 @@ public void CreateAgent_WhenTemplateExists_ReturnsOk() [Fact] public void LoadAgent_WhenJsonContainsLastError_LoadsPersistedFailureState() { - var service = CreateService(out var paths); + var service = CreateService(out var paths, out _); var projectSlug = new ProjectSlug("demo-project"); var agentSlug = new AgentSlug("backend-dev"); var agentDir = paths.AgentDir(projectSlug, agentSlug); @@ -75,15 +71,9 @@ public void LoadAgent_WhenJsonContainsLastError_LoadsPersistedFailureState() [Fact] public void CreateAgent_WhenTemplateHasCompactContent_WritesCompactClaudeMd() { - var service = CreateService(out var paths); + var service = CreateService(out var paths, out var templatesDir); var projectSlug = new ProjectSlug("demo-project"); - var templateJsonPath = paths.SafeTemplatePath("generic-standard", ".json")!; - var templateMdPath = paths.SafeTemplatePath("generic-standard", ".md")!; - var templateCompactPath = paths.SafeTemplatePath("generic-standard", ".compact.md")!; - Directory.CreateDirectory(Path.GetDirectoryName(templateJsonPath.Value)!); - File.WriteAllText(templateJsonPath.Value, "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); - File.WriteAllText(templateMdPath.Value, "# Generic\n\nFull content."); - File.WriteAllText(templateCompactPath.Value, "# Generic\n\nCompact content."); + WriteTemplate(templatesDir, "generic-standard", compactContent: "# Generic\n\nCompact content."); service.CreateAgent(projectSlug, "backend-dev", "Backend Dev", "generic-standard"); @@ -96,13 +86,9 @@ public void CreateAgent_WhenTemplateHasCompactContent_WritesCompactClaudeMd() [Fact] public void CreateAgent_WhenTemplateHasNoCompactContent_DoesNotWriteCompactClaudeMd() { - var service = CreateService(out var paths); + var service = CreateService(out var paths, out var templatesDir); var projectSlug = new ProjectSlug("demo-project"); - var templateJsonPath = paths.SafeTemplatePath("generic-standard", ".json")!; - var templateMdPath = paths.SafeTemplatePath("generic-standard", ".md")!; - Directory.CreateDirectory(Path.GetDirectoryName(templateJsonPath.Value)!); - File.WriteAllText(templateJsonPath.Value, "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); - File.WriteAllText(templateMdPath.Value, "# Generic\n\nFull content."); + WriteTemplate(templatesDir, "generic-standard"); service.CreateAgent(projectSlug, "backend-dev", "Backend Dev", "generic-standard"); @@ -111,16 +97,27 @@ public void CreateAgent_WhenTemplateHasNoCompactContent_DoesNotWriteCompactClaud File.Exists(compactPath).ShouldBeFalse(); } - private static AgentService CreateService(out WorkspacePaths paths) + private static void WriteTemplate(string templatesDir, string slug, string? compactContent = null) + { + Directory.CreateDirectory(templatesDir); + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.json"), + "{\"slug\":\"generic-standard\",\"name\":\"Generic\",\"role\":\"Implement features\",\"model\":\"sonnet\",\"description\":\"Generalist\",\"content\":\"\"}"); + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.md"), "# Generic\n\nFull content."); + if (compactContent is not null) + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.compact.md"), compactContent); + } + + private static AgentService CreateService(out WorkspacePaths paths, out string templatesDir) { var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); paths = new WorkspacePaths(root); + templatesDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); var modelRegistry = Substitute.For(); modelRegistry.Find(Arg.Any(), Arg.Any()).Returns((ModelDescriptor?)null); modelRegistry.GetModelsForExecutor(Arg.Any()).Returns([]); return new AgentService( paths, - new AgentTemplatesService(paths), + new AgentTemplatesService(templatesDir), new AtomicFileWriter(), new ProjectMutationCoordinator(), modelRegistry, diff --git a/ai-dev-net.tests.unit/AgentTemplatesServiceTests.cs b/ai-dev-net.tests.unit/AgentTemplatesServiceTests.cs index 782e264..4e00060 100644 --- a/ai-dev-net.tests.unit/AgentTemplatesServiceTests.cs +++ b/ai-dev-net.tests.unit/AgentTemplatesServiceTests.cs @@ -2,27 +2,25 @@ namespace AiDevNet.Tests.Unit; public class AgentTemplatesServiceTests { - private static (AgentTemplatesService service, WorkspacePaths paths) CreateService() + private static (AgentTemplatesService service, string templatesDir) CreateService() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - return (new AgentTemplatesService(paths), paths); + var templatesDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + return (new AgentTemplatesService(templatesDir), templatesDir); } - private static void WriteTemplate(WorkspacePaths paths, string slug, string mdContent, string? compactContent = null) + private static void WriteTemplate(string templatesDir, string slug, string mdContent, string? compactContent = null) { - var dir = paths.AgentTemplatesDir.Value; - Directory.CreateDirectory(dir); - File.WriteAllText(Path.Combine(dir, $"{slug}.json"), + Directory.CreateDirectory(templatesDir); + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.json"), $"{{\"slug\":\"{slug}\",\"name\":\"Test\",\"role\":\"tester\",\"model\":\"sonnet\",\"description\":\"Test agent\",\"content\":\"\"}}"); - File.WriteAllText(Path.Combine(dir, $"{slug}.md"), mdContent); + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.md"), mdContent); if (compactContent is not null) - File.WriteAllText(Path.Combine(dir, $"{slug}.compact.md"), compactContent); + File.WriteAllText(Path.Combine(templatesDir, $"{slug}.compact.md"), compactContent); } - private static void WritePartial(WorkspacePaths paths, string partialKey, string content) + private static void WritePartial(string templatesDir, string partialKey, string content) { - var sharedDir = Path.Combine(paths.AgentTemplatesDir.Value, "shared"); + var sharedDir = Path.Combine(templatesDir, "shared"); Directory.CreateDirectory(sharedDir); var fileName = partialKey.Replace("shared/", "") + ".md"; File.WriteAllText(Path.Combine(sharedDir, fileName), content); @@ -31,9 +29,9 @@ private static void WritePartial(WorkspacePaths paths, string partialKey, string [Fact] public void GetTemplate_WithPartialIncludes_ComposesContentFromPartials() { - var (service, paths) = CreateService(); - WritePartial(paths, "shared/tools", "## Tools\nUse MCP."); - WriteTemplate(paths, "developer-standard", "# Developer\n\n{{> shared/tools}}\n\n## Workflow"); + var (service, templatesDir) = CreateService(); + WritePartial(templatesDir, "shared/tools", "## Tools\nUse MCP."); + WriteTemplate(templatesDir, "developer-standard", "# Developer\n\n{{> shared/tools}}\n\n## Workflow"); var template = service.GetTemplate("developer-standard"); @@ -45,8 +43,8 @@ public void GetTemplate_WithPartialIncludes_ComposesContentFromPartials() [Fact] public void GetTemplate_WithCompactFile_PopulatesCompactContent() { - var (service, paths) = CreateService(); - WriteTemplate(paths, "developer-standard", + var (service, templatesDir) = CreateService(); + WriteTemplate(templatesDir, "developer-standard", mdContent: "# Developer\n\nFull content.", compactContent: "# Developer\n\nCompact content."); @@ -59,8 +57,8 @@ public void GetTemplate_WithCompactFile_PopulatesCompactContent() [Fact] public void GetTemplate_WithoutCompactFile_CompactContentIsEmpty() { - var (service, paths) = CreateService(); - WriteTemplate(paths, "developer-standard", mdContent: "# Developer\n\nFull content."); + var (service, templatesDir) = CreateService(); + WriteTemplate(templatesDir, "developer-standard", mdContent: "# Developer\n\nFull content."); var template = service.GetTemplate("developer-standard"); diff --git a/ai-dev-net.tests.unit/ConsistencyCheckServiceTests.cs b/ai-dev-net.tests.unit/ConsistencyCheckServiceTests.cs index 10d82ad..7d48687 100644 --- a/ai-dev-net.tests.unit/ConsistencyCheckServiceTests.cs +++ b/ai-dev-net.tests.unit/ConsistencyCheckServiceTests.cs @@ -7,15 +7,10 @@ public class ConsistencyCheckServiceTests [Fact] public async Task CheckProjectAsync_WhenBoardIsMissingDefaultColumn_ReturnsWarning() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var taskId = TaskId.New(); var board = new Board( @@ -36,15 +31,10 @@ [new BoardColumn(ColumnId.Backlog, "Backlog")], [Fact] public async Task CheckProjectAsync_WhenDecisionStatusMismatchesDirectory_ReturnsWarning() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); Directory.CreateDirectory(paths.DecisionsPendingDir(projectSlug)); File.WriteAllText(Path.Combine(paths.DecisionsPendingDir(projectSlug), "20260101-000000-test.md"), "---\nstatus: resolved\nsubject: Test\nfrom: overwatch\npriority: normal\n---\n\nBody"); @@ -54,39 +44,13 @@ public async Task CheckProjectAsync_WhenDecisionStatusMismatchesDirectory_Return report.Findings.ShouldContain(f => f.Code == "DECISION_STATUS_DIRECTORY_MISMATCH"); } - [Fact] - public async Task CheckWorkspaceAsync_WithMultipleProjects_ChecksAll() - { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); - var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); - var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - - workspace.CreateProject("project1", "Project 1", null).ShouldBeOfType>(); - workspace.CreateProject("project2", "Project 2", null).ShouldBeOfType>(); - - var report = await service.CheckWorkspaceAsync(TestContext.Current.CancellationToken); - - report.Projects.Count.ShouldBe(2); - report.Projects[0].ProjectSlug.Value.ShouldBe("project1"); - report.Projects[1].ProjectSlug.Value.ShouldBe("project2"); - } - [Fact] public async Task CheckProjectAsync_WithValidBoardAndDecisions_ReturnsSuccess() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var board = new Board( projectSlug, @@ -109,18 +73,12 @@ public async Task CheckProjectAsync_WithValidBoardAndDecisions_ReturnsSuccess() [Fact] public async Task CheckProjectAsync_WhenBoardReadFails_ReportsError() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); - // Create an invalid board.json file (malformed JSON) var boardPath = paths.BoardPath(projectSlug); Directory.CreateDirectory(Path.GetDirectoryName(boardPath.Value)!); File.WriteAllText(boardPath.Value, "{ not valid json"); @@ -134,20 +92,14 @@ public async Task CheckProjectAsync_WhenBoardReadFails_ReportsError() [Fact] public async Task CheckProjectAsync_WhenDecisionReadFails_ReportsError() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var resolvedDir = paths.DecisionsResolvedDir(projectSlug); Directory.CreateDirectory(resolvedDir.Value); - // Create a decision file with invalid YAML that will cause parse failure var decisionContent = @"--- title: Test status: {invalid: yaml: structure @@ -157,27 +109,20 @@ public async Task CheckProjectAsync_WhenDecisionReadFails_ReportsError() var report = await service.CheckProjectAsync(projectSlug, TestContext.Current.CancellationToken); - // Should either report a parse failure or handle it gracefully report.Findings.ShouldNotBeNull(); } [Fact] public async Task CheckProjectAsync_WhenOrphanedTaskInBoard_MovesToBacklog() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var orphanedTaskId = TaskId.New(); var task = new BoardTask(orphanedTaskId, "Orphaned Task"); - // Board has the task but it's not assigned to any column var board = new Board( projectSlug, new List @@ -198,15 +143,10 @@ public async Task CheckProjectAsync_WhenOrphanedTaskInBoard_MovesToBacklog() [Fact] public async Task CheckProjectAsync_WhenTaskDuplicateInMultipleColumns_RemovesDuplicate() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var sharedTaskId = TaskId.New(); var task = new BoardTask(sharedTaskId, "Shared Task"); @@ -230,15 +170,10 @@ public async Task CheckProjectAsync_WhenTaskDuplicateInMultipleColumns_RemovesDu [Fact] public async Task CheckProjectAsync_IgnoresNonMarkdownFilesInDecisions() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - var paths = new WorkspacePaths(root); - var writer = new AtomicFileWriter(); - var workspace = new WorkspaceService(paths, writer); + var (paths, workspace) = CreateServices(); var coordinator = new ProjectMutationCoordinator(); - var boardService = new BoardService(paths, new PassingDispatcher(), writer, coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); + var boardService = new BoardService(paths, new PassingDispatcher(), new AtomicFileWriter(), coordinator, NullLogger.Instance, new ProjectStateChangedNotifier()); var service = new ConsistencyCheckService(paths, workspace, boardService, NullLogger.Instance); - workspace.CreateProject("demo-project", "Demo Project", null).ShouldBeOfType>(); - var projectSlug = new ProjectSlug("demo-project"); var pendingDir = paths.DecisionsPendingDir(projectSlug); Directory.CreateDirectory(pendingDir.Value); @@ -251,10 +186,20 @@ public async Task CheckProjectAsync_IgnoresNonMarkdownFilesInDecisions() report.Findings.Where(f => f.Code.StartsWith("DECISION")).ShouldBeEmpty(); } + private static (WorkspacePaths paths, WorkspaceService workspace) CreateServices() + { + var codebasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(codebasePath); + var holder = new ActiveWorkspaceHolder(); + holder.Activate(codebasePath); + var workspace = new WorkspaceService(holder, new AtomicFileWriter()); + workspace.CreateProject(codebasePath, "demo-project", "Demo Project", null).ShouldBeOfType>(); + return (holder.Paths, workspace); + } + private sealed class PassingDispatcher : IDomainEventDispatcher { public Task> Dispatch(IReadOnlyList events, CancellationToken ct = default) => Task.FromResult>(new Ok(AiDev.Models.Unit.Value)); } } - diff --git a/ai-dev-net.tests.unit/DecisionChatServiceTests.cs b/ai-dev-net.tests.unit/DecisionChatServiceTests.cs index 6d23c7a..96ae9ca 100644 --- a/ai-dev-net.tests.unit/DecisionChatServiceTests.cs +++ b/ai-dev-net.tests.unit/DecisionChatServiceTests.cs @@ -187,7 +187,7 @@ private static AgentRunnerService CreateRunner(WorkspacePaths paths, AtomicFileW new AgentStatusWriter(NullLogger.Instance), [new ImmediateExecutor()], modelRegistry, - new AgentService(paths, new AgentTemplatesService(paths), fileWriter, new ProjectMutationCoordinator(), modelRegistry, NullLogger.Instance), + new AgentService(paths, new AgentTemplatesService(), fileWriter, new ProjectMutationCoordinator(), modelRegistry, NullLogger.Instance), new AgentPromptBuilder(new KbService(paths, fileWriter, new ProjectMutationCoordinator()), new PlaybookService(paths, fileWriter, new ProjectMutationCoordinator()), NullLogger.Instance), new SessionCompletionProcessor(paths, new BoardService(paths, dispatcher, fileWriter, new ProjectMutationCoordinator(), NullLogger.Instance, projectStateNotifier), new InsightsService([], settings, NullLogger.Instance), projectStateNotifier, NullLogger.Instance), new SecretsService(paths, fileWriter), diff --git a/ai-dev-net.tests.unit/DigestServiceTests.cs b/ai-dev-net.tests.unit/DigestServiceTests.cs index 957e276..1138d92 100644 --- a/ai-dev-net.tests.unit/DigestServiceTests.cs +++ b/ai-dev-net.tests.unit/DigestServiceTests.cs @@ -240,7 +240,7 @@ private static DigestService CreateService(out WorkspacePaths paths) modelRegistry.Find(Arg.Any(), Arg.Any()).Returns((ModelDescriptor?)null); var agentService = new AgentService( paths, - new AgentTemplatesService(paths), + new AgentTemplatesService(), new AtomicFileWriter(), new ProjectMutationCoordinator(), modelRegistry, diff --git a/ai-dev-net.tests.unit/GlobalUsings.cs b/ai-dev-net.tests.unit/GlobalUsings.cs index 0aab773..b281bdb 100644 --- a/ai-dev-net.tests.unit/GlobalUsings.cs +++ b/ai-dev-net.tests.unit/GlobalUsings.cs @@ -2,6 +2,7 @@ global using AiDev.Executors; global using AiDev.Features.Agent; global using AiDev.Features.Planning; +global using AiDev.Features.Workspace; global using AiDev.Models; global using AiDev.Models.Types; global using AiDev.Services; diff --git a/ai-dev-net.tests.unit/ProjectConfigReaderTests.cs b/ai-dev-net.tests.unit/ProjectConfigReaderTests.cs new file mode 100644 index 0000000..a715d4a --- /dev/null +++ b/ai-dev-net.tests.unit/ProjectConfigReaderTests.cs @@ -0,0 +1,124 @@ +namespace AiDevNet.Tests.Unit; + +public class ProjectConfigReaderTests +{ + [Fact] + public void TryRead_WhenConfigFileExists_ReturnsProjectConfig() + { + var dir = TempDir(); + WriteConfig(dir, projectSlug: "my-app", apiPort: 5100); + + var result = ProjectConfigReader.TryRead(dir); + + result.ShouldNotBeNull(); + result!.ProjectSlug.ShouldBe("my-app"); + result.ApiPort.ShouldBe(5100); + } + + [Fact] + public void TryRead_WhenConfigFileAbsent_ReturnsNull() + { + var dir = TempDir(); + + var result = ProjectConfigReader.TryRead(dir); + + result.ShouldBeNull(); + } + + [Fact] + public void TryRead_WhenConfigFileMalformed_ReturnsNull() + { + var dir = TempDir(); + WriteRawConfig(dir, "{ not valid json }"); + + var result = ProjectConfigReader.TryRead(dir); + + result.ShouldBeNull(); + } + + [Fact] + public void TryRead_WhenConfigFileMissingRequiredFields_ReturnsNull() + { + var dir = TempDir(); + WriteRawConfig(dir, "{}"); + + var result = ProjectConfigReader.TryRead(dir); + + result.ShouldBeNull(); + } + + [Fact] + public void TryReadFull_WhenConfigHasExtendedFields_ReturnsAllFields() + { + var dir = TempDir(); + var aiDevDir = Path.Combine(dir, ".ai-dev"); + Directory.CreateDirectory(aiDevDir); + File.WriteAllText(Path.Combine(aiDevDir, "project.json"), + """{"projectSlug":"my-app","apiPort":5100,"name":"My App","description":"A test project","createdAt":"2026-01-01T00:00:00Z"}"""); + + var result = ProjectConfigReader.TryReadFull(dir); + + result.ShouldNotBeNull(); + result!.ProjectSlug.ShouldBe("my-app"); + result.ApiPort.ShouldBe(5100); + result.Name.ShouldBe("My App"); + result.Description.ShouldBe("A test project"); + result.CreatedAt.ShouldNotBeNull(); + } + + [Fact] + public void TryReadFull_WhenOnlyMinimalFields_ReturnsConfigWithNullOptionals() + { + var dir = TempDir(); + WriteConfig(dir, projectSlug: "my-app", apiPort: 5100); + + var result = ProjectConfigReader.TryReadFull(dir); + + result.ShouldNotBeNull(); + result!.ProjectSlug.ShouldBe("my-app"); + result.Name.ShouldBeNull(); + result.Description.ShouldBeNull(); + } + + [Fact] + public void WorkspacePaths_WhenConfigPresent_UsesAiDevSubdirectoryAsRoot() + { + var dir = TempDir(); + WriteConfig(dir, projectSlug: "my-app", apiPort: 5100); + + var paths = ProjectConfigReader.CreateWorkspacePaths(dir, fallback: null); + + var expectedRoot = Path.Combine(dir, ".ai-dev"); + paths.Root.Value.ShouldBe(expectedRoot); + } + + [Fact] + public void WorkspacePaths_WhenConfigAbsent_UsesFallbackRoot() + { + var dir = TempDir(); + var fallback = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); + + var paths = ProjectConfigReader.CreateWorkspacePaths(dir, fallback); + + paths.Root.ShouldBe(fallback); + } + + private static string TempDir() => + Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + + private static void WriteConfig(string dir, string projectSlug, int apiPort) + { + var aiDevDir = Path.Combine(dir, ".ai-dev"); + Directory.CreateDirectory(aiDevDir); + File.WriteAllText( + Path.Combine(aiDevDir, "project.json"), + $$"""{"projectSlug":"{{projectSlug}}","apiPort":{{apiPort}}}"""); + } + + private static void WriteRawConfig(string dir, string content) + { + var aiDevDir = Path.Combine(dir, ".ai-dev"); + Directory.CreateDirectory(aiDevDir); + File.WriteAllText(Path.Combine(aiDevDir, "project.json"), content); + } +} diff --git a/ai-dev-net.tests.unit/SecretsServiceTests.cs b/ai-dev-net.tests.unit/SecretsServiceTests.cs index 54a8780..3589f89 100644 --- a/ai-dev-net.tests.unit/SecretsServiceTests.cs +++ b/ai-dev-net.tests.unit/SecretsServiceTests.cs @@ -198,20 +198,20 @@ public void ListSecrets_AfterDeleteSecret_NoLongerIncludes() } [Fact] - public void Secrets_AreSeparatePerProject() + public void Secrets_AreSeparatePerWorkspace() { - var service = CreateService(out _); - var project1 = new ProjectSlug("project-1"); - var project2 = new ProjectSlug("project-2"); - - service.SetSecret(project1, "key", "value1"); - service.SetSecret(project2, "key", "value2"); + // Each workspace is a separate .ai-dev root — isolation is at the workspace level. + var root1 = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); + var root2 = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); + var service1 = new SecretsService(new WorkspacePaths(root1), new AtomicFileWriter()); + var service2 = new SecretsService(new WorkspacePaths(root2), new AtomicFileWriter()); + var slug = new ProjectSlug("my-project"); - var secrets1 = service.LoadDecryptedSecrets(project1); - var secrets2 = service.LoadDecryptedSecrets(project2); + service1.SetSecret(slug, "key", "value1"); + service2.SetSecret(slug, "key", "value2"); - secrets1["key"].ShouldBe("value1"); - secrets2["key"].ShouldBe("value2"); + service1.LoadDecryptedSecrets(slug)["key"].ShouldBe("value1"); + service2.LoadDecryptedSecrets(slug)["key"].ShouldBe("value2"); } [Fact] diff --git a/ai-dev-net.tests.unit/WorkspaceServiceTests.cs b/ai-dev-net.tests.unit/WorkspaceServiceTests.cs index b31e5b3..0e138cc 100644 --- a/ai-dev-net.tests.unit/WorkspaceServiceTests.cs +++ b/ai-dev-net.tests.unit/WorkspaceServiceTests.cs @@ -5,9 +5,9 @@ public class WorkspaceServiceTests [Fact] public void CreateProject_WhenSlugInvalid_ReturnsError() { - var service = CreateService(out _); + var (service, codebasePath) = CreateService(); - var result = service.CreateProject("Invalid Slug", "Demo", null); + var result = service.CreateProject(codebasePath, "Invalid Slug", "Demo", null); result.ShouldBeOfType>(); } @@ -15,28 +15,31 @@ public void CreateProject_WhenSlugInvalid_ReturnsError() [Fact] public void CreateProject_WhenValid_ReturnsOk() { - var service = CreateService(out var paths); + var (service, codebasePath) = CreateService(); + var paths = new WorkspacePaths(new RootDir(Path.Combine(codebasePath, ".ai-dev"))); - var result = service.CreateProject("demo-project", "Demo Project", "Main app"); + var result = service.CreateProject(codebasePath, "demo-project", "Demo Project", "Main app"); result.ShouldBeOfType>(); - File.Exists(paths.ProjectJsonPath(new ProjectSlug("demo-project"))).ShouldBeTrue(); + paths.ProjectJsonPath(new ProjectSlug("demo-project")).Exists().ShouldBeTrue(); } [Fact] public void UpdateProject_WhenMissing_ReturnsError() { - var service = CreateService(out _); + var (service, codebasePath) = CreateService(); - var result = service.UpdateProject(new ProjectSlug("demo-project"), "Demo Project", null, null); + var result = service.UpdateProject(new ProjectSlug("demo-project"), "Demo Project", null); result.ShouldBeOfType>(); } - private static WorkspaceService CreateService(out WorkspacePaths paths) + private static (WorkspaceService service, string codebasePath) CreateService() { - var root = new RootDir(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); - paths = new WorkspacePaths(root); - return new WorkspaceService(paths, new AtomicFileWriter()); + var codebasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(codebasePath); + var holder = new ActiveWorkspaceHolder(); + holder.Activate(codebasePath); + return (new WorkspaceService(holder, new AtomicFileWriter()), codebasePath); } } diff --git a/ai-dev-vscode/.vscodeignore b/ai-dev-vscode/.vscodeignore new file mode 100644 index 0000000..074b47e --- /dev/null +++ b/ai-dev-vscode/.vscodeignore @@ -0,0 +1,11 @@ +src/** +out/** +node_modules/** +scripts/** +.vscode/** +.vs/** +esbuild.mjs +jest.config.js +tsconfig.json +**/*.map +**/*.test.ts diff --git a/ai-dev-vscode/LICENSE b/ai-dev-vscode/LICENSE new file mode 100644 index 0000000..12c0b79 --- /dev/null +++ b/ai-dev-vscode/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 JJS Waste + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ai-dev-vscode/README.md b/ai-dev-vscode/README.md new file mode 100644 index 0000000..331160e --- /dev/null +++ b/ai-dev-vscode/README.md @@ -0,0 +1,104 @@ +# AI Dev Studio + +AI Dev Studio is a VS Code extension that provides a live sidebar for monitoring and controlling AI agent workflows running on your local machine. It automatically detects AI Dev Studio projects in your workspace, starts the backend API, and keeps three panels in sync via real-time SignalR updates. + +--- + +## Features + +### Agents panel + +Lists every agent configured for the current project, showing whether each one is running or rate-limited. You can start or stop any agent directly from the panel without leaving your editor. + +### Messages panel + +Shows unprocessed inbox messages queued for each agent. Badge counts on the panel tab give you an at-a-glance count. You can trigger processing of a message from the panel. + +### Decisions panel + +Lists pending decisions that are blocking agent progress. Badge counts highlight how many decisions are waiting. You can submit a resolution inline, unblocking the relevant agent immediately. + +### Status bar + +A status bar item in the bottom-left corner shows the current backend state — **Starting**, **Running**, or **Disconnected**. Clicking it triggers a backend restart. + +--- + +## Requirements + +- VS Code 1.90 or later +- An AI Dev Studio project with a `.ai-dev/project.json` file in the workspace root + +The extension bundles the backend API binary. No separate installation is required. + +--- + +## Getting started + +1. Open a folder (or workspace) that contains a `.ai-dev/project.json` file. +2. The extension detects the project automatically and starts the backend on the configured port. +3. The **AI Dev Studio** activity bar icon appears. Click it to open the Agents, Messages, and Decisions panels. + +### project.json format + +The extension reads `.ai-dev/project.json` from your workspace root: + +```json +{ + "projectSlug": "my-project", + "apiPort": 5100 +} +``` + +| Field | Description | +|---|---| +| `projectSlug` | Unique identifier for the project. Used to scope all API and SignalR calls. | +| `apiPort` | Port the backend API will listen on. | + +--- + +## Commands + +| Command | Description | +|---|---| +| `AI Dev: Restart Backend` | Tears down the current backend process and SignalR connection, then rescans the workspace and reconnects. | + +--- + +## How it works + +1. On activation, `WorkspaceDetector` watches for `.ai-dev/project.json` in each open workspace folder. +2. When a config file is found, `BackendProcessManager` spawns the bundled platform binary (`bin/ai-dev-api.exe` on Windows, `bin/ai-dev-api` on macOS/Linux) and polls `/api/health` until the backend is ready (up to 30 attempts, 1 s apart). +3. If the binary is absent (development mode), the extension skips spawning and connects to a backend that is already running on the configured port. +4. `StudioSignalRClient` connects to `/hubs/project` and joins the project room. `StateChanged` events from the hub drive incremental refreshes of each panel — only the affected panel fetches new data. +5. REST calls through `StudioApiClient` handle all reads and writes (list agents, run/stop, list messages, process, list decisions, resolve). + +--- + +## Development + +```bash +# Install dependencies +cd ai-dev-vscode +npm install + +# Build once +npm run build + +# Watch mode +npm run watch + +# Run tests +npm test + +# Package VSIX +npm run package +``` + +To test against a live backend, run the `ai-dev.api` project externally on the port matching your `.ai-dev/project.json`, then press **F5** in VS Code to launch the extension in the Extension Development Host. + +--- + +## License + +MIT — see [LICENSE](LICENSE). diff --git a/ai-dev-vscode/dist/extension.js b/ai-dev-vscode/dist/extension.js new file mode 100644 index 0000000..c4c9506 --- /dev/null +++ b/ai-dev-vscode/dist/extension.js @@ -0,0 +1,28 @@ +"use strict";var Ln=Object.create;var ue=Object.defineProperty;var Pn=Object.getOwnPropertyDescriptor;var Tn=Object.getOwnPropertyNames;var kn=Object.getPrototypeOf,En=Object.prototype.hasOwnProperty;var p=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),In=(r,e)=>{for(var t in e)ue(r,t,{get:e[t],enumerable:!0})},Rt=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Tn(e))!En.call(r,o)&&o!==t&&ue(r,o,{get:()=>e[o],enumerable:!(n=Pn(e,o))||n.enumerable});return r};var D=(r,e,t)=>(t=r!=null?Ln(kn(r)):{},Rt(e||!r||!r.__esModule?ue(t,"default",{value:r,enumerable:!0}):t,r)),Dn=r=>Rt(ue({},"__esModule",{value:!0}),r);var A=p(y=>{"use strict";Object.defineProperty(y,"__esModule",{value:!0});y.AggregateErrors=y.FailedToNegotiateWithServerError=y.FailedToStartTransportError=y.DisabledTransportError=y.UnsupportedTransportError=y.AbortError=y.TimeoutError=y.HttpError=void 0;var Ve=class extends Error{constructor(e,t){let n=new.target.prototype;super(`${e}: Status code '${t}'`),this.statusCode=t,this.__proto__=n}};y.HttpError=Ve;var Je=class extends Error{constructor(e="A timeout occurred."){let t=new.target.prototype;super(e),this.__proto__=t}};y.TimeoutError=Je;var Xe=class extends Error{constructor(e="An abort occurred."){let t=new.target.prototype;super(e),this.__proto__=t}};y.AbortError=Xe;var Ke=class extends Error{constructor(e,t){let n=new.target.prototype;super(e),this.transport=t,this.errorType="UnsupportedTransportError",this.__proto__=n}};y.UnsupportedTransportError=Ke;var Ge=class extends Error{constructor(e,t){let n=new.target.prototype;super(e),this.transport=t,this.errorType="DisabledTransportError",this.__proto__=n}};y.DisabledTransportError=Ge;var Ye=class extends Error{constructor(e,t){let n=new.target.prototype;super(e),this.transport=t,this.errorType="FailedToStartTransportError",this.__proto__=n}};y.FailedToStartTransportError=Ye;var Qe=class extends Error{constructor(e){let t=new.target.prototype;super(e),this.errorType="FailedToNegotiateWithServerError",this.__proto__=t}};y.FailedToNegotiateWithServerError=Qe;var Ze=class extends Error{constructor(e,t){let n=new.target.prototype;super(e),this.innerErrors=t,this.__proto__=n}};y.AggregateErrors=Ze});var K=p(X=>{"use strict";Object.defineProperty(X,"__esModule",{value:!0});X.HttpClient=X.HttpResponse=void 0;var et=class{constructor(e,t,n){this.statusCode=e,this.statusText=t,this.content=n}};X.HttpResponse=et;var tt=class{get(e,t){return this.send({...t,method:"GET",url:e})}post(e,t){return this.send({...t,method:"POST",url:e})}delete(e,t){return this.send({...t,method:"DELETE",url:e})}getCookieString(e){return""}};X.HttpClient=tt});var P=p(ne=>{"use strict";Object.defineProperty(ne,"__esModule",{value:!0});ne.LogLevel=void 0;var Mn;(function(r){r[r.Trace=0]="Trace",r[r.Debug=1]="Debug",r[r.Information=2]="Information",r[r.Warning=3]="Warning",r[r.Error=4]="Error",r[r.Critical=5]="Critical",r[r.None=6]="None"})(Mn=ne.LogLevel||(ne.LogLevel={}))});var re=p(me=>{"use strict";Object.defineProperty(me,"__esModule",{value:!0});me.NullLogger=void 0;var oe=class{constructor(){}log(e,t){}};me.NullLogger=oe;oe.instance=new oe});var xt=p(be=>{"use strict";Object.defineProperty(be,"__esModule",{value:!0});be.VERSION=void 0;be.VERSION="10.0.0"});var L=p(g=>{"use strict";Object.defineProperty(g,"__esModule",{value:!0});g.getGlobalThis=g.getErrorString=g.constructUserAgent=g.getUserAgentHeader=g.ConsoleLogger=g.SubjectSubscription=g.createLogger=g.sendMessage=g.isArrayBuffer=g.formatArrayBuffer=g.getDataDetail=g.Platform=g.Arg=g.VERSION=void 0;var $=P(),Hn=re(),jt=xt();Object.defineProperty(g,"VERSION",{enumerable:!0,get:function(){return jt.VERSION}});var nt=class{static isRequired(e,t){if(e==null)throw new Error(`The '${t}' argument is required.`)}static isNotEmpty(e,t){if(!e||e.match(/^\s*$/))throw new Error(`The '${t}' argument should not be empty.`)}static isIn(e,t,n){if(!(e in t))throw new Error(`Unknown ${n} value: ${e}.`)}};g.Arg=nt;var q=class r{static get isBrowser(){return!r.isNode&&typeof window=="object"&&typeof window.document=="object"}static get isWebWorker(){return!r.isNode&&typeof self=="object"&&"importScripts"in self}static get isReactNative(){return!r.isNode&&typeof window=="object"&&typeof window.document>"u"}static get isNode(){return typeof process<"u"&&process.release&&process.release.name==="node"}};g.Platform=q;function Wt(r,e){let t="";return rt(r)?(t=`Binary data of length ${r.byteLength}`,e&&(t+=`. Content: '${Ft(r)}'`)):typeof r=="string"&&(t=`String data of length ${r.length}`,e&&(t+=`. Content: '${r}'`)),t}g.getDataDetail=Wt;function Ft(r){let e=new Uint8Array(r),t="";return e.forEach(n=>{let o=n<16?"0":"";t+=`0x${o}${n.toString(16)} `}),t.substring(0,t.length-1)}g.formatArrayBuffer=Ft;function rt(r){return r&&typeof ArrayBuffer<"u"&&(r instanceof ArrayBuffer||r.constructor&&r.constructor.name==="ArrayBuffer")}g.isArrayBuffer=rt;async function Rn(r,e,t,n,o,s){let i={},[a,c]=Ot();i[a]=c,r.log($.LogLevel.Trace,`(${e} transport) sending data. ${Wt(o,s.logMessageContent)}.`);let h=rt(o)?"arraybuffer":"text",l=await t.post(n,{content:o,headers:{...i,...s.headers},responseType:h,timeout:s.timeout,withCredentials:s.withCredentials});r.log($.LogLevel.Trace,`(${e} transport) request complete. Response status: ${l.statusCode}.`)}g.sendMessage=Rn;function An(r){return r===void 0?new se($.LogLevel.Information):r===null?Hn.NullLogger.instance:r.log!==void 0?r:new se(r)}g.createLogger=An;var ot=class{constructor(e,t){this._subject=e,this._observer=t}dispose(){let e=this._subject.observers.indexOf(this._observer);e>-1&&this._subject.observers.splice(e,1),this._subject.observers.length===0&&this._subject.cancelCallback&&this._subject.cancelCallback().catch(t=>{})}};g.SubjectSubscription=ot;var se=class{constructor(e){this._minLevel=e,this.out=console}log(e,t){if(e>=this._minLevel){let n=`[${new Date().toISOString()}] ${$.LogLevel[e]}: ${t}`;switch(e){case $.LogLevel.Critical:case $.LogLevel.Error:this.out.error(n);break;case $.LogLevel.Warning:this.out.warn(n);break;case $.LogLevel.Information:this.out.info(n);break;default:this.out.log(n);break}}}};g.ConsoleLogger=se;function Ot(){let r="X-SignalR-User-Agent";return q.isNode&&(r="User-Agent"),[r,Ut(jt.VERSION,$n(),jn(),xn())]}g.getUserAgentHeader=Ot;function Ut(r,e,t,n){let o="Microsoft SignalR/",s=r.split(".");return o+=`${s[0]}.${s[1]}`,o+=` (${r}; `,e&&e!==""?o+=`${e}; `:o+="Unknown OS; ",o+=`${t}`,n?o+=`; ${n}`:o+="; Unknown Runtime Version",o+=")",o}g.constructUserAgent=Ut;function $n(){if(q.isNode)switch(process.platform){case"win32":return"Windows NT";case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}else return""}function xn(){if(q.isNode)return process.versions.node}function jn(){return q.isNode?"NodeJS":"Browser"}function Wn(r){return r.stack?r.stack:r.message?r.message:`${r}`}g.getErrorString=Wn;function Fn(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global;throw new Error("could not find global")}g.getGlobalThis=Fn});var zt=p(Se=>{"use strict";Object.defineProperty(Se,"__esModule",{value:!0});Se.FetchHttpClient=void 0;var ye=A(),qt=K(),Bt=P(),we=L(),st=class extends qt.HttpClient{constructor(e){if(super(),this._logger=e,typeof fetch>"u"||we.Platform.isNode){let t=typeof __webpack_require__=="function"?__non_webpack_require__:require;this._jar=new(t("tough-cookie")).CookieJar,typeof fetch>"u"?this._fetchType=t("node-fetch"):this._fetchType=fetch,this._fetchType=t("fetch-cookie")(this._fetchType,this._jar)}else this._fetchType=fetch.bind((0,we.getGlobalThis)());if(typeof AbortController>"u"){let t=typeof __webpack_require__=="function"?__non_webpack_require__:require;this._abortControllerType=t("abort-controller")}else this._abortControllerType=AbortController}async send(e){if(e.abortSignal&&e.abortSignal.aborted)throw new ye.AbortError;if(!e.method)throw new Error("No method defined.");if(!e.url)throw new Error("No url defined.");let t=new this._abortControllerType,n;e.abortSignal&&(e.abortSignal.onabort=()=>{t.abort(),n=new ye.AbortError});let o=null;if(e.timeout){let c=e.timeout;o=setTimeout(()=>{t.abort(),this._logger.log(Bt.LogLevel.Warning,"Timeout from HTTP request."),n=new ye.TimeoutError},c)}e.content===""&&(e.content=void 0),e.content&&(e.headers=e.headers||{},(0,we.isArrayBuffer)(e.content)?e.headers["Content-Type"]="application/octet-stream":e.headers["Content-Type"]="text/plain;charset=UTF-8");let s;try{s=await this._fetchType(e.url,{body:e.content,cache:"no-cache",credentials:e.withCredentials===!0?"include":"same-origin",headers:{"X-Requested-With":"XMLHttpRequest",...e.headers},method:e.method,mode:"cors",redirect:"follow",signal:t.signal})}catch(c){throw n||(this._logger.log(Bt.LogLevel.Warning,`Error from HTTP request. ${c}.`),c)}finally{o&&clearTimeout(o),e.abortSignal&&(e.abortSignal.onabort=null)}if(!s.ok){let c=await Nt(s,"text");throw new ye.HttpError(c||s.statusText,s.status)}let a=await Nt(s,e.responseType);return new qt.HttpResponse(s.status,s.statusText,a)}getCookieString(e){let t="";return we.Platform.isNode&&this._jar&&this._jar.getCookies(e,(n,o)=>t=o.join("; ")),t}};Se.FetchHttpClient=st;function Nt(r,e){let t;switch(e){case"arraybuffer":t=r.arrayBuffer();break;case"text":t=r.text();break;case"blob":case"document":case"json":throw new Error(`${e} is not supported.`);default:t=r.text();break}return t}});var Xt=p(Ce=>{"use strict";Object.defineProperty(Ce,"__esModule",{value:!0});Ce.XhrHttpClient=void 0;var ie=A(),Vt=K(),Jt=P(),On=L(),it=class extends Vt.HttpClient{constructor(e){super(),this._logger=e}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new ie.AbortError):e.method?e.url?new Promise((t,n)=>{let o=new XMLHttpRequest;o.open(e.method,e.url,!0),o.withCredentials=e.withCredentials===void 0?!0:e.withCredentials,o.setRequestHeader("X-Requested-With","XMLHttpRequest"),e.content===""&&(e.content=void 0),e.content&&((0,On.isArrayBuffer)(e.content)?o.setRequestHeader("Content-Type","application/octet-stream"):o.setRequestHeader("Content-Type","text/plain;charset=UTF-8"));let s=e.headers;s&&Object.keys(s).forEach(i=>{o.setRequestHeader(i,s[i])}),e.responseType&&(o.responseType=e.responseType),e.abortSignal&&(e.abortSignal.onabort=()=>{o.abort(),n(new ie.AbortError)}),e.timeout&&(o.timeout=e.timeout),o.onload=()=>{e.abortSignal&&(e.abortSignal.onabort=null),o.status>=200&&o.status<300?t(new Vt.HttpResponse(o.status,o.statusText,o.response||o.responseText)):n(new ie.HttpError(o.response||o.responseText||o.statusText,o.status))},o.onerror=()=>{this._logger.log(Jt.LogLevel.Warning,`Error from HTTP request. ${o.status}: ${o.statusText}.`),n(new ie.HttpError(o.statusText,o.status))},o.ontimeout=()=>{this._logger.log(Jt.LogLevel.Warning,"Timeout from HTTP request."),n(new ie.TimeoutError)},o.send(e.content)}):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}};Ce.XhrHttpClient=it});var ct=p(Le=>{"use strict";Object.defineProperty(Le,"__esModule",{value:!0});Le.DefaultHttpClient=void 0;var Un=A(),qn=zt(),Bn=K(),Nn=L(),zn=Xt(),at=class extends Bn.HttpClient{constructor(e){if(super(),typeof fetch<"u"||Nn.Platform.isNode)this._httpClient=new qn.FetchHttpClient(e);else if(typeof XMLHttpRequest<"u")this._httpClient=new zn.XhrHttpClient(e);else throw new Error("No usable HttpClient found.")}send(e){return e.abortSignal&&e.abortSignal.aborted?Promise.reject(new Un.AbortError):e.method?e.url?this._httpClient.send(e):Promise.reject(new Error("No url defined.")):Promise.reject(new Error("No method defined."))}getCookieString(e){return this._httpClient.getCookieString(e)}};Le.DefaultHttpClient=at});var lt=p(Pe=>{"use strict";Object.defineProperty(Pe,"__esModule",{value:!0});Pe.TextMessageFormat=void 0;var G=class r{static write(e){return`${e}${r.RecordSeparator}`}static parse(e){if(e[e.length-1]!==r.RecordSeparator)throw new Error("Message is incomplete.");let t=e.split(r.RecordSeparator);return t.pop(),t}};Pe.TextMessageFormat=G;G.RecordSeparatorCode=30;G.RecordSeparator=String.fromCharCode(G.RecordSeparatorCode)});var Kt=p(ke=>{"use strict";Object.defineProperty(ke,"__esModule",{value:!0});ke.HandshakeProtocol=void 0;var Te=lt(),Vn=L(),ht=class{writeHandshakeRequest(e){return Te.TextMessageFormat.write(JSON.stringify(e))}parseHandshakeResponse(e){let t,n;if((0,Vn.isArrayBuffer)(e)){let a=new Uint8Array(e),c=a.indexOf(Te.TextMessageFormat.RecordSeparatorCode);if(c===-1)throw new Error("Message is incomplete.");let h=c+1;t=String.fromCharCode.apply(null,Array.prototype.slice.call(a.slice(0,h))),n=a.byteLength>h?a.slice(h).buffer:null}else{let a=e,c=a.indexOf(Te.TextMessageFormat.RecordSeparator);if(c===-1)throw new Error("Message is incomplete.");let h=c+1;t=a.substring(0,h),n=a.length>h?a.substring(h):null}let o=Te.TextMessageFormat.parse(t),s=JSON.parse(o[0]);if(s.type)throw new Error("Expected a handshake response from the server.");return[n,s]}};ke.HandshakeProtocol=ht});var ce=p(ae=>{"use strict";Object.defineProperty(ae,"__esModule",{value:!0});ae.MessageType=void 0;var Jn;(function(r){r[r.Invocation=1]="Invocation",r[r.StreamItem=2]="StreamItem",r[r.Completion=3]="Completion",r[r.StreamInvocation=4]="StreamInvocation",r[r.CancelInvocation=5]="CancelInvocation",r[r.Ping=6]="Ping",r[r.Close=7]="Close",r[r.Ack=8]="Ack",r[r.Sequence=9]="Sequence"})(Jn=ae.MessageType||(ae.MessageType={}))});var ut=p(Ee=>{"use strict";Object.defineProperty(Ee,"__esModule",{value:!0});Ee.Subject=void 0;var Xn=L(),dt=class{constructor(){this.observers=[]}next(e){for(let t of this.observers)t.next(e)}error(e){for(let t of this.observers)t.error&&t.error(e)}complete(){for(let e of this.observers)e.complete&&e.complete()}subscribe(e){return this.observers.push(e),new Xn.SubjectSubscription(this,e)}};Ee.Subject=dt});var Yt=p(Ie=>{"use strict";Object.defineProperty(Ie,"__esModule",{value:!0});Ie.MessageBuffer=void 0;var T=ce(),Gt=L(),gt=class{constructor(e,t,n){this._bufferSize=1e5,this._messages=[],this._totalMessageCount=0,this._waitForSequenceMessage=!1,this._nextReceivingSequenceId=1,this._latestReceivedSequenceId=0,this._bufferedByteCount=0,this._reconnectInProgress=!1,this._protocol=e,this._connection=t,this._bufferSize=n}async _send(e){let t=this._protocol.writeMessage(e),n=Promise.resolve();if(this._isInvocationMessage(e)){this._totalMessageCount++;let o=()=>{},s=()=>{};(0,Gt.isArrayBuffer)(t)?this._bufferedByteCount+=t.byteLength:this._bufferedByteCount+=t.length,this._bufferedByteCount>=this._bufferSize&&(n=new Promise((i,a)=>{o=i,s=a})),this._messages.push(new pt(t,this._totalMessageCount,o,s))}try{this._reconnectInProgress||await this._connection.send(t)}catch{this._disconnected()}await n}_ack(e){let t=-1;for(let n=0;nthis._nextReceivingSequenceId){this._connection.stop(new Error("Sequence ID greater than amount of messages we've received."));return}this._nextReceivingSequenceId=e.sequenceId}_disconnected(){this._reconnectInProgress=!0,this._waitForSequenceMessage=!0}async _resend(){let e=this._messages.length!==0?this._messages[0]._id:this._totalMessageCount+1;await this._connection.send(this._protocol.writeMessage({type:T.MessageType.Sequence,sequenceId:e}));let t=this._messages;for(let n of t)await this._connection.send(n._message);this._reconnectInProgress=!1}_dispose(e){e??(e=new Error("Unable to reconnect to server."));for(let t of this._messages)t._rejector(e)}_isInvocationMessage(e){switch(e.type){case T.MessageType.Invocation:case T.MessageType.StreamItem:case T.MessageType.Completion:case T.MessageType.StreamInvocation:case T.MessageType.CancelInvocation:return!0;case T.MessageType.Close:case T.MessageType.Sequence:case T.MessageType.Ping:case T.MessageType.Ack:return!1}}_ackTimer(){this._ackTimerHandle===void 0&&(this._ackTimerHandle=setTimeout(async()=>{try{this._reconnectInProgress||await this._connection.send(this._protocol.writeMessage({type:T.MessageType.Ack,sequenceId:this._latestReceivedSequenceId}))}catch{}clearTimeout(this._ackTimerHandle),this._ackTimerHandle=void 0},1e3))}};Ie.MessageBuffer=gt;var pt=class{constructor(e,t,n,o){this._message=e,this._id=t,this._resolver=n,this._rejector=o}}});var _t=p(B=>{"use strict";Object.defineProperty(B,"__esModule",{value:!0});B.HubConnection=B.HubConnectionState=void 0;var Kn=Kt(),Qt=A(),m=ce(),d=P(),Gn=ut(),x=L(),Yn=Yt(),Qn=30*1e3,Zn=15*1e3,eo=1e5,_;(function(r){r.Disconnected="Disconnected",r.Connecting="Connecting",r.Connected="Connected",r.Disconnecting="Disconnecting",r.Reconnecting="Reconnecting"})(_=B.HubConnectionState||(B.HubConnectionState={}));var ft=class r{static create(e,t,n,o,s,i,a){return new r(e,t,n,o,s,i,a)}constructor(e,t,n,o,s,i,a){this._nextKeepAlive=0,this._freezeEventListener=()=>{this._logger.log(d.LogLevel.Warning,"The page is being frozen, this will likely lead to the connection being closed and messages being lost. For more information see the docs at https://learn.microsoft.com/aspnet/core/signalr/javascript-client#bsleep")},x.Arg.isRequired(e,"connection"),x.Arg.isRequired(t,"logger"),x.Arg.isRequired(n,"protocol"),this.serverTimeoutInMilliseconds=s??Qn,this.keepAliveIntervalInMilliseconds=i??Zn,this._statefulReconnectBufferSize=a??eo,this._logger=t,this._protocol=n,this.connection=e,this._reconnectPolicy=o,this._handshakeProtocol=new Kn.HandshakeProtocol,this.connection.onreceive=c=>this._processIncomingData(c),this.connection.onclose=c=>this._connectionClosed(c),this._callbacks={},this._methods={},this._closedCallbacks=[],this._reconnectingCallbacks=[],this._reconnectedCallbacks=[],this._invocationId=0,this._receivedHandshakeResponse=!1,this._connectionState=_.Disconnected,this._connectionStarted=!1,this._cachedPingMessage=this._protocol.writeMessage({type:m.MessageType.Ping})}get state(){return this._connectionState}get connectionId(){return this.connection&&this.connection.connectionId||null}get baseUrl(){return this.connection.baseUrl||""}set baseUrl(e){if(this._connectionState!==_.Disconnected&&this._connectionState!==_.Reconnecting)throw new Error("The HubConnection must be in the Disconnected or Reconnecting state to change the url.");if(!e)throw new Error("The HubConnection url must be a valid url.");this.connection.baseUrl=e}start(){return this._startPromise=this._startWithStateTransitions(),this._startPromise}async _startWithStateTransitions(){if(this._connectionState!==_.Disconnected)return Promise.reject(new Error("Cannot start a HubConnection that is not in the 'Disconnected' state."));this._connectionState=_.Connecting,this._logger.log(d.LogLevel.Debug,"Starting HubConnection.");try{await this._startInternal(),x.Platform.isBrowser&&window.document.addEventListener("freeze",this._freezeEventListener),this._connectionState=_.Connected,this._connectionStarted=!0,this._logger.log(d.LogLevel.Debug,"HubConnection connected successfully.")}catch(e){return this._connectionState=_.Disconnected,this._logger.log(d.LogLevel.Debug,`HubConnection failed to start successfully because of error '${e}'.`),Promise.reject(e)}}async _startInternal(){this._stopDuringStartError=void 0,this._receivedHandshakeResponse=!1;let e=new Promise((t,n)=>{this._handshakeResolver=t,this._handshakeRejecter=n});await this.connection.start(this._protocol.transferFormat);try{let t=this._protocol.version;this.connection.features.reconnect||(t=1);let n={protocol:this._protocol.name,version:t};if(this._logger.log(d.LogLevel.Debug,"Sending handshake request."),await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(n)),this._logger.log(d.LogLevel.Information,`Using HubProtocol '${this._protocol.name}'.`),this._cleanupTimeout(),this._resetTimeoutPeriod(),this._resetKeepAliveInterval(),await e,this._stopDuringStartError)throw this._stopDuringStartError;(this.connection.features.reconnect||!1)&&(this._messageBuffer=new Yn.MessageBuffer(this._protocol,this.connection,this._statefulReconnectBufferSize),this.connection.features.disconnected=this._messageBuffer._disconnected.bind(this._messageBuffer),this.connection.features.resend=()=>{if(this._messageBuffer)return this._messageBuffer._resend()}),this.connection.features.inherentKeepAlive||await this._sendMessage(this._cachedPingMessage)}catch(t){throw this._logger.log(d.LogLevel.Debug,`Hub handshake failed with error '${t}' during start(). Stopping HubConnection.`),this._cleanupTimeout(),this._cleanupPingTimer(),await this.connection.stop(t),t}}async stop(){let e=this._startPromise;this.connection.features.reconnect=!1,this._stopPromise=this._stopInternal(),await this._stopPromise;try{await e}catch{}}_stopInternal(e){if(this._connectionState===_.Disconnected)return this._logger.log(d.LogLevel.Debug,`Call to HubConnection.stop(${e}) ignored because it is already in the disconnected state.`),Promise.resolve();if(this._connectionState===_.Disconnecting)return this._logger.log(d.LogLevel.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise;let t=this._connectionState;return this._connectionState=_.Disconnecting,this._logger.log(d.LogLevel.Debug,"Stopping HubConnection."),this._reconnectDelayHandle?(this._logger.log(d.LogLevel.Debug,"Connection stopped during reconnect delay. Done reconnecting."),clearTimeout(this._reconnectDelayHandle),this._reconnectDelayHandle=void 0,this._completeClose(),Promise.resolve()):(t===_.Connected&&this._sendCloseMessage(),this._cleanupTimeout(),this._cleanupPingTimer(),this._stopDuringStartError=e||new Qt.AbortError("The connection was stopped before the hub handshake could complete."),this.connection.stop(e))}async _sendCloseMessage(){try{await this._sendWithProtocol(this._createCloseMessage())}catch{}}stream(e,...t){let[n,o]=this._replaceStreamingParams(t),s=this._createStreamInvocation(e,t,o),i,a=new Gn.Subject;return a.cancelCallback=()=>{let c=this._createCancelInvocation(s.invocationId);return delete this._callbacks[s.invocationId],i.then(()=>this._sendWithProtocol(c))},this._callbacks[s.invocationId]=(c,h)=>{if(h){a.error(h);return}else c&&(c.type===m.MessageType.Completion?c.error?a.error(new Error(c.error)):a.complete():a.next(c.item))},i=this._sendWithProtocol(s).catch(c=>{a.error(c),delete this._callbacks[s.invocationId]}),this._launchStreams(n,i),a}_sendMessage(e){return this._resetKeepAliveInterval(),this.connection.send(e)}_sendWithProtocol(e){return this._messageBuffer?this._messageBuffer._send(e):this._sendMessage(this._protocol.writeMessage(e))}send(e,...t){let[n,o]=this._replaceStreamingParams(t),s=this._sendWithProtocol(this._createInvocation(e,t,!0,o));return this._launchStreams(n,s),s}invoke(e,...t){let[n,o]=this._replaceStreamingParams(t),s=this._createInvocation(e,t,!1,o);return new Promise((a,c)=>{this._callbacks[s.invocationId]=(l,S)=>{if(S){c(S);return}else l&&(l.type===m.MessageType.Completion?l.error?c(new Error(l.error)):a(l.result):c(new Error(`Unexpected message type: ${l.type}`)))};let h=this._sendWithProtocol(s).catch(l=>{c(l),delete this._callbacks[s.invocationId]});this._launchStreams(n,h)})}on(e,t){!e||!t||(e=e.toLowerCase(),this._methods[e]||(this._methods[e]=[]),this._methods[e].indexOf(t)===-1&&this._methods[e].push(t))}off(e,t){if(!e)return;e=e.toLowerCase();let n=this._methods[e];if(n)if(t){let o=n.indexOf(t);o!==-1&&(n.splice(o,1),n.length===0&&delete this._methods[e])}else delete this._methods[e]}onclose(e){e&&this._closedCallbacks.push(e)}onreconnecting(e){e&&this._reconnectingCallbacks.push(e)}onreconnected(e){e&&this._reconnectedCallbacks.push(e)}_processIncomingData(e){if(this._cleanupTimeout(),this._receivedHandshakeResponse||(e=this._processHandshakeResponse(e),this._receivedHandshakeResponse=!0),e){let t=this._protocol.parseMessages(e,this._logger);for(let n of t)if(!(this._messageBuffer&&!this._messageBuffer._shouldProcessMessage(n)))switch(n.type){case m.MessageType.Invocation:this._invokeClientMethod(n).catch(o=>{this._logger.log(d.LogLevel.Error,`Invoke client method threw error: ${(0,x.getErrorString)(o)}`)});break;case m.MessageType.StreamItem:case m.MessageType.Completion:{let o=this._callbacks[n.invocationId];if(o){n.type===m.MessageType.Completion&&delete this._callbacks[n.invocationId];try{o(n)}catch(s){this._logger.log(d.LogLevel.Error,`Stream callback threw error: ${(0,x.getErrorString)(s)}`)}}break}case m.MessageType.Ping:break;case m.MessageType.Close:{this._logger.log(d.LogLevel.Information,"Close message received from server.");let o=n.error?new Error("Server returned an error on close: "+n.error):void 0;n.allowReconnect===!0?this.connection.stop(o):this._stopPromise=this._stopInternal(o);break}case m.MessageType.Ack:this._messageBuffer&&this._messageBuffer._ack(n);break;case m.MessageType.Sequence:this._messageBuffer&&this._messageBuffer._resetSequence(n);break;default:this._logger.log(d.LogLevel.Warning,`Invalid message type: ${n.type}.`);break}}this._resetTimeoutPeriod()}_processHandshakeResponse(e){let t,n;try{[n,t]=this._handshakeProtocol.parseHandshakeResponse(e)}catch(o){let s="Error parsing handshake response: "+o;this._logger.log(d.LogLevel.Error,s);let i=new Error(s);throw this._handshakeRejecter(i),i}if(t.error){let o="Server returned handshake error: "+t.error;this._logger.log(d.LogLevel.Error,o);let s=new Error(o);throw this._handshakeRejecter(s),s}else this._logger.log(d.LogLevel.Debug,"Server handshake complete.");return this._handshakeResolver(),n}_resetKeepAliveInterval(){this.connection.features.inherentKeepAlive||(this._nextKeepAlive=new Date().getTime()+this.keepAliveIntervalInMilliseconds,this._cleanupPingTimer())}_resetTimeoutPeriod(){if(!this.connection.features||!this.connection.features.inherentKeepAlive){this._timeoutHandle=setTimeout(()=>this.serverTimeout(),this.serverTimeoutInMilliseconds);let e=this._nextKeepAlive-new Date().getTime();if(e<0){this._connectionState===_.Connected&&this._trySendPingMessage();return}this._pingServerHandle===void 0&&(e<0&&(e=0),this._pingServerHandle=setTimeout(async()=>{this._connectionState===_.Connected&&await this._trySendPingMessage()},e))}}serverTimeout(){this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."))}async _invokeClientMethod(e){let t=e.target.toLowerCase(),n=this._methods[t];if(!n){this._logger.log(d.LogLevel.Warning,`No client method with the name '${t}' found.`),e.invocationId&&(this._logger.log(d.LogLevel.Warning,`No result given for '${t}' method and invocation ID '${e.invocationId}'.`),await this._sendWithProtocol(this._createCompletionMessage(e.invocationId,"Client didn't provide a result.",null)));return}let o=n.slice(),s=!!e.invocationId,i,a,c;for(let h of o)try{let l=i;i=await h.apply(this,e.arguments),s&&i&&l&&(this._logger.log(d.LogLevel.Error,`Multiple results provided for '${t}'. Sending error to server.`),c=this._createCompletionMessage(e.invocationId,"Client provided multiple results.",null)),a=void 0}catch(l){a=l,this._logger.log(d.LogLevel.Error,`A callback for the method '${t}' threw error '${l}'.`)}c?await this._sendWithProtocol(c):s?(a?c=this._createCompletionMessage(e.invocationId,`${a}`,null):i!==void 0?c=this._createCompletionMessage(e.invocationId,null,i):(this._logger.log(d.LogLevel.Warning,`No result given for '${t}' method and invocation ID '${e.invocationId}'.`),c=this._createCompletionMessage(e.invocationId,"Client didn't provide a result.",null)),await this._sendWithProtocol(c)):i&&this._logger.log(d.LogLevel.Error,`Result given for '${t}' method but server is not expecting a result.`)}_connectionClosed(e){this._logger.log(d.LogLevel.Debug,`HubConnection.connectionClosed(${e}) called while in state ${this._connectionState}.`),this._stopDuringStartError=this._stopDuringStartError||e||new Qt.AbortError("The underlying connection was closed before the hub handshake could complete."),this._handshakeResolver&&this._handshakeResolver(),this._cancelCallbacksWithError(e||new Error("Invocation canceled due to the underlying connection being closed.")),this._cleanupTimeout(),this._cleanupPingTimer(),this._connectionState===_.Disconnecting?this._completeClose(e):this._connectionState===_.Connected&&this._reconnectPolicy?this._reconnect(e):this._connectionState===_.Connected&&this._completeClose(e)}_completeClose(e){if(this._connectionStarted){this._connectionState=_.Disconnected,this._connectionStarted=!1,this._messageBuffer&&(this._messageBuffer._dispose(e??new Error("Connection closed.")),this._messageBuffer=void 0),x.Platform.isBrowser&&window.document.removeEventListener("freeze",this._freezeEventListener);try{this._closedCallbacks.forEach(t=>t.apply(this,[e]))}catch(t){this._logger.log(d.LogLevel.Error,`An onclose callback called with error '${e}' threw error '${t}'.`)}}}async _reconnect(e){let t=Date.now(),n=0,o=e!==void 0?e:new Error("Attempting to reconnect due to a unknown error."),s=this._getNextRetryDelay(n,0,o);if(s===null){this._logger.log(d.LogLevel.Debug,"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt."),this._completeClose(e);return}if(this._connectionState=_.Reconnecting,e?this._logger.log(d.LogLevel.Information,`Connection reconnecting because of error '${e}'.`):this._logger.log(d.LogLevel.Information,"Connection reconnecting."),this._reconnectingCallbacks.length!==0){try{this._reconnectingCallbacks.forEach(i=>i.apply(this,[e]))}catch(i){this._logger.log(d.LogLevel.Error,`An onreconnecting callback called with error '${e}' threw error '${i}'.`)}if(this._connectionState!==_.Reconnecting){this._logger.log(d.LogLevel.Debug,"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.");return}}for(;s!==null;){if(this._logger.log(d.LogLevel.Information,`Reconnect attempt number ${n+1} will start in ${s} ms.`),await new Promise(i=>{this._reconnectDelayHandle=setTimeout(i,s)}),this._reconnectDelayHandle=void 0,this._connectionState!==_.Reconnecting){this._logger.log(d.LogLevel.Debug,"Connection left the reconnecting state during reconnect delay. Done reconnecting.");return}try{if(await this._startInternal(),this._connectionState=_.Connected,this._logger.log(d.LogLevel.Information,"HubConnection reconnected successfully."),this._reconnectedCallbacks.length!==0)try{this._reconnectedCallbacks.forEach(i=>i.apply(this,[this.connection.connectionId]))}catch(i){this._logger.log(d.LogLevel.Error,`An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${i}'.`)}return}catch(i){if(this._logger.log(d.LogLevel.Information,`Reconnect attempt failed because of error '${i}'.`),this._connectionState!==_.Reconnecting){this._logger.log(d.LogLevel.Debug,`Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`),this._connectionState===_.Disconnecting&&this._completeClose();return}n++,o=i instanceof Error?i:new Error(i.toString()),s=this._getNextRetryDelay(n,Date.now()-t,o)}}this._logger.log(d.LogLevel.Information,`Reconnect retries have been exhausted after ${Date.now()-t} ms and ${n} failed attempts. Connection disconnecting.`),this._completeClose()}_getNextRetryDelay(e,t,n){try{return this._reconnectPolicy.nextRetryDelayInMilliseconds({elapsedMilliseconds:t,previousRetryCount:e,retryReason:n})}catch(o){return this._logger.log(d.LogLevel.Error,`IRetryPolicy.nextRetryDelayInMilliseconds(${e}, ${t}) threw error '${o}'.`),null}}_cancelCallbacksWithError(e){let t=this._callbacks;this._callbacks={},Object.keys(t).forEach(n=>{let o=t[n];try{o(null,e)}catch(s){this._logger.log(d.LogLevel.Error,`Stream 'error' callback called with '${e}' threw error: ${(0,x.getErrorString)(s)}`)}})}_cleanupPingTimer(){this._pingServerHandle&&(clearTimeout(this._pingServerHandle),this._pingServerHandle=void 0)}_cleanupTimeout(){this._timeoutHandle&&clearTimeout(this._timeoutHandle)}_createInvocation(e,t,n,o){if(n)return o.length!==0?{target:e,arguments:t,streamIds:o,type:m.MessageType.Invocation}:{target:e,arguments:t,type:m.MessageType.Invocation};{let s=this._invocationId;return this._invocationId++,o.length!==0?{target:e,arguments:t,invocationId:s.toString(),streamIds:o,type:m.MessageType.Invocation}:{target:e,arguments:t,invocationId:s.toString(),type:m.MessageType.Invocation}}}_launchStreams(e,t){if(e.length!==0){t||(t=Promise.resolve());for(let n in e)e[n].subscribe({complete:()=>{t=t.then(()=>this._sendWithProtocol(this._createCompletionMessage(n)))},error:o=>{let s;o instanceof Error?s=o.message:o&&o.toString?s=o.toString():s="Unknown error",t=t.then(()=>this._sendWithProtocol(this._createCompletionMessage(n,s)))},next:o=>{t=t.then(()=>this._sendWithProtocol(this._createStreamItemMessage(n,o)))}})}}_replaceStreamingParams(e){let t=[],n=[];for(let o=0;o{"use strict";Object.defineProperty(De,"__esModule",{value:!0});De.DefaultReconnectPolicy=void 0;var to=[0,2e3,1e4,3e4,null],vt=class{constructor(e){this._retryDelays=e!==void 0?[...e,null]:to}nextRetryDelayInMilliseconds(e){return this._retryDelays[e.previousRetryCount]}};De.DefaultReconnectPolicy=vt});var mt=p(Me=>{"use strict";Object.defineProperty(Me,"__esModule",{value:!0});Me.HeaderNames=void 0;var le=class{};Me.HeaderNames=le;le.Authorization="Authorization";le.Cookie="Cookie"});var en=p(He=>{"use strict";Object.defineProperty(He,"__esModule",{value:!0});He.AccessTokenHttpClient=void 0;var bt=mt(),no=K(),yt=class extends no.HttpClient{constructor(e,t){super(),this._innerClient=e,this._accessTokenFactory=t}async send(e){let t=!0;this._accessTokenFactory&&(!this._accessToken||e.url&&e.url.indexOf("/negotiate?")>0)&&(t=!1,this._accessToken=await this._accessTokenFactory()),this._setAuthorizationHeader(e);let n=await this._innerClient.send(e);return t&&n.statusCode===401&&this._accessTokenFactory?(this._accessToken=await this._accessTokenFactory(),this._setAuthorizationHeader(e),await this._innerClient.send(e)):n}_setAuthorizationHeader(e){e.headers||(e.headers={}),this._accessToken?e.headers[bt.HeaderNames.Authorization]=`Bearer ${this._accessToken}`:this._accessTokenFactory&&e.headers[bt.HeaderNames.Authorization]&&delete e.headers[bt.HeaderNames.Authorization]}getCookieString(e){return this._innerClient.getCookieString(e)}};He.AccessTokenHttpClient=yt});var N=p(j=>{"use strict";Object.defineProperty(j,"__esModule",{value:!0});j.TransferFormat=j.HttpTransportType=void 0;var oo;(function(r){r[r.None=0]="None",r[r.WebSockets=1]="WebSockets",r[r.ServerSentEvents=2]="ServerSentEvents",r[r.LongPolling=4]="LongPolling"})(oo=j.HttpTransportType||(j.HttpTransportType={}));var ro;(function(r){r[r.Text=1]="Text",r[r.Binary=2]="Binary"})(ro=j.TransferFormat||(j.TransferFormat={}))});var tn=p(Re=>{"use strict";Object.defineProperty(Re,"__esModule",{value:!0});Re.AbortController=void 0;var wt=class{constructor(){this._isAborted=!1,this.onabort=null}abort(){this._isAborted||(this._isAborted=!0,this.onabort&&this.onabort())}get signal(){return this}get aborted(){return this._isAborted}};Re.AbortController=wt});var nn=p($e=>{"use strict";Object.defineProperty($e,"__esModule",{value:!0});$e.LongPollingTransport=void 0;var so=tn(),Ae=A(),w=P(),St=N(),z=L(),Ct=class{get pollAborted(){return this._pollAbort.aborted}constructor(e,t,n){this._httpClient=e,this._logger=t,this._pollAbort=new so.AbortController,this._options=n,this._running=!1,this.onreceive=null,this.onclose=null}async connect(e,t){if(z.Arg.isRequired(e,"url"),z.Arg.isRequired(t,"transferFormat"),z.Arg.isIn(t,St.TransferFormat,"transferFormat"),this._url=e,this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Connecting."),t===St.TransferFormat.Binary&&typeof XMLHttpRequest<"u"&&typeof new XMLHttpRequest().responseType!="string")throw new Error("Binary protocols over XmlHttpRequest not implementing advanced features are not supported.");let[n,o]=(0,z.getUserAgentHeader)(),s={[n]:o,...this._options.headers},i={abortSignal:this._pollAbort.signal,headers:s,timeout:1e5,withCredentials:this._options.withCredentials};t===St.TransferFormat.Binary&&(i.responseType="arraybuffer");let a=`${e}&_=${Date.now()}`;this._logger.log(w.LogLevel.Trace,`(LongPolling transport) polling: ${a}.`);let c=await this._httpClient.get(a,i);c.statusCode!==200?(this._logger.log(w.LogLevel.Error,`(LongPolling transport) Unexpected response code: ${c.statusCode}.`),this._closeError=new Ae.HttpError(c.statusText||"",c.statusCode),this._running=!1):this._running=!0,this._receiving=this._poll(this._url,i)}async _poll(e,t){try{for(;this._running;)try{let n=`${e}&_=${Date.now()}`;this._logger.log(w.LogLevel.Trace,`(LongPolling transport) polling: ${n}.`);let o=await this._httpClient.get(n,t);o.statusCode===204?(this._logger.log(w.LogLevel.Information,"(LongPolling transport) Poll terminated by server."),this._running=!1):o.statusCode!==200?(this._logger.log(w.LogLevel.Error,`(LongPolling transport) Unexpected response code: ${o.statusCode}.`),this._closeError=new Ae.HttpError(o.statusText||"",o.statusCode),this._running=!1):o.content?(this._logger.log(w.LogLevel.Trace,`(LongPolling transport) data received. ${(0,z.getDataDetail)(o.content,this._options.logMessageContent)}.`),this.onreceive&&this.onreceive(o.content)):this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Poll timed out, reissuing.")}catch(n){this._running?n instanceof Ae.TimeoutError?this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Poll timed out, reissuing."):(this._closeError=n,this._running=!1):this._logger.log(w.LogLevel.Trace,`(LongPolling transport) Poll errored after shutdown: ${n.message}`)}}finally{this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Polling complete."),this.pollAborted||this._raiseOnClose()}}async send(e){return this._running?(0,z.sendMessage)(this._logger,"LongPolling",this._httpClient,this._url,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}async stop(){this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Stopping polling."),this._running=!1,this._pollAbort.abort();try{await this._receiving,this._logger.log(w.LogLevel.Trace,`(LongPolling transport) sending DELETE request to ${this._url}.`);let e={},[t,n]=(0,z.getUserAgentHeader)();e[t]=n;let o={headers:{...e,...this._options.headers},timeout:this._options.timeout,withCredentials:this._options.withCredentials},s;try{await this._httpClient.delete(this._url,o)}catch(i){s=i}s?s instanceof Ae.HttpError&&(s.statusCode===404?this._logger.log(w.LogLevel.Trace,"(LongPolling transport) A 404 response was returned from sending a DELETE request."):this._logger.log(w.LogLevel.Trace,`(LongPolling transport) Error sending a DELETE request: ${s}`)):this._logger.log(w.LogLevel.Trace,"(LongPolling transport) DELETE request accepted.")}finally{this._logger.log(w.LogLevel.Trace,"(LongPolling transport) Stop finished."),this._raiseOnClose()}}_raiseOnClose(){if(this.onclose){let e="(LongPolling transport) Firing onclose event.";this._closeError&&(e+=" Error: "+this._closeError),this._logger.log(w.LogLevel.Trace,e),this.onclose(this._closeError)}}};$e.LongPollingTransport=Ct});var rn=p(xe=>{"use strict";Object.defineProperty(xe,"__esModule",{value:!0});xe.ServerSentEventsTransport=void 0;var Lt=P(),on=N(),W=L(),Pt=class{constructor(e,t,n,o){this._httpClient=e,this._accessToken=t,this._logger=n,this._options=o,this.onreceive=null,this.onclose=null}async connect(e,t){return W.Arg.isRequired(e,"url"),W.Arg.isRequired(t,"transferFormat"),W.Arg.isIn(t,on.TransferFormat,"transferFormat"),this._logger.log(Lt.LogLevel.Trace,"(SSE transport) Connecting."),this._url=e,this._accessToken&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(this._accessToken)}`),new Promise((n,o)=>{let s=!1;if(t!==on.TransferFormat.Text){o(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"));return}let i;if(W.Platform.isBrowser||W.Platform.isWebWorker)i=new this._options.EventSource(e,{withCredentials:this._options.withCredentials});else{let a=this._httpClient.getCookieString(e),c={};c.Cookie=a;let[h,l]=(0,W.getUserAgentHeader)();c[h]=l,i=new this._options.EventSource(e,{withCredentials:this._options.withCredentials,headers:{...c,...this._options.headers}})}try{i.onmessage=a=>{if(this.onreceive)try{this._logger.log(Lt.LogLevel.Trace,`(SSE transport) data received. ${(0,W.getDataDetail)(a.data,this._options.logMessageContent)}.`),this.onreceive(a.data)}catch(c){this._close(c);return}},i.onerror=a=>{s?this._close():o(new Error("EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled."))},i.onopen=()=>{this._logger.log(Lt.LogLevel.Information,`SSE connected to ${this._url}`),this._eventSource=i,s=!0,n()}}catch(a){o(a);return}})}async send(e){return this._eventSource?(0,W.sendMessage)(this._logger,"SSE",this._httpClient,this._url,e,this._options):Promise.reject(new Error("Cannot send until the transport is connected"))}stop(){return this._close(),Promise.resolve()}_close(e){this._eventSource&&(this._eventSource.close(),this._eventSource=void 0,this.onclose&&this.onclose(e))}};xe.ServerSentEventsTransport=Pt});var cn=p(je=>{"use strict";Object.defineProperty(je,"__esModule",{value:!0});je.WebSocketTransport=void 0;var sn=mt(),Y=P(),an=N(),F=L(),Tt=class{constructor(e,t,n,o,s,i){this._logger=n,this._accessTokenFactory=t,this._logMessageContent=o,this._webSocketConstructor=s,this._httpClient=e,this.onreceive=null,this.onclose=null,this._headers=i}async connect(e,t){F.Arg.isRequired(e,"url"),F.Arg.isRequired(t,"transferFormat"),F.Arg.isIn(t,an.TransferFormat,"transferFormat"),this._logger.log(Y.LogLevel.Trace,"(WebSockets transport) Connecting.");let n;return this._accessTokenFactory&&(n=await this._accessTokenFactory()),new Promise((o,s)=>{e=e.replace(/^http/,"ws");let i,a=this._httpClient.getCookieString(e),c=!1;if(F.Platform.isNode||F.Platform.isReactNative){let h={},[l,S]=(0,F.getUserAgentHeader)();h[l]=S,n&&(h[sn.HeaderNames.Authorization]=`Bearer ${n}`),a&&(h[sn.HeaderNames.Cookie]=a),i=new this._webSocketConstructor(e,void 0,{headers:{...h,...this._headers}})}else n&&(e+=(e.indexOf("?")<0?"?":"&")+`access_token=${encodeURIComponent(n)}`);i||(i=new this._webSocketConstructor(e)),t===an.TransferFormat.Binary&&(i.binaryType="arraybuffer"),i.onopen=h=>{this._logger.log(Y.LogLevel.Information,`WebSocket connected to ${e}.`),this._webSocket=i,c=!0,o()},i.onerror=h=>{let l=null;typeof ErrorEvent<"u"&&h instanceof ErrorEvent?l=h.error:l="There was an error with the transport",this._logger.log(Y.LogLevel.Information,`(WebSockets transport) ${l}.`)},i.onmessage=h=>{if(this._logger.log(Y.LogLevel.Trace,`(WebSockets transport) data received. ${(0,F.getDataDetail)(h.data,this._logMessageContent)}.`),this.onreceive)try{this.onreceive(h.data)}catch(l){this._close(l);return}},i.onclose=h=>{if(c)this._close(h);else{let l=null;typeof ErrorEvent<"u"&&h instanceof ErrorEvent?l=h.error:l="WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.",s(new Error(l))}}})}send(e){return this._webSocket&&this._webSocket.readyState===this._webSocketConstructor.OPEN?(this._logger.log(Y.LogLevel.Trace,`(WebSockets transport) sending data. ${(0,F.getDataDetail)(e,this._logMessageContent)}.`),this._webSocket.send(e),Promise.resolve()):Promise.reject("WebSocket is not in the OPEN state")}stop(){return this._webSocket&&this._close(void 0),Promise.resolve()}_close(e){this._webSocket&&(this._webSocket.onclose=()=>{},this._webSocket.onmessage=()=>{},this._webSocket.onerror=()=>{},this._webSocket.close(),this._webSocket=void 0),this._logger.log(Y.LogLevel.Trace,"(WebSockets transport) socket closed."),this.onclose&&(this._isCloseEvent(e)&&(e.wasClean===!1||e.code!==1e3)?this.onclose(new Error(`WebSocket closed with status code: ${e.code} (${e.reason||"no reason given"}).`)):e instanceof Error?this.onclose(e):this.onclose())}_isCloseEvent(e){return e&&typeof e.wasClean=="boolean"&&typeof e.code=="number"}};je.WebSocketTransport=Tt});var dn=p(Z=>{"use strict";Object.defineProperty(Z,"__esModule",{value:!0});Z.TransportSendQueue=Z.HttpConnection=void 0;var io=en(),ao=ct(),E=A(),f=P(),v=N(),ln=nn(),co=rn(),I=L(),lo=cn(),hn=100,kt=class{constructor(e,t={}){if(this._stopPromiseResolver=()=>{},this.features={},this._negotiateVersion=1,I.Arg.isRequired(e,"url"),this._logger=(0,I.createLogger)(t.logger),this.baseUrl=this._resolveUrl(e),t=t||{},t.logMessageContent=t.logMessageContent===void 0?!1:t.logMessageContent,typeof t.withCredentials=="boolean"||t.withCredentials===void 0)t.withCredentials=t.withCredentials===void 0?!0:t.withCredentials;else throw new Error("withCredentials option was not a 'boolean' or 'undefined' value");t.timeout=t.timeout===void 0?100*1e3:t.timeout;let n=null,o=null;if(I.Platform.isNode&&typeof require<"u"){let s=typeof __webpack_require__=="function"?__non_webpack_require__:require;n=s("ws"),o=s("eventsource")}!I.Platform.isNode&&typeof WebSocket<"u"&&!t.WebSocket?t.WebSocket=WebSocket:I.Platform.isNode&&!t.WebSocket&&n&&(t.WebSocket=n),!I.Platform.isNode&&typeof EventSource<"u"&&!t.EventSource?t.EventSource=EventSource:I.Platform.isNode&&!t.EventSource&&typeof o<"u"&&(t.EventSource=o),this._httpClient=new io.AccessTokenHttpClient(t.httpClient||new ao.DefaultHttpClient(this._logger),t.accessTokenFactory),this._connectionState="Disconnected",this._connectionStarted=!1,this._options=t,this.onreceive=null,this.onclose=null}async start(e){if(e=e||v.TransferFormat.Binary,I.Arg.isIn(e,v.TransferFormat,"transferFormat"),this._logger.log(f.LogLevel.Debug,`Starting connection with transfer format '${v.TransferFormat[e]}'.`),this._connectionState!=="Disconnected")return Promise.reject(new Error("Cannot start an HttpConnection that is not in the 'Disconnected' state."));if(this._connectionState="Connecting",this._startInternalPromise=this._startInternal(e),await this._startInternalPromise,this._connectionState==="Disconnecting"){let t="Failed to start the HttpConnection before stop() was called.";return this._logger.log(f.LogLevel.Error,t),await this._stopPromise,Promise.reject(new E.AbortError(t))}else if(this._connectionState!=="Connected"){let t="HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!";return this._logger.log(f.LogLevel.Error,t),Promise.reject(new E.AbortError(t))}this._connectionStarted=!0}send(e){return this._connectionState!=="Connected"?Promise.reject(new Error("Cannot send data if the connection is not in the 'Connected' State.")):(this._sendQueue||(this._sendQueue=new We(this.transport)),this._sendQueue.send(e))}async stop(e){if(this._connectionState==="Disconnected")return this._logger.log(f.LogLevel.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnected state.`),Promise.resolve();if(this._connectionState==="Disconnecting")return this._logger.log(f.LogLevel.Debug,`Call to HttpConnection.stop(${e}) ignored because the connection is already in the disconnecting state.`),this._stopPromise;this._connectionState="Disconnecting",this._stopPromise=new Promise(t=>{this._stopPromiseResolver=t}),await this._stopInternal(e),await this._stopPromise}async _stopInternal(e){this._stopError=e;try{await this._startInternalPromise}catch{}if(this.transport){try{await this.transport.stop()}catch(t){this._logger.log(f.LogLevel.Error,`HttpConnection.transport.stop() threw error '${t}'.`),this._stopConnection()}this.transport=void 0}else this._logger.log(f.LogLevel.Debug,"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.")}async _startInternal(e){let t=this.baseUrl;this._accessTokenFactory=this._options.accessTokenFactory,this._httpClient._accessTokenFactory=this._accessTokenFactory;try{if(this._options.skipNegotiation)if(this._options.transport===v.HttpTransportType.WebSockets)this.transport=this._constructTransport(v.HttpTransportType.WebSockets),await this._startTransport(t,e);else throw new Error("Negotiation can only be skipped when using the WebSocket transport directly.");else{let n=null,o=0;do{if(n=await this._getNegotiationResponse(t),this._connectionState==="Disconnecting"||this._connectionState==="Disconnected")throw new E.AbortError("The connection was stopped during negotiation.");if(n.error)throw new Error(n.error);if(n.ProtocolVersion)throw new Error("Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.");if(n.url&&(t=n.url),n.accessToken){let s=n.accessToken;this._accessTokenFactory=()=>s,this._httpClient._accessToken=s,this._httpClient._accessTokenFactory=void 0}o++}while(n.url&&o0?Promise.reject(new E.AggregateErrors(`Unable to connect to the server with any of the available transports. ${i.join(" ")}`,i)):Promise.reject(new Error("None of the transports supported by the client are supported by the server."))}_constructTransport(e){switch(e){case v.HttpTransportType.WebSockets:if(!this._options.WebSocket)throw new Error("'WebSocket' is not supported in your environment.");return new lo.WebSocketTransport(this._httpClient,this._accessTokenFactory,this._logger,this._options.logMessageContent,this._options.WebSocket,this._options.headers||{});case v.HttpTransportType.ServerSentEvents:if(!this._options.EventSource)throw new Error("'EventSource' is not supported in your environment.");return new co.ServerSentEventsTransport(this._httpClient,this._httpClient._accessToken,this._logger,this._options);case v.HttpTransportType.LongPolling:return new ln.LongPollingTransport(this._httpClient,this._logger,this._options);default:throw new Error(`Unknown transport: ${e}.`)}}_startTransport(e,t){return this.transport.onreceive=this.onreceive,this.features.reconnect?this.transport.onclose=async n=>{let o=!1;if(this.features.reconnect)try{this.features.disconnected(),await this.transport.connect(e,t),await this.features.resend()}catch{o=!0}else{this._stopConnection(n);return}o&&this._stopConnection(n)}:this.transport.onclose=n=>this._stopConnection(n),this.transport.connect(e,t)}_resolveTransportOrError(e,t,n,o){let s=v.HttpTransportType[e.transport];if(s==null)return this._logger.log(f.LogLevel.Debug,`Skipping transport '${e.transport}' because it is not supported by this client.`),new Error(`Skipping transport '${e.transport}' because it is not supported by this client.`);if(ho(t,s))if(e.transferFormats.map(a=>v.TransferFormat[a]).indexOf(n)>=0){if(s===v.HttpTransportType.WebSockets&&!this._options.WebSocket||s===v.HttpTransportType.ServerSentEvents&&!this._options.EventSource)return this._logger.log(f.LogLevel.Debug,`Skipping transport '${v.HttpTransportType[s]}' because it is not supported in your environment.'`),new E.UnsupportedTransportError(`'${v.HttpTransportType[s]}' is not supported in your environment.`,s);this._logger.log(f.LogLevel.Debug,`Selecting transport '${v.HttpTransportType[s]}'.`);try{return this.features.reconnect=s===v.HttpTransportType.WebSockets?o:void 0,this._constructTransport(s)}catch(a){return a}}else return this._logger.log(f.LogLevel.Debug,`Skipping transport '${v.HttpTransportType[s]}' because it does not support the requested transfer format '${v.TransferFormat[n]}'.`),new Error(`'${v.HttpTransportType[s]}' does not support ${v.TransferFormat[n]}.`);else return this._logger.log(f.LogLevel.Debug,`Skipping transport '${v.HttpTransportType[s]}' because it was disabled by the client.`),new E.DisabledTransportError(`'${v.HttpTransportType[s]}' is disabled by the client.`,s)}_isITransport(e){return e&&typeof e=="object"&&"connect"in e}_stopConnection(e){if(this._logger.log(f.LogLevel.Debug,`HttpConnection.stopConnection(${e}) called while in state ${this._connectionState}.`),this.transport=void 0,e=this._stopError||e,this._stopError=void 0,this._connectionState==="Disconnected"){this._logger.log(f.LogLevel.Debug,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is already in the disconnected state.`);return}if(this._connectionState==="Connecting")throw this._logger.log(f.LogLevel.Warning,`Call to HttpConnection.stopConnection(${e}) was ignored because the connection is still in the connecting state.`),new Error(`HttpConnection.stopConnection(${e}) was called while the connection is still in the connecting state.`);if(this._connectionState==="Disconnecting"&&this._stopPromiseResolver(),e?this._logger.log(f.LogLevel.Error,`Connection disconnected with error '${e}'.`):this._logger.log(f.LogLevel.Information,"Connection disconnected."),this._sendQueue&&(this._sendQueue.stop().catch(t=>{this._logger.log(f.LogLevel.Error,`TransportSendQueue.stop() threw error '${t}'.`)}),this._sendQueue=void 0),this.connectionId=void 0,this._connectionState="Disconnected",this._connectionStarted){this._connectionStarted=!1;try{this.onclose&&this.onclose(e)}catch(t){this._logger.log(f.LogLevel.Error,`HttpConnection.onclose(${e}) threw error '${t}'.`)}}}_resolveUrl(e){if(e.lastIndexOf("https://",0)===0||e.lastIndexOf("http://",0)===0)return e;if(!I.Platform.isBrowser)throw new Error(`Cannot resolve '${e}'.`);let t=window.document.createElement("a");return t.href=e,this._logger.log(f.LogLevel.Information,`Normalizing '${e}' to '${t.href}'.`),t.href}_resolveNegotiateUrl(e){let t=new URL(e);t.pathname.endsWith("/")?t.pathname+="negotiate":t.pathname+="/negotiate";let n=new URLSearchParams(t.searchParams);return n.has("negotiateVersion")||n.append("negotiateVersion",this._negotiateVersion.toString()),n.has("useStatefulReconnect")?n.get("useStatefulReconnect")==="true"&&(this._options._useStatefulReconnect=!0):this._options._useStatefulReconnect===!0&&n.append("useStatefulReconnect","true"),t.search=n.toString(),t.toString()}};Z.HttpConnection=kt;function ho(r,e){return!r||(e&r)!==0}var We=class r{constructor(e){this._transport=e,this._buffer=[],this._executing=!0,this._sendBufferedData=new Q,this._transportResult=new Q,this._sendLoopPromise=this._sendLoop()}send(e){return this._bufferData(e),this._transportResult||(this._transportResult=new Q),this._transportResult.promise}stop(){return this._executing=!1,this._sendBufferedData.resolve(),this._sendLoopPromise}_bufferData(e){if(this._buffer.length&&typeof this._buffer[0]!=typeof e)throw new Error(`Expected data to be of type ${typeof this._buffer} but was of type ${typeof e}`);this._buffer.push(e),this._sendBufferedData.resolve()}async _sendLoop(){for(;;){if(await this._sendBufferedData.promise,!this._executing){this._transportResult&&this._transportResult.reject("Connection stopped.");break}this._sendBufferedData=new Q;let e=this._transportResult;this._transportResult=void 0;let t=typeof this._buffer[0]=="string"?this._buffer.join(""):r._concatBuffers(this._buffer);this._buffer.length=0;try{await this._transport.send(t),e.resolve()}catch(n){e.reject(n)}}}static _concatBuffers(e){let t=e.map(s=>s.byteLength).reduce((s,i)=>s+i),n=new Uint8Array(t),o=0;for(let s of e)n.set(new Uint8Array(s),o),o+=s.byteLength;return n.buffer}};Z.TransportSendQueue=We;var Q=class{constructor(){this.promise=new Promise((e,t)=>[this._resolver,this._rejecter]=[e,t])}resolve(){this._resolver()}reject(e){this._rejecter(e)}}});var It=p(Fe=>{"use strict";Object.defineProperty(Fe,"__esModule",{value:!0});Fe.JsonHubProtocol=void 0;var V=ce(),uo=P(),go=N(),po=re(),un=lt(),fo="json",Et=class{constructor(){this.name=fo,this.version=2,this.transferFormat=go.TransferFormat.Text}parseMessages(e,t){if(typeof e!="string")throw new Error("Invalid input for JSON hub protocol. Expected a string.");if(!e)return[];t===null&&(t=po.NullLogger.instance);let n=un.TextMessageFormat.parse(e),o=[];for(let s of n){let i=JSON.parse(s);if(typeof i.type!="number")throw new Error("Invalid payload.");switch(i.type){case V.MessageType.Invocation:this._isInvocationMessage(i);break;case V.MessageType.StreamItem:this._isStreamItemMessage(i);break;case V.MessageType.Completion:this._isCompletionMessage(i);break;case V.MessageType.Ping:break;case V.MessageType.Close:break;case V.MessageType.Ack:this._isAckMessage(i);break;case V.MessageType.Sequence:this._isSequenceMessage(i);break;default:t.log(uo.LogLevel.Information,"Unknown message type '"+i.type+"' ignored.");continue}o.push(i)}return o}writeMessage(e){return un.TextMessageFormat.write(JSON.stringify(e))}_isInvocationMessage(e){this._assertNotEmptyString(e.target,"Invalid payload for Invocation message."),e.invocationId!==void 0&&this._assertNotEmptyString(e.invocationId,"Invalid payload for Invocation message.")}_isStreamItemMessage(e){if(this._assertNotEmptyString(e.invocationId,"Invalid payload for StreamItem message."),e.item===void 0)throw new Error("Invalid payload for StreamItem message.")}_isCompletionMessage(e){if(e.result&&e.error)throw new Error("Invalid payload for Completion message.");!e.result&&e.error&&this._assertNotEmptyString(e.error,"Invalid payload for Completion message."),this._assertNotEmptyString(e.invocationId,"Invalid payload for Completion message.")}_isAckMessage(e){if(typeof e.sequenceId!="number")throw new Error("Invalid SequenceId for Ack message.")}_isSequenceMessage(e){if(typeof e.sequenceId!="number")throw new Error("Invalid SequenceId for Sequence message.")}_assertNotEmptyString(e,t){if(typeof e!="string"||e==="")throw new Error(t)}};Fe.JsonHubProtocol=Et});var pn=p(Oe=>{"use strict";Object.defineProperty(Oe,"__esModule",{value:!0});Oe.HubConnectionBuilder=void 0;var gn=Zt(),_o=dn(),vo=_t(),M=P(),mo=It(),bo=re(),O=L(),yo={trace:M.LogLevel.Trace,debug:M.LogLevel.Debug,info:M.LogLevel.Information,information:M.LogLevel.Information,warn:M.LogLevel.Warning,warning:M.LogLevel.Warning,error:M.LogLevel.Error,critical:M.LogLevel.Critical,none:M.LogLevel.None};function wo(r){let e=yo[r.toLowerCase()];if(typeof e<"u")return e;throw new Error(`Unknown log level: ${r}`)}var Dt=class{configureLogging(e){if(O.Arg.isRequired(e,"logging"),So(e))this.logger=e;else if(typeof e=="string"){let t=wo(e);this.logger=new O.ConsoleLogger(t)}else this.logger=new O.ConsoleLogger(e);return this}withUrl(e,t){return O.Arg.isRequired(e,"url"),O.Arg.isNotEmpty(e,"url"),this.url=e,typeof t=="object"?this.httpConnectionOptions={...this.httpConnectionOptions,...t}:this.httpConnectionOptions={...this.httpConnectionOptions,transport:t},this}withHubProtocol(e){return O.Arg.isRequired(e,"protocol"),this.protocol=e,this}withAutomaticReconnect(e){if(this.reconnectPolicy)throw new Error("A reconnectPolicy has already been set.");return e?Array.isArray(e)?this.reconnectPolicy=new gn.DefaultReconnectPolicy(e):this.reconnectPolicy=e:this.reconnectPolicy=new gn.DefaultReconnectPolicy,this}withServerTimeout(e){return O.Arg.isRequired(e,"milliseconds"),this._serverTimeoutInMilliseconds=e,this}withKeepAliveInterval(e){return O.Arg.isRequired(e,"milliseconds"),this._keepAliveIntervalInMilliseconds=e,this}withStatefulReconnect(e){return this.httpConnectionOptions===void 0&&(this.httpConnectionOptions={}),this.httpConnectionOptions._useStatefulReconnect=!0,this._statefulReconnectBufferSize=e?.bufferSize,this}build(){let e=this.httpConnectionOptions||{};if(e.logger===void 0&&(e.logger=this.logger),!this.url)throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");let t=new _o.HttpConnection(this.url,e);return vo.HubConnection.create(t,this.logger||bo.NullLogger.instance,this.protocol||new mo.JsonHubProtocol,this.reconnectPolicy,this._serverTimeoutInMilliseconds,this._keepAliveIntervalInMilliseconds,this._statefulReconnectBufferSize)}};Oe.HubConnectionBuilder=Dt;function So(r){return r.log!==void 0}});var mn=p(u=>{"use strict";Object.defineProperty(u,"__esModule",{value:!0});u.VERSION=u.Subject=u.JsonHubProtocol=u.NullLogger=u.TransferFormat=u.HttpTransportType=u.LogLevel=u.MessageType=u.HubConnectionBuilder=u.HubConnectionState=u.HubConnection=u.DefaultHttpClient=u.HttpResponse=u.HttpClient=u.TimeoutError=u.HttpError=u.AbortError=void 0;var Mt=A();Object.defineProperty(u,"AbortError",{enumerable:!0,get:function(){return Mt.AbortError}});Object.defineProperty(u,"HttpError",{enumerable:!0,get:function(){return Mt.HttpError}});Object.defineProperty(u,"TimeoutError",{enumerable:!0,get:function(){return Mt.TimeoutError}});var fn=K();Object.defineProperty(u,"HttpClient",{enumerable:!0,get:function(){return fn.HttpClient}});Object.defineProperty(u,"HttpResponse",{enumerable:!0,get:function(){return fn.HttpResponse}});var Co=ct();Object.defineProperty(u,"DefaultHttpClient",{enumerable:!0,get:function(){return Co.DefaultHttpClient}});var _n=_t();Object.defineProperty(u,"HubConnection",{enumerable:!0,get:function(){return _n.HubConnection}});Object.defineProperty(u,"HubConnectionState",{enumerable:!0,get:function(){return _n.HubConnectionState}});var Lo=pn();Object.defineProperty(u,"HubConnectionBuilder",{enumerable:!0,get:function(){return Lo.HubConnectionBuilder}});var Po=ce();Object.defineProperty(u,"MessageType",{enumerable:!0,get:function(){return Po.MessageType}});var To=P();Object.defineProperty(u,"LogLevel",{enumerable:!0,get:function(){return To.LogLevel}});var vn=N();Object.defineProperty(u,"HttpTransportType",{enumerable:!0,get:function(){return vn.HttpTransportType}});Object.defineProperty(u,"TransferFormat",{enumerable:!0,get:function(){return vn.TransferFormat}});var ko=re();Object.defineProperty(u,"NullLogger",{enumerable:!0,get:function(){return ko.NullLogger}});var Eo=It();Object.defineProperty(u,"JsonHubProtocol",{enumerable:!0,get:function(){return Eo.JsonHubProtocol}});var Io=ut();Object.defineProperty(u,"Subject",{enumerable:!0,get:function(){return Io.Subject}});var Do=L();Object.defineProperty(u,"VERSION",{enumerable:!0,get:function(){return Do.VERSION}})});var $o={};In($o,{activate:()=>Ho,deactivate:()=>Ao,log:()=>b});module.exports=Dn($o);var k=D(require("vscode")),Sn=D(require("path")),ze=D(require("fs")),Cn=require("child_process");var At=require("events"),$t=D(require("path")),ge=class extends At.EventEmitter{constructor(t,n){super();this.createWatcher=t;this.readFile=n}watcher;start(t){for(let n of t){let o=$t.join(n,".ai-dev","project.json");this.tryEmitDetected(o,n)}this.watcher=this.createWatcher("**/.ai-dev/project.json"),this.watcher.onCreated(n=>{let o=this.resolveWorkspacePath(n,t);o&&this.tryEmitDetected(n,o)}),this.watcher.onDeleted(n=>{let o=this.resolveWorkspacePath(n,t);o&&this.emit("projectRemoved",o)})}tryEmitDetected(t,n){let o=this.readFile(t);if(o)try{let s=JSON.parse(o);s.projectSlug&&s.apiPort&&this.emit("projectDetected",{config:s,workspaceFolderPath:n})}catch{}}resolveWorkspacePath(t,n){let o=t.replace(/\\/g,"/");return n.find(s=>{let i=s.replace(/\\/g,"/");return o.startsWith(i+"/")})}dispose(){this.watcher?.dispose()}};var pe=class{constructor(e,t,n,o=i=>new Promise(a=>setTimeout(a,i)),s=i=>{try{return require("fs").accessSync(i),!0}catch{return!1}}){this.options=e;this.spawner=t;this.fetcher=n;this.delay=o;this.fileExists=s}_state="not-started";_process;get state(){return this._state}async start(){if(this._state!=="not-started")return;this._state="starting",this.fileExists(this.options.binaryPath)&&(this._process=this.spawner(this.options.binaryPath,[],{}),this._process.on("exit",()=>{this._state!=="stopped"&&(this._state="stopped")}),this._process.on("error",()=>{this._state!=="stopped"&&(this._state="stopped")}));let e=`http://localhost:${this.options.port}/api/health`;for(let t=0;tfetch(n,o)){this.baseUrl=e;this.fetcher=t}async listAgents(e){return this.get(`/api/agents?projectSlug=${C(e)}`)}async runAgent(e,t){await this.post(`/api/agents/${C(t)}/run?projectSlug=${C(e)}`)}async stopAgent(e,t){await this.post(`/api/agents/${C(t)}/stop?projectSlug=${C(e)}`)}async listMessages(e,t,n){let o=`/api/messages?projectSlug=${C(e)}`;return t&&(o+=`&agentSlug=${C(t)}`),n!==void 0&&(o+=`&processed=${n}`),this.get(o)}async listAllMessages(e){let t=await this.listAgents(e);return(await Promise.all(t.map(o=>this.listMessages(e,o.slug,!1).then(s=>s.map(i=>({...i,agentSlug:o.slug})))))).flat()}async processMessage(e,t,n){await this.post(`/api/messages/${C(n)}/process?projectSlug=${C(e)}&agentSlug=${C(t)}`)}async listDecisions(e,t){let n=`/api/decisions?projectSlug=${C(e)}`;return t&&(n+=`&status=${C(t)}`),this.get(n)}async resolveDecision(e,t,n){await this.post(`/api/decisions/${C(t)}/resolve?projectSlug=${C(e)}`,{resolution:n})}async get(e){let t=await this.fetcher(this.baseUrl+e);if(!t.ok)throw new ve(t.status,e);return t.json()}async post(e,t){let n=await this.fetcher(this.baseUrl+e,{method:"POST",headers:t?{"Content-Type":"application/json"}:void 0,body:t?JSON.stringify(t):void 0});if(!n.ok)throw new ve(n.status,e)}};function C(r){return encodeURIComponent(r)}var ve=class extends Error{constructor(t,n){super(`API error ${t} for ${n}`);this.statusCode=t;this.path=n;this.name="ApiError"}};var he=D(require("vscode")),ee=D(mn()),Mo={build:r=>new ee.HubConnectionBuilder().withUrl(r).withAutomaticReconnect({nextRetryDelayInMilliseconds:e=>Math.min(1e3*2**e.previousRetryCount,3e4)+Math.random()*1e3}).configureLogging(ee.LogLevel.Warning).build()},Ue=class{constructor(e,t=Mo){this.hubUrl=e;this.factory=t}connection;projectSlug;_onConnectionStateChanged=new he.EventEmitter;_onAgentsChanged=new he.EventEmitter;_onMessagesChanged=new he.EventEmitter;_onDecisionsChanged=new he.EventEmitter;onConnectionStateChanged=this._onConnectionStateChanged.event;onAgentsChanged=this._onAgentsChanged.event;onMessagesChanged=this._onMessagesChanged.event;onDecisionsChanged=this._onDecisionsChanged.event;_connectionState="disconnected";get connectionState(){return this._connectionState}async start(e){this.projectSlug=e,this.connection=this.factory.build(this.hubUrl),this.connection.onreconnecting(()=>this.setState("connecting")),this.connection.onreconnected(()=>this.setState("connected")),this.connection.onclose(()=>this.setState("disconnected")),this.connection.on("StateChanged",t=>{if(t.projectSlug!==this.projectSlug)return;let n=t.kinds.map(o=>o.toLowerCase());n.includes("agents")&&this._onAgentsChanged.fire(),n.includes("messages")&&this._onMessagesChanged.fire(),n.includes("decisions")&&this._onDecisionsChanged.fire(),n.includes("board")&&this._onAgentsChanged.fire()}),this.setState("connecting"),await this.connection.start(),await this.connection.invoke("JoinProject",e),this.setState("connected")}async stop(){if(this.connection?.state===ee.HubConnectionState.Connected)try{await this.connection.invoke("LeaveProject",this.projectSlug)}catch{}await this.connection?.stop(),this.setState("disconnected")}dispose(){this._onConnectionStateChanged.dispose(),this._onAgentsChanged.dispose(),this._onMessagesChanged.dispose(),this._onDecisionsChanged.dispose(),this.connection?.stop()}setState(e){this._connectionState!==e&&(this._connectionState=e,this._onConnectionStateChanged.fire(e))}};var Ht=D(require("vscode")),bn=D(require("crypto")),U=class{constructor(e,t,n){this.viewId=e;this.extensionUri=t;this.webviewScript=n}view;projectSlug;api;signalR;connectionDisposables=[];resolveWebviewView(e){this.view=e,this.api?(this.enableScripts(e),this.wireUp(e)):(e.webview.options={enableScripts:!1},e.webview.html=this.buildPlaceholderHtml())}connect(e,t,n){this.projectSlug=e,this.api=t,this.signalR=n,this.view&&(this.enableScripts(this.view),this.wireUp(this.view))}enableScripts(e){e.webview.options={enableScripts:!0,localResourceRoots:[Ht.Uri.joinPath(this.extensionUri,"dist","webviews")]},e.webview.html=this.buildHtml(e.webview)}disconnect(){for(let e of this.connectionDisposables)e.dispose();this.connectionDisposables=[],this.projectSlug=void 0,this.api=void 0,this.signalR=void 0,this.send({type:"loading"})}send(e){this.view?.webview.postMessage(e)}wireUp(e){for(let t of this.connectionDisposables)t.dispose();this.connectionDisposables=[],this.onConnected(e,this.connectionDisposables)}buildPlaceholderHtml(){return` + +

Waiting for AI Dev Studio backend\u2026

`}buildHtml(e){let t=bn.randomBytes(16).toString("hex"),n=e.asWebviewUri(Ht.Uri.joinPath(this.extensionUri,"dist","webviews",this.webviewScript));return` + + + + + + + + +
+ + +`}};var qe=class extends U{constructor(e){super("aidev.agents",e,"agents/main.js")}onConnected(e,t){t.push(this.signalR.onAgentsChanged(()=>void this.refresh())),t.push(e.webview.onDidReceiveMessage(async n=>{try{n.type==="run"?await this.api.runAgent(this.projectSlug,n.agentSlug):n.type==="stop"&&await this.api.stopAgent(this.projectSlug,n.agentSlug),await this.refresh()}catch(o){this.send({type:"error",message:String(o)})}})),this.refresh()}async refresh(){if(this.api){this.send({type:"loading"});try{let e=await this.api.listAgents(this.projectSlug);this.send({type:"agents",data:e})}catch(e){this.send({type:"error",message:`Failed to load agents: ${e}`})}}}};var Be=class extends U{constructor(e){super("aidev.messages",e,"messages/main.js")}onConnected(e,t){t.push(this.signalR.onMessagesChanged(()=>void this.refresh(e))),t.push(e.webview.onDidReceiveMessage(async n=>{try{n.type==="process"&&(await this.api.processMessage(this.projectSlug,n.agentSlug,n.fileName),await this.refresh(e))}catch(o){this.send({type:"error",message:String(o)})}})),this.refresh(e)}async refresh(e){if(this.api){this.send({type:"loading"});try{let t=await this.api.listAllMessages(this.projectSlug);this.send({type:"messages",data:t}),e.badge=t.length>0?{value:t.length,tooltip:`${t.length} unprocessed message(s)`}:void 0}catch(t){this.send({type:"error",message:`Failed to load messages: ${t}`})}}}};var Ne=class extends U{constructor(e){super("aidev.decisions",e,"decisions/main.js")}onConnected(e,t){t.push(this.signalR.onDecisionsChanged(()=>void this.refresh(e))),t.push(e.webview.onDidReceiveMessage(async n=>{try{n.type==="resolve"&&(await this.api.resolveDecision(this.projectSlug,n.decisionId,n.resolution),await this.refresh(e))}catch(o){this.send({type:"error",message:String(o)})}})),this.refresh(e)}async refresh(e){if(this.api){this.send({type:"loading"});try{let t=await this.api.listDecisions(this.projectSlug,"pending");this.send({type:"decisions",data:t}),e.badge=t.length>0?{value:t.length,tooltip:`${t.length} pending decision(s)`}:void 0}catch(t){this.send({type:"error",message:`Failed to load decisions: ${t}`})}}}};var te,H,R,b;async function Ho(r){b=k.window.createOutputChannel("AI Dev Studio"),r.subscriptions.push(b),b.appendLine(`Activating \u2014 extensionPath: ${r.extensionPath}`),R=new fe,r.subscriptions.push(R);let e=new qe(r.extensionUri),t=new Be(r.extensionUri),n=new Ne(r.extensionUri);r.subscriptions.push(k.window.registerWebviewViewProvider("aidev.agents",e),k.window.registerWebviewViewProvider("aidev.messages",t),k.window.registerWebviewViewProvider("aidev.decisions",n));let o=new ge(s=>{let i=k.workspace.createFileSystemWatcher(s);return{onCreated:a=>i.onDidCreate(c=>a(c.fsPath)),onDeleted:a=>i.onDidDelete(c=>a(c.fsPath)),dispose:()=>i.dispose()}},s=>{try{return ze.readFileSync(s,"utf8")}catch{return}});r.subscriptions.push(o),o.on("projectDetected",async({config:s,workspaceFolderPath:i})=>{if(b.appendLine(`Project detected: slug=${s.projectSlug} port=${s.apiPort} at ${i}`),te){b.appendLine("Backend already running \u2014 skipping.");return}await Ro(r,s,i,e,t,n)}),o.on("projectRemoved",s=>{b.appendLine(`Project removed: ${s}`),wn(e,t,n)}),r.subscriptions.push(k.commands.registerCommand("aidev.restartBackend",async()=>{b.appendLine("Restart backend command invoked."),await wn(e,t,n),yn(o)})),r.subscriptions.push(k.workspace.onDidChangeWorkspaceFolders(s=>{b.appendLine(`Workspace folders changed: +${s.added.length} -${s.removed.length}`),s.added.length>0&&o.start(s.added.map(i=>i.uri.fsPath))})),yn(o)}function yn(r){let e=k.workspace.workspaceFolders??[];b.appendLine(`Scanning ${e.length} folder(s): ${e.map(t=>t.uri.fsPath).join(", ")||"(none \u2014 open a folder containing .ai-dev/project.json)"}`),r.start(e.map(t=>t.uri.fsPath))}async function Ro(r,e,t,n,o,s){let i=process.platform==="win32"?"ai-dev-api.exe":"ai-dev-api",a=Sn.join(r.extensionPath,"bin",i);b.appendLine(`Binary: ${a} (exists: ${ze.existsSync(a)})`),te=new pe({binaryPath:a,port:e.apiPort,maxAttempts:30,retryDelayMs:1e3},(l,S,de)=>(0,Cn.spawn)(l,S,{...de,stdio:"pipe",env:{...process.env,WORKSPACE_ROOT:t}}),async l=>{let S=await fetch(l);return b.appendLine(`Health check ${l} \u2192 ${S.status}`),{ok:S.ok}}),R?.setStarting(),b.appendLine(`Waiting for backend on port ${e.apiPort}\u2026`);try{await te.start(),b.appendLine("Backend ready.")}catch(l){b.appendLine(`Backend failed: ${l}`),R?.setDisconnected(),k.window.showErrorMessage("AI Dev Studio: backend failed to start. See Output > AI Dev Studio.");return}let c=`http://localhost:${e.apiPort}`,h=new _e(c);H=new Ue(`${c}/hubs/project`),H.onConnectionStateChanged(l=>{b.appendLine(`SignalR: ${l}`),l==="connected"?R?.setRunning():l==="connecting"?R?.setStarting():R?.setDisconnected()});try{await H.start(e.projectSlug),b.appendLine("SignalR connected.")}catch(l){b.appendLine(`SignalR failed (non-fatal, REST still works): ${l}`)}R?.setRunning(),n.connect(e.projectSlug,h,H),o.connect(e.projectSlug,h,H),s.connect(e.projectSlug,h,H),b.appendLine("Panels connected.")}async function wn(r,e,t){b?.appendLine("Tearing down."),await H?.stop(),H=void 0,te?.stop(),te=void 0,R?.setDisconnected(),r.disconnect(),e.disconnect(),t.disconnect()}function Ao(){b?.appendLine("Deactivating."),te?.stop(),H?.stop()}0&&(module.exports={activate,deactivate,log}); +//# sourceMappingURL=extension.js.map diff --git a/ai-dev-vscode/dist/extension.js.map b/ai-dev-vscode/dist/extension.js.map new file mode 100644 index 0000000..5667a6d --- /dev/null +++ b/ai-dev-vscode/dist/extension.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../node_modules/@microsoft/signalr/src/Errors.ts", "../node_modules/@microsoft/signalr/src/HttpClient.ts", "../node_modules/@microsoft/signalr/src/ILogger.ts", "../node_modules/@microsoft/signalr/src/Loggers.ts", "../node_modules/@microsoft/signalr/src/pkg-version.ts", "../node_modules/@microsoft/signalr/src/Utils.ts", "../node_modules/@microsoft/signalr/src/FetchHttpClient.ts", "../node_modules/@microsoft/signalr/src/XhrHttpClient.ts", "../node_modules/@microsoft/signalr/src/DefaultHttpClient.ts", "../node_modules/@microsoft/signalr/src/TextMessageFormat.ts", "../node_modules/@microsoft/signalr/src/HandshakeProtocol.ts", "../node_modules/@microsoft/signalr/src/IHubProtocol.ts", "../node_modules/@microsoft/signalr/src/Subject.ts", "../node_modules/@microsoft/signalr/src/MessageBuffer.ts", "../node_modules/@microsoft/signalr/src/HubConnection.ts", "../node_modules/@microsoft/signalr/src/DefaultReconnectPolicy.ts", "../node_modules/@microsoft/signalr/src/HeaderNames.ts", "../node_modules/@microsoft/signalr/src/AccessTokenHttpClient.ts", "../node_modules/@microsoft/signalr/src/ITransport.ts", "../node_modules/@microsoft/signalr/src/AbortController.ts", "../node_modules/@microsoft/signalr/src/LongPollingTransport.ts", "../node_modules/@microsoft/signalr/src/ServerSentEventsTransport.ts", "../node_modules/@microsoft/signalr/src/WebSocketTransport.ts", "../node_modules/@microsoft/signalr/src/HttpConnection.ts", "../node_modules/@microsoft/signalr/src/JsonHubProtocol.ts", "../node_modules/@microsoft/signalr/src/HubConnectionBuilder.ts", "../node_modules/@microsoft/signalr/src/index.ts", "../src/extension.ts", "../src/WorkspaceDetector.ts", "../src/BackendProcessManager.ts", "../src/StatusBarManager.ts", "../src/StudioApiClient.ts", "../src/StudioSignalRClient.ts", "../src/panels/BasePanelProvider.ts", "../src/panels/AgentsPanelProvider.ts", "../src/panels/MessagesPanelProvider.ts", "../src/panels/DecisionsPanelProvider.ts"], + "sourcesContent": ["// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HttpTransportType } from \"./ITransport\";\r\n\r\n/** Error thrown when an HTTP request fails. */\r\nexport class HttpError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The HTTP status code represented by this error. */\r\n public statusCode: number;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpError}.\r\n *\r\n * @param {string} errorMessage A descriptive error message.\r\n * @param {number} statusCode The HTTP status code represented by this error.\r\n */\r\n constructor(errorMessage: string, statusCode: number) {\r\n const trueProto = new.target.prototype;\r\n super(`${errorMessage}: Status code '${statusCode}'`);\r\n this.statusCode = statusCode;\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when a timeout elapses. */\r\nexport class TimeoutError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.TimeoutError}.\r\n *\r\n * @param {string} errorMessage A descriptive error message.\r\n */\r\n constructor(errorMessage: string = \"A timeout occurred.\") {\r\n const trueProto = new.target.prototype;\r\n super(errorMessage);\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when an action is aborted. */\r\nexport class AbortError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** Constructs a new instance of {@link AbortError}.\r\n *\r\n * @param {string} errorMessage A descriptive error message.\r\n */\r\n constructor(errorMessage: string = \"An abort occurred.\") {\r\n const trueProto = new.target.prototype;\r\n super(errorMessage);\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when the selected transport is unsupported by the browser. */\r\n/** @private */\r\nexport class UnsupportedTransportError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The {@link @microsoft/signalr.HttpTransportType} this error occurred on. */\r\n public transport: HttpTransportType;\r\n\r\n /** The type name of this error. */\r\n public errorType: string;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.UnsupportedTransportError}.\r\n *\r\n * @param {string} message A descriptive error message.\r\n * @param {HttpTransportType} transport The {@link @microsoft/signalr.HttpTransportType} this error occurred on.\r\n */\r\n constructor(message: string, transport: HttpTransportType) {\r\n const trueProto = new.target.prototype;\r\n super(message);\r\n this.transport = transport;\r\n this.errorType = 'UnsupportedTransportError';\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when the selected transport is disabled by the browser. */\r\n/** @private */\r\nexport class DisabledTransportError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The {@link @microsoft/signalr.HttpTransportType} this error occurred on. */\r\n public transport: HttpTransportType;\r\n\r\n /** The type name of this error. */\r\n public errorType: string;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.DisabledTransportError}.\r\n *\r\n * @param {string} message A descriptive error message.\r\n * @param {HttpTransportType} transport The {@link @microsoft/signalr.HttpTransportType} this error occurred on.\r\n */\r\n constructor(message: string, transport: HttpTransportType) {\r\n const trueProto = new.target.prototype;\r\n super(message);\r\n this.transport = transport;\r\n this.errorType = 'DisabledTransportError';\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when the selected transport cannot be started. */\r\n/** @private */\r\nexport class FailedToStartTransportError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The {@link @microsoft/signalr.HttpTransportType} this error occurred on. */\r\n public transport: HttpTransportType;\r\n\r\n /** The type name of this error. */\r\n public errorType: string;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.FailedToStartTransportError}.\r\n *\r\n * @param {string} message A descriptive error message.\r\n * @param {HttpTransportType} transport The {@link @microsoft/signalr.HttpTransportType} this error occurred on.\r\n */\r\n constructor(message: string, transport: HttpTransportType) {\r\n const trueProto = new.target.prototype;\r\n super(message);\r\n this.transport = transport;\r\n this.errorType = 'FailedToStartTransportError';\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when the negotiation with the server failed to complete. */\r\n/** @private */\r\nexport class FailedToNegotiateWithServerError extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The type name of this error. */\r\n public errorType: string;\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.FailedToNegotiateWithServerError}.\r\n *\r\n * @param {string} message A descriptive error message.\r\n */\r\n constructor(message: string) {\r\n const trueProto = new.target.prototype;\r\n super(message);\r\n this.errorType = 'FailedToNegotiateWithServerError';\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n\r\n/** Error thrown when multiple errors have occurred. */\r\n/** @private */\r\nexport class AggregateErrors extends Error {\r\n // @ts-ignore: Intentionally unused.\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private __proto__: Error;\r\n\r\n /** The collection of errors this error is aggregating. */\r\n public innerErrors: Error[];\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.AggregateErrors}.\r\n *\r\n * @param {string} message A descriptive error message.\r\n * @param {Error[]} innerErrors The collection of errors this error is aggregating.\r\n */\r\n constructor(message: string, innerErrors: Error[]) {\r\n const trueProto = new.target.prototype;\r\n super(message);\r\n\r\n this.innerErrors = innerErrors;\r\n\r\n // Workaround issue in Typescript compiler\r\n // https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200\r\n this.__proto__ = trueProto;\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AbortSignal } from \"./AbortController\";\r\nimport { MessageHeaders } from \"./IHubProtocol\";\r\n\r\n/** Represents an HTTP request. */\r\nexport interface HttpRequest {\r\n /** The HTTP method to use for the request. */\r\n method?: string;\r\n\r\n /** The URL for the request. */\r\n url?: string;\r\n\r\n /** The body content for the request. May be a string or an ArrayBuffer (for binary data). */\r\n content?: string | ArrayBuffer;\r\n\r\n /** An object describing headers to apply to the request. */\r\n headers?: MessageHeaders;\r\n\r\n /** The XMLHttpRequestResponseType to apply to the request. */\r\n responseType?: XMLHttpRequestResponseType;\r\n\r\n /** An AbortSignal that can be monitored for cancellation. */\r\n abortSignal?: AbortSignal;\r\n\r\n /** The time to wait for the request to complete before throwing a TimeoutError. Measured in milliseconds. */\r\n timeout?: number;\r\n\r\n /** This controls whether credentials such as cookies are sent in cross-site requests. */\r\n withCredentials?: boolean;\r\n}\r\n\r\n/** Represents an HTTP response. */\r\nexport class HttpResponse {\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpResponse} with the specified status code.\r\n *\r\n * @param {number} statusCode The status code of the response.\r\n */\r\n constructor(statusCode: number);\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpResponse} with the specified status code and message.\r\n *\r\n * @param {number} statusCode The status code of the response.\r\n * @param {string} statusText The status message of the response.\r\n */\r\n constructor(statusCode: number, statusText: string);\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpResponse} with the specified status code, message and string content.\r\n *\r\n * @param {number} statusCode The status code of the response.\r\n * @param {string} statusText The status message of the response.\r\n * @param {string} content The content of the response.\r\n */\r\n constructor(statusCode: number, statusText: string, content: string);\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpResponse} with the specified status code, message and binary content.\r\n *\r\n * @param {number} statusCode The status code of the response.\r\n * @param {string} statusText The status message of the response.\r\n * @param {ArrayBuffer} content The content of the response.\r\n */\r\n constructor(statusCode: number, statusText: string, content: ArrayBuffer);\r\n\r\n /** Constructs a new instance of {@link @microsoft/signalr.HttpResponse} with the specified status code, message and binary content.\r\n *\r\n * @param {number} statusCode The status code of the response.\r\n * @param {string} statusText The status message of the response.\r\n * @param {string | ArrayBuffer} content The content of the response.\r\n */\r\n constructor(statusCode: number, statusText: string, content: string | ArrayBuffer);\r\n constructor(\r\n public readonly statusCode: number,\r\n public readonly statusText?: string,\r\n public readonly content?: string | ArrayBuffer) {\r\n }\r\n}\r\n\r\n/** Abstraction over an HTTP client.\r\n *\r\n * This class provides an abstraction over an HTTP client so that a different implementation can be provided on different platforms.\r\n */\r\nexport abstract class HttpClient {\r\n /** Issues an HTTP GET request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public get(url: string): Promise;\r\n\r\n /** Issues an HTTP GET request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @param {HttpRequest} options Additional options to configure the request. The 'url' field in this object will be overridden by the url parameter.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public get(url: string, options: HttpRequest): Promise;\r\n public get(url: string, options?: HttpRequest): Promise {\r\n return this.send({\r\n ...options,\r\n method: \"GET\",\r\n url,\r\n });\r\n }\r\n\r\n /** Issues an HTTP POST request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public post(url: string): Promise;\r\n\r\n /** Issues an HTTP POST request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @param {HttpRequest} options Additional options to configure the request. The 'url' field in this object will be overridden by the url parameter.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public post(url: string, options: HttpRequest): Promise;\r\n public post(url: string, options?: HttpRequest): Promise {\r\n return this.send({\r\n ...options,\r\n method: \"POST\",\r\n url,\r\n });\r\n }\r\n\r\n /** Issues an HTTP DELETE request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public delete(url: string): Promise;\r\n\r\n /** Issues an HTTP DELETE request to the specified URL, returning a Promise that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {string} url The URL for the request.\r\n * @param {HttpRequest} options Additional options to configure the request. The 'url' field in this object will be overridden by the url parameter.\r\n * @returns {Promise} A Promise that resolves with an {@link @microsoft/signalr.HttpResponse} describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public delete(url: string, options: HttpRequest): Promise;\r\n public delete(url: string, options?: HttpRequest): Promise {\r\n return this.send({\r\n ...options,\r\n method: \"DELETE\",\r\n url,\r\n });\r\n }\r\n\r\n /** Issues an HTTP request to the specified URL, returning a {@link Promise} that resolves with an {@link @microsoft/signalr.HttpResponse} representing the result.\r\n *\r\n * @param {HttpRequest} request An {@link @microsoft/signalr.HttpRequest} describing the request to send.\r\n * @returns {Promise} A Promise that resolves with an HttpResponse describing the response, or rejects with an Error indicating a failure.\r\n */\r\n public abstract send(request: HttpRequest): Promise;\r\n\r\n /** Gets all cookies that apply to the specified URL.\r\n *\r\n * @param url The URL that the cookies are valid for.\r\n * @returns {string} A string containing all the key-value cookie pairs for the specified URL.\r\n */\r\n // @ts-ignore\r\n public getCookieString(url: string): string {\r\n return \"\";\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// These values are designed to match the ASP.NET Log Levels since that's the pattern we're emulating here.\r\n/** Indicates the severity of a log message.\r\n *\r\n * Log Levels are ordered in increasing severity. So `Debug` is more severe than `Trace`, etc.\r\n */\r\nexport enum LogLevel {\r\n /** Log level for very low severity diagnostic messages. */\r\n Trace = 0,\r\n /** Log level for low severity diagnostic messages. */\r\n Debug = 1,\r\n /** Log level for informational diagnostic messages. */\r\n Information = 2,\r\n /** Log level for diagnostic messages that indicate a non-fatal problem. */\r\n Warning = 3,\r\n /** Log level for diagnostic messages that indicate a failure in the current operation. */\r\n Error = 4,\r\n /** Log level for diagnostic messages that indicate a failure that will terminate the entire application. */\r\n Critical = 5,\r\n /** The highest possible log level. Used when configuring logging to indicate that no log messages should be emitted. */\r\n None = 6,\r\n}\r\n\r\n/** An abstraction that provides a sink for diagnostic messages. */\r\nexport interface ILogger {\r\n /** Called by the framework to emit a diagnostic message.\r\n *\r\n * @param {LogLevel} logLevel The severity level of the message.\r\n * @param {string} message The message.\r\n */\r\n log(logLevel: LogLevel, message: string): void;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\n\r\n/** A logger that does nothing when log messages are sent to it. */\r\nexport class NullLogger implements ILogger {\r\n /** The singleton instance of the {@link @microsoft/signalr.NullLogger}. */\r\n public static instance: ILogger = new NullLogger();\r\n\r\n private constructor() {}\r\n\r\n /** @inheritDoc */\r\n // eslint-disable-next-line\r\n public log(_logLevel: LogLevel, _message: string): void {\r\n }\r\n}\r\n", "export const VERSION = '10.0.0';", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HttpClient } from \"./HttpClient\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { NullLogger } from \"./Loggers\";\r\nimport { IStreamSubscriber, ISubscription } from \"./Stream\";\r\nimport { Subject } from \"./Subject\";\r\nimport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\nimport { VERSION } from \"./pkg-version\";\r\n\r\n// Version token that will be replaced by the prepack command\r\n/** The version of the SignalR client. */\r\n\r\nexport { VERSION };\r\n/** @private */\r\nexport class Arg {\r\n public static isRequired(val: any, name: string): void {\r\n if (val === null || val === undefined) {\r\n throw new Error(`The '${name}' argument is required.`);\r\n }\r\n }\r\n public static isNotEmpty(val: string, name: string): void {\r\n if (!val || val.match(/^\\s*$/)) {\r\n throw new Error(`The '${name}' argument should not be empty.`);\r\n }\r\n }\r\n\r\n public static isIn(val: any, values: any, name: string): void {\r\n // TypeScript enums have keys for **both** the name and the value of each enum member on the type itself.\r\n if (!(val in values)) {\r\n throw new Error(`Unknown ${name} value: ${val}.`);\r\n }\r\n }\r\n}\r\n\r\n/** @private */\r\nexport class Platform {\r\n // react-native has a window but no document so we should check both\r\n public static get isBrowser(): boolean {\r\n return !Platform.isNode && typeof window === \"object\" && typeof window.document === \"object\";\r\n }\r\n\r\n // WebWorkers don't have a window object so the isBrowser check would fail\r\n public static get isWebWorker(): boolean {\r\n return !Platform.isNode && typeof self === \"object\" && \"importScripts\" in self;\r\n }\r\n\r\n // react-native has a window but no document\r\n static get isReactNative(): boolean {\r\n return !Platform.isNode && typeof window === \"object\" && typeof window.document === \"undefined\";\r\n }\r\n\r\n // Node apps shouldn't have a window object, but WebWorkers don't either\r\n // so we need to check for both WebWorker and window\r\n public static get isNode(): boolean {\r\n return typeof process !== \"undefined\" && process.release && process.release.name === \"node\";\r\n }\r\n}\r\n\r\n/** @private */\r\nexport function getDataDetail(data: any, includeContent: boolean): string {\r\n let detail = \"\";\r\n if (isArrayBuffer(data)) {\r\n detail = `Binary data of length ${data.byteLength}`;\r\n if (includeContent) {\r\n detail += `. Content: '${formatArrayBuffer(data)}'`;\r\n }\r\n } else if (typeof data === \"string\") {\r\n detail = `String data of length ${data.length}`;\r\n if (includeContent) {\r\n detail += `. Content: '${data}'`;\r\n }\r\n }\r\n return detail;\r\n}\r\n\r\n/** @private */\r\nexport function formatArrayBuffer(data: ArrayBuffer): string {\r\n const view = new Uint8Array(data);\r\n\r\n // Uint8Array.map only supports returning another Uint8Array?\r\n let str = \"\";\r\n view.forEach((num) => {\r\n const pad = num < 16 ? \"0\" : \"\";\r\n str += `0x${pad}${num.toString(16)} `;\r\n });\r\n\r\n // Trim of trailing space.\r\n return str.substring(0, str.length - 1);\r\n}\r\n\r\n// Also in signalr-protocol-msgpack/Utils.ts\r\n/** @private */\r\nexport function isArrayBuffer(val: any): val is ArrayBuffer {\r\n return val && typeof ArrayBuffer !== \"undefined\" &&\r\n (val instanceof ArrayBuffer ||\r\n // Sometimes we get an ArrayBuffer that doesn't satisfy instanceof\r\n (val.constructor && val.constructor.name === \"ArrayBuffer\"));\r\n}\r\n\r\n/** @private */\r\nexport async function sendMessage(logger: ILogger, transportName: string, httpClient: HttpClient, url: string,\r\n content: string | ArrayBuffer, options: IHttpConnectionOptions): Promise {\r\n const headers: {[k: string]: string} = {};\r\n\r\n const [name, value] = getUserAgentHeader();\r\n headers[name] = value;\r\n\r\n logger.log(LogLevel.Trace, `(${transportName} transport) sending data. ${getDataDetail(content, options.logMessageContent!)}.`);\r\n\r\n const responseType = isArrayBuffer(content) ? \"arraybuffer\" : \"text\";\r\n const response = await httpClient.post(url, {\r\n content,\r\n headers: { ...headers, ...options.headers},\r\n responseType,\r\n timeout: options.timeout,\r\n withCredentials: options.withCredentials,\r\n });\r\n\r\n logger.log(LogLevel.Trace, `(${transportName} transport) request complete. Response status: ${response.statusCode}.`);\r\n}\r\n\r\n/** @private */\r\nexport function createLogger(logger?: ILogger | LogLevel): ILogger {\r\n if (logger === undefined) {\r\n return new ConsoleLogger(LogLevel.Information);\r\n }\r\n\r\n if (logger === null) {\r\n return NullLogger.instance;\r\n }\r\n\r\n if ((logger as ILogger).log !== undefined) {\r\n return logger as ILogger;\r\n }\r\n\r\n return new ConsoleLogger(logger as LogLevel);\r\n}\r\n\r\n/** @private */\r\nexport class SubjectSubscription implements ISubscription {\r\n private _subject: Subject;\r\n private _observer: IStreamSubscriber;\r\n\r\n constructor(subject: Subject, observer: IStreamSubscriber) {\r\n this._subject = subject;\r\n this._observer = observer;\r\n }\r\n\r\n public dispose(): void {\r\n const index: number = this._subject.observers.indexOf(this._observer);\r\n if (index > -1) {\r\n this._subject.observers.splice(index, 1);\r\n }\r\n\r\n if (this._subject.observers.length === 0 && this._subject.cancelCallback) {\r\n this._subject.cancelCallback().catch((_) => { });\r\n }\r\n }\r\n}\r\n\r\n/** @private */\r\nexport class ConsoleLogger implements ILogger {\r\n private readonly _minLevel: LogLevel;\r\n\r\n // Public for testing purposes.\r\n public out: {\r\n error(message: any): void,\r\n warn(message: any): void,\r\n info(message: any): void,\r\n log(message: any): void,\r\n };\r\n\r\n constructor(minimumLogLevel: LogLevel) {\r\n this._minLevel = minimumLogLevel;\r\n this.out = console;\r\n }\r\n\r\n public log(logLevel: LogLevel, message: string): void {\r\n if (logLevel >= this._minLevel) {\r\n const msg = `[${new Date().toISOString()}] ${LogLevel[logLevel]}: ${message}`;\r\n switch (logLevel) {\r\n case LogLevel.Critical:\r\n case LogLevel.Error:\r\n this.out.error(msg);\r\n break;\r\n case LogLevel.Warning:\r\n this.out.warn(msg);\r\n break;\r\n case LogLevel.Information:\r\n this.out.info(msg);\r\n break;\r\n default:\r\n // console.debug only goes to attached debuggers in Node, so we use console.log for Trace and Debug\r\n this.out.log(msg);\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/** @private */\r\nexport function getUserAgentHeader(): [string, string] {\r\n let userAgentHeaderName = \"X-SignalR-User-Agent\";\r\n if (Platform.isNode) {\r\n userAgentHeaderName = \"User-Agent\";\r\n }\r\n return [ userAgentHeaderName, constructUserAgent(VERSION, getOsName(), getRuntime(), getRuntimeVersion()) ];\r\n}\r\n\r\n/** @private */\r\nexport function constructUserAgent(version: string, os: string, runtime: string, runtimeVersion: string | undefined): string {\r\n // Microsoft SignalR/[Version] ([Detailed Version]; [Operating System]; [Runtime]; [Runtime Version])\r\n let userAgent: string = \"Microsoft SignalR/\";\r\n\r\n const majorAndMinor = version.split(\".\");\r\n userAgent += `${majorAndMinor[0]}.${majorAndMinor[1]}`;\r\n userAgent += ` (${version}; `;\r\n\r\n if (os && os !== \"\") {\r\n userAgent += `${os}; `;\r\n } else {\r\n userAgent += \"Unknown OS; \";\r\n }\r\n\r\n userAgent += `${runtime}`;\r\n\r\n if (runtimeVersion) {\r\n userAgent += `; ${runtimeVersion}`;\r\n } else {\r\n userAgent += \"; Unknown Runtime Version\";\r\n }\r\n\r\n userAgent += \")\";\r\n return userAgent;\r\n}\r\n\r\n// eslint-disable-next-line spaced-comment\r\n/*#__PURE__*/ function getOsName(): string {\r\n if (Platform.isNode) {\r\n switch (process.platform) {\r\n case \"win32\":\r\n return \"Windows NT\";\r\n case \"darwin\":\r\n return \"macOS\";\r\n case \"linux\":\r\n return \"Linux\";\r\n default:\r\n return process.platform;\r\n }\r\n } else {\r\n return \"\";\r\n }\r\n}\r\n\r\n// eslint-disable-next-line spaced-comment\r\n/*#__PURE__*/ function getRuntimeVersion(): string | undefined {\r\n if (Platform.isNode) {\r\n return process.versions.node;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction getRuntime(): string {\r\n if (Platform.isNode) {\r\n return \"NodeJS\";\r\n } else {\r\n return \"Browser\";\r\n }\r\n}\r\n\r\n/** @private */\r\nexport function getErrorString(e: any): string {\r\n if (e.stack) {\r\n return e.stack;\r\n } else if (e.message) {\r\n return e.message;\r\n }\r\n return `${e}`;\r\n}\r\n\r\n/** @private */\r\nexport function getGlobalThis(): unknown {\r\n // globalThis is semi-new and not available in Node until v12\r\n if (typeof globalThis !== \"undefined\") {\r\n return globalThis;\r\n }\r\n if (typeof self !== \"undefined\") {\r\n return self;\r\n }\r\n if (typeof window !== \"undefined\") {\r\n return window;\r\n }\r\n if (typeof global !== \"undefined\") {\r\n return global;\r\n }\r\n throw new Error(\"could not find global\");\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// @ts-ignore: This will be removed from built files and is here to make the types available during dev work\r\nimport { CookieJar } from \"@types/tough-cookie\";\r\n\r\nimport { AbortError, HttpError, TimeoutError } from \"./Errors\";\r\nimport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { Platform, getGlobalThis, isArrayBuffer } from \"./Utils\";\r\n\r\nexport class FetchHttpClient extends HttpClient {\r\n private readonly _abortControllerType: { prototype: AbortController, new(): AbortController };\r\n private readonly _fetchType: (input: RequestInfo, init?: RequestInit) => Promise;\r\n private readonly _jar?: CookieJar;\r\n\r\n private readonly _logger: ILogger;\r\n\r\n public constructor(logger: ILogger) {\r\n super();\r\n this._logger = logger;\r\n\r\n // Node added a fetch implementation to the global scope starting in v18.\r\n // We need to add a cookie jar in node to be able to share cookies with WebSocket\r\n if (typeof fetch === \"undefined\" || Platform.isNode) {\r\n // In order to ignore the dynamic require in webpack builds we need to do this magic\r\n // @ts-ignore: TS doesn't know about these names\r\n const requireFunc = typeof __webpack_require__ === \"function\" ? __non_webpack_require__ : require;\r\n\r\n // Cookies aren't automatically handled in Node so we need to add a CookieJar to preserve cookies across requests\r\n this._jar = new (requireFunc(\"tough-cookie\")).CookieJar();\r\n\r\n if (typeof fetch === \"undefined\") {\r\n this._fetchType = requireFunc(\"node-fetch\");\r\n } else {\r\n // Use fetch from Node if available\r\n this._fetchType = fetch;\r\n }\r\n\r\n // node-fetch doesn't have a nice API for getting and setting cookies\r\n // fetch-cookie will wrap a fetch implementation with a default CookieJar or a provided one\r\n this._fetchType = requireFunc(\"fetch-cookie\")(this._fetchType, this._jar);\r\n } else {\r\n this._fetchType = fetch.bind(getGlobalThis());\r\n }\r\n if (typeof AbortController === \"undefined\") {\r\n // In order to ignore the dynamic require in webpack builds we need to do this magic\r\n // @ts-ignore: TS doesn't know about these names\r\n const requireFunc = typeof __webpack_require__ === \"function\" ? __non_webpack_require__ : require;\r\n\r\n // Node needs EventListener methods on AbortController which our custom polyfill doesn't provide\r\n this._abortControllerType = requireFunc(\"abort-controller\");\r\n } else {\r\n this._abortControllerType = AbortController;\r\n }\r\n }\r\n\r\n /** @inheritDoc */\r\n public async send(request: HttpRequest): Promise {\r\n // Check that abort was not signaled before calling send\r\n if (request.abortSignal && request.abortSignal.aborted) {\r\n throw new AbortError();\r\n }\r\n\r\n if (!request.method) {\r\n throw new Error(\"No method defined.\");\r\n }\r\n if (!request.url) {\r\n throw new Error(\"No url defined.\");\r\n }\r\n\r\n const abortController = new this._abortControllerType();\r\n\r\n let error: any;\r\n // Hook our abortSignal into the abort controller\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = () => {\r\n abortController.abort();\r\n error = new AbortError();\r\n };\r\n }\r\n\r\n // If a timeout has been passed in, setup a timeout to call abort\r\n // Type needs to be any to fit window.setTimeout and NodeJS.setTimeout\r\n let timeoutId: any = null;\r\n if (request.timeout) {\r\n const msTimeout = request.timeout!;\r\n timeoutId = setTimeout(() => {\r\n abortController.abort();\r\n this._logger.log(LogLevel.Warning, `Timeout from HTTP request.`);\r\n error = new TimeoutError();\r\n }, msTimeout);\r\n }\r\n\r\n if (request.content === \"\") {\r\n request.content = undefined;\r\n }\r\n if (request.content) {\r\n // Explicitly setting the Content-Type header for React Native on Android platform.\r\n request.headers = request.headers || {};\r\n if (isArrayBuffer(request.content)) {\r\n request.headers[\"Content-Type\"] = \"application/octet-stream\";\r\n } else {\r\n request.headers[\"Content-Type\"] = \"text/plain;charset=UTF-8\";\r\n }\r\n }\r\n\r\n let response: Response;\r\n try {\r\n response = await this._fetchType(request.url!, {\r\n body: request.content,\r\n cache: \"no-cache\",\r\n credentials: request.withCredentials === true ? \"include\" : \"same-origin\",\r\n headers: {\r\n \"X-Requested-With\": \"XMLHttpRequest\",\r\n ...request.headers,\r\n },\r\n method: request.method!,\r\n mode: \"cors\",\r\n redirect: \"follow\",\r\n signal: abortController.signal,\r\n });\r\n } catch (e) {\r\n if (error) {\r\n throw error;\r\n }\r\n this._logger.log(\r\n LogLevel.Warning,\r\n `Error from HTTP request. ${e}.`,\r\n );\r\n throw e;\r\n } finally {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = null;\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n const errorMessage = await deserializeContent(response, \"text\") as string;\r\n throw new HttpError(errorMessage || response.statusText, response.status);\r\n }\r\n\r\n const content = deserializeContent(response, request.responseType);\r\n const payload = await content;\r\n\r\n return new HttpResponse(\r\n response.status,\r\n response.statusText,\r\n payload,\r\n );\r\n }\r\n\r\n public getCookieString(url: string): string {\r\n let cookies: string = \"\";\r\n if (Platform.isNode && this._jar) {\r\n // @ts-ignore: unused variable\r\n this._jar.getCookies(url, (e, c) => cookies = c.join(\"; \"));\r\n }\r\n return cookies;\r\n }\r\n}\r\n\r\nfunction deserializeContent(response: Response, responseType?: XMLHttpRequestResponseType): Promise {\r\n let content;\r\n switch (responseType) {\r\n case \"arraybuffer\":\r\n content = response.arrayBuffer();\r\n break;\r\n case \"text\":\r\n content = response.text();\r\n break;\r\n case \"blob\":\r\n case \"document\":\r\n case \"json\":\r\n throw new Error(`${responseType} is not supported.`);\r\n default:\r\n content = response.text();\r\n break;\r\n }\r\n\r\n return content;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AbortError, HttpError, TimeoutError } from \"./Errors\";\r\nimport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { isArrayBuffer } from \"./Utils\";\r\n\r\nexport class XhrHttpClient extends HttpClient {\r\n private readonly _logger: ILogger;\r\n\r\n public constructor(logger: ILogger) {\r\n super();\r\n this._logger = logger;\r\n }\r\n\r\n /** @inheritDoc */\r\n public send(request: HttpRequest): Promise {\r\n // Check that abort was not signaled before calling send\r\n if (request.abortSignal && request.abortSignal.aborted) {\r\n return Promise.reject(new AbortError());\r\n }\r\n\r\n if (!request.method) {\r\n return Promise.reject(new Error(\"No method defined.\"));\r\n }\r\n if (!request.url) {\r\n return Promise.reject(new Error(\"No url defined.\"));\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest();\r\n\r\n xhr.open(request.method!, request.url!, true);\r\n xhr.withCredentials = request.withCredentials === undefined ? true : request.withCredentials;\r\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\r\n if (request.content === \"\") {\r\n request.content = undefined;\r\n }\r\n if (request.content) {\r\n // Explicitly setting the Content-Type header for React Native on Android platform.\r\n if (isArrayBuffer(request.content)) {\r\n xhr.setRequestHeader(\"Content-Type\", \"application/octet-stream\");\r\n } else {\r\n xhr.setRequestHeader(\"Content-Type\", \"text/plain;charset=UTF-8\");\r\n }\r\n }\r\n\r\n const headers = request.headers;\r\n if (headers) {\r\n Object.keys(headers)\r\n .forEach((header) => {\r\n xhr.setRequestHeader(header, headers[header]);\r\n });\r\n }\r\n\r\n if (request.responseType) {\r\n xhr.responseType = request.responseType;\r\n }\r\n\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = () => {\r\n xhr.abort();\r\n reject(new AbortError());\r\n };\r\n }\r\n\r\n if (request.timeout) {\r\n xhr.timeout = request.timeout;\r\n }\r\n\r\n xhr.onload = () => {\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = null;\r\n }\r\n\r\n if (xhr.status >= 200 && xhr.status < 300) {\r\n resolve(new HttpResponse(xhr.status, xhr.statusText, xhr.response || xhr.responseText));\r\n } else {\r\n reject(new HttpError(xhr.response || xhr.responseText || xhr.statusText, xhr.status));\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n this._logger.log(LogLevel.Warning, `Error from HTTP request. ${xhr.status}: ${xhr.statusText}.`);\r\n reject(new HttpError(xhr.statusText, xhr.status));\r\n };\r\n\r\n xhr.ontimeout = () => {\r\n this._logger.log(LogLevel.Warning, `Timeout from HTTP request.`);\r\n reject(new TimeoutError());\r\n };\r\n\r\n xhr.send(request.content);\r\n });\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AbortError } from \"./Errors\";\r\nimport { FetchHttpClient } from \"./FetchHttpClient\";\r\nimport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\nimport { ILogger } from \"./ILogger\";\r\nimport { Platform } from \"./Utils\";\r\nimport { XhrHttpClient } from \"./XhrHttpClient\";\r\n\r\n/** Default implementation of {@link @microsoft/signalr.HttpClient}. */\r\nexport class DefaultHttpClient extends HttpClient {\r\n private readonly _httpClient: HttpClient;\r\n\r\n /** Creates a new instance of the {@link @microsoft/signalr.DefaultHttpClient}, using the provided {@link @microsoft/signalr.ILogger} to log messages. */\r\n public constructor(logger: ILogger) {\r\n super();\r\n\r\n if (typeof fetch !== \"undefined\" || Platform.isNode) {\r\n this._httpClient = new FetchHttpClient(logger);\r\n } else if (typeof XMLHttpRequest !== \"undefined\") {\r\n this._httpClient = new XhrHttpClient(logger);\r\n } else {\r\n throw new Error(\"No usable HttpClient found.\");\r\n }\r\n }\r\n\r\n /** @inheritDoc */\r\n public send(request: HttpRequest): Promise {\r\n // Check that abort was not signaled before calling send\r\n if (request.abortSignal && request.abortSignal.aborted) {\r\n return Promise.reject(new AbortError());\r\n }\r\n\r\n if (!request.method) {\r\n return Promise.reject(new Error(\"No method defined.\"));\r\n }\r\n if (!request.url) {\r\n return Promise.reject(new Error(\"No url defined.\"));\r\n }\r\n\r\n return this._httpClient.send(request);\r\n }\r\n\r\n public getCookieString(url: string): string {\r\n return this._httpClient.getCookieString(url);\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// Not exported from index\r\n/** @private */\r\nexport class TextMessageFormat {\r\n public static RecordSeparatorCode = 0x1e;\r\n public static RecordSeparator = String.fromCharCode(TextMessageFormat.RecordSeparatorCode);\r\n\r\n public static write(output: string): string {\r\n return `${output}${TextMessageFormat.RecordSeparator}`;\r\n }\r\n\r\n public static parse(input: string): string[] {\r\n if (input[input.length - 1] !== TextMessageFormat.RecordSeparator) {\r\n throw new Error(\"Message is incomplete.\");\r\n }\r\n\r\n const messages = input.split(TextMessageFormat.RecordSeparator);\r\n messages.pop();\r\n return messages;\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { TextMessageFormat } from \"./TextMessageFormat\";\r\nimport { isArrayBuffer } from \"./Utils\";\r\n\r\n/** @private */\r\nexport interface HandshakeRequestMessage {\r\n readonly protocol: string;\r\n readonly version: number;\r\n}\r\n\r\n/** @private */\r\nexport interface HandshakeResponseMessage {\r\n readonly error: string;\r\n readonly minorVersion: number;\r\n}\r\n\r\n/** @private */\r\nexport class HandshakeProtocol {\r\n // Handshake request is always JSON\r\n public writeHandshakeRequest(handshakeRequest: HandshakeRequestMessage): string {\r\n return TextMessageFormat.write(JSON.stringify(handshakeRequest));\r\n }\r\n\r\n public parseHandshakeResponse(data: any): [any, HandshakeResponseMessage] {\r\n let messageData: string;\r\n let remainingData: any;\r\n\r\n if (isArrayBuffer(data)) {\r\n // Format is binary but still need to read JSON text from handshake response\r\n const binaryData = new Uint8Array(data);\r\n const separatorIndex = binaryData.indexOf(TextMessageFormat.RecordSeparatorCode);\r\n if (separatorIndex === -1) {\r\n throw new Error(\"Message is incomplete.\");\r\n }\r\n\r\n // content before separator is handshake response\r\n // optional content after is additional messages\r\n const responseLength = separatorIndex + 1;\r\n messageData = String.fromCharCode.apply(null, Array.prototype.slice.call(binaryData.slice(0, responseLength)));\r\n remainingData = (binaryData.byteLength > responseLength) ? binaryData.slice(responseLength).buffer : null;\r\n } else {\r\n const textData: string = data;\r\n const separatorIndex = textData.indexOf(TextMessageFormat.RecordSeparator);\r\n if (separatorIndex === -1) {\r\n throw new Error(\"Message is incomplete.\");\r\n }\r\n\r\n // content before separator is handshake response\r\n // optional content after is additional messages\r\n const responseLength = separatorIndex + 1;\r\n messageData = textData.substring(0, responseLength);\r\n remainingData = (textData.length > responseLength) ? textData.substring(responseLength) : null;\r\n }\r\n\r\n // At this point we should have just the single handshake message\r\n const messages = TextMessageFormat.parse(messageData);\r\n const response = JSON.parse(messages[0]);\r\n if (response.type) {\r\n throw new Error(\"Expected a handshake response from the server.\");\r\n }\r\n const responseMessage: HandshakeResponseMessage = response;\r\n\r\n // multiple messages could have arrived with handshake\r\n // return additional data to be parsed as usual, or null if all parsed\r\n return [remainingData, responseMessage];\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { ILogger } from \"./ILogger\";\r\nimport { TransferFormat } from \"./ITransport\";\r\n\r\n/** Defines the type of a Hub Message. */\r\nexport enum MessageType {\r\n /** Indicates the message is an Invocation message and implements the {@link @microsoft/signalr.InvocationMessage} interface. */\r\n Invocation = 1,\r\n /** Indicates the message is a StreamItem message and implements the {@link @microsoft/signalr.StreamItemMessage} interface. */\r\n StreamItem = 2,\r\n /** Indicates the message is a Completion message and implements the {@link @microsoft/signalr.CompletionMessage} interface. */\r\n Completion = 3,\r\n /** Indicates the message is a Stream Invocation message and implements the {@link @microsoft/signalr.StreamInvocationMessage} interface. */\r\n StreamInvocation = 4,\r\n /** Indicates the message is a Cancel Invocation message and implements the {@link @microsoft/signalr.CancelInvocationMessage} interface. */\r\n CancelInvocation = 5,\r\n /** Indicates the message is a Ping message and implements the {@link @microsoft/signalr.PingMessage} interface. */\r\n Ping = 6,\r\n /** Indicates the message is a Close message and implements the {@link @microsoft/signalr.CloseMessage} interface. */\r\n Close = 7,\r\n Ack = 8,\r\n Sequence = 9\r\n}\r\n\r\n/** Defines a dictionary of string keys and string values representing headers attached to a Hub message. */\r\nexport interface MessageHeaders {\r\n /** Gets or sets the header with the specified key. */\r\n [key: string]: string;\r\n}\r\n\r\n/** Union type of all known Hub messages. */\r\nexport type HubMessage =\r\n InvocationMessage |\r\n StreamInvocationMessage |\r\n StreamItemMessage |\r\n CompletionMessage |\r\n CancelInvocationMessage |\r\n PingMessage |\r\n CloseMessage |\r\n AckMessage |\r\n SequenceMessage;\r\n\r\n/** Defines properties common to all Hub messages. */\r\nexport interface HubMessageBase {\r\n /** A {@link @microsoft/signalr.MessageType} value indicating the type of this message. */\r\n readonly type: MessageType;\r\n}\r\n\r\n/** Defines properties common to all Hub messages relating to a specific invocation. */\r\nexport interface HubInvocationMessage extends HubMessageBase {\r\n /** A {@link @microsoft/signalr.MessageHeaders} dictionary containing headers attached to the message. */\r\n readonly headers?: MessageHeaders;\r\n /** The ID of the invocation relating to this message.\r\n *\r\n * This is expected to be present for {@link @microsoft/signalr.StreamInvocationMessage} and {@link @microsoft/signalr.CompletionMessage}. It may\r\n * be 'undefined' for an {@link @microsoft/signalr.InvocationMessage} if the sender does not expect a response.\r\n */\r\n readonly invocationId?: string;\r\n}\r\n\r\n/** A hub message representing a non-streaming invocation. */\r\nexport interface InvocationMessage extends HubInvocationMessage {\r\n /** @inheritDoc */\r\n readonly type: MessageType.Invocation;\r\n /** The target method name. */\r\n readonly target: string;\r\n /** The target method arguments. */\r\n readonly arguments: any[];\r\n /** The target methods stream IDs. */\r\n readonly streamIds?: string[];\r\n}\r\n\r\n/** A hub message representing a streaming invocation. */\r\nexport interface StreamInvocationMessage extends HubInvocationMessage {\r\n /** @inheritDoc */\r\n readonly type: MessageType.StreamInvocation;\r\n\r\n /** The invocation ID. */\r\n readonly invocationId: string;\r\n /** The target method name. */\r\n readonly target: string;\r\n /** The target method arguments. */\r\n readonly arguments: any[];\r\n /** The target methods stream IDs. */\r\n readonly streamIds?: string[];\r\n}\r\n\r\n/** A hub message representing a single item produced as part of a result stream. */\r\nexport interface StreamItemMessage extends HubInvocationMessage {\r\n /** @inheritDoc */\r\n readonly type: MessageType.StreamItem;\r\n\r\n /** The invocation ID. */\r\n readonly invocationId: string;\r\n\r\n /** The item produced by the server. */\r\n readonly item?: any;\r\n}\r\n\r\n/** A hub message representing the result of an invocation. */\r\nexport interface CompletionMessage extends HubInvocationMessage {\r\n /** @inheritDoc */\r\n readonly type: MessageType.Completion;\r\n /** The invocation ID. */\r\n readonly invocationId: string;\r\n /** The error produced by the invocation, if any.\r\n *\r\n * Either {@link @microsoft/signalr.CompletionMessage.error} or {@link @microsoft/signalr.CompletionMessage.result} must be defined, but not both.\r\n */\r\n readonly error?: string;\r\n /** The result produced by the invocation, if any.\r\n *\r\n * Either {@link @microsoft/signalr.CompletionMessage.error} or {@link @microsoft/signalr.CompletionMessage.result} must be defined, but not both.\r\n */\r\n readonly result?: any;\r\n}\r\n\r\n/** A hub message indicating that the sender is still active. */\r\nexport interface PingMessage extends HubMessageBase {\r\n /** @inheritDoc */\r\n readonly type: MessageType.Ping;\r\n}\r\n\r\n/** A hub message indicating that the sender is closing the connection.\r\n *\r\n * If {@link @microsoft/signalr.CloseMessage.error} is defined, the sender is closing the connection due to an error.\r\n */\r\nexport interface CloseMessage extends HubMessageBase {\r\n /** @inheritDoc */\r\n readonly type: MessageType.Close;\r\n /** The error that triggered the close, if any.\r\n *\r\n * If this property is undefined, the connection was closed normally and without error.\r\n */\r\n readonly error?: string;\r\n\r\n /** If true, clients with automatic reconnects enabled should attempt to reconnect after receiving the CloseMessage. Otherwise, they should not. */\r\n readonly allowReconnect?: boolean;\r\n}\r\n\r\n/** A hub message sent to request that a streaming invocation be canceled. */\r\nexport interface CancelInvocationMessage extends HubInvocationMessage {\r\n /** @inheritDoc */\r\n readonly type: MessageType.CancelInvocation;\r\n /** The invocation ID. */\r\n readonly invocationId: string;\r\n}\r\n\r\nexport interface AckMessage extends HubMessageBase\r\n{\r\n readonly type: MessageType.Ack;\r\n\r\n readonly sequenceId: number;\r\n}\r\n\r\nexport interface SequenceMessage extends HubMessageBase\r\n{\r\n readonly type: MessageType.Sequence;\r\n\r\n readonly sequenceId: number;\r\n}\r\n\r\n/** A protocol abstraction for communicating with SignalR Hubs. */\r\nexport interface IHubProtocol {\r\n /** The name of the protocol. This is used by SignalR to resolve the protocol between the client and server. */\r\n readonly name: string;\r\n /** The version of the protocol. */\r\n readonly version: number;\r\n /** The {@link @microsoft/signalr.TransferFormat} of the protocol. */\r\n readonly transferFormat: TransferFormat;\r\n\r\n /** Creates an array of {@link @microsoft/signalr.HubMessage} objects from the specified serialized representation.\r\n *\r\n * If {@link @microsoft/signalr.IHubProtocol.transferFormat} is 'Text', the `input` parameter must be a string, otherwise it must be an ArrayBuffer.\r\n *\r\n * @param {string | ArrayBuffer} input A string or ArrayBuffer containing the serialized representation.\r\n * @param {ILogger} logger A logger that will be used to log messages that occur during parsing.\r\n */\r\n parseMessages(input: string | ArrayBuffer, logger: ILogger): HubMessage[];\r\n\r\n /** Writes the specified {@link @microsoft/signalr.HubMessage} to a string or ArrayBuffer and returns it.\r\n *\r\n * If {@link @microsoft/signalr.IHubProtocol.transferFormat} is 'Text', the result of this method will be a string, otherwise it will be an ArrayBuffer.\r\n *\r\n * @param {HubMessage} message The message to write.\r\n * @returns {string | ArrayBuffer} A string or ArrayBuffer containing the serialized representation of the message.\r\n */\r\n writeMessage(message: HubMessage): string | ArrayBuffer;\r\n}", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { IStreamResult, IStreamSubscriber, ISubscription } from \"./Stream\";\r\nimport { SubjectSubscription } from \"./Utils\";\r\n\r\n/** Stream implementation to stream items to the server. */\r\nexport class Subject implements IStreamResult {\r\n /** @internal */\r\n public observers: IStreamSubscriber[];\r\n\r\n /** @internal */\r\n public cancelCallback?: () => Promise;\r\n\r\n constructor() {\r\n this.observers = [];\r\n }\r\n\r\n public next(item: T): void {\r\n for (const observer of this.observers) {\r\n observer.next(item);\r\n }\r\n }\r\n\r\n public error(err: any): void {\r\n for (const observer of this.observers) {\r\n if (observer.error) {\r\n observer.error(err);\r\n }\r\n }\r\n }\r\n\r\n public complete(): void {\r\n for (const observer of this.observers) {\r\n if (observer.complete) {\r\n observer.complete();\r\n }\r\n }\r\n }\r\n\r\n public subscribe(observer: IStreamSubscriber): ISubscription {\r\n this.observers.push(observer);\r\n return new SubjectSubscription(this, observer);\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { IConnection } from \"./IConnection\";\r\nimport { AckMessage, HubMessage, IHubProtocol, MessageType, SequenceMessage } from \"./IHubProtocol\";\r\nimport { isArrayBuffer } from \"./Utils\";\r\n\r\n/** @private */\r\nexport class MessageBuffer {\r\n private readonly _protocol: IHubProtocol;\r\n private readonly _connection: IConnection;\r\n\r\n private readonly _bufferSize: number = 100_000;\r\n\r\n private _messages: BufferedItem[] = [];\r\n private _totalMessageCount: number = 0;\r\n private _waitForSequenceMessage: boolean = false;\r\n\r\n // Message IDs start at 1 and always increment by 1\r\n private _nextReceivingSequenceId = 1;\r\n private _latestReceivedSequenceId = 0;\r\n private _bufferedByteCount: number = 0;\r\n private _reconnectInProgress: boolean = false;\r\n\r\n private _ackTimerHandle?: any;\r\n\r\n constructor(protocol: IHubProtocol, connection: IConnection, bufferSize: number) {\r\n this._protocol = protocol;\r\n this._connection = connection;\r\n this._bufferSize = bufferSize;\r\n }\r\n\r\n public async _send(message: HubMessage): Promise {\r\n const serializedMessage = this._protocol.writeMessage(message);\r\n\r\n let backpressurePromise: Promise = Promise.resolve();\r\n\r\n // Only count invocation messages. Acks, pings, etc. don't need to be resent on reconnect\r\n if (this._isInvocationMessage(message)) {\r\n this._totalMessageCount++;\r\n let backpressurePromiseResolver: (value: void) => void = () => {};\r\n let backpressurePromiseRejector: (value?: void) => void = () => {};\r\n\r\n if (isArrayBuffer(serializedMessage)) {\r\n this._bufferedByteCount += serializedMessage.byteLength;\r\n } else {\r\n this._bufferedByteCount += serializedMessage.length;\r\n }\r\n\r\n if (this._bufferedByteCount >= this._bufferSize) {\r\n backpressurePromise = new Promise((resolve, reject) => {\r\n backpressurePromiseResolver = resolve;\r\n backpressurePromiseRejector = reject;\r\n });\r\n }\r\n\r\n this._messages.push(new BufferedItem(serializedMessage, this._totalMessageCount,\r\n backpressurePromiseResolver, backpressurePromiseRejector));\r\n }\r\n\r\n try {\r\n // If this is set it means we are reconnecting or resending\r\n // We don't want to send on a disconnected connection\r\n // And we don't want to send if resend is running since that would mean sending\r\n // this message twice\r\n if (!this._reconnectInProgress) {\r\n await this._connection.send(serializedMessage);\r\n }\r\n } catch {\r\n this._disconnected();\r\n }\r\n await backpressurePromise;\r\n }\r\n\r\n public _ack(ackMessage: AckMessage): void {\r\n let newestAckedMessage = -1;\r\n\r\n // Find index of newest message being acked\r\n for (let index = 0; index < this._messages.length; index++) {\r\n const element = this._messages[index];\r\n if (element._id <= ackMessage.sequenceId) {\r\n newestAckedMessage = index;\r\n if (isArrayBuffer(element._message)) {\r\n this._bufferedByteCount -= element._message.byteLength;\r\n } else {\r\n this._bufferedByteCount -= element._message.length;\r\n }\r\n // resolve items that have already been sent and acked\r\n element._resolver();\r\n } else if (this._bufferedByteCount < this._bufferSize) {\r\n // resolve items that now fall under the buffer limit but haven't been acked\r\n element._resolver();\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n if (newestAckedMessage !== -1) {\r\n // We're removing everything including the message pointed to, so add 1\r\n this._messages = this._messages.slice(newestAckedMessage + 1);\r\n }\r\n }\r\n\r\n public _shouldProcessMessage(message: HubMessage): boolean {\r\n if (this._waitForSequenceMessage) {\r\n if (message.type !== MessageType.Sequence) {\r\n return false;\r\n } else {\r\n this._waitForSequenceMessage = false;\r\n return true;\r\n }\r\n }\r\n\r\n // No special processing for acks, pings, etc.\r\n if (!this._isInvocationMessage(message)) {\r\n return true;\r\n }\r\n\r\n const currentId = this._nextReceivingSequenceId;\r\n this._nextReceivingSequenceId++;\r\n if (currentId <= this._latestReceivedSequenceId) {\r\n if (currentId === this._latestReceivedSequenceId) {\r\n // Should only hit this if we just reconnected and the server is sending\r\n // Messages it has buffered, which would mean it hasn't seen an Ack for these messages\r\n this._ackTimer();\r\n }\r\n // Ignore, this is a duplicate message\r\n return false;\r\n }\r\n\r\n this._latestReceivedSequenceId = currentId;\r\n\r\n // Only start the timer for sending an Ack message when we have a message to ack. This also conveniently solves\r\n // timer throttling by not having a recursive timer, and by starting the timer via a network call (recv)\r\n this._ackTimer();\r\n return true;\r\n }\r\n\r\n public _resetSequence(message: SequenceMessage): void {\r\n if (message.sequenceId > this._nextReceivingSequenceId) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this._connection.stop(new Error(\"Sequence ID greater than amount of messages we've received.\"));\r\n return;\r\n }\r\n\r\n this._nextReceivingSequenceId = message.sequenceId;\r\n }\r\n\r\n public _disconnected(): void {\r\n this._reconnectInProgress = true;\r\n this._waitForSequenceMessage = true;\r\n }\r\n\r\n public async _resend(): Promise {\r\n const sequenceId = this._messages.length !== 0\r\n ? this._messages[0]._id\r\n : this._totalMessageCount + 1;\r\n await this._connection.send(this._protocol.writeMessage({ type: MessageType.Sequence, sequenceId }));\r\n\r\n // Get a local variable to the _messages, just in case messages are acked while resending\r\n // Which would slice the _messages array (which creates a new copy)\r\n const messages = this._messages;\r\n for (const element of messages) {\r\n await this._connection.send(element._message);\r\n }\r\n\r\n this._reconnectInProgress = false;\r\n }\r\n\r\n public _dispose(error?: Error): void {\r\n error ??= new Error(\"Unable to reconnect to server.\")\r\n\r\n // Unblock backpressure if any\r\n for (const element of this._messages) {\r\n element._rejector(error);\r\n }\r\n }\r\n\r\n private _isInvocationMessage(message: HubMessage): boolean {\r\n // There is no way to check if something implements an interface.\r\n // So we individually check the messages in a switch statement.\r\n // To make sure we don't miss any message types we rely on the compiler\r\n // seeing the function returns a value and it will do the\r\n // exhaustive check for us on the switch statement, since we don't use 'case default'\r\n switch (message.type) {\r\n case MessageType.Invocation:\r\n case MessageType.StreamItem:\r\n case MessageType.Completion:\r\n case MessageType.StreamInvocation:\r\n case MessageType.CancelInvocation:\r\n return true;\r\n case MessageType.Close:\r\n case MessageType.Sequence:\r\n case MessageType.Ping:\r\n case MessageType.Ack:\r\n return false;\r\n }\r\n }\r\n\r\n private _ackTimer(): void {\r\n if (this._ackTimerHandle === undefined) {\r\n this._ackTimerHandle = setTimeout(async () => {\r\n try {\r\n if (!this._reconnectInProgress) {\r\n await this._connection.send(this._protocol.writeMessage({ type: MessageType.Ack, sequenceId: this._latestReceivedSequenceId }))\r\n }\r\n // Ignore errors, that means the connection is closed and we don't care about the Ack message anymore.\r\n } catch { }\r\n\r\n clearTimeout(this._ackTimerHandle);\r\n this._ackTimerHandle = undefined;\r\n // 1 second delay so we don't spam Ack messages if there are many messages being received at once.\r\n }, 1000);\r\n }\r\n }\r\n}\r\n\r\nclass BufferedItem {\r\n constructor(message: string | ArrayBuffer, id: number, resolver: (value: void) => void, rejector: (value?: any) => void) {\r\n this._message = message;\r\n this._id = id;\r\n this._resolver = resolver;\r\n this._rejector = rejector;\r\n }\r\n\r\n _message: string | ArrayBuffer;\r\n _id: number;\r\n _resolver: (value: void) => void;\r\n _rejector: (value?: any) => void;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HandshakeProtocol, HandshakeRequestMessage, HandshakeResponseMessage } from \"./HandshakeProtocol\";\r\nimport { IConnection } from \"./IConnection\";\r\nimport { AbortError } from \"./Errors\";\r\nimport { CancelInvocationMessage, CloseMessage, CompletionMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from \"./IHubProtocol\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { IRetryPolicy } from \"./IRetryPolicy\";\r\nimport { IStreamResult } from \"./Stream\";\r\nimport { Subject } from \"./Subject\";\r\nimport { Arg, getErrorString, Platform } from \"./Utils\";\r\nimport { MessageBuffer } from \"./MessageBuffer\";\r\n\r\nconst DEFAULT_TIMEOUT_IN_MS: number = 30 * 1000;\r\nconst DEFAULT_PING_INTERVAL_IN_MS: number = 15 * 1000;\r\nconst DEFAULT_STATEFUL_RECONNECT_BUFFER_SIZE = 100_000;\r\n\r\n/** Describes the current state of the {@link HubConnection} to the server. */\r\nexport enum HubConnectionState {\r\n /** The hub connection is disconnected. */\r\n Disconnected = \"Disconnected\",\r\n /** The hub connection is connecting. */\r\n Connecting = \"Connecting\",\r\n /** The hub connection is connected. */\r\n Connected = \"Connected\",\r\n /** The hub connection is disconnecting. */\r\n Disconnecting = \"Disconnecting\",\r\n /** The hub connection is reconnecting. */\r\n Reconnecting = \"Reconnecting\",\r\n}\r\n\r\n/** Represents a connection to a SignalR Hub. */\r\nexport class HubConnection {\r\n private readonly _cachedPingMessage: string | ArrayBuffer;\r\n // Needs to not start with _ for tests\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private readonly connection: IConnection;\r\n private readonly _logger: ILogger;\r\n private readonly _reconnectPolicy?: IRetryPolicy;\r\n private readonly _statefulReconnectBufferSize: number;\r\n private _protocol: IHubProtocol;\r\n private _handshakeProtocol: HandshakeProtocol;\r\n private _callbacks: { [invocationId: string]: (invocationEvent: StreamItemMessage | CompletionMessage | null, error?: Error) => void };\r\n private _methods: { [name: string]: (((...args: any[]) => void) | ((...args: any[]) => any))[] };\r\n private _invocationId: number;\r\n private _messageBuffer?: MessageBuffer;\r\n\r\n private _closedCallbacks: ((error?: Error) => void)[];\r\n private _reconnectingCallbacks: ((error?: Error) => void)[];\r\n private _reconnectedCallbacks: ((connectionId?: string) => void)[];\r\n\r\n private _receivedHandshakeResponse: boolean;\r\n private _handshakeResolver!: (value?: PromiseLike<{}>) => void;\r\n private _handshakeRejecter!: (reason?: any) => void;\r\n private _stopDuringStartError?: Error;\r\n\r\n private _connectionState: HubConnectionState;\r\n // connectionStarted is tracked independently from connectionState, so we can check if the\r\n // connection ever did successfully transition from connecting to connected before disconnecting.\r\n private _connectionStarted: boolean;\r\n private _startPromise?: Promise;\r\n private _stopPromise?: Promise;\r\n private _nextKeepAlive: number = 0;\r\n\r\n // The type of these a) doesn't matter and b) varies when building in browser and node contexts\r\n // Since we're building the WebPack bundle directly from the TypeScript, this matters (previously\r\n // we built the bundle from the compiled JavaScript).\r\n private _reconnectDelayHandle?: any;\r\n private _timeoutHandle?: any;\r\n private _pingServerHandle?: any;\r\n\r\n private _freezeEventListener = () =>\r\n {\r\n this._logger.log(LogLevel.Warning, \"The page is being frozen, this will likely lead to the connection being closed and messages being lost. For more information see the docs at https://learn.microsoft.com/aspnet/core/signalr/javascript-client#bsleep\");\r\n };\r\n\r\n /** The server timeout in milliseconds.\r\n *\r\n * If this timeout elapses without receiving any messages from the server, the connection will be terminated with an error.\r\n * The default timeout value is 30,000 milliseconds (30 seconds).\r\n */\r\n public serverTimeoutInMilliseconds: number;\r\n\r\n /** Default interval at which to ping the server.\r\n *\r\n * The default value is 15,000 milliseconds (15 seconds).\r\n * Allows the server to detect hard disconnects (like when a client unplugs their computer).\r\n * The ping will happen at most as often as the server pings.\r\n * If the server pings every 5 seconds, a value lower than 5 will ping every 5 seconds.\r\n */\r\n public keepAliveIntervalInMilliseconds: number;\r\n\r\n /** @internal */\r\n // Using a public static factory method means we can have a private constructor and an _internal_\r\n // create method that can be used by HubConnectionBuilder. An \"internal\" constructor would just\r\n // be stripped away and the '.d.ts' file would have no constructor, which is interpreted as a\r\n // public parameter-less constructor.\r\n public static create(\r\n connection: IConnection,\r\n logger: ILogger,\r\n protocol: IHubProtocol,\r\n reconnectPolicy?: IRetryPolicy,\r\n serverTimeoutInMilliseconds?: number,\r\n keepAliveIntervalInMilliseconds?: number,\r\n statefulReconnectBufferSize?: number): HubConnection {\r\n return new HubConnection(connection, logger, protocol, reconnectPolicy,\r\n serverTimeoutInMilliseconds, keepAliveIntervalInMilliseconds, statefulReconnectBufferSize);\r\n }\r\n\r\n private constructor(\r\n connection: IConnection,\r\n logger: ILogger,\r\n protocol: IHubProtocol,\r\n reconnectPolicy?: IRetryPolicy,\r\n serverTimeoutInMilliseconds?: number,\r\n keepAliveIntervalInMilliseconds?: number,\r\n statefulReconnectBufferSize?: number) {\r\n Arg.isRequired(connection, \"connection\");\r\n Arg.isRequired(logger, \"logger\");\r\n Arg.isRequired(protocol, \"protocol\");\r\n\r\n this.serverTimeoutInMilliseconds = serverTimeoutInMilliseconds ?? DEFAULT_TIMEOUT_IN_MS;\r\n this.keepAliveIntervalInMilliseconds = keepAliveIntervalInMilliseconds ?? DEFAULT_PING_INTERVAL_IN_MS;\r\n\r\n this._statefulReconnectBufferSize = statefulReconnectBufferSize ?? DEFAULT_STATEFUL_RECONNECT_BUFFER_SIZE;\r\n\r\n this._logger = logger;\r\n this._protocol = protocol;\r\n this.connection = connection;\r\n this._reconnectPolicy = reconnectPolicy;\r\n this._handshakeProtocol = new HandshakeProtocol();\r\n\r\n this.connection.onreceive = (data: any) => this._processIncomingData(data);\r\n this.connection.onclose = (error?: Error) => this._connectionClosed(error);\r\n\r\n this._callbacks = {};\r\n this._methods = {};\r\n this._closedCallbacks = [];\r\n this._reconnectingCallbacks = [];\r\n this._reconnectedCallbacks = [];\r\n this._invocationId = 0;\r\n this._receivedHandshakeResponse = false;\r\n this._connectionState = HubConnectionState.Disconnected;\r\n this._connectionStarted = false;\r\n\r\n this._cachedPingMessage = this._protocol.writeMessage({ type: MessageType.Ping });\r\n }\r\n\r\n /** Indicates the state of the {@link HubConnection} to the server. */\r\n get state(): HubConnectionState {\r\n return this._connectionState;\r\n }\r\n\r\n /** Represents the connection id of the {@link HubConnection} on the server. The connection id will be null when the connection is either\r\n * in the disconnected state or if the negotiation step was skipped.\r\n */\r\n get connectionId(): string | null {\r\n return this.connection ? (this.connection.connectionId || null) : null;\r\n }\r\n\r\n /** Indicates the url of the {@link HubConnection} to the server. */\r\n get baseUrl(): string {\r\n return this.connection.baseUrl || \"\";\r\n }\r\n\r\n /**\r\n * Sets a new url for the HubConnection. Note that the url can only be changed when the connection is in either the Disconnected or\r\n * Reconnecting states.\r\n * @param {string} url The url to connect to.\r\n */\r\n set baseUrl(url: string) {\r\n if (this._connectionState !== HubConnectionState.Disconnected && this._connectionState !== HubConnectionState.Reconnecting) {\r\n throw new Error(\"The HubConnection must be in the Disconnected or Reconnecting state to change the url.\");\r\n }\r\n\r\n if (!url) {\r\n throw new Error(\"The HubConnection url must be a valid url.\");\r\n }\r\n\r\n this.connection.baseUrl = url;\r\n }\r\n\r\n /** Starts the connection.\r\n *\r\n * @returns {Promise} A Promise that resolves when the connection has been successfully established, or rejects with an error.\r\n */\r\n public start(): Promise {\r\n this._startPromise = this._startWithStateTransitions();\r\n return this._startPromise;\r\n }\r\n\r\n private async _startWithStateTransitions(): Promise {\r\n if (this._connectionState !== HubConnectionState.Disconnected) {\r\n return Promise.reject(new Error(\"Cannot start a HubConnection that is not in the 'Disconnected' state.\"));\r\n }\r\n\r\n this._connectionState = HubConnectionState.Connecting;\r\n this._logger.log(LogLevel.Debug, \"Starting HubConnection.\");\r\n\r\n try {\r\n await this._startInternal();\r\n\r\n if (Platform.isBrowser) {\r\n // Log when the browser freezes the tab so users know why their connection unexpectedly stopped working\r\n window.document.addEventListener(\"freeze\", this._freezeEventListener);\r\n }\r\n\r\n this._connectionState = HubConnectionState.Connected;\r\n this._connectionStarted = true;\r\n this._logger.log(LogLevel.Debug, \"HubConnection connected successfully.\");\r\n } catch (e) {\r\n this._connectionState = HubConnectionState.Disconnected;\r\n this._logger.log(LogLevel.Debug, `HubConnection failed to start successfully because of error '${e}'.`);\r\n return Promise.reject(e);\r\n }\r\n }\r\n\r\n private async _startInternal() {\r\n this._stopDuringStartError = undefined;\r\n this._receivedHandshakeResponse = false;\r\n // Set up the promise before any connection is (re)started otherwise it could race with received messages\r\n const handshakePromise = new Promise((resolve, reject) => {\r\n this._handshakeResolver = resolve;\r\n this._handshakeRejecter = reject;\r\n });\r\n\r\n await this.connection.start(this._protocol.transferFormat);\r\n\r\n try {\r\n let version = this._protocol.version;\r\n if (!this.connection.features.reconnect) {\r\n // Stateful Reconnect starts with HubProtocol version 2, newer clients connecting to older servers will fail to connect due to\r\n // the handshake only supporting version 1, so we will try to send version 1 during the handshake to keep old servers working.\r\n version = 1;\r\n }\r\n\r\n const handshakeRequest: HandshakeRequestMessage = {\r\n protocol: this._protocol.name,\r\n version,\r\n };\r\n\r\n this._logger.log(LogLevel.Debug, \"Sending handshake request.\");\r\n\r\n await this._sendMessage(this._handshakeProtocol.writeHandshakeRequest(handshakeRequest));\r\n\r\n this._logger.log(LogLevel.Information, `Using HubProtocol '${this._protocol.name}'.`);\r\n\r\n // defensively cleanup timeout in case we receive a message from the server before we finish start\r\n this._cleanupTimeout();\r\n this._resetTimeoutPeriod();\r\n this._resetKeepAliveInterval();\r\n\r\n await handshakePromise;\r\n\r\n // It's important to check the stopDuringStartError instead of just relying on the handshakePromise\r\n // being rejected on close, because this continuation can run after both the handshake completed successfully\r\n // and the connection was closed.\r\n if (this._stopDuringStartError) {\r\n // It's important to throw instead of returning a rejected promise, because we don't want to allow any state\r\n // transitions to occur between now and the calling code observing the exceptions. Returning a rejected promise\r\n // will cause the calling continuation to get scheduled to run later.\r\n // eslint-disable-next-line @typescript-eslint/no-throw-literal\r\n throw this._stopDuringStartError;\r\n }\r\n\r\n const useStatefulReconnect = this.connection.features.reconnect || false;\r\n if (useStatefulReconnect) {\r\n this._messageBuffer = new MessageBuffer(this._protocol, this.connection, this._statefulReconnectBufferSize);\r\n this.connection.features.disconnected = this._messageBuffer._disconnected.bind(this._messageBuffer);\r\n this.connection.features.resend = () => {\r\n if (this._messageBuffer) {\r\n return this._messageBuffer._resend();\r\n }\r\n }\r\n }\r\n\r\n if (!this.connection.features.inherentKeepAlive) {\r\n await this._sendMessage(this._cachedPingMessage);\r\n }\r\n } catch (e) {\r\n this._logger.log(LogLevel.Debug, `Hub handshake failed with error '${e}' during start(). Stopping HubConnection.`);\r\n\r\n this._cleanupTimeout();\r\n this._cleanupPingTimer();\r\n\r\n // HttpConnection.stop() should not complete until after the onclose callback is invoked.\r\n // This will transition the HubConnection to the disconnected state before HttpConnection.stop() completes.\r\n await this.connection.stop(e);\r\n throw e;\r\n }\r\n }\r\n\r\n /** Stops the connection.\r\n *\r\n * @returns {Promise} A Promise that resolves when the connection has been successfully terminated, or rejects with an error.\r\n */\r\n public async stop(): Promise {\r\n // Capture the start promise before the connection might be restarted in an onclose callback.\r\n const startPromise = this._startPromise;\r\n this.connection.features.reconnect = false;\r\n\r\n this._stopPromise = this._stopInternal();\r\n await this._stopPromise;\r\n\r\n try {\r\n // Awaiting undefined continues immediately\r\n await startPromise;\r\n } catch (e) {\r\n // This exception is returned to the user as a rejected Promise from the start method.\r\n }\r\n }\r\n\r\n private _stopInternal(error?: Error): Promise {\r\n if (this._connectionState === HubConnectionState.Disconnected) {\r\n this._logger.log(LogLevel.Debug, `Call to HubConnection.stop(${error}) ignored because it is already in the disconnected state.`);\r\n return Promise.resolve();\r\n }\r\n\r\n if (this._connectionState === HubConnectionState.Disconnecting) {\r\n this._logger.log(LogLevel.Debug, `Call to HttpConnection.stop(${error}) ignored because the connection is already in the disconnecting state.`);\r\n return this._stopPromise!;\r\n }\r\n\r\n const state = this._connectionState;\r\n this._connectionState = HubConnectionState.Disconnecting;\r\n\r\n this._logger.log(LogLevel.Debug, \"Stopping HubConnection.\");\r\n\r\n if (this._reconnectDelayHandle) {\r\n // We're in a reconnect delay which means the underlying connection is currently already stopped.\r\n // Just clear the handle to stop the reconnect loop (which no one is waiting on thankfully) and\r\n // fire the onclose callbacks.\r\n this._logger.log(LogLevel.Debug, \"Connection stopped during reconnect delay. Done reconnecting.\");\r\n\r\n clearTimeout(this._reconnectDelayHandle);\r\n this._reconnectDelayHandle = undefined;\r\n\r\n this._completeClose();\r\n return Promise.resolve();\r\n }\r\n\r\n if (state === HubConnectionState.Connected) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this._sendCloseMessage();\r\n }\r\n\r\n this._cleanupTimeout();\r\n this._cleanupPingTimer();\r\n this._stopDuringStartError = error || new AbortError(\"The connection was stopped before the hub handshake could complete.\");\r\n\r\n // HttpConnection.stop() should not complete until after either HttpConnection.start() fails\r\n // or the onclose callback is invoked. The onclose callback will transition the HubConnection\r\n // to the disconnected state if need be before HttpConnection.stop() completes.\r\n return this.connection.stop(error);\r\n }\r\n\r\n private async _sendCloseMessage() {\r\n try {\r\n await this._sendWithProtocol(this._createCloseMessage());\r\n } catch {\r\n // Ignore, this is a best effort attempt to let the server know the client closed gracefully.\r\n }\r\n }\r\n\r\n /** Invokes a streaming hub method on the server using the specified name and arguments.\r\n *\r\n * @typeparam T The type of the items returned by the server.\r\n * @param {string} methodName The name of the server method to invoke.\r\n * @param {any[]} args The arguments used to invoke the server method.\r\n * @returns {IStreamResult} An object that yields results from the server as they are received.\r\n */\r\n public stream(methodName: string, ...args: any[]): IStreamResult {\r\n const [streams, streamIds] = this._replaceStreamingParams(args);\r\n const invocationDescriptor = this._createStreamInvocation(methodName, args, streamIds);\r\n\r\n // eslint-disable-next-line prefer-const\r\n let promiseQueue: Promise;\r\n\r\n const subject = new Subject();\r\n subject.cancelCallback = () => {\r\n const cancelInvocation: CancelInvocationMessage = this._createCancelInvocation(invocationDescriptor.invocationId);\r\n\r\n delete this._callbacks[invocationDescriptor.invocationId];\r\n\r\n return promiseQueue.then(() => {\r\n return this._sendWithProtocol(cancelInvocation);\r\n });\r\n };\r\n\r\n this._callbacks[invocationDescriptor.invocationId] = (invocationEvent: CompletionMessage | StreamItemMessage | null, error?: Error) => {\r\n if (error) {\r\n subject.error(error);\r\n return;\r\n } else if (invocationEvent) {\r\n // invocationEvent will not be null when an error is not passed to the callback\r\n if (invocationEvent.type === MessageType.Completion) {\r\n if (invocationEvent.error) {\r\n subject.error(new Error(invocationEvent.error));\r\n } else {\r\n subject.complete();\r\n }\r\n } else {\r\n subject.next((invocationEvent.item) as T);\r\n }\r\n }\r\n };\r\n\r\n promiseQueue = this._sendWithProtocol(invocationDescriptor)\r\n .catch((e) => {\r\n subject.error(e);\r\n delete this._callbacks[invocationDescriptor.invocationId];\r\n });\r\n\r\n this._launchStreams(streams, promiseQueue);\r\n\r\n return subject;\r\n }\r\n\r\n private _sendMessage(message: any) {\r\n this._resetKeepAliveInterval();\r\n return this.connection.send(message);\r\n }\r\n\r\n /**\r\n * Sends a js object to the server.\r\n * @param message The js object to serialize and send.\r\n */\r\n private _sendWithProtocol(message: any) {\r\n if (this._messageBuffer) {\r\n return this._messageBuffer._send(message);\r\n } else {\r\n return this._sendMessage(this._protocol.writeMessage(message));\r\n }\r\n }\r\n\r\n /** Invokes a hub method on the server using the specified name and arguments. Does not wait for a response from the receiver.\r\n *\r\n * The Promise returned by this method resolves when the client has sent the invocation to the server. The server may still\r\n * be processing the invocation.\r\n *\r\n * @param {string} methodName The name of the server method to invoke.\r\n * @param {any[]} args The arguments used to invoke the server method.\r\n * @returns {Promise} A Promise that resolves when the invocation has been successfully sent, or rejects with an error.\r\n */\r\n public send(methodName: string, ...args: any[]): Promise {\r\n const [streams, streamIds] = this._replaceStreamingParams(args);\r\n const sendPromise = this._sendWithProtocol(this._createInvocation(methodName, args, true, streamIds));\r\n\r\n this._launchStreams(streams, sendPromise);\r\n\r\n return sendPromise;\r\n }\r\n\r\n /** Invokes a hub method on the server using the specified name and arguments.\r\n *\r\n * The Promise returned by this method resolves when the server indicates it has finished invoking the method. When the promise\r\n * resolves, the server has finished invoking the method. If the server method returns a result, it is produced as the result of\r\n * resolving the Promise.\r\n *\r\n * @typeparam T The expected return type.\r\n * @param {string} methodName The name of the server method to invoke.\r\n * @param {any[]} args The arguments used to invoke the server method.\r\n * @returns {Promise} A Promise that resolves with the result of the server method (if any), or rejects with an error.\r\n */\r\n public invoke(methodName: string, ...args: any[]): Promise {\r\n const [streams, streamIds] = this._replaceStreamingParams(args);\r\n const invocationDescriptor = this._createInvocation(methodName, args, false, streamIds);\r\n\r\n const p = new Promise((resolve, reject) => {\r\n // invocationId will always have a value for a non-blocking invocation\r\n this._callbacks[invocationDescriptor.invocationId!] = (invocationEvent: StreamItemMessage | CompletionMessage | null, error?: Error) => {\r\n if (error) {\r\n reject(error);\r\n return;\r\n } else if (invocationEvent) {\r\n // invocationEvent will not be null when an error is not passed to the callback\r\n if (invocationEvent.type === MessageType.Completion) {\r\n if (invocationEvent.error) {\r\n reject(new Error(invocationEvent.error));\r\n } else {\r\n resolve(invocationEvent.result);\r\n }\r\n } else {\r\n reject(new Error(`Unexpected message type: ${invocationEvent.type}`));\r\n }\r\n }\r\n };\r\n\r\n const promiseQueue = this._sendWithProtocol(invocationDescriptor)\r\n .catch((e) => {\r\n reject(e);\r\n // invocationId will always have a value for a non-blocking invocation\r\n delete this._callbacks[invocationDescriptor.invocationId!];\r\n });\r\n\r\n this._launchStreams(streams, promiseQueue);\r\n });\r\n\r\n return p;\r\n }\r\n\r\n /** Registers a handler that will be invoked when the hub method with the specified method name is invoked.\r\n *\r\n * @param {string} methodName The name of the hub method to define.\r\n * @param {Function} newMethod The handler that will be raised when the hub method is invoked.\r\n */\r\n public on(methodName: string, newMethod: (...args: any[]) => any): void\r\n public on(methodName: string, newMethod: (...args: any[]) => void): void {\r\n if (!methodName || !newMethod) {\r\n return;\r\n }\r\n\r\n methodName = methodName.toLowerCase();\r\n if (!this._methods[methodName]) {\r\n this._methods[methodName] = [];\r\n }\r\n\r\n // Preventing adding the same handler multiple times.\r\n if (this._methods[methodName].indexOf(newMethod) !== -1) {\r\n return;\r\n }\r\n\r\n this._methods[methodName].push(newMethod);\r\n }\r\n\r\n /** Removes all handlers for the specified hub method.\r\n *\r\n * @param {string} methodName The name of the method to remove handlers for.\r\n */\r\n public off(methodName: string): void;\r\n\r\n /** Removes the specified handler for the specified hub method.\r\n *\r\n * You must pass the exact same Function instance as was previously passed to {@link @microsoft/signalr.HubConnection.on}. Passing a different instance (even if the function\r\n * body is the same) will not remove the handler.\r\n *\r\n * @param {string} methodName The name of the method to remove handlers for.\r\n * @param {Function} method The handler to remove. This must be the same Function instance as the one passed to {@link @microsoft/signalr.HubConnection.on}.\r\n */\r\n public off(methodName: string, method: (...args: any[]) => void): void;\r\n public off(methodName: string, method?: (...args: any[]) => void): void {\r\n if (!methodName) {\r\n return;\r\n }\r\n\r\n methodName = methodName.toLowerCase();\r\n const handlers = this._methods[methodName];\r\n if (!handlers) {\r\n return;\r\n }\r\n if (method) {\r\n const removeIdx = handlers.indexOf(method);\r\n if (removeIdx !== -1) {\r\n handlers.splice(removeIdx, 1);\r\n if (handlers.length === 0) {\r\n delete this._methods[methodName];\r\n }\r\n }\r\n } else {\r\n delete this._methods[methodName];\r\n }\r\n\r\n }\r\n\r\n /** Registers a handler that will be invoked when the connection is closed.\r\n *\r\n * @param {Function} callback The handler that will be invoked when the connection is closed. Optionally receives a single argument containing the error that caused the connection to close (if any).\r\n */\r\n public onclose(callback: (error?: Error) => void): void {\r\n if (callback) {\r\n this._closedCallbacks.push(callback);\r\n }\r\n }\r\n\r\n /** Registers a handler that will be invoked when the connection starts reconnecting.\r\n *\r\n * @param {Function} callback The handler that will be invoked when the connection starts reconnecting. Optionally receives a single argument containing the error that caused the connection to start reconnecting (if any).\r\n */\r\n public onreconnecting(callback: (error?: Error) => void): void {\r\n if (callback) {\r\n this._reconnectingCallbacks.push(callback);\r\n }\r\n }\r\n\r\n /** Registers a handler that will be invoked when the connection successfully reconnects.\r\n *\r\n * @param {Function} callback The handler that will be invoked when the connection successfully reconnects.\r\n */\r\n public onreconnected(callback: (connectionId?: string) => void): void {\r\n if (callback) {\r\n this._reconnectedCallbacks.push(callback);\r\n }\r\n }\r\n\r\n private _processIncomingData(data: any) {\r\n this._cleanupTimeout();\r\n\r\n if (!this._receivedHandshakeResponse) {\r\n data = this._processHandshakeResponse(data);\r\n this._receivedHandshakeResponse = true;\r\n }\r\n\r\n // Data may have all been read when processing handshake response\r\n if (data) {\r\n // Parse the messages\r\n const messages = this._protocol.parseMessages(data, this._logger);\r\n\r\n for (const message of messages) {\r\n if (this._messageBuffer && !this._messageBuffer._shouldProcessMessage(message)) {\r\n // Don't process the message, we are either waiting for a SequenceMessage or received a duplicate message\r\n continue;\r\n }\r\n\r\n switch (message.type) {\r\n case MessageType.Invocation:\r\n this._invokeClientMethod(message)\r\n .catch((e) => {\r\n this._logger.log(LogLevel.Error, `Invoke client method threw error: ${getErrorString(e)}`)\r\n });\r\n break;\r\n case MessageType.StreamItem:\r\n case MessageType.Completion: {\r\n const callback = this._callbacks[message.invocationId];\r\n if (callback) {\r\n if (message.type === MessageType.Completion) {\r\n delete this._callbacks[message.invocationId];\r\n }\r\n try {\r\n callback(message);\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `Stream callback threw error: ${getErrorString(e)}`);\r\n }\r\n }\r\n break;\r\n }\r\n case MessageType.Ping:\r\n // Don't care about pings\r\n break;\r\n case MessageType.Close: {\r\n this._logger.log(LogLevel.Information, \"Close message received from server.\");\r\n\r\n const error = message.error ? new Error(\"Server returned an error on close: \" + message.error) : undefined;\r\n\r\n if (message.allowReconnect === true) {\r\n // It feels wrong not to await connection.stop() here, but processIncomingData is called as part of an onreceive callback which is not async,\r\n // this is already the behavior for serverTimeout(), and HttpConnection.Stop() should catch and log all possible exceptions.\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.connection.stop(error);\r\n } else {\r\n // We cannot await stopInternal() here, but subsequent calls to stop() will await this if stopInternal() is still ongoing.\r\n this._stopPromise = this._stopInternal(error);\r\n }\r\n\r\n break;\r\n }\r\n case MessageType.Ack:\r\n if (this._messageBuffer) {\r\n this._messageBuffer._ack(message);\r\n }\r\n break;\r\n case MessageType.Sequence:\r\n if (this._messageBuffer) {\r\n this._messageBuffer._resetSequence(message);\r\n }\r\n break;\r\n default:\r\n this._logger.log(LogLevel.Warning, `Invalid message type: ${message.type}.`);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n this._resetTimeoutPeriod();\r\n }\r\n\r\n private _processHandshakeResponse(data: any): any {\r\n let responseMessage: HandshakeResponseMessage;\r\n let remainingData: any;\r\n\r\n try {\r\n [remainingData, responseMessage] = this._handshakeProtocol.parseHandshakeResponse(data);\r\n } catch (e) {\r\n const message = \"Error parsing handshake response: \" + e;\r\n this._logger.log(LogLevel.Error, message);\r\n\r\n const error = new Error(message);\r\n this._handshakeRejecter(error);\r\n throw error;\r\n }\r\n if (responseMessage.error) {\r\n const message = \"Server returned handshake error: \" + responseMessage.error;\r\n this._logger.log(LogLevel.Error, message);\r\n\r\n const error = new Error(message);\r\n this._handshakeRejecter(error);\r\n throw error;\r\n } else {\r\n this._logger.log(LogLevel.Debug, \"Server handshake complete.\");\r\n }\r\n\r\n this._handshakeResolver();\r\n return remainingData;\r\n }\r\n\r\n private _resetKeepAliveInterval() {\r\n if (this.connection.features.inherentKeepAlive) {\r\n return;\r\n }\r\n\r\n // Set the time we want the next keep alive to be sent\r\n // Timer will be setup on next message receive\r\n this._nextKeepAlive = new Date().getTime() + this.keepAliveIntervalInMilliseconds;\r\n\r\n this._cleanupPingTimer();\r\n }\r\n\r\n private _resetTimeoutPeriod() {\r\n if (!this.connection.features || !this.connection.features.inherentKeepAlive) {\r\n // Set the timeout timer\r\n this._timeoutHandle = setTimeout(() => this.serverTimeout(), this.serverTimeoutInMilliseconds);\r\n\r\n // Immediately fire Keep-Alive ping if nextPing is overdue to avoid dependency on JS timers\r\n let nextPing = this._nextKeepAlive - new Date().getTime();\r\n if (nextPing < 0) {\r\n if (this._connectionState === HubConnectionState.Connected) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this._trySendPingMessage();\r\n }\r\n return;\r\n }\r\n\r\n // Set keepAlive timer if there isn't one\r\n if (this._pingServerHandle === undefined)\r\n {\r\n if (nextPing < 0) {\r\n nextPing = 0;\r\n }\r\n\r\n // The timer needs to be set from a networking callback to avoid Chrome timer throttling from causing timers to run once a minute\r\n this._pingServerHandle = setTimeout(async () => {\r\n if (this._connectionState === HubConnectionState.Connected) {\r\n await this._trySendPingMessage();\r\n }\r\n }, nextPing);\r\n }\r\n }\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private serverTimeout() {\r\n // The server hasn't talked to us in a while. It doesn't like us anymore ... :(\r\n // Terminate the connection, but we don't need to wait on the promise. This could trigger reconnecting.\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.connection.stop(new Error(\"Server timeout elapsed without receiving a message from the server.\"));\r\n }\r\n\r\n private async _invokeClientMethod(invocationMessage: InvocationMessage) {\r\n const methodName = invocationMessage.target.toLowerCase();\r\n const methods = this._methods[methodName];\r\n if (!methods) {\r\n this._logger.log(LogLevel.Warning, `No client method with the name '${methodName}' found.`);\r\n\r\n // No handlers provided by client but the server is expecting a response still, so we send an error\r\n if (invocationMessage.invocationId) {\r\n this._logger.log(LogLevel.Warning, `No result given for '${methodName}' method and invocation ID '${invocationMessage.invocationId}'.`);\r\n await this._sendWithProtocol(this._createCompletionMessage(invocationMessage.invocationId, \"Client didn't provide a result.\", null));\r\n }\r\n return;\r\n }\r\n\r\n // Avoid issues with handlers removing themselves thus modifying the list while iterating through it\r\n const methodsCopy = methods.slice();\r\n\r\n // Server expects a response\r\n const expectsResponse = invocationMessage.invocationId ? true : false;\r\n // We preserve the last result or exception but still call all handlers\r\n let res;\r\n let exception;\r\n let completionMessage;\r\n for (const m of methodsCopy) {\r\n try {\r\n const prevRes = res;\r\n res = await m.apply(this, invocationMessage.arguments);\r\n if (expectsResponse && res && prevRes) {\r\n this._logger.log(LogLevel.Error, `Multiple results provided for '${methodName}'. Sending error to server.`);\r\n completionMessage = this._createCompletionMessage(invocationMessage.invocationId!, `Client provided multiple results.`, null);\r\n }\r\n // Ignore exception if we got a result after, the exception will be logged\r\n exception = undefined;\r\n } catch (e) {\r\n exception = e;\r\n this._logger.log(LogLevel.Error, `A callback for the method '${methodName}' threw error '${e}'.`);\r\n }\r\n }\r\n if (completionMessage) {\r\n await this._sendWithProtocol(completionMessage);\r\n } else if (expectsResponse) {\r\n // If there is an exception that means either no result was given or a handler after a result threw\r\n if (exception) {\r\n completionMessage = this._createCompletionMessage(invocationMessage.invocationId!, `${exception}`, null);\r\n } else if (res !== undefined) {\r\n completionMessage = this._createCompletionMessage(invocationMessage.invocationId!, null, res);\r\n } else {\r\n this._logger.log(LogLevel.Warning, `No result given for '${methodName}' method and invocation ID '${invocationMessage.invocationId}'.`);\r\n // Client didn't provide a result or throw from a handler, server expects a response so we send an error\r\n completionMessage = this._createCompletionMessage(invocationMessage.invocationId!, \"Client didn't provide a result.\", null);\r\n }\r\n await this._sendWithProtocol(completionMessage);\r\n } else {\r\n if (res) {\r\n this._logger.log(LogLevel.Error, `Result given for '${methodName}' method but server is not expecting a result.`);\r\n }\r\n }\r\n }\r\n\r\n private _connectionClosed(error?: Error) {\r\n this._logger.log(LogLevel.Debug, `HubConnection.connectionClosed(${error}) called while in state ${this._connectionState}.`);\r\n\r\n // Triggering this.handshakeRejecter is insufficient because it could already be resolved without the continuation having run yet.\r\n this._stopDuringStartError = this._stopDuringStartError || error || new AbortError(\"The underlying connection was closed before the hub handshake could complete.\");\r\n\r\n // If the handshake is in progress, start will be waiting for the handshake promise, so we complete it.\r\n // If it has already completed, this should just noop.\r\n if (this._handshakeResolver) {\r\n this._handshakeResolver();\r\n }\r\n\r\n this._cancelCallbacksWithError(error || new Error(\"Invocation canceled due to the underlying connection being closed.\"));\r\n\r\n this._cleanupTimeout();\r\n this._cleanupPingTimer();\r\n\r\n if (this._connectionState === HubConnectionState.Disconnecting) {\r\n this._completeClose(error);\r\n } else if (this._connectionState === HubConnectionState.Connected && this._reconnectPolicy) {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this._reconnect(error);\r\n } else if (this._connectionState === HubConnectionState.Connected) {\r\n this._completeClose(error);\r\n }\r\n\r\n // If none of the above if conditions were true were called the HubConnection must be in either:\r\n // 1. The Connecting state in which case the handshakeResolver will complete it and stopDuringStartError will fail it.\r\n // 2. The Reconnecting state in which case the handshakeResolver will complete it and stopDuringStartError will fail the current reconnect attempt\r\n // and potentially continue the reconnect() loop.\r\n // 3. The Disconnected state in which case we're already done.\r\n }\r\n\r\n private _completeClose(error?: Error) {\r\n if (this._connectionStarted) {\r\n this._connectionState = HubConnectionState.Disconnected;\r\n this._connectionStarted = false;\r\n if (this._messageBuffer) {\r\n this._messageBuffer._dispose(error ?? new Error(\"Connection closed.\"));\r\n this._messageBuffer = undefined;\r\n }\r\n\r\n if (Platform.isBrowser) {\r\n window.document.removeEventListener(\"freeze\", this._freezeEventListener);\r\n }\r\n\r\n try {\r\n this._closedCallbacks.forEach((c) => c.apply(this, [error]));\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `An onclose callback called with error '${error}' threw error '${e}'.`);\r\n }\r\n }\r\n }\r\n\r\n private async _reconnect(error?: Error) {\r\n const reconnectStartTime = Date.now();\r\n let previousReconnectAttempts = 0;\r\n let retryError = error !== undefined ? error : new Error(\"Attempting to reconnect due to a unknown error.\");\r\n\r\n let nextRetryDelay = this._getNextRetryDelay(previousReconnectAttempts, 0, retryError);\r\n\r\n if (nextRetryDelay === null) {\r\n this._logger.log(LogLevel.Debug, \"Connection not reconnecting because the IRetryPolicy returned null on the first reconnect attempt.\");\r\n this._completeClose(error);\r\n return;\r\n }\r\n\r\n this._connectionState = HubConnectionState.Reconnecting;\r\n\r\n if (error) {\r\n this._logger.log(LogLevel.Information, `Connection reconnecting because of error '${error}'.`);\r\n } else {\r\n this._logger.log(LogLevel.Information, \"Connection reconnecting.\");\r\n }\r\n\r\n if (this._reconnectingCallbacks.length !== 0) {\r\n try {\r\n this._reconnectingCallbacks.forEach((c) => c.apply(this, [error]));\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `An onreconnecting callback called with error '${error}' threw error '${e}'.`);\r\n }\r\n\r\n // Exit early if an onreconnecting callback called connection.stop().\r\n if (this._connectionState !== HubConnectionState.Reconnecting) {\r\n this._logger.log(LogLevel.Debug, \"Connection left the reconnecting state in onreconnecting callback. Done reconnecting.\");\r\n return;\r\n }\r\n }\r\n\r\n while (nextRetryDelay !== null) {\r\n this._logger.log(LogLevel.Information, `Reconnect attempt number ${previousReconnectAttempts + 1} will start in ${nextRetryDelay} ms.`);\r\n\r\n await new Promise((resolve) => {\r\n this._reconnectDelayHandle = setTimeout(resolve, nextRetryDelay!);\r\n });\r\n this._reconnectDelayHandle = undefined;\r\n\r\n if (this._connectionState !== HubConnectionState.Reconnecting) {\r\n this._logger.log(LogLevel.Debug, \"Connection left the reconnecting state during reconnect delay. Done reconnecting.\");\r\n return;\r\n }\r\n\r\n try {\r\n await this._startInternal();\r\n\r\n this._connectionState = HubConnectionState.Connected;\r\n this._logger.log(LogLevel.Information, \"HubConnection reconnected successfully.\");\r\n\r\n if (this._reconnectedCallbacks.length !== 0) {\r\n try {\r\n this._reconnectedCallbacks.forEach((c) => c.apply(this, [this.connection.connectionId]));\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `An onreconnected callback called with connectionId '${this.connection.connectionId}; threw error '${e}'.`);\r\n }\r\n }\r\n\r\n return;\r\n } catch (e) {\r\n this._logger.log(LogLevel.Information, `Reconnect attempt failed because of error '${e}'.`);\r\n\r\n if (this._connectionState !== HubConnectionState.Reconnecting) {\r\n this._logger.log(LogLevel.Debug, `Connection moved to the '${this._connectionState}' from the reconnecting state during reconnect attempt. Done reconnecting.`);\r\n // The TypeScript compiler thinks that connectionState must be Connected here. The TypeScript compiler is wrong.\r\n if (this._connectionState as any === HubConnectionState.Disconnecting) {\r\n this._completeClose();\r\n }\r\n return;\r\n }\r\n\r\n previousReconnectAttempts++;\r\n retryError = e instanceof Error ? e : new Error((e as any).toString());\r\n nextRetryDelay = this._getNextRetryDelay(previousReconnectAttempts, Date.now() - reconnectStartTime, retryError);\r\n }\r\n }\r\n\r\n this._logger.log(LogLevel.Information, `Reconnect retries have been exhausted after ${Date.now() - reconnectStartTime} ms and ${previousReconnectAttempts} failed attempts. Connection disconnecting.`);\r\n\r\n this._completeClose();\r\n }\r\n\r\n private _getNextRetryDelay(previousRetryCount: number, elapsedMilliseconds: number, retryReason: Error) {\r\n try {\r\n return this._reconnectPolicy!.nextRetryDelayInMilliseconds({\r\n elapsedMilliseconds,\r\n previousRetryCount,\r\n retryReason,\r\n });\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `IRetryPolicy.nextRetryDelayInMilliseconds(${previousRetryCount}, ${elapsedMilliseconds}) threw error '${e}'.`);\r\n return null;\r\n }\r\n }\r\n\r\n private _cancelCallbacksWithError(error: Error) {\r\n const callbacks = this._callbacks;\r\n this._callbacks = {};\r\n\r\n Object.keys(callbacks)\r\n .forEach((key) => {\r\n const callback = callbacks[key];\r\n try {\r\n callback(null, error);\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `Stream 'error' callback called with '${error}' threw error: ${getErrorString(e)}`);\r\n }\r\n });\r\n }\r\n\r\n private _cleanupPingTimer(): void {\r\n if (this._pingServerHandle) {\r\n clearTimeout(this._pingServerHandle);\r\n this._pingServerHandle = undefined;\r\n }\r\n }\r\n\r\n private _cleanupTimeout(): void {\r\n if (this._timeoutHandle) {\r\n clearTimeout(this._timeoutHandle);\r\n }\r\n }\r\n\r\n private _createInvocation(methodName: string, args: any[], nonblocking: boolean, streamIds: string[]): InvocationMessage {\r\n if (nonblocking) {\r\n if (streamIds.length !== 0) {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n streamIds,\r\n type: MessageType.Invocation,\r\n };\r\n } else {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n type: MessageType.Invocation,\r\n };\r\n }\r\n } else {\r\n const invocationId = this._invocationId;\r\n this._invocationId++;\r\n\r\n if (streamIds.length !== 0) {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n invocationId: invocationId.toString(),\r\n streamIds,\r\n type: MessageType.Invocation,\r\n };\r\n } else {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n invocationId: invocationId.toString(),\r\n type: MessageType.Invocation,\r\n };\r\n }\r\n }\r\n }\r\n\r\n private _launchStreams(streams: IStreamResult[], promiseQueue: Promise): void {\r\n if (streams.length === 0) {\r\n return;\r\n }\r\n\r\n // Synchronize stream data so they arrive in-order on the server\r\n if (!promiseQueue) {\r\n promiseQueue = Promise.resolve();\r\n }\r\n\r\n // We want to iterate over the keys, since the keys are the stream ids\r\n // eslint-disable-next-line guard-for-in\r\n for (const streamId in streams) {\r\n streams[streamId].subscribe({\r\n complete: () => {\r\n promiseQueue = promiseQueue.then(() => this._sendWithProtocol(this._createCompletionMessage(streamId)));\r\n },\r\n error: (err) => {\r\n let message: string;\r\n if (err instanceof Error) {\r\n message = err.message;\r\n } else if (err && err.toString) {\r\n message = err.toString();\r\n } else {\r\n message = \"Unknown error\";\r\n }\r\n\r\n promiseQueue = promiseQueue.then(() => this._sendWithProtocol(this._createCompletionMessage(streamId, message)));\r\n },\r\n next: (item) => {\r\n promiseQueue = promiseQueue.then(() => this._sendWithProtocol(this._createStreamItemMessage(streamId, item)));\r\n },\r\n });\r\n }\r\n }\r\n\r\n private _replaceStreamingParams(args: any[]): [IStreamResult[], string[]] {\r\n const streams: IStreamResult[] = [];\r\n const streamIds: string[] = [];\r\n for (let i = 0; i < args.length; i++) {\r\n const argument = args[i];\r\n if (this._isObservable(argument)) {\r\n const streamId = this._invocationId;\r\n this._invocationId++;\r\n // Store the stream for later use\r\n streams[streamId] = argument;\r\n streamIds.push(streamId.toString());\r\n\r\n // remove stream from args\r\n args.splice(i, 1);\r\n }\r\n }\r\n\r\n return [streams, streamIds];\r\n }\r\n\r\n private _isObservable(arg: any): arg is IStreamResult {\r\n // This allows other stream implementations to just work (like rxjs)\r\n return arg && arg.subscribe && typeof arg.subscribe === \"function\";\r\n }\r\n\r\n private _createStreamInvocation(methodName: string, args: any[], streamIds: string[]): StreamInvocationMessage {\r\n const invocationId = this._invocationId;\r\n this._invocationId++;\r\n\r\n if (streamIds.length !== 0) {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n invocationId: invocationId.toString(),\r\n streamIds,\r\n type: MessageType.StreamInvocation,\r\n };\r\n } else {\r\n return {\r\n target: methodName,\r\n arguments: args,\r\n invocationId: invocationId.toString(),\r\n type: MessageType.StreamInvocation,\r\n };\r\n }\r\n }\r\n\r\n private _createCancelInvocation(id: string): CancelInvocationMessage {\r\n return {\r\n invocationId: id,\r\n type: MessageType.CancelInvocation,\r\n };\r\n }\r\n\r\n private _createStreamItemMessage(id: string, item: any): StreamItemMessage {\r\n return {\r\n invocationId: id,\r\n item,\r\n type: MessageType.StreamItem,\r\n };\r\n }\r\n\r\n private _createCompletionMessage(id: string, error?: any, result?: any): CompletionMessage {\r\n if (error) {\r\n return {\r\n error,\r\n invocationId: id,\r\n type: MessageType.Completion,\r\n };\r\n }\r\n\r\n return {\r\n invocationId: id,\r\n result,\r\n type: MessageType.Completion,\r\n };\r\n }\r\n\r\n private _createCloseMessage(): CloseMessage {\r\n return { type: MessageType.Close };\r\n }\r\n\r\n private async _trySendPingMessage(): Promise {\r\n try {\r\n await this._sendMessage(this._cachedPingMessage);\r\n } catch {\r\n // We don't care about the error. It should be seen elsewhere in the client.\r\n // The connection is probably in a bad or closed state now, cleanup the timer so it stops triggering\r\n this._cleanupPingTimer();\r\n }\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { IRetryPolicy, RetryContext } from \"./IRetryPolicy\";\r\n\r\n// 0, 2, 10, 30 second delays before reconnect attempts.\r\nconst DEFAULT_RETRY_DELAYS_IN_MILLISECONDS = [0, 2000, 10000, 30000, null];\r\n\r\n/** @private */\r\nexport class DefaultReconnectPolicy implements IRetryPolicy {\r\n private readonly _retryDelays: (number | null)[];\r\n\r\n constructor(retryDelays?: number[]) {\r\n this._retryDelays = retryDelays !== undefined ? [...retryDelays, null] : DEFAULT_RETRY_DELAYS_IN_MILLISECONDS;\r\n }\r\n\r\n public nextRetryDelayInMilliseconds(retryContext: RetryContext): number | null {\r\n return this._retryDelays[retryContext.previousRetryCount];\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nexport abstract class HeaderNames {\r\n static readonly Authorization = \"Authorization\";\r\n static readonly Cookie = \"Cookie\";\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HeaderNames } from \"./HeaderNames\";\r\nimport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\n\r\n/** @private */\r\nexport class AccessTokenHttpClient extends HttpClient {\r\n private _innerClient: HttpClient;\r\n _accessToken: string | undefined;\r\n _accessTokenFactory: (() => string | Promise) | undefined;\r\n\r\n constructor(innerClient: HttpClient, accessTokenFactory: (() => string | Promise) | undefined) {\r\n super();\r\n\r\n this._innerClient = innerClient;\r\n this._accessTokenFactory = accessTokenFactory;\r\n }\r\n\r\n public async send(request: HttpRequest): Promise {\r\n let allowRetry = true;\r\n if (this._accessTokenFactory && (!this._accessToken || (request.url && request.url.indexOf(\"/negotiate?\") > 0))) {\r\n // don't retry if the request is a negotiate or if we just got a potentially new token from the access token factory\r\n allowRetry = false;\r\n this._accessToken = await this._accessTokenFactory();\r\n }\r\n this._setAuthorizationHeader(request);\r\n const response = await this._innerClient.send(request);\r\n\r\n if (allowRetry && response.statusCode === 401 && this._accessTokenFactory) {\r\n this._accessToken = await this._accessTokenFactory();\r\n this._setAuthorizationHeader(request);\r\n return await this._innerClient.send(request);\r\n }\r\n return response;\r\n }\r\n\r\n private _setAuthorizationHeader(request: HttpRequest) {\r\n if (!request.headers) {\r\n request.headers = {};\r\n }\r\n if (this._accessToken) {\r\n request.headers[HeaderNames.Authorization] = `Bearer ${this._accessToken}`\r\n }\r\n // don't remove the header if there isn't an access token factory, the user manually added the header in this case\r\n else if (this._accessTokenFactory) {\r\n if (request.headers[HeaderNames.Authorization]) {\r\n delete request.headers[HeaderNames.Authorization];\r\n }\r\n }\r\n }\r\n\r\n public getCookieString(url: string): string {\r\n return this._innerClient.getCookieString(url);\r\n }\r\n}", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// This will be treated as a bit flag in the future, so we keep it using power-of-two values.\r\n/** Specifies a specific HTTP transport type. */\r\nexport enum HttpTransportType {\r\n /** Specifies no transport preference. */\r\n None = 0,\r\n /** Specifies the WebSockets transport. */\r\n WebSockets = 1,\r\n /** Specifies the Server-Sent Events transport. */\r\n ServerSentEvents = 2,\r\n /** Specifies the Long Polling transport. */\r\n LongPolling = 4,\r\n}\r\n\r\n/** Specifies the transfer format for a connection. */\r\nexport enum TransferFormat {\r\n /** Specifies that only text data will be transmitted over the connection. */\r\n Text = 1,\r\n /** Specifies that binary data will be transmitted over the connection. */\r\n Binary = 2,\r\n}\r\n\r\n/** An abstraction over the behavior of transports. This is designed to support the framework and not intended for use by applications. */\r\nexport interface ITransport {\r\n connect(url: string, transferFormat: TransferFormat): Promise;\r\n send(data: any): Promise;\r\n stop(): Promise;\r\n onreceive: ((data: string | ArrayBuffer) => void) | null;\r\n onclose: ((error?: Error) => void) | null;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// Rough polyfill of https://developer.mozilla.org/en-US/docs/Web/API/AbortController\r\n// We don't actually ever use the API being polyfilled, we always use the polyfill because\r\n// it's a very new API right now.\r\n\r\n// Not exported from index.\r\n/** @private */\r\nexport class AbortController implements AbortSignal {\r\n private _isAborted: boolean = false;\r\n public onabort: (() => void) | null = null;\r\n\r\n public abort(): void {\r\n if (!this._isAborted) {\r\n this._isAborted = true;\r\n if (this.onabort) {\r\n this.onabort();\r\n }\r\n }\r\n }\r\n\r\n get signal(): AbortSignal {\r\n return this;\r\n }\r\n\r\n get aborted(): boolean {\r\n return this._isAborted;\r\n }\r\n}\r\n\r\n/** Represents a signal that can be monitored to determine if a request has been aborted. */\r\nexport interface AbortSignal {\r\n /** Indicates if the request has been aborted. */\r\n aborted: boolean;\r\n /** Set this to a handler that will be invoked when the request is aborted. */\r\n onabort: (() => void) | null;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AbortController } from \"./AbortController\";\r\nimport { HttpError, TimeoutError } from \"./Errors\";\r\nimport { HttpClient, HttpRequest } from \"./HttpClient\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { ITransport, TransferFormat } from \"./ITransport\";\r\nimport { Arg, getDataDetail, getUserAgentHeader, sendMessage } from \"./Utils\";\r\nimport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\n\r\n// Not exported from 'index', this type is internal.\r\n/** @private */\r\nexport class LongPollingTransport implements ITransport {\r\n private readonly _httpClient: HttpClient;\r\n private readonly _logger: ILogger;\r\n private readonly _options: IHttpConnectionOptions;\r\n private readonly _pollAbort: AbortController;\r\n\r\n private _url?: string;\r\n private _running: boolean;\r\n private _receiving?: Promise;\r\n private _closeError?: Error | unknown;\r\n\r\n public onreceive: ((data: string | ArrayBuffer) => void) | null;\r\n public onclose: ((error?: Error | unknown) => void) | null;\r\n\r\n // This is an internal type, not exported from 'index' so this is really just internal.\r\n public get pollAborted(): boolean {\r\n return this._pollAbort.aborted;\r\n }\r\n\r\n constructor(httpClient: HttpClient, logger: ILogger, options: IHttpConnectionOptions) {\r\n this._httpClient = httpClient;\r\n this._logger = logger;\r\n this._pollAbort = new AbortController();\r\n this._options = options;\r\n\r\n this._running = false;\r\n\r\n this.onreceive = null;\r\n this.onclose = null;\r\n }\r\n\r\n public async connect(url: string, transferFormat: TransferFormat): Promise {\r\n Arg.isRequired(url, \"url\");\r\n Arg.isRequired(transferFormat, \"transferFormat\");\r\n Arg.isIn(transferFormat, TransferFormat, \"transferFormat\");\r\n\r\n this._url = url;\r\n\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Connecting.\");\r\n\r\n // Allow binary format on Node and Browsers that support binary content (indicated by the presence of responseType property)\r\n if (transferFormat === TransferFormat.Binary &&\r\n (typeof XMLHttpRequest !== \"undefined\" && typeof new XMLHttpRequest().responseType !== \"string\")) {\r\n throw new Error(\"Binary protocols over XmlHttpRequest not implementing advanced features are not supported.\");\r\n }\r\n\r\n const [name, value] = getUserAgentHeader();\r\n const headers = { [name]: value, ...this._options.headers };\r\n\r\n const pollOptions: HttpRequest = {\r\n abortSignal: this._pollAbort.signal,\r\n headers,\r\n timeout: 100000,\r\n withCredentials: this._options.withCredentials,\r\n };\r\n\r\n if (transferFormat === TransferFormat.Binary) {\r\n pollOptions.responseType = \"arraybuffer\";\r\n }\r\n\r\n // Make initial long polling request\r\n // Server uses first long polling request to finish initializing connection and it returns without data\r\n const pollUrl = `${url}&_=${Date.now()}`;\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`);\r\n const response = await this._httpClient.get(pollUrl, pollOptions);\r\n if (response.statusCode !== 200) {\r\n this._logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`);\r\n\r\n // Mark running as false so that the poll immediately ends and runs the close logic\r\n this._closeError = new HttpError(response.statusText || \"\", response.statusCode);\r\n this._running = false;\r\n } else {\r\n this._running = true;\r\n }\r\n\r\n this._receiving = this._poll(this._url, pollOptions);\r\n }\r\n\r\n private async _poll(url: string, pollOptions: HttpRequest): Promise {\r\n try {\r\n while (this._running) {\r\n try {\r\n const pollUrl = `${url}&_=${Date.now()}`;\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) polling: ${pollUrl}.`);\r\n const response = await this._httpClient.get(pollUrl, pollOptions);\r\n\r\n if (response.statusCode === 204) {\r\n this._logger.log(LogLevel.Information, \"(LongPolling transport) Poll terminated by server.\");\r\n\r\n this._running = false;\r\n } else if (response.statusCode !== 200) {\r\n this._logger.log(LogLevel.Error, `(LongPolling transport) Unexpected response code: ${response.statusCode}.`);\r\n\r\n // Unexpected status code\r\n this._closeError = new HttpError(response.statusText || \"\", response.statusCode);\r\n this._running = false;\r\n } else {\r\n // Process the response\r\n if (response.content) {\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) data received. ${getDataDetail(response.content, this._options.logMessageContent!)}.`);\r\n if (this.onreceive) {\r\n this.onreceive(response.content);\r\n }\r\n } else {\r\n // This is another way timeout manifest.\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Poll timed out, reissuing.\");\r\n }\r\n }\r\n } catch (e) {\r\n if (!this._running) {\r\n // Log but disregard errors that occur after stopping\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) Poll errored after shutdown: ${(e as any).message}`);\r\n } else {\r\n if (e instanceof TimeoutError) {\r\n // Ignore timeouts and reissue the poll.\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Poll timed out, reissuing.\");\r\n } else {\r\n // Close the connection with the error as the result.\r\n this._closeError = e;\r\n this._running = false;\r\n }\r\n }\r\n }\r\n }\r\n } finally {\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Polling complete.\");\r\n\r\n // We will reach here with pollAborted==false when the server returned a response causing the transport to stop.\r\n // If pollAborted==true then client initiated the stop and the stop method will raise the close event after DELETE is sent.\r\n if (!this.pollAborted) {\r\n this._raiseOnClose();\r\n }\r\n }\r\n }\r\n\r\n public async send(data: any): Promise {\r\n if (!this._running) {\r\n return Promise.reject(new Error(\"Cannot send until the transport is connected\"));\r\n }\r\n return sendMessage(this._logger, \"LongPolling\", this._httpClient, this._url!, data, this._options);\r\n }\r\n\r\n public async stop(): Promise {\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Stopping polling.\");\r\n\r\n // Tell receiving loop to stop, abort any current request, and then wait for it to finish\r\n this._running = false;\r\n this._pollAbort.abort();\r\n\r\n try {\r\n await this._receiving;\r\n\r\n // Send DELETE to clean up long polling on the server\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) sending DELETE request to ${this._url}.`);\r\n\r\n const headers: {[k: string]: string} = {};\r\n const [name, value] = getUserAgentHeader();\r\n headers[name] = value;\r\n\r\n const deleteOptions: HttpRequest = {\r\n headers: { ...headers, ...this._options.headers },\r\n timeout: this._options.timeout,\r\n withCredentials: this._options.withCredentials,\r\n };\r\n\r\n let error;\r\n try {\r\n await this._httpClient.delete(this._url!, deleteOptions);\r\n } catch (err) {\r\n error = err;\r\n }\r\n\r\n if (error) {\r\n if (error instanceof HttpError) {\r\n if (error.statusCode === 404) {\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) A 404 response was returned from sending a DELETE request.\");\r\n } else {\r\n this._logger.log(LogLevel.Trace, `(LongPolling transport) Error sending a DELETE request: ${error}`);\r\n }\r\n }\r\n } else {\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) DELETE request accepted.\");\r\n }\r\n\r\n } finally {\r\n this._logger.log(LogLevel.Trace, \"(LongPolling transport) Stop finished.\");\r\n\r\n // Raise close event here instead of in polling\r\n // It needs to happen after the DELETE request is sent\r\n this._raiseOnClose();\r\n }\r\n }\r\n\r\n private _raiseOnClose() {\r\n if (this.onclose) {\r\n let logMessage = \"(LongPolling transport) Firing onclose event.\";\r\n if (this._closeError) {\r\n logMessage += \" Error: \" + this._closeError;\r\n }\r\n this._logger.log(LogLevel.Trace, logMessage);\r\n this.onclose(this._closeError);\r\n }\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HttpClient } from \"./HttpClient\";\r\nimport { MessageHeaders } from \"./IHubProtocol\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { ITransport, TransferFormat } from \"./ITransport\";\r\nimport { Arg, getDataDetail, getUserAgentHeader, Platform, sendMessage } from \"./Utils\";\r\nimport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\n\r\n/** @private */\r\nexport class ServerSentEventsTransport implements ITransport {\r\n private readonly _httpClient: HttpClient;\r\n private readonly _accessToken: string | undefined;\r\n private readonly _logger: ILogger;\r\n private readonly _options: IHttpConnectionOptions;\r\n private _eventSource?: EventSource;\r\n private _url?: string;\r\n\r\n public onreceive: ((data: string | ArrayBuffer) => void) | null;\r\n public onclose: ((error?: Error | unknown) => void) | null;\r\n\r\n constructor(httpClient: HttpClient, accessToken: string | undefined, logger: ILogger,\r\n options: IHttpConnectionOptions) {\r\n this._httpClient = httpClient;\r\n this._accessToken = accessToken;\r\n this._logger = logger;\r\n this._options = options;\r\n\r\n this.onreceive = null;\r\n this.onclose = null;\r\n }\r\n\r\n public async connect(url: string, transferFormat: TransferFormat): Promise {\r\n Arg.isRequired(url, \"url\");\r\n Arg.isRequired(transferFormat, \"transferFormat\");\r\n Arg.isIn(transferFormat, TransferFormat, \"transferFormat\");\r\n\r\n this._logger.log(LogLevel.Trace, \"(SSE transport) Connecting.\");\r\n\r\n // set url before accessTokenFactory because this._url is only for send and we set the auth header instead of the query string for send\r\n this._url = url;\r\n\r\n if (this._accessToken) {\r\n url += (url.indexOf(\"?\") < 0 ? \"?\" : \"&\") + `access_token=${encodeURIComponent(this._accessToken)}`;\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n let opened = false;\r\n if (transferFormat !== TransferFormat.Text) {\r\n reject(new Error(\"The Server-Sent Events transport only supports the 'Text' transfer format\"));\r\n return;\r\n }\r\n\r\n let eventSource: EventSource;\r\n if (Platform.isBrowser || Platform.isWebWorker) {\r\n eventSource = new this._options.EventSource!(url, { withCredentials: this._options.withCredentials });\r\n } else {\r\n // Non-browser passes cookies via the dictionary\r\n const cookies = this._httpClient.getCookieString(url);\r\n const headers: MessageHeaders = {};\r\n headers.Cookie = cookies;\r\n const [name, value] = getUserAgentHeader();\r\n headers[name] = value;\r\n\r\n eventSource = new this._options.EventSource!(url, { withCredentials: this._options.withCredentials, headers: { ...headers, ...this._options.headers} } as EventSourceInit);\r\n }\r\n\r\n try {\r\n eventSource.onmessage = (e: MessageEvent) => {\r\n if (this.onreceive) {\r\n try {\r\n this._logger.log(LogLevel.Trace, `(SSE transport) data received. ${getDataDetail(e.data, this._options.logMessageContent!)}.`);\r\n this.onreceive(e.data);\r\n } catch (error) {\r\n this._close(error);\r\n return;\r\n }\r\n }\r\n };\r\n\r\n // @ts-ignore: not using event on purpose\r\n eventSource.onerror = (e: Event) => {\r\n // EventSource doesn't give any useful information about server side closes.\r\n if (opened) {\r\n this._close();\r\n } else {\r\n reject(new Error(\"EventSource failed to connect. The connection could not be found on the server,\"\r\n + \" either the connection ID is not present on the server, or a proxy is refusing/buffering the connection.\"\r\n + \" If you have multiple servers check that sticky sessions are enabled.\"));\r\n }\r\n };\r\n\r\n eventSource.onopen = () => {\r\n this._logger.log(LogLevel.Information, `SSE connected to ${this._url}`);\r\n this._eventSource = eventSource;\r\n opened = true;\r\n resolve();\r\n };\r\n } catch (e) {\r\n reject(e);\r\n return;\r\n }\r\n });\r\n }\r\n\r\n public async send(data: any): Promise {\r\n if (!this._eventSource) {\r\n return Promise.reject(new Error(\"Cannot send until the transport is connected\"));\r\n }\r\n return sendMessage(this._logger, \"SSE\", this._httpClient, this._url!, data, this._options);\r\n }\r\n\r\n public stop(): Promise {\r\n this._close();\r\n return Promise.resolve();\r\n }\r\n\r\n private _close(e?: Error | unknown) {\r\n if (this._eventSource) {\r\n this._eventSource.close();\r\n this._eventSource = undefined;\r\n\r\n if (this.onclose) {\r\n this.onclose(e);\r\n }\r\n }\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { HeaderNames } from \"./HeaderNames\";\r\nimport { HttpClient } from \"./HttpClient\";\r\nimport { MessageHeaders } from \"./IHubProtocol\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { ITransport, TransferFormat } from \"./ITransport\";\r\nimport { WebSocketConstructor } from \"./Polyfills\";\r\nimport { Arg, getDataDetail, getUserAgentHeader, Platform } from \"./Utils\";\r\n\r\n/** @private */\r\nexport class WebSocketTransport implements ITransport {\r\n private readonly _logger: ILogger;\r\n private readonly _accessTokenFactory: (() => string | Promise) | undefined;\r\n private readonly _logMessageContent: boolean;\r\n private readonly _webSocketConstructor: WebSocketConstructor;\r\n private readonly _httpClient: HttpClient;\r\n private _webSocket?: WebSocket;\r\n private _headers: MessageHeaders;\r\n\r\n public onreceive: ((data: string | ArrayBuffer) => void) | null;\r\n public onclose: ((error?: Error) => void) | null;\r\n\r\n constructor(httpClient: HttpClient, accessTokenFactory: (() => string | Promise) | undefined, logger: ILogger,\r\n logMessageContent: boolean, webSocketConstructor: WebSocketConstructor, headers: MessageHeaders) {\r\n this._logger = logger;\r\n this._accessTokenFactory = accessTokenFactory;\r\n this._logMessageContent = logMessageContent;\r\n this._webSocketConstructor = webSocketConstructor;\r\n this._httpClient = httpClient;\r\n\r\n this.onreceive = null;\r\n this.onclose = null;\r\n this._headers = headers;\r\n }\r\n\r\n public async connect(url: string, transferFormat: TransferFormat): Promise {\r\n Arg.isRequired(url, \"url\");\r\n Arg.isRequired(transferFormat, \"transferFormat\");\r\n Arg.isIn(transferFormat, TransferFormat, \"transferFormat\");\r\n this._logger.log(LogLevel.Trace, \"(WebSockets transport) Connecting.\");\r\n\r\n let token: string;\r\n if (this._accessTokenFactory) {\r\n token = await this._accessTokenFactory();\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n url = url.replace(/^http/, \"ws\");\r\n let webSocket: WebSocket | undefined;\r\n const cookies = this._httpClient.getCookieString(url);\r\n let opened = false;\r\n\r\n if (Platform.isNode || Platform.isReactNative) {\r\n const headers: {[k: string]: string} = {};\r\n const [name, value] = getUserAgentHeader();\r\n headers[name] = value;\r\n if (token) {\r\n headers[HeaderNames.Authorization] = `Bearer ${token}`;\r\n }\r\n\r\n if (cookies) {\r\n headers[HeaderNames.Cookie] = cookies;\r\n }\r\n\r\n // Only pass headers when in non-browser environments\r\n webSocket = new this._webSocketConstructor(url, undefined, {\r\n headers: { ...headers, ...this._headers },\r\n });\r\n }\r\n else\r\n {\r\n if (token) {\r\n url += (url.indexOf(\"?\") < 0 ? \"?\" : \"&\") + `access_token=${encodeURIComponent(token)}`;\r\n }\r\n }\r\n\r\n if (!webSocket) {\r\n // Chrome is not happy with passing 'undefined' as protocol\r\n webSocket = new this._webSocketConstructor(url);\r\n }\r\n\r\n if (transferFormat === TransferFormat.Binary) {\r\n webSocket.binaryType = \"arraybuffer\";\r\n }\r\n\r\n webSocket.onopen = (_event: Event) => {\r\n this._logger.log(LogLevel.Information, `WebSocket connected to ${url}.`);\r\n this._webSocket = webSocket;\r\n opened = true;\r\n resolve();\r\n };\r\n\r\n webSocket.onerror = (event: Event) => {\r\n let error: any = null;\r\n // ErrorEvent is a browser only type we need to check if the type exists before using it\r\n if (typeof ErrorEvent !== \"undefined\" && event instanceof ErrorEvent) {\r\n error = event.error;\r\n } else {\r\n error = \"There was an error with the transport\";\r\n }\r\n\r\n this._logger.log(LogLevel.Information, `(WebSockets transport) ${error}.`);\r\n };\r\n\r\n webSocket.onmessage = (message: MessageEvent) => {\r\n this._logger.log(LogLevel.Trace, `(WebSockets transport) data received. ${getDataDetail(message.data, this._logMessageContent)}.`);\r\n if (this.onreceive) {\r\n try {\r\n this.onreceive(message.data);\r\n } catch (error) {\r\n this._close(error);\r\n return;\r\n }\r\n }\r\n };\r\n\r\n webSocket.onclose = (event: CloseEvent) => {\r\n // Don't call close handler if connection was never established\r\n // We'll reject the connect call instead\r\n if (opened) {\r\n this._close(event);\r\n } else {\r\n let error: any = null;\r\n // ErrorEvent is a browser only type we need to check if the type exists before using it\r\n if (typeof ErrorEvent !== \"undefined\" && event instanceof ErrorEvent) {\r\n error = event.error;\r\n } else {\r\n error = \"WebSocket failed to connect. The connection could not be found on the server,\"\r\n + \" either the endpoint may not be a SignalR endpoint,\"\r\n + \" the connection ID is not present on the server, or there is a proxy blocking WebSockets.\"\r\n + \" If you have multiple servers check that sticky sessions are enabled.\";\r\n }\r\n\r\n reject(new Error(error));\r\n }\r\n };\r\n });\r\n }\r\n\r\n public send(data: any): Promise {\r\n if (this._webSocket && this._webSocket.readyState === this._webSocketConstructor.OPEN) {\r\n this._logger.log(LogLevel.Trace, `(WebSockets transport) sending data. ${getDataDetail(data, this._logMessageContent)}.`);\r\n this._webSocket.send(data);\r\n return Promise.resolve();\r\n }\r\n\r\n return Promise.reject(\"WebSocket is not in the OPEN state\");\r\n }\r\n\r\n public stop(): Promise {\r\n if (this._webSocket) {\r\n // Manually invoke onclose callback inline so we know the HttpConnection was closed properly before returning\r\n // This also solves an issue where websocket.onclose could take 18+ seconds to trigger during network disconnects\r\n this._close(undefined);\r\n }\r\n\r\n return Promise.resolve();\r\n }\r\n\r\n private _close(event: CloseEvent | Error | unknown): void {\r\n // webSocket will be null if the transport did not start successfully\r\n if (this._webSocket) {\r\n // Clear websocket handlers because we are considering the socket closed now\r\n this._webSocket.onclose = () => {};\r\n this._webSocket.onmessage = () => {};\r\n this._webSocket.onerror = () => {};\r\n this._webSocket.close();\r\n this._webSocket = undefined;\r\n }\r\n\r\n this._logger.log(LogLevel.Trace, \"(WebSockets transport) socket closed.\");\r\n\r\n if (this.onclose) {\r\n if (this._isCloseEvent(event) && (event.wasClean === false || event.code !== 1000)) {\r\n this.onclose(new Error(`WebSocket closed with status code: ${event.code} (${event.reason || \"no reason given\"}).`));\r\n } else if (event instanceof Error) {\r\n this.onclose(event);\r\n } else {\r\n this.onclose();\r\n }\r\n }\r\n }\r\n\r\n private _isCloseEvent(event?: any): event is CloseEvent {\r\n return event && typeof event.wasClean === \"boolean\" && typeof event.code === \"number\";\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AccessTokenHttpClient } from \"./AccessTokenHttpClient\";\r\nimport { DefaultHttpClient } from \"./DefaultHttpClient\";\r\nimport { AggregateErrors, DisabledTransportError, FailedToNegotiateWithServerError, FailedToStartTransportError, HttpError, UnsupportedTransportError, AbortError } from \"./Errors\";\r\nimport { IConnection } from \"./IConnection\";\r\nimport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { HttpTransportType, ITransport, TransferFormat } from \"./ITransport\";\r\nimport { LongPollingTransport } from \"./LongPollingTransport\";\r\nimport { ServerSentEventsTransport } from \"./ServerSentEventsTransport\";\r\nimport { Arg, createLogger, getUserAgentHeader, Platform } from \"./Utils\";\r\nimport { WebSocketTransport } from \"./WebSocketTransport\";\r\n\r\n/** @private */\r\nconst enum ConnectionState {\r\n Connecting = \"Connecting\",\r\n Connected = \"Connected\",\r\n Disconnected = \"Disconnected\",\r\n Disconnecting = \"Disconnecting\",\r\n}\r\n\r\n/** @private */\r\nexport interface INegotiateResponse {\r\n connectionId?: string;\r\n connectionToken?: string;\r\n negotiateVersion?: number;\r\n availableTransports?: IAvailableTransport[];\r\n url?: string;\r\n accessToken?: string;\r\n error?: string;\r\n useStatefulReconnect?: boolean;\r\n}\r\n\r\n/** @private */\r\nexport interface IAvailableTransport {\r\n transport: keyof typeof HttpTransportType;\r\n transferFormats: (keyof typeof TransferFormat)[];\r\n}\r\n\r\nconst MAX_REDIRECTS = 100;\r\n\r\n/** @private */\r\nexport class HttpConnection implements IConnection {\r\n private _connectionState: ConnectionState;\r\n // connectionStarted is tracked independently from connectionState, so we can check if the\r\n // connection ever did successfully transition from connecting to connected before disconnecting.\r\n private _connectionStarted: boolean;\r\n private readonly _httpClient: AccessTokenHttpClient;\r\n private readonly _logger: ILogger;\r\n private readonly _options: IHttpConnectionOptions;\r\n // Needs to not start with _ to be available for tests\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n private transport?: ITransport;\r\n private _startInternalPromise?: Promise;\r\n private _stopPromise?: Promise;\r\n private _stopPromiseResolver: (value?: PromiseLike) => void = () => {};\r\n private _stopError?: Error;\r\n private _accessTokenFactory?: () => string | Promise;\r\n private _sendQueue?: TransportSendQueue;\r\n\r\n public readonly features: any = {};\r\n public baseUrl: string;\r\n public connectionId?: string;\r\n public onreceive: ((data: string | ArrayBuffer) => void) | null;\r\n public onclose: ((e?: Error) => void) | null;\r\n\r\n private readonly _negotiateVersion: number = 1;\r\n\r\n constructor(url: string, options: IHttpConnectionOptions = {}) {\r\n Arg.isRequired(url, \"url\");\r\n\r\n this._logger = createLogger(options.logger);\r\n this.baseUrl = this._resolveUrl(url);\r\n\r\n options = options || {};\r\n options.logMessageContent = options.logMessageContent === undefined ? false : options.logMessageContent;\r\n if (typeof options.withCredentials === \"boolean\" || options.withCredentials === undefined) {\r\n options.withCredentials = options.withCredentials === undefined ? true : options.withCredentials;\r\n } else {\r\n throw new Error(\"withCredentials option was not a 'boolean' or 'undefined' value\");\r\n }\r\n options.timeout = options.timeout === undefined ? 100 * 1000 : options.timeout;\r\n\r\n let webSocketModule: any = null;\r\n let eventSourceModule: any = null;\r\n\r\n if (Platform.isNode && typeof require !== \"undefined\") {\r\n // In order to ignore the dynamic require in webpack builds we need to do this magic\r\n // @ts-ignore: TS doesn't know about these names\r\n const requireFunc = typeof __webpack_require__ === \"function\" ? __non_webpack_require__ : require;\r\n webSocketModule = requireFunc(\"ws\");\r\n eventSourceModule = requireFunc(\"eventsource\");\r\n }\r\n\r\n if (!Platform.isNode && typeof WebSocket !== \"undefined\" && !options.WebSocket) {\r\n options.WebSocket = WebSocket;\r\n } else if (Platform.isNode && !options.WebSocket) {\r\n if (webSocketModule) {\r\n options.WebSocket = webSocketModule;\r\n }\r\n }\r\n\r\n if (!Platform.isNode && typeof EventSource !== \"undefined\" && !options.EventSource) {\r\n options.EventSource = EventSource;\r\n } else if (Platform.isNode && !options.EventSource) {\r\n if (typeof eventSourceModule !== \"undefined\") {\r\n options.EventSource = eventSourceModule;\r\n }\r\n }\r\n\r\n this._httpClient = new AccessTokenHttpClient(options.httpClient || new DefaultHttpClient(this._logger), options.accessTokenFactory);\r\n this._connectionState = ConnectionState.Disconnected;\r\n this._connectionStarted = false;\r\n this._options = options;\r\n\r\n this.onreceive = null;\r\n this.onclose = null;\r\n }\r\n\r\n public start(): Promise;\r\n public start(transferFormat: TransferFormat): Promise;\r\n public async start(transferFormat?: TransferFormat): Promise {\r\n transferFormat = transferFormat || TransferFormat.Binary;\r\n\r\n Arg.isIn(transferFormat, TransferFormat, \"transferFormat\");\r\n\r\n this._logger.log(LogLevel.Debug, `Starting connection with transfer format '${TransferFormat[transferFormat]}'.`);\r\n\r\n if (this._connectionState !== ConnectionState.Disconnected) {\r\n return Promise.reject(new Error(\"Cannot start an HttpConnection that is not in the 'Disconnected' state.\"));\r\n }\r\n\r\n this._connectionState = ConnectionState.Connecting;\r\n\r\n this._startInternalPromise = this._startInternal(transferFormat);\r\n await this._startInternalPromise;\r\n\r\n // The TypeScript compiler thinks that connectionState must be Connecting here. The TypeScript compiler is wrong.\r\n if (this._connectionState as any === ConnectionState.Disconnecting) {\r\n // stop() was called and transitioned the client into the Disconnecting state.\r\n const message = \"Failed to start the HttpConnection before stop() was called.\";\r\n this._logger.log(LogLevel.Error, message);\r\n\r\n // We cannot await stopPromise inside startInternal since stopInternal awaits the startInternalPromise.\r\n await this._stopPromise;\r\n\r\n return Promise.reject(new AbortError(message));\r\n } else if (this._connectionState as any !== ConnectionState.Connected) {\r\n // stop() was called and transitioned the client into the Disconnecting state.\r\n const message = \"HttpConnection.startInternal completed gracefully but didn't enter the connection into the connected state!\";\r\n this._logger.log(LogLevel.Error, message);\r\n return Promise.reject(new AbortError(message));\r\n }\r\n\r\n this._connectionStarted = true;\r\n }\r\n\r\n public send(data: string | ArrayBuffer): Promise {\r\n if (this._connectionState !== ConnectionState.Connected) {\r\n return Promise.reject(new Error(\"Cannot send data if the connection is not in the 'Connected' State.\"));\r\n }\r\n\r\n if (!this._sendQueue) {\r\n this._sendQueue = new TransportSendQueue(this.transport!);\r\n }\r\n\r\n // Transport will not be null if state is connected\r\n return this._sendQueue.send(data);\r\n }\r\n\r\n public async stop(error?: Error): Promise {\r\n if (this._connectionState === ConnectionState.Disconnected) {\r\n this._logger.log(LogLevel.Debug, `Call to HttpConnection.stop(${error}) ignored because the connection is already in the disconnected state.`);\r\n return Promise.resolve();\r\n }\r\n\r\n if (this._connectionState === ConnectionState.Disconnecting) {\r\n this._logger.log(LogLevel.Debug, `Call to HttpConnection.stop(${error}) ignored because the connection is already in the disconnecting state.`);\r\n return this._stopPromise;\r\n }\r\n\r\n this._connectionState = ConnectionState.Disconnecting;\r\n\r\n this._stopPromise = new Promise((resolve) => {\r\n // Don't complete stop() until stopConnection() completes.\r\n this._stopPromiseResolver = resolve;\r\n });\r\n\r\n // stopInternal should never throw so just observe it.\r\n await this._stopInternal(error);\r\n await this._stopPromise;\r\n }\r\n\r\n private async _stopInternal(error?: Error): Promise {\r\n // Set error as soon as possible otherwise there is a race between\r\n // the transport closing and providing an error and the error from a close message\r\n // We would prefer the close message error.\r\n this._stopError = error;\r\n\r\n try {\r\n await this._startInternalPromise;\r\n } catch (e) {\r\n // This exception is returned to the user as a rejected Promise from the start method.\r\n }\r\n\r\n // The transport's onclose will trigger stopConnection which will run our onclose event.\r\n // The transport should always be set if currently connected. If it wasn't set, it's likely because\r\n // stop was called during start() and start() failed.\r\n if (this.transport) {\r\n try {\r\n await this.transport.stop();\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `HttpConnection.transport.stop() threw error '${e}'.`);\r\n this._stopConnection();\r\n }\r\n\r\n this.transport = undefined;\r\n } else {\r\n this._logger.log(LogLevel.Debug, \"HttpConnection.transport is undefined in HttpConnection.stop() because start() failed.\");\r\n }\r\n }\r\n\r\n private async _startInternal(transferFormat: TransferFormat): Promise {\r\n // Store the original base url and the access token factory since they may change\r\n // as part of negotiating\r\n let url = this.baseUrl;\r\n this._accessTokenFactory = this._options.accessTokenFactory;\r\n this._httpClient._accessTokenFactory = this._accessTokenFactory;\r\n\r\n try {\r\n if (this._options.skipNegotiation) {\r\n if (this._options.transport === HttpTransportType.WebSockets) {\r\n // No need to add a connection ID in this case\r\n this.transport = this._constructTransport(HttpTransportType.WebSockets);\r\n // We should just call connect directly in this case.\r\n // No fallback or negotiate in this case.\r\n await this._startTransport(url, transferFormat);\r\n } else {\r\n throw new Error(\"Negotiation can only be skipped when using the WebSocket transport directly.\");\r\n }\r\n } else {\r\n let negotiateResponse: INegotiateResponse | null = null;\r\n let redirects = 0;\r\n\r\n do {\r\n negotiateResponse = await this._getNegotiationResponse(url);\r\n // the user tries to stop the connection when it is being started\r\n if (this._connectionState === ConnectionState.Disconnecting || this._connectionState === ConnectionState.Disconnected) {\r\n throw new AbortError(\"The connection was stopped during negotiation.\");\r\n }\r\n\r\n if (negotiateResponse.error) {\r\n throw new Error(negotiateResponse.error);\r\n }\r\n\r\n if ((negotiateResponse as any).ProtocolVersion) {\r\n throw new Error(\"Detected a connection attempt to an ASP.NET SignalR Server. This client only supports connecting to an ASP.NET Core SignalR Server. See https://aka.ms/signalr-core-differences for details.\");\r\n }\r\n\r\n if (negotiateResponse.url) {\r\n url = negotiateResponse.url;\r\n }\r\n\r\n if (negotiateResponse.accessToken) {\r\n // Replace the current access token factory with one that uses\r\n // the returned access token\r\n const accessToken = negotiateResponse.accessToken;\r\n this._accessTokenFactory = () => accessToken;\r\n // set the factory to undefined so the AccessTokenHttpClient won't retry with the same token, since we know it won't change until a connection restart\r\n this._httpClient._accessToken = accessToken;\r\n this._httpClient._accessTokenFactory = undefined;\r\n }\r\n\r\n redirects++;\r\n }\r\n while (negotiateResponse.url && redirects < MAX_REDIRECTS);\r\n\r\n if (redirects === MAX_REDIRECTS && negotiateResponse.url) {\r\n throw new Error(\"Negotiate redirection limit exceeded.\");\r\n }\r\n\r\n await this._createTransport(url, this._options.transport, negotiateResponse, transferFormat);\r\n }\r\n\r\n if (this.transport instanceof LongPollingTransport) {\r\n this.features.inherentKeepAlive = true;\r\n }\r\n\r\n if (this._connectionState === ConnectionState.Connecting) {\r\n // Ensure the connection transitions to the connected state prior to completing this.startInternalPromise.\r\n // start() will handle the case when stop was called and startInternal exits still in the disconnecting state.\r\n this._logger.log(LogLevel.Debug, \"The HttpConnection connected successfully.\");\r\n this._connectionState = ConnectionState.Connected;\r\n }\r\n\r\n // stop() is waiting on us via this.startInternalPromise so keep this.transport around so it can clean up.\r\n // This is the only case startInternal can exit in neither the connected nor disconnected state because stopConnection()\r\n // will transition to the disconnected state. start() will wait for the transition using the stopPromise.\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, \"Failed to start the connection: \" + e);\r\n this._connectionState = ConnectionState.Disconnected;\r\n this.transport = undefined;\r\n\r\n // if start fails, any active calls to stop assume that start will complete the stop promise\r\n this._stopPromiseResolver();\r\n return Promise.reject(e);\r\n }\r\n }\r\n\r\n private async _getNegotiationResponse(url: string): Promise {\r\n const headers: {[k: string]: string} = {};\r\n const [name, value] = getUserAgentHeader();\r\n headers[name] = value;\r\n\r\n const negotiateUrl = this._resolveNegotiateUrl(url);\r\n this._logger.log(LogLevel.Debug, `Sending negotiation request: ${negotiateUrl}.`);\r\n try {\r\n const response = await this._httpClient.post(negotiateUrl, {\r\n content: \"\",\r\n headers: { ...headers, ...this._options.headers },\r\n timeout: this._options.timeout,\r\n withCredentials: this._options.withCredentials,\r\n });\r\n\r\n if (response.statusCode !== 200) {\r\n return Promise.reject(new Error(`Unexpected status code returned from negotiate '${response.statusCode}'`));\r\n }\r\n\r\n const negotiateResponse = JSON.parse(response.content as string) as INegotiateResponse;\r\n if (!negotiateResponse.negotiateVersion || negotiateResponse.negotiateVersion < 1) {\r\n // Negotiate version 0 doesn't use connectionToken\r\n // So we set it equal to connectionId so all our logic can use connectionToken without being aware of the negotiate version\r\n negotiateResponse.connectionToken = negotiateResponse.connectionId;\r\n }\r\n\r\n if (negotiateResponse.useStatefulReconnect && this._options._useStatefulReconnect !== true) {\r\n return Promise.reject(new FailedToNegotiateWithServerError(\"Client didn't negotiate Stateful Reconnect but the server did.\"));\r\n }\r\n\r\n return negotiateResponse;\r\n } catch (e) {\r\n let errorMessage = \"Failed to complete negotiation with the server: \" + e;\r\n if (e instanceof HttpError) {\r\n if (e.statusCode === 404) {\r\n errorMessage = errorMessage + \" Either this is not a SignalR endpoint or there is a proxy blocking the connection.\";\r\n }\r\n }\r\n this._logger.log(LogLevel.Error, errorMessage);\r\n\r\n return Promise.reject(new FailedToNegotiateWithServerError(errorMessage));\r\n }\r\n }\r\n\r\n private _createConnectUrl(url: string, connectionToken: string | null | undefined) {\r\n if (!connectionToken) {\r\n return url;\r\n }\r\n\r\n return url + (url.indexOf(\"?\") === -1 ? \"?\" : \"&\") + `id=${connectionToken}`;\r\n }\r\n\r\n private async _createTransport(url: string, requestedTransport: HttpTransportType | ITransport | undefined, negotiateResponse: INegotiateResponse, requestedTransferFormat: TransferFormat): Promise {\r\n let connectUrl = this._createConnectUrl(url, negotiateResponse.connectionToken);\r\n if (this._isITransport(requestedTransport)) {\r\n this._logger.log(LogLevel.Debug, \"Connection was provided an instance of ITransport, using that directly.\");\r\n this.transport = requestedTransport;\r\n await this._startTransport(connectUrl, requestedTransferFormat);\r\n\r\n this.connectionId = negotiateResponse.connectionId;\r\n return;\r\n }\r\n\r\n const transportExceptions: any[] = [];\r\n const transports = negotiateResponse.availableTransports || [];\r\n let negotiate: INegotiateResponse | undefined = negotiateResponse;\r\n for (const endpoint of transports) {\r\n const transportOrError = this._resolveTransportOrError(endpoint, requestedTransport, requestedTransferFormat,\r\n negotiate?.useStatefulReconnect === true);\r\n if (transportOrError instanceof Error) {\r\n // Store the error and continue, we don't want to cause a re-negotiate in these cases\r\n transportExceptions.push(`${endpoint.transport} failed:`);\r\n transportExceptions.push(transportOrError);\r\n } else if (this._isITransport(transportOrError)) {\r\n this.transport = transportOrError;\r\n if (!negotiate) {\r\n try {\r\n negotiate = await this._getNegotiationResponse(url);\r\n } catch (ex) {\r\n return Promise.reject(ex);\r\n }\r\n connectUrl = this._createConnectUrl(url, negotiate.connectionToken);\r\n }\r\n try {\r\n await this._startTransport(connectUrl, requestedTransferFormat);\r\n this.connectionId = negotiate.connectionId;\r\n return;\r\n } catch (ex) {\r\n this._logger.log(LogLevel.Error, `Failed to start the transport '${endpoint.transport}': ${ex}`);\r\n negotiate = undefined;\r\n transportExceptions.push(new FailedToStartTransportError(`${endpoint.transport} failed: ${ex}`, HttpTransportType[endpoint.transport]));\r\n\r\n if (this._connectionState !== ConnectionState.Connecting) {\r\n const message = \"Failed to select transport before stop() was called.\";\r\n this._logger.log(LogLevel.Debug, message);\r\n return Promise.reject(new AbortError(message));\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (transportExceptions.length > 0) {\r\n return Promise.reject(new AggregateErrors(`Unable to connect to the server with any of the available transports. ${transportExceptions.join(\" \")}`, transportExceptions));\r\n }\r\n return Promise.reject(new Error(\"None of the transports supported by the client are supported by the server.\"));\r\n }\r\n\r\n private _constructTransport(transport: HttpTransportType): ITransport {\r\n switch (transport) {\r\n case HttpTransportType.WebSockets:\r\n if (!this._options.WebSocket) {\r\n throw new Error(\"'WebSocket' is not supported in your environment.\");\r\n }\r\n return new WebSocketTransport(this._httpClient, this._accessTokenFactory, this._logger, this._options.logMessageContent!,\r\n this._options.WebSocket, this._options.headers || {});\r\n case HttpTransportType.ServerSentEvents:\r\n if (!this._options.EventSource) {\r\n throw new Error(\"'EventSource' is not supported in your environment.\");\r\n }\r\n return new ServerSentEventsTransport(this._httpClient, this._httpClient._accessToken, this._logger, this._options);\r\n case HttpTransportType.LongPolling:\r\n return new LongPollingTransport(this._httpClient, this._logger, this._options);\r\n default:\r\n throw new Error(`Unknown transport: ${transport}.`);\r\n }\r\n }\r\n\r\n private _startTransport(url: string, transferFormat: TransferFormat): Promise {\r\n this.transport!.onreceive = this.onreceive;\r\n if (this.features.reconnect) {\r\n this.transport!.onclose = async (e) => {\r\n let callStop = false;\r\n if (this.features.reconnect) {\r\n try {\r\n this.features.disconnected();\r\n await this.transport!.connect(url, transferFormat);\r\n await this.features.resend();\r\n } catch {\r\n callStop = true;\r\n }\r\n } else {\r\n this._stopConnection(e);\r\n return;\r\n }\r\n\r\n if (callStop) {\r\n this._stopConnection(e);\r\n }\r\n };\r\n } else {\r\n this.transport!.onclose = (e) => this._stopConnection(e);\r\n }\r\n return this.transport!.connect(url, transferFormat);\r\n }\r\n\r\n private _resolveTransportOrError(endpoint: IAvailableTransport, requestedTransport: HttpTransportType | undefined,\r\n requestedTransferFormat: TransferFormat, useStatefulReconnect: boolean): ITransport | Error | unknown {\r\n const transport = HttpTransportType[endpoint.transport];\r\n if (transport === null || transport === undefined) {\r\n this._logger.log(LogLevel.Debug, `Skipping transport '${endpoint.transport}' because it is not supported by this client.`);\r\n return new Error(`Skipping transport '${endpoint.transport}' because it is not supported by this client.`);\r\n } else {\r\n if (transportMatches(requestedTransport, transport)) {\r\n const transferFormats = endpoint.transferFormats.map((s) => TransferFormat[s]);\r\n if (transferFormats.indexOf(requestedTransferFormat) >= 0) {\r\n if ((transport === HttpTransportType.WebSockets && !this._options.WebSocket) ||\r\n (transport === HttpTransportType.ServerSentEvents && !this._options.EventSource)) {\r\n this._logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it is not supported in your environment.'`);\r\n return new UnsupportedTransportError(`'${HttpTransportType[transport]}' is not supported in your environment.`, transport);\r\n } else {\r\n this._logger.log(LogLevel.Debug, `Selecting transport '${HttpTransportType[transport]}'.`);\r\n try {\r\n this.features.reconnect = transport === HttpTransportType.WebSockets ? useStatefulReconnect : undefined;\r\n return this._constructTransport(transport);\r\n } catch (ex) {\r\n return ex;\r\n }\r\n }\r\n } else {\r\n this._logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it does not support the requested transfer format '${TransferFormat[requestedTransferFormat]}'.`);\r\n return new Error(`'${HttpTransportType[transport]}' does not support ${TransferFormat[requestedTransferFormat]}.`);\r\n }\r\n } else {\r\n this._logger.log(LogLevel.Debug, `Skipping transport '${HttpTransportType[transport]}' because it was disabled by the client.`);\r\n return new DisabledTransportError(`'${HttpTransportType[transport]}' is disabled by the client.`, transport);\r\n }\r\n }\r\n }\r\n\r\n private _isITransport(transport: any): transport is ITransport {\r\n return transport && typeof (transport) === \"object\" && \"connect\" in transport;\r\n }\r\n\r\n private _stopConnection(error?: Error): void {\r\n this._logger.log(LogLevel.Debug, `HttpConnection.stopConnection(${error}) called while in state ${this._connectionState}.`);\r\n\r\n this.transport = undefined;\r\n\r\n // If we have a stopError, it takes precedence over the error from the transport\r\n error = this._stopError || error;\r\n this._stopError = undefined;\r\n\r\n if (this._connectionState === ConnectionState.Disconnected) {\r\n this._logger.log(LogLevel.Debug, `Call to HttpConnection.stopConnection(${error}) was ignored because the connection is already in the disconnected state.`);\r\n return;\r\n }\r\n\r\n if (this._connectionState === ConnectionState.Connecting) {\r\n this._logger.log(LogLevel.Warning, `Call to HttpConnection.stopConnection(${error}) was ignored because the connection is still in the connecting state.`);\r\n throw new Error(`HttpConnection.stopConnection(${error}) was called while the connection is still in the connecting state.`);\r\n }\r\n\r\n if (this._connectionState === ConnectionState.Disconnecting) {\r\n // A call to stop() induced this call to stopConnection and needs to be completed.\r\n // Any stop() awaiters will be scheduled to continue after the onclose callback fires.\r\n this._stopPromiseResolver();\r\n }\r\n\r\n if (error) {\r\n this._logger.log(LogLevel.Error, `Connection disconnected with error '${error}'.`);\r\n } else {\r\n this._logger.log(LogLevel.Information, \"Connection disconnected.\");\r\n }\r\n\r\n if (this._sendQueue) {\r\n this._sendQueue.stop().catch((e) => {\r\n this._logger.log(LogLevel.Error, `TransportSendQueue.stop() threw error '${e}'.`);\r\n });\r\n this._sendQueue = undefined;\r\n }\r\n\r\n this.connectionId = undefined;\r\n this._connectionState = ConnectionState.Disconnected;\r\n\r\n if (this._connectionStarted) {\r\n this._connectionStarted = false;\r\n try {\r\n if (this.onclose) {\r\n this.onclose(error);\r\n }\r\n } catch (e) {\r\n this._logger.log(LogLevel.Error, `HttpConnection.onclose(${error}) threw error '${e}'.`);\r\n }\r\n }\r\n }\r\n\r\n private _resolveUrl(url: string): string {\r\n // startsWith is not supported in IE\r\n if (url.lastIndexOf(\"https://\", 0) === 0 || url.lastIndexOf(\"http://\", 0) === 0) {\r\n return url;\r\n }\r\n\r\n if (!Platform.isBrowser) {\r\n throw new Error(`Cannot resolve '${url}'.`);\r\n }\r\n\r\n // Setting the url to the href propery of an anchor tag handles normalization\r\n // for us. There are 3 main cases.\r\n // 1. Relative path normalization e.g \"b\" -> \"http://localhost:5000/a/b\"\r\n // 2. Absolute path normalization e.g \"/a/b\" -> \"http://localhost:5000/a/b\"\r\n // 3. Networkpath reference normalization e.g \"//localhost:5000/a/b\" -> \"http://localhost:5000/a/b\"\r\n const aTag = window.document.createElement(\"a\");\r\n aTag.href = url;\r\n\r\n this._logger.log(LogLevel.Information, `Normalizing '${url}' to '${aTag.href}'.`);\r\n return aTag.href;\r\n }\r\n\r\n private _resolveNegotiateUrl(url: string): string {\r\n const negotiateUrl = new URL(url);\r\n\r\n if (negotiateUrl.pathname.endsWith('/')) {\r\n negotiateUrl.pathname += \"negotiate\";\r\n } else {\r\n negotiateUrl.pathname += \"/negotiate\";\r\n }\r\n const searchParams = new URLSearchParams(negotiateUrl.searchParams);\r\n\r\n if (!searchParams.has(\"negotiateVersion\")) {\r\n searchParams.append(\"negotiateVersion\", this._negotiateVersion.toString());\r\n }\r\n\r\n if (searchParams.has(\"useStatefulReconnect\")) {\r\n if (searchParams.get(\"useStatefulReconnect\") === \"true\") {\r\n this._options._useStatefulReconnect = true;\r\n }\r\n } else if (this._options._useStatefulReconnect === true) {\r\n searchParams.append(\"useStatefulReconnect\", \"true\");\r\n }\r\n\r\n negotiateUrl.search = searchParams.toString();\r\n\r\n return negotiateUrl.toString();\r\n }\r\n}\r\n\r\nfunction transportMatches(requestedTransport: HttpTransportType | undefined, actualTransport: HttpTransportType) {\r\n return !requestedTransport || ((actualTransport & requestedTransport) !== 0);\r\n}\r\n\r\n/** @private */\r\nexport class TransportSendQueue {\r\n private _buffer: any[] = [];\r\n private _sendBufferedData: PromiseSource;\r\n private _executing: boolean = true;\r\n private _transportResult?: PromiseSource;\r\n private _sendLoopPromise: Promise;\r\n\r\n constructor(private readonly _transport: ITransport) {\r\n this._sendBufferedData = new PromiseSource();\r\n this._transportResult = new PromiseSource();\r\n\r\n this._sendLoopPromise = this._sendLoop();\r\n }\r\n\r\n public send(data: string | ArrayBuffer): Promise {\r\n this._bufferData(data);\r\n if (!this._transportResult) {\r\n this._transportResult = new PromiseSource();\r\n }\r\n return this._transportResult.promise;\r\n }\r\n\r\n public stop(): Promise {\r\n this._executing = false;\r\n this._sendBufferedData.resolve();\r\n return this._sendLoopPromise;\r\n }\r\n\r\n private _bufferData(data: string | ArrayBuffer): void {\r\n if (this._buffer.length && typeof(this._buffer[0]) !== typeof(data)) {\r\n throw new Error(`Expected data to be of type ${typeof(this._buffer)} but was of type ${typeof(data)}`);\r\n }\r\n\r\n this._buffer.push(data);\r\n this._sendBufferedData.resolve();\r\n }\r\n\r\n private async _sendLoop(): Promise {\r\n while (true) {\r\n await this._sendBufferedData.promise;\r\n\r\n if (!this._executing) {\r\n if (this._transportResult) {\r\n this._transportResult.reject(\"Connection stopped.\");\r\n }\r\n\r\n break;\r\n }\r\n\r\n this._sendBufferedData = new PromiseSource();\r\n\r\n const transportResult = this._transportResult!;\r\n this._transportResult = undefined;\r\n\r\n const data = typeof(this._buffer[0]) === \"string\" ?\r\n this._buffer.join(\"\") :\r\n TransportSendQueue._concatBuffers(this._buffer);\r\n\r\n this._buffer.length = 0;\r\n\r\n try {\r\n await this._transport.send(data);\r\n transportResult.resolve();\r\n } catch (error) {\r\n transportResult.reject(error);\r\n }\r\n }\r\n }\r\n\r\n private static _concatBuffers(arrayBuffers: ArrayBuffer[]): ArrayBuffer {\r\n const totalLength = arrayBuffers.map((b) => b.byteLength).reduce((a, b) => a + b);\r\n const result = new Uint8Array(totalLength);\r\n let offset = 0;\r\n for (const item of arrayBuffers) {\r\n result.set(new Uint8Array(item), offset);\r\n offset += item.byteLength;\r\n }\r\n\r\n return result.buffer;\r\n }\r\n}\r\n\r\nclass PromiseSource {\r\n private _resolver?: () => void;\r\n private _rejecter!: (reason?: any) => void;\r\n public promise: Promise;\r\n\r\n constructor() {\r\n this.promise = new Promise((resolve, reject) => [this._resolver, this._rejecter] = [resolve, reject]);\r\n }\r\n\r\n public resolve(): void {\r\n this._resolver!();\r\n }\r\n\r\n public reject(reason?: any): void {\r\n this._rejecter!(reason);\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { AckMessage, CompletionMessage, HubMessage, IHubProtocol, InvocationMessage, MessageType, SequenceMessage, StreamItemMessage } from \"./IHubProtocol\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { TransferFormat } from \"./ITransport\";\r\nimport { NullLogger } from \"./Loggers\";\r\nimport { TextMessageFormat } from \"./TextMessageFormat\";\r\n\r\nconst JSON_HUB_PROTOCOL_NAME: string = \"json\";\r\n\r\n/** Implements the JSON Hub Protocol. */\r\nexport class JsonHubProtocol implements IHubProtocol {\r\n\r\n /** @inheritDoc */\r\n public readonly name: string = JSON_HUB_PROTOCOL_NAME;\r\n /** @inheritDoc */\r\n public readonly version: number = 2;\r\n\r\n /** @inheritDoc */\r\n public readonly transferFormat: TransferFormat = TransferFormat.Text;\r\n\r\n /** Creates an array of {@link @microsoft/signalr.HubMessage} objects from the specified serialized representation.\r\n *\r\n * @param {string} input A string containing the serialized representation.\r\n * @param {ILogger} logger A logger that will be used to log messages that occur during parsing.\r\n */\r\n public parseMessages(input: string, logger: ILogger): HubMessage[] {\r\n // The interface does allow \"ArrayBuffer\" to be passed in, but this implementation does not. So let's throw a useful error.\r\n if (typeof input !== \"string\") {\r\n throw new Error(\"Invalid input for JSON hub protocol. Expected a string.\");\r\n }\r\n\r\n if (!input) {\r\n return [];\r\n }\r\n\r\n if (logger === null) {\r\n logger = NullLogger.instance;\r\n }\r\n\r\n // Parse the messages\r\n const messages = TextMessageFormat.parse(input);\r\n\r\n const hubMessages = [];\r\n for (const message of messages) {\r\n const parsedMessage = JSON.parse(message) as HubMessage;\r\n if (typeof parsedMessage.type !== \"number\") {\r\n throw new Error(\"Invalid payload.\");\r\n }\r\n switch (parsedMessage.type) {\r\n case MessageType.Invocation:\r\n this._isInvocationMessage(parsedMessage);\r\n break;\r\n case MessageType.StreamItem:\r\n this._isStreamItemMessage(parsedMessage);\r\n break;\r\n case MessageType.Completion:\r\n this._isCompletionMessage(parsedMessage);\r\n break;\r\n case MessageType.Ping:\r\n // Single value, no need to validate\r\n break;\r\n case MessageType.Close:\r\n // All optional values, no need to validate\r\n break;\r\n case MessageType.Ack:\r\n this._isAckMessage(parsedMessage);\r\n break;\r\n case MessageType.Sequence:\r\n this._isSequenceMessage(parsedMessage);\r\n break;\r\n default:\r\n // Future protocol changes can add message types, old clients can ignore them\r\n logger.log(LogLevel.Information, \"Unknown message type '\" + parsedMessage.type + \"' ignored.\");\r\n continue;\r\n }\r\n hubMessages.push(parsedMessage);\r\n }\r\n\r\n return hubMessages;\r\n }\r\n\r\n /** Writes the specified {@link @microsoft/signalr.HubMessage} to a string and returns it.\r\n *\r\n * @param {HubMessage} message The message to write.\r\n * @returns {string} A string containing the serialized representation of the message.\r\n */\r\n public writeMessage(message: HubMessage): string {\r\n return TextMessageFormat.write(JSON.stringify(message));\r\n }\r\n\r\n private _isInvocationMessage(message: InvocationMessage): void {\r\n this._assertNotEmptyString(message.target, \"Invalid payload for Invocation message.\");\r\n\r\n if (message.invocationId !== undefined) {\r\n this._assertNotEmptyString(message.invocationId, \"Invalid payload for Invocation message.\");\r\n }\r\n }\r\n\r\n private _isStreamItemMessage(message: StreamItemMessage): void {\r\n this._assertNotEmptyString(message.invocationId, \"Invalid payload for StreamItem message.\");\r\n\r\n if (message.item === undefined) {\r\n throw new Error(\"Invalid payload for StreamItem message.\");\r\n }\r\n }\r\n\r\n private _isCompletionMessage(message: CompletionMessage): void {\r\n if (message.result && message.error) {\r\n throw new Error(\"Invalid payload for Completion message.\");\r\n }\r\n\r\n if (!message.result && message.error) {\r\n this._assertNotEmptyString(message.error, \"Invalid payload for Completion message.\");\r\n }\r\n\r\n this._assertNotEmptyString(message.invocationId, \"Invalid payload for Completion message.\");\r\n }\r\n\r\n private _isAckMessage(message: AckMessage): void {\r\n if (typeof message.sequenceId !== 'number') {\r\n throw new Error(\"Invalid SequenceId for Ack message.\");\r\n }\r\n }\r\n\r\n private _isSequenceMessage(message: SequenceMessage): void {\r\n if (typeof message.sequenceId !== 'number') {\r\n throw new Error(\"Invalid SequenceId for Sequence message.\");\r\n }\r\n }\r\n\r\n private _assertNotEmptyString(value: any, errorMessage: string): void {\r\n if (typeof value !== \"string\" || value === \"\") {\r\n throw new Error(errorMessage);\r\n }\r\n }\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\nimport { DefaultReconnectPolicy } from \"./DefaultReconnectPolicy\";\r\nimport { HttpConnection } from \"./HttpConnection\";\r\nimport { HubConnection } from \"./HubConnection\";\r\nimport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\nimport { IHubProtocol } from \"./IHubProtocol\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { IRetryPolicy } from \"./IRetryPolicy\";\r\nimport { IStatefulReconnectOptions } from \"./IStatefulReconnectOptions\";\r\nimport { HttpTransportType } from \"./ITransport\";\r\nimport { JsonHubProtocol } from \"./JsonHubProtocol\";\r\nimport { NullLogger } from \"./Loggers\";\r\nimport { Arg, ConsoleLogger } from \"./Utils\";\r\n\r\nconst LogLevelNameMapping: {[k: string]: LogLevel} = {\r\n trace: LogLevel.Trace,\r\n debug: LogLevel.Debug,\r\n info: LogLevel.Information,\r\n information: LogLevel.Information,\r\n warn: LogLevel.Warning,\r\n warning: LogLevel.Warning,\r\n error: LogLevel.Error,\r\n critical: LogLevel.Critical,\r\n none: LogLevel.None,\r\n};\r\n\r\nfunction parseLogLevel(name: string): LogLevel {\r\n // Case-insensitive matching via lower-casing\r\n // Yes, I know case-folding is a complicated problem in Unicode, but we only support\r\n // the ASCII strings defined in LogLevelNameMapping anyway, so it's fine -anurse.\r\n const mapping = LogLevelNameMapping[name.toLowerCase()];\r\n if (typeof mapping !== \"undefined\") {\r\n return mapping;\r\n } else {\r\n throw new Error(`Unknown log level: ${name}`);\r\n }\r\n}\r\n\r\n/** A builder for configuring {@link @microsoft/signalr.HubConnection} instances. */\r\nexport class HubConnectionBuilder {\r\n private _serverTimeoutInMilliseconds?: number;\r\n private _keepAliveIntervalInMilliseconds ?: number;\r\n\r\n /** @internal */\r\n public protocol?: IHubProtocol;\r\n /** @internal */\r\n public httpConnectionOptions?: IHttpConnectionOptions;\r\n /** @internal */\r\n public url?: string;\r\n /** @internal */\r\n public logger?: ILogger;\r\n\r\n /** If defined, this indicates the client should automatically attempt to reconnect if the connection is lost. */\r\n /** @internal */\r\n public reconnectPolicy?: IRetryPolicy;\r\n\r\n private _statefulReconnectBufferSize?: number;\r\n\r\n /** Configures console logging for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @param {LogLevel} logLevel The minimum level of messages to log. Anything at this level, or a more severe level, will be logged.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public configureLogging(logLevel: LogLevel): HubConnectionBuilder;\r\n\r\n /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @param {ILogger} logger An object implementing the {@link @microsoft/signalr.ILogger} interface, which will be used to write all log messages.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public configureLogging(logger: ILogger): HubConnectionBuilder;\r\n\r\n /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @param {string} logLevel A string representing a LogLevel setting a minimum level of messages to log.\r\n * See {@link https://learn.microsoft.com/aspnet/core/signalr/configuration#configure-logging|the documentation for client logging configuration} for more details.\r\n */\r\n public configureLogging(logLevel: string): HubConnectionBuilder;\r\n\r\n /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @param {LogLevel | string | ILogger} logging A {@link @microsoft/signalr.LogLevel}, a string representing a LogLevel, or an object implementing the {@link @microsoft/signalr.ILogger} interface.\r\n * See {@link https://learn.microsoft.com/aspnet/core/signalr/configuration#configure-logging|the documentation for client logging configuration} for more details.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public configureLogging(logging: LogLevel | string | ILogger): HubConnectionBuilder;\r\n public configureLogging(logging: LogLevel | string | ILogger): HubConnectionBuilder {\r\n Arg.isRequired(logging, \"logging\");\r\n\r\n if (isLogger(logging)) {\r\n this.logger = logging;\r\n } else if (typeof logging === \"string\") {\r\n const logLevel = parseLogLevel(logging);\r\n this.logger = new ConsoleLogger(logLevel);\r\n } else {\r\n this.logger = new ConsoleLogger(logging);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to use HTTP-based transports to connect to the specified URL.\r\n *\r\n * The transport will be selected automatically based on what the server and client support.\r\n *\r\n * @param {string} url The URL the connection will use.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withUrl(url: string): HubConnectionBuilder;\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to use the specified HTTP-based transport to connect to the specified URL.\r\n *\r\n * @param {string} url The URL the connection will use.\r\n * @param {HttpTransportType} transportType The specific transport to use.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withUrl(url: string, transportType: HttpTransportType): HubConnectionBuilder;\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to use HTTP-based transports to connect to the specified URL.\r\n *\r\n * @param {string} url The URL the connection will use.\r\n * @param {IHttpConnectionOptions} options An options object used to configure the connection.\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withUrl(url: string, options: IHttpConnectionOptions): HubConnectionBuilder;\r\n public withUrl(url: string, transportTypeOrOptions?: IHttpConnectionOptions | HttpTransportType): HubConnectionBuilder {\r\n Arg.isRequired(url, \"url\");\r\n Arg.isNotEmpty(url, \"url\");\r\n\r\n this.url = url;\r\n\r\n // Flow-typing knows where it's at. Since HttpTransportType is a number and IHttpConnectionOptions is guaranteed\r\n // to be an object, we know (as does TypeScript) this comparison is all we need to figure out which overload was called.\r\n if (typeof transportTypeOrOptions === \"object\") {\r\n this.httpConnectionOptions = { ...this.httpConnectionOptions, ...transportTypeOrOptions };\r\n } else {\r\n this.httpConnectionOptions = {\r\n ...this.httpConnectionOptions,\r\n transport: transportTypeOrOptions,\r\n };\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to use the specified Hub Protocol.\r\n *\r\n * @param {IHubProtocol} protocol The {@link @microsoft/signalr.IHubProtocol} implementation to use.\r\n */\r\n public withHubProtocol(protocol: IHubProtocol): HubConnectionBuilder {\r\n Arg.isRequired(protocol, \"protocol\");\r\n\r\n this.protocol = protocol;\r\n return this;\r\n }\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.\r\n * By default, the client will wait 0, 2, 10 and 30 seconds respectively before trying up to 4 reconnect attempts.\r\n */\r\n public withAutomaticReconnect(): HubConnectionBuilder;\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.\r\n *\r\n * @param {number[]} retryDelays An array containing the delays in milliseconds before trying each reconnect attempt.\r\n * The length of the array represents how many failed reconnect attempts it takes before the client will stop attempting to reconnect.\r\n */\r\n public withAutomaticReconnect(retryDelays: number[]): HubConnectionBuilder;\r\n\r\n /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.\r\n *\r\n * @param {IRetryPolicy} reconnectPolicy An {@link @microsoft/signalR.IRetryPolicy} that controls the timing and number of reconnect attempts.\r\n */\r\n public withAutomaticReconnect(reconnectPolicy: IRetryPolicy): HubConnectionBuilder;\r\n public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IRetryPolicy): HubConnectionBuilder {\r\n if (this.reconnectPolicy) {\r\n throw new Error(\"A reconnectPolicy has already been set.\");\r\n }\r\n\r\n if (!retryDelaysOrReconnectPolicy) {\r\n this.reconnectPolicy = new DefaultReconnectPolicy();\r\n } else if (Array.isArray(retryDelaysOrReconnectPolicy)) {\r\n this.reconnectPolicy = new DefaultReconnectPolicy(retryDelaysOrReconnectPolicy);\r\n } else {\r\n this.reconnectPolicy = retryDelaysOrReconnectPolicy;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /** Configures {@link @microsoft/signalr.HubConnection.serverTimeoutInMilliseconds} for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withServerTimeout(milliseconds: number): HubConnectionBuilder {\r\n Arg.isRequired(milliseconds, \"milliseconds\");\r\n\r\n this._serverTimeoutInMilliseconds = milliseconds;\r\n\r\n return this;\r\n }\r\n\r\n /** Configures {@link @microsoft/signalr.HubConnection.keepAliveIntervalInMilliseconds} for the {@link @microsoft/signalr.HubConnection}.\r\n *\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withKeepAliveInterval(milliseconds: number): HubConnectionBuilder {\r\n Arg.isRequired(milliseconds, \"milliseconds\");\r\n\r\n this._keepAliveIntervalInMilliseconds = milliseconds;\r\n\r\n return this;\r\n }\r\n\r\n /** Enables and configures options for the Stateful Reconnect feature.\r\n *\r\n * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\r\n */\r\n public withStatefulReconnect(options?: IStatefulReconnectOptions): HubConnectionBuilder {\r\n if (this.httpConnectionOptions === undefined) {\r\n this.httpConnectionOptions = {};\r\n }\r\n this.httpConnectionOptions._useStatefulReconnect = true;\r\n\r\n this._statefulReconnectBufferSize = options?.bufferSize;\r\n\r\n return this;\r\n }\r\n\r\n /** Creates a {@link @microsoft/signalr.HubConnection} from the configuration options specified in this builder.\r\n *\r\n * @returns {HubConnection} The configured {@link @microsoft/signalr.HubConnection}.\r\n */\r\n public build(): HubConnection {\r\n // If httpConnectionOptions has a logger, use it. Otherwise, override it with the one\r\n // provided to configureLogger\r\n const httpConnectionOptions = this.httpConnectionOptions || {};\r\n\r\n // If it's 'null', the user **explicitly** asked for null, don't mess with it.\r\n if (httpConnectionOptions.logger === undefined) {\r\n // If our logger is undefined or null, that's OK, the HttpConnection constructor will handle it.\r\n httpConnectionOptions.logger = this.logger;\r\n }\r\n\r\n // Now create the connection\r\n if (!this.url) {\r\n throw new Error(\"The 'HubConnectionBuilder.withUrl' method must be called before building the connection.\");\r\n }\r\n const connection = new HttpConnection(this.url, httpConnectionOptions);\r\n\r\n return HubConnection.create(\r\n connection,\r\n this.logger || NullLogger.instance,\r\n this.protocol || new JsonHubProtocol(),\r\n this.reconnectPolicy,\r\n this._serverTimeoutInMilliseconds,\r\n this._keepAliveIntervalInMilliseconds,\r\n this._statefulReconnectBufferSize);\r\n }\r\n}\r\n\r\nfunction isLogger(logger: any): logger is ILogger {\r\n return logger.log !== undefined;\r\n}\r\n", "// Licensed to the .NET Foundation under one or more agreements.\r\n// The .NET Foundation licenses this file to you under the MIT license.\r\n\r\n// Everything that users need to access must be exported here. Including interfaces.\r\nexport { AbortSignal } from \"./AbortController\";\r\nexport { AbortError, HttpError, TimeoutError } from \"./Errors\";\r\nexport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\nexport { DefaultHttpClient } from \"./DefaultHttpClient\";\r\nexport { IHttpConnectionOptions } from \"./IHttpConnectionOptions\";\r\nexport { IStatefulReconnectOptions } from \"./IStatefulReconnectOptions\";\r\nexport { HubConnection, HubConnectionState } from \"./HubConnection\";\r\nexport { HubConnectionBuilder } from \"./HubConnectionBuilder\";\r\nexport { AckMessage, SequenceMessage, MessageType, MessageHeaders, HubMessage, HubMessageBase,\r\n HubInvocationMessage, InvocationMessage, StreamInvocationMessage, StreamItemMessage, CompletionMessage,\r\n PingMessage, CloseMessage, CancelInvocationMessage, IHubProtocol } from \"./IHubProtocol\";\r\nexport { ILogger, LogLevel } from \"./ILogger\";\r\nexport { HttpTransportType, TransferFormat, ITransport } from \"./ITransport\";\r\nexport { IStreamSubscriber, IStreamResult, ISubscription } from \"./Stream\";\r\nexport { NullLogger } from \"./Loggers\";\r\nexport { JsonHubProtocol } from \"./JsonHubProtocol\";\r\nexport { Subject } from \"./Subject\";\r\nexport { IRetryPolicy, RetryContext } from \"./IRetryPolicy\";\r\nexport { VERSION } from \"./Utils\";\r\n", "import * as vscode from 'vscode';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { spawn } from 'child_process';\nimport { WorkspaceDetector } from './WorkspaceDetector';\nimport { BackendProcessManager } from './BackendProcessManager';\nimport { StatusBarManager } from './StatusBarManager';\nimport { StudioApiClient } from './StudioApiClient';\nimport { StudioSignalRClient } from './StudioSignalRClient';\nimport { AgentsPanelProvider } from './panels/AgentsPanelProvider';\nimport { MessagesPanelProvider } from './panels/MessagesPanelProvider';\nimport { DecisionsPanelProvider } from './panels/DecisionsPanelProvider';\nimport type { ProjectConfig } from './types';\n\nlet backendManager: BackendProcessManager | undefined;\nlet signalRClient: StudioSignalRClient | undefined;\nlet statusBar: StatusBarManager | undefined;\nexport let log: vscode.OutputChannel;\n\nexport async function activate(context: vscode.ExtensionContext): Promise {\n log = vscode.window.createOutputChannel('AI Dev Studio');\n context.subscriptions.push(log);\n log.appendLine(`Activating \u2014 extensionPath: ${context.extensionPath}`);\n\n statusBar = new StatusBarManager();\n context.subscriptions.push(statusBar);\n\n // Register placeholder panel providers immediately so panels never show \"\u2014\"\n const agentsProvider = new AgentsPanelProvider(context.extensionUri);\n const messagesProvider = new MessagesPanelProvider(context.extensionUri);\n const decisionsProvider = new DecisionsPanelProvider(context.extensionUri);\n\n context.subscriptions.push(\n vscode.window.registerWebviewViewProvider('aidev.agents', agentsProvider),\n vscode.window.registerWebviewViewProvider('aidev.messages', messagesProvider),\n vscode.window.registerWebviewViewProvider('aidev.decisions', decisionsProvider),\n );\n\n const detector = new WorkspaceDetector(\n glob => {\n const watcher = vscode.workspace.createFileSystemWatcher(glob);\n return {\n onCreated: handler => watcher.onDidCreate(uri => handler(uri.fsPath)),\n onDeleted: handler => watcher.onDidDelete(uri => handler(uri.fsPath)),\n dispose: () => watcher.dispose(),\n };\n },\n filePath => {\n try { return fs.readFileSync(filePath, 'utf8'); }\n catch { return undefined; }\n },\n );\n context.subscriptions.push(detector);\n\n detector.on('projectDetected', async ({ config, workspaceFolderPath }) => {\n log.appendLine(`Project detected: slug=${config.projectSlug} port=${config.apiPort} at ${workspaceFolderPath}`);\n if (backendManager) {\n log.appendLine('Backend already running \u2014 skipping.');\n return;\n }\n await connectBackend(context, config, workspaceFolderPath, agentsProvider, messagesProvider, decisionsProvider);\n });\n\n detector.on('projectRemoved', wsPath => {\n log.appendLine(`Project removed: ${wsPath}`);\n void teardown(agentsProvider, messagesProvider, decisionsProvider);\n });\n\n context.subscriptions.push(\n vscode.commands.registerCommand('aidev.restartBackend', async () => {\n log.appendLine('Restart backend command invoked.');\n await teardown(agentsProvider, messagesProvider, decisionsProvider);\n scanWorkspace(detector);\n }),\n );\n\n context.subscriptions.push(\n vscode.workspace.onDidChangeWorkspaceFolders(e => {\n log.appendLine(`Workspace folders changed: +${e.added.length} -${e.removed.length}`);\n if (e.added.length > 0)\n detector.start(e.added.map(f => f.uri.fsPath));\n }),\n );\n\n scanWorkspace(detector);\n}\n\nfunction scanWorkspace(detector: WorkspaceDetector): void {\n const folders = vscode.workspace.workspaceFolders ?? [];\n log.appendLine(`Scanning ${folders.length} folder(s): ${folders.map(f => f.uri.fsPath).join(', ') || '(none \u2014 open a folder containing .ai-dev/project.json)'}`);\n detector.start(folders.map(f => f.uri.fsPath));\n}\n\nasync function connectBackend(\n context: vscode.ExtensionContext,\n config: ProjectConfig,\n workspaceFolderPath: string,\n agentsProvider: AgentsPanelProvider,\n messagesProvider: MessagesPanelProvider,\n decisionsProvider: DecisionsPanelProvider,\n): Promise {\n const binaryName = process.platform === 'win32' ? 'ai-dev-api.exe' : 'ai-dev-api';\n const binaryPath = path.join(context.extensionPath, 'bin', binaryName);\n log.appendLine(`Binary: ${binaryPath} (exists: ${fs.existsSync(binaryPath)})`);\n\n backendManager = new BackendProcessManager(\n { binaryPath, port: config.apiPort, maxAttempts: 30, retryDelayMs: 1000 },\n (binary, args, options) => spawn(binary, args, {\n ...options,\n stdio: 'pipe',\n env: { ...process.env, WORKSPACE_ROOT: workspaceFolderPath },\n }),\n async url => {\n const r = await fetch(url);\n log.appendLine(`Health check ${url} \u2192 ${r.status}`);\n return { ok: r.ok };\n },\n );\n\n statusBar?.setStarting();\n log.appendLine(`Waiting for backend on port ${config.apiPort}\u2026`);\n try {\n await backendManager.start();\n log.appendLine('Backend ready.');\n } catch (e) {\n log.appendLine(`Backend failed: ${e}`);\n statusBar?.setDisconnected();\n vscode.window.showErrorMessage('AI Dev Studio: backend failed to start. See Output > AI Dev Studio.');\n return;\n }\n\n const baseUrl = `http://localhost:${config.apiPort}`;\n const api = new StudioApiClient(baseUrl);\n\n signalRClient = new StudioSignalRClient(`${baseUrl}/hubs/project`);\n signalRClient.onConnectionStateChanged(state => {\n log.appendLine(`SignalR: ${state}`);\n if (state === 'connected') statusBar?.setRunning();\n else if (state === 'connecting') statusBar?.setStarting();\n else statusBar?.setDisconnected();\n });\n\n try {\n await signalRClient.start(config.projectSlug);\n log.appendLine('SignalR connected.');\n } catch (e) {\n log.appendLine(`SignalR failed (non-fatal, REST still works): ${e}`);\n }\n\n statusBar?.setRunning();\n\n // Wire up the already-registered providers with live API + SignalR\n agentsProvider.connect(config.projectSlug, api, signalRClient);\n messagesProvider.connect(config.projectSlug, api, signalRClient);\n decisionsProvider.connect(config.projectSlug, api, signalRClient);\n log.appendLine('Panels connected.');\n}\n\nasync function teardown(\n agentsProvider: AgentsPanelProvider,\n messagesProvider: MessagesPanelProvider,\n decisionsProvider: DecisionsPanelProvider,\n): Promise {\n log?.appendLine('Tearing down.');\n await signalRClient?.stop();\n signalRClient = undefined;\n backendManager?.stop();\n backendManager = undefined;\n statusBar?.setDisconnected();\n agentsProvider.disconnect();\n messagesProvider.disconnect();\n decisionsProvider.disconnect();\n}\n\nexport function deactivate(): void {\n log?.appendLine('Deactivating.');\n backendManager?.stop();\n void signalRClient?.stop();\n}\n", "import { EventEmitter } from 'events';\nimport * as path from 'path';\nimport { DetectedProject, ProjectConfig } from './types';\n\nexport interface FileWatcherLike {\n onCreated(handler: (filePath: string) => void): void;\n onDeleted(handler: (filePath: string) => void): void;\n dispose(): void;\n}\n\nexport type WatcherFactory = (glob: string) => FileWatcherLike;\nexport type FileReader = (filePath: string) => string | undefined;\n\nexport declare interface WorkspaceDetector {\n on(event: 'projectDetected', listener: (project: DetectedProject) => void): this;\n on(event: 'projectRemoved', listener: (workspaceFolderPath: string) => void): this;\n emit(event: 'projectDetected', project: DetectedProject): boolean;\n emit(event: 'projectRemoved', workspaceFolderPath: string): boolean;\n}\n\nexport class WorkspaceDetector extends EventEmitter {\n private watcher?: FileWatcherLike;\n\n constructor(\n private readonly createWatcher: WatcherFactory,\n private readonly readFile: FileReader,\n ) {\n super();\n }\n\n start(workspacePaths: string[]): void {\n for (const wsPath of workspacePaths) {\n const configPath = path.join(wsPath, '.ai-dev', 'project.json');\n this.tryEmitDetected(configPath, wsPath);\n }\n\n this.watcher = this.createWatcher('**/.ai-dev/project.json');\n this.watcher.onCreated(filePath => {\n const wsPath = this.resolveWorkspacePath(filePath, workspacePaths);\n if (wsPath) this.tryEmitDetected(filePath, wsPath);\n });\n this.watcher.onDeleted(filePath => {\n const wsPath = this.resolveWorkspacePath(filePath, workspacePaths);\n if (wsPath) this.emit('projectRemoved', wsPath);\n });\n }\n\n private tryEmitDetected(filePath: string, workspaceFolderPath: string): void {\n const raw = this.readFile(filePath);\n if (!raw) return;\n try {\n const config = JSON.parse(raw) as ProjectConfig;\n if (config.projectSlug && config.apiPort) {\n this.emit('projectDetected', { config, workspaceFolderPath });\n }\n } catch {\n // malformed JSON \u2014 skip silently\n }\n }\n\n private resolveWorkspacePath(filePath: string, workspacePaths: string[]): string | undefined {\n const normalised = filePath.replace(/\\\\/g, '/');\n return workspacePaths.find(ws => {\n const normWs = ws.replace(/\\\\/g, '/');\n return normalised.startsWith(normWs + '/');\n });\n }\n\n dispose(): void {\n this.watcher?.dispose();\n }\n}\n", "export type FileExistsFn = (path: string) => boolean;\n\nexport type ProcessLike = {\n kill(): void;\n on(event: 'exit', handler: (code: number | null) => void): void;\n on(event: 'error', handler: (err: Error) => void): void;\n};\n\nexport type Spawner = (\n binary: string,\n args: string[],\n options: { env?: NodeJS.ProcessEnv; cwd?: string },\n) => ProcessLike;\n\nexport type Fetcher = (url: string) => Promise<{ ok: boolean }>;\n\nexport type BackendState = 'not-started' | 'starting' | 'ready' | 'stopped';\n\nexport interface BackendProcessManagerOptions {\n binaryPath: string;\n port: number;\n maxAttempts: number;\n retryDelayMs: number;\n}\n\nexport class BackendProcessManager {\n private _state: BackendState = 'not-started';\n private _process?: ProcessLike;\n\n constructor(\n private readonly options: BackendProcessManagerOptions,\n private readonly spawner: Spawner,\n private readonly fetcher: Fetcher,\n private readonly delay: (ms: number) => Promise = ms =>\n new Promise(resolve => setTimeout(resolve, ms)),\n private readonly fileExists: FileExistsFn = p => {\n try { require('fs').accessSync(p); return true; } catch { return false; }\n },\n ) {}\n\n get state(): BackendState {\n return this._state;\n }\n\n async start(): Promise {\n if (this._state !== 'not-started') return;\n this._state = 'starting';\n\n // Skip spawning when binary is absent \u2014 dev mode where backend runs externally.\n if (this.fileExists(this.options.binaryPath)) {\n this._process = this.spawner(this.options.binaryPath, [], {});\n this._process.on('exit', () => {\n if (this._state !== 'stopped') this._state = 'stopped';\n });\n this._process.on('error', () => {\n if (this._state !== 'stopped') this._state = 'stopped';\n });\n }\n\n const healthUrl = `http://localhost:${this.options.port}/api/health`;\n for (let attempt = 0; attempt < this.options.maxAttempts; attempt++) {\n try {\n const res = await this.fetcher(healthUrl);\n if (res.ok) {\n this._state = 'ready';\n return;\n }\n } catch {\n // backend not ready yet\n }\n await this.delay(this.options.retryDelayMs);\n }\n\n if (this._process) {\n try { this._process.kill(); } catch { }\n }\n this._state = 'stopped';\n throw new Error(\n `AI Dev backend did not become healthy after ${this.options.maxAttempts} attempts`,\n );\n }\n\n stop(): void {\n if (this._state === 'stopped' || this._state === 'not-started') return;\n if (this._process) {\n try { this._process.kill(); } catch { }\n }\n this._state = 'stopped';\n }\n}\n", "import * as vscode from 'vscode';\n\nexport class StatusBarManager {\n private readonly item: vscode.StatusBarItem;\n\n constructor() {\n this.item = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);\n this.item.command = 'aidev.restartBackend';\n this.setDisconnected();\n this.item.show();\n }\n\n setRunning(): void {\n this.item.text = '$(check) AI Dev: Running';\n this.item.tooltip = 'AI Dev Studio backend is running. Click to restart.';\n this.item.backgroundColor = undefined;\n }\n\n setStarting(): void {\n this.item.text = '$(loading~spin) AI Dev: Starting';\n this.item.tooltip = 'AI Dev Studio backend is starting...';\n this.item.backgroundColor = undefined;\n }\n\n setDisconnected(): void {\n this.item.text = '$(x) AI Dev: Disconnected';\n this.item.tooltip = 'AI Dev Studio backend is not running. Click to retry.';\n this.item.backgroundColor = new vscode.ThemeColor('statusBarItem.errorBackground');\n }\n\n dispose(): void {\n this.item.dispose();\n }\n}\n", "export type { AgentSummary, MessageItem, DecisionItem } from './types';\nimport type { AgentSummary, MessageItem, DecisionItem } from './types';\n\nexport type Fetcher = (url: string, init?: RequestInit) => Promise;\n\nexport class StudioApiClient {\n constructor(\n private readonly baseUrl: string,\n private readonly fetcher: Fetcher = (url, init) => fetch(url, init),\n ) {}\n\n // \u2500\u2500 Agents \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async listAgents(projectSlug: string): Promise {\n return this.get(`/api/agents?projectSlug=${enc(projectSlug)}`);\n }\n\n async runAgent(projectSlug: string, agentSlug: string): Promise {\n await this.post(`/api/agents/${enc(agentSlug)}/run?projectSlug=${enc(projectSlug)}`);\n }\n\n async stopAgent(projectSlug: string, agentSlug: string): Promise {\n await this.post(`/api/agents/${enc(agentSlug)}/stop?projectSlug=${enc(projectSlug)}`);\n }\n\n // \u2500\u2500 Messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async listMessages(projectSlug: string, agentSlug?: string, processed?: boolean): Promise {\n let url = `/api/messages?projectSlug=${enc(projectSlug)}`;\n if (agentSlug) url += `&agentSlug=${enc(agentSlug)}`;\n if (processed !== undefined) url += `&processed=${processed}`;\n return this.get(url);\n }\n\n async listAllMessages(projectSlug: string): Promise {\n const agents = await this.listAgents(projectSlug);\n const perAgent = await Promise.all(\n agents.map(a =>\n this.listMessages(projectSlug, a.slug, false)\n .then(msgs => msgs.map(m => ({ ...m, agentSlug: a.slug }))),\n ),\n );\n return perAgent.flat();\n }\n\n async processMessage(projectSlug: string, agentSlug: string, fileName: string): Promise {\n await this.post(\n `/api/messages/${enc(fileName)}/process?projectSlug=${enc(projectSlug)}&agentSlug=${enc(agentSlug)}`,\n );\n }\n\n // \u2500\u2500 Decisions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n async listDecisions(projectSlug: string, status?: string): Promise {\n let url = `/api/decisions?projectSlug=${enc(projectSlug)}`;\n if (status) url += `&status=${enc(status)}`;\n return this.get(url);\n }\n\n async resolveDecision(projectSlug: string, decisionId: string, resolution: string): Promise {\n await this.post(`/api/decisions/${enc(decisionId)}/resolve?projectSlug=${enc(projectSlug)}`, {\n resolution,\n });\n }\n\n // \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async get(path: string): Promise {\n const res = await this.fetcher(this.baseUrl + path);\n if (!res.ok) throw new ApiError(res.status, path);\n return res.json() as Promise;\n }\n\n private async post(path: string, body?: unknown): Promise {\n const res = await this.fetcher(this.baseUrl + path, {\n method: 'POST',\n headers: body ? { 'Content-Type': 'application/json' } : undefined,\n body: body ? JSON.stringify(body) : undefined,\n });\n if (!res.ok) throw new ApiError(res.status, path);\n }\n}\n\nfunction enc(value: string): string {\n return encodeURIComponent(value);\n}\n\nexport class ApiError extends Error {\n constructor(\n public readonly statusCode: number,\n public readonly path: string,\n ) {\n super(`API error ${statusCode} for ${path}`);\n this.name = 'ApiError';\n }\n}\n", "import * as vscode from 'vscode';\nimport {\n HubConnection,\n HubConnectionBuilder,\n HubConnectionState,\n LogLevel,\n} from '@microsoft/signalr';\n\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected';\n\nexport interface StateChangedMessage {\n projectSlug: string;\n kinds: string[];\n}\n\nexport interface HubConnectionFactory {\n build(url: string): HubConnection;\n}\n\nconst defaultFactory: HubConnectionFactory = {\n build: url =>\n new HubConnectionBuilder()\n .withUrl(url)\n .withAutomaticReconnect({\n nextRetryDelayInMilliseconds: ctx => {\n const base = Math.min(1000 * 2 ** ctx.previousRetryCount, 30_000);\n return base + Math.random() * 1000;\n },\n })\n .configureLogging(LogLevel.Warning)\n .build(),\n};\n\nexport class StudioSignalRClient {\n private connection?: HubConnection;\n private projectSlug?: string;\n\n private readonly _onConnectionStateChanged = new vscode.EventEmitter();\n private readonly _onAgentsChanged = new vscode.EventEmitter();\n private readonly _onMessagesChanged = new vscode.EventEmitter();\n private readonly _onDecisionsChanged = new vscode.EventEmitter();\n\n readonly onConnectionStateChanged = this._onConnectionStateChanged.event;\n readonly onAgentsChanged = this._onAgentsChanged.event;\n readonly onMessagesChanged = this._onMessagesChanged.event;\n readonly onDecisionsChanged = this._onDecisionsChanged.event;\n\n private _connectionState: ConnectionState = 'disconnected';\n\n constructor(\n private readonly hubUrl: string,\n private readonly factory: HubConnectionFactory = defaultFactory,\n ) {}\n\n get connectionState(): ConnectionState {\n return this._connectionState;\n }\n\n async start(projectSlug: string): Promise {\n this.projectSlug = projectSlug;\n this.connection = this.factory.build(this.hubUrl);\n\n this.connection.onreconnecting(() => this.setState('connecting'));\n this.connection.onreconnected(() => this.setState('connected'));\n this.connection.onclose(() => this.setState('disconnected'));\n\n this.connection.on('StateChanged', (msg: StateChangedMessage) => {\n if (msg.projectSlug !== this.projectSlug) return;\n const kinds = msg.kinds.map(k => k.toLowerCase());\n if (kinds.includes('agents')) this._onAgentsChanged.fire();\n if (kinds.includes('messages')) this._onMessagesChanged.fire();\n if (kinds.includes('decisions')) this._onDecisionsChanged.fire();\n if (kinds.includes('board')) this._onAgentsChanged.fire(); // board changes affect agent views\n });\n\n this.setState('connecting');\n await this.connection.start();\n await this.connection.invoke('JoinProject', projectSlug);\n this.setState('connected');\n }\n\n async stop(): Promise {\n if (this.connection?.state === HubConnectionState.Connected) {\n try { await this.connection.invoke('LeaveProject', this.projectSlug); } catch { }\n }\n await this.connection?.stop();\n this.setState('disconnected');\n }\n\n dispose(): void {\n this._onConnectionStateChanged.dispose();\n this._onAgentsChanged.dispose();\n this._onMessagesChanged.dispose();\n this._onDecisionsChanged.dispose();\n void this.connection?.stop();\n }\n\n private setState(state: ConnectionState): void {\n if (this._connectionState === state) return;\n this._connectionState = state;\n this._onConnectionStateChanged.fire(state);\n }\n}\n", "import * as vscode from 'vscode';\nimport * as crypto from 'crypto';\nimport { StudioApiClient } from '../StudioApiClient';\nimport { StudioSignalRClient } from '../StudioSignalRClient';\n\nexport abstract class BasePanelProvider implements vscode.WebviewViewProvider {\n protected view?: vscode.WebviewView;\n protected projectSlug?: string;\n protected api?: StudioApiClient;\n protected signalR?: StudioSignalRClient;\n private connectionDisposables: vscode.Disposable[] = [];\n\n constructor(\n protected readonly viewId: string,\n protected readonly extensionUri: vscode.Uri,\n protected readonly webviewScript: string,\n ) {}\n\n resolveWebviewView(webviewView: vscode.WebviewView): void {\n this.view = webviewView;\n if (this.api) {\n this.enableScripts(webviewView);\n this.wireUp(webviewView);\n } else {\n webviewView.webview.options = { enableScripts: false };\n webviewView.webview.html = this.buildPlaceholderHtml();\n }\n }\n\n connect(projectSlug: string, api: StudioApiClient, signalR: StudioSignalRClient): void {\n this.projectSlug = projectSlug;\n this.api = api;\n this.signalR = signalR;\n if (this.view) {\n this.enableScripts(this.view);\n this.wireUp(this.view);\n }\n }\n\n private enableScripts(webviewView: vscode.WebviewView): void {\n webviewView.webview.options = {\n enableScripts: true,\n localResourceRoots: [vscode.Uri.joinPath(this.extensionUri, 'dist', 'webviews')],\n };\n webviewView.webview.html = this.buildHtml(webviewView.webview);\n }\n\n disconnect(): void {\n for (const d of this.connectionDisposables) d.dispose();\n this.connectionDisposables = [];\n this.projectSlug = undefined;\n this.api = undefined;\n this.signalR = undefined;\n this.send({ type: 'loading' });\n }\n\n protected send(message: unknown): void {\n this.view?.webview.postMessage(message);\n }\n\n private wireUp(view: vscode.WebviewView): void {\n for (const d of this.connectionDisposables) d.dispose();\n this.connectionDisposables = [];\n this.onConnected(view, this.connectionDisposables);\n }\n\n protected abstract onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void;\n\n private buildPlaceholderHtml(): string {\n return `\n\n

Waiting for AI Dev Studio backend\u2026

`;\n }\n\n private buildHtml(webview: vscode.Webview): string {\n const nonce = crypto.randomBytes(16).toString('hex');\n const scriptUri = webview.asWebviewUri(\n vscode.Uri.joinPath(this.extensionUri, 'dist', 'webviews', this.webviewScript),\n );\n return `\n\n\n \n \n \n \n\n\n
\n \n\n`;\n }\n}\n", "import * as vscode from 'vscode';\nimport { BasePanelProvider } from './BasePanelProvider';\nimport type { FromAgentsWebview } from '../webviews/shared/protocol';\n\nexport class AgentsPanelProvider extends BasePanelProvider {\n constructor(extensionUri: vscode.Uri) {\n super('aidev.agents', extensionUri, 'agents/main.js');\n }\n\n protected onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void {\n disposables.push(this.signalR!.onAgentsChanged(() => void this.refresh()));\n\n disposables.push(view.webview.onDidReceiveMessage(async (msg: FromAgentsWebview) => {\n try {\n if (msg.type === 'run') {\n await this.api!.runAgent(this.projectSlug!, msg.agentSlug);\n } else if (msg.type === 'stop') {\n await this.api!.stopAgent(this.projectSlug!, msg.agentSlug);\n }\n await this.refresh();\n } catch (e) {\n this.send({ type: 'error', message: String(e) });\n }\n }));\n\n void this.refresh();\n }\n\n private async refresh(): Promise {\n if (!this.api) return;\n this.send({ type: 'loading' });\n try {\n const data = await this.api.listAgents(this.projectSlug!);\n this.send({ type: 'agents', data });\n } catch (e) {\n this.send({ type: 'error', message: `Failed to load agents: ${e}` });\n }\n }\n}\n", "import * as vscode from 'vscode';\nimport { BasePanelProvider } from './BasePanelProvider';\nimport type { FromMessagesWebview } from '../webviews/shared/protocol';\n\nexport class MessagesPanelProvider extends BasePanelProvider {\n constructor(extensionUri: vscode.Uri) {\n super('aidev.messages', extensionUri, 'messages/main.js');\n }\n\n protected onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void {\n disposables.push(this.signalR!.onMessagesChanged(() => void this.refresh(view)));\n\n disposables.push(view.webview.onDidReceiveMessage(async (msg: FromMessagesWebview) => {\n try {\n if (msg.type === 'process') {\n await this.api!.processMessage(this.projectSlug!, msg.agentSlug, msg.fileName);\n await this.refresh(view);\n }\n } catch (e) {\n this.send({ type: 'error', message: String(e) });\n }\n }));\n\n void this.refresh(view);\n }\n\n private async refresh(view: vscode.WebviewView): Promise {\n if (!this.api) return;\n this.send({ type: 'loading' });\n try {\n const data = await this.api.listAllMessages(this.projectSlug!);\n this.send({ type: 'messages', data });\n view.badge = data.length > 0\n ? { value: data.length, tooltip: `${data.length} unprocessed message(s)` }\n : undefined;\n } catch (e) {\n this.send({ type: 'error', message: `Failed to load messages: ${e}` });\n }\n }\n}\n", "import * as vscode from 'vscode';\nimport { BasePanelProvider } from './BasePanelProvider';\nimport type { FromDecisionsWebview } from '../webviews/shared/protocol';\n\nexport class DecisionsPanelProvider extends BasePanelProvider {\n constructor(extensionUri: vscode.Uri) {\n super('aidev.decisions', extensionUri, 'decisions/main.js');\n }\n\n protected onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void {\n disposables.push(this.signalR!.onDecisionsChanged(() => void this.refresh(view)));\n\n disposables.push(view.webview.onDidReceiveMessage(async (msg: FromDecisionsWebview) => {\n try {\n if (msg.type === 'resolve') {\n await this.api!.resolveDecision(this.projectSlug!, msg.decisionId, msg.resolution);\n await this.refresh(view);\n }\n } catch (e) {\n this.send({ type: 'error', message: String(e) });\n }\n }));\n\n void this.refresh(view);\n }\n\n private async refresh(view: vscode.WebviewView): Promise {\n if (!this.api) return;\n this.send({ type: 'loading' });\n try {\n const data = await this.api.listDecisions(this.projectSlug!, 'pending');\n this.send({ type: 'decisions', data });\n view.badge = data.length > 0\n ? { value: data.length, tooltip: `${data.length} pending decision(s)` }\n : undefined;\n } catch (e) {\n this.send({ type: 'error', message: `Failed to load decisions: ${e}` });\n }\n }\n}\n"], + "mappings": "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", + "names": ["HttpError", "errorMessage", "statusCode", "trueProto", "exports", "TimeoutError", "AbortError", "UnsupportedTransportError", "message", "transport", "DisabledTransportError", "FailedToStartTransportError", "FailedToNegotiateWithServerError", "AggregateErrors", "innerErrors", "HttpResponse", "statusCode", "statusText", "content", "exports", "HttpClient", "url", "options", "LogLevel", "exports", "NullLogger", "_logLevel", "_message", "exports", "exports", "ILogger_1", "Loggers_1", "pkg_version_1", "exports", "Arg", "val", "name", "values", "Platform", "_Platform", "getDataDetail", "data", "includeContent", "detail", "isArrayBuffer", "formatArrayBuffer", "view", "str", "num", "pad", "sendMessage", "logger", "transportName", "httpClient", "url", "content", "options", "headers", "value", "getUserAgentHeader", "responseType", "response", "createLogger", "ConsoleLogger", "SubjectSubscription", "subject", "observer", "index", "_", "minimumLogLevel", "logLevel", "message", "msg", "userAgentHeaderName", "constructUserAgent", "getOsName", "getRuntime", "getRuntimeVersion", "version", "os", "runtime", "runtimeVersion", "userAgent", "majorAndMinor", "getErrorString", "e", "getGlobalThis", "Errors_1", "HttpClient_1", "ILogger_1", "Utils_1", "FetchHttpClient", "logger", "requireFunc", "request", "abortController", "error", "timeoutId", "msTimeout", "response", "e", "errorMessage", "deserializeContent", "payload", "url", "cookies", "c", "exports", "responseType", "content", "Errors_1", "HttpClient_1", "ILogger_1", "Utils_1", "XhrHttpClient", "logger", "request", "resolve", "reject", "xhr", "headers", "header", "exports", "Errors_1", "FetchHttpClient_1", "HttpClient_1", "Utils_1", "XhrHttpClient_1", "DefaultHttpClient", "logger", "request", "url", "exports", "TextMessageFormat", "_TextMessageFormat", "output", "input", "messages", "exports", "TextMessageFormat_1", "Utils_1", "HandshakeProtocol", "handshakeRequest", "data", "messageData", "remainingData", "binaryData", "separatorIndex", "responseLength", "textData", "messages", "response", "exports", "MessageType", "exports", "Utils_1", "Subject", "item", "observer", "err", "exports", "IHubProtocol_1", "Utils_1", "MessageBuffer", "protocol", "connection", "bufferSize", "message", "serializedMessage", "backpressurePromise", "backpressurePromiseResolver", "backpressurePromiseRejector", "resolve", "reject", "BufferedItem", "ackMessage", "newestAckedMessage", "index", "element", "currentId", "sequenceId", "messages", "error", "exports", "id", "resolver", "rejector", "HandshakeProtocol_1", "Errors_1", "IHubProtocol_1", "ILogger_1", "Subject_1", "Utils_1", "MessageBuffer_1", "DEFAULT_TIMEOUT_IN_MS", "DEFAULT_PING_INTERVAL_IN_MS", "DEFAULT_STATEFUL_RECONNECT_BUFFER_SIZE", "HubConnectionState", "exports", "HubConnection", "_HubConnection", "connection", "logger", "protocol", "reconnectPolicy", "serverTimeoutInMilliseconds", "keepAliveIntervalInMilliseconds", "statefulReconnectBufferSize", "data", "error", "url", "handshakePromise", "resolve", "reject", "version", "handshakeRequest", "e", "startPromise", "state", "methodName", "args", "streams", "streamIds", "invocationDescriptor", "promiseQueue", "subject", "cancelInvocation", "invocationEvent", "message", "sendPromise", "newMethod", "method", "handlers", "removeIdx", "callback", "messages", "responseMessage", "remainingData", "nextPing", "invocationMessage", "methods", "methodsCopy", "expectsResponse", "res", "exception", "completionMessage", "m", "prevRes", "c", "reconnectStartTime", "previousReconnectAttempts", "retryError", "nextRetryDelay", "previousRetryCount", "elapsedMilliseconds", "retryReason", "callbacks", "key", "nonblocking", "invocationId", "streamId", "err", "item", "i", "argument", "arg", "id", "result", "DEFAULT_RETRY_DELAYS_IN_MILLISECONDS", "DefaultReconnectPolicy", "retryDelays", "retryContext", "exports", "HeaderNames", "exports", "HeaderNames_1", "HttpClient_1", "AccessTokenHttpClient", "innerClient", "accessTokenFactory", "request", "allowRetry", "response", "url", "exports", "HttpTransportType", "exports", "TransferFormat", "AbortController", "exports", "AbortController_1", "Errors_1", "ILogger_1", "ITransport_1", "Utils_1", "LongPollingTransport", "httpClient", "logger", "options", "url", "transferFormat", "name", "value", "headers", "pollOptions", "pollUrl", "response", "e", "data", "deleteOptions", "error", "err", "logMessage", "exports", "ILogger_1", "ITransport_1", "Utils_1", "ServerSentEventsTransport", "httpClient", "accessToken", "logger", "options", "url", "transferFormat", "resolve", "reject", "opened", "eventSource", "cookies", "headers", "name", "value", "e", "error", "data", "exports", "HeaderNames_1", "ILogger_1", "ITransport_1", "Utils_1", "WebSocketTransport", "httpClient", "accessTokenFactory", "logger", "logMessageContent", "webSocketConstructor", "headers", "url", "transferFormat", "token", "resolve", "reject", "webSocket", "cookies", "opened", "name", "value", "_event", "event", "error", "message", "data", "exports", "AccessTokenHttpClient_1", "DefaultHttpClient_1", "Errors_1", "ILogger_1", "ITransport_1", "LongPollingTransport_1", "ServerSentEventsTransport_1", "Utils_1", "WebSocketTransport_1", "MAX_REDIRECTS", "HttpConnection", "url", "options", "webSocketModule", "eventSourceModule", "requireFunc", "transferFormat", "message", "data", "TransportSendQueue", "error", "resolve", "e", "negotiateResponse", "redirects", "accessToken", "headers", "name", "value", "negotiateUrl", "response", "errorMessage", "connectionToken", "requestedTransport", "requestedTransferFormat", "connectUrl", "transportExceptions", "transports", "negotiate", "endpoint", "transportOrError", "ex", "transport", "callStop", "useStatefulReconnect", "transportMatches", "s", "aTag", "searchParams", "exports", "actualTransport", "_TransportSendQueue", "_transport", "PromiseSource", "transportResult", "arrayBuffers", "totalLength", "b", "a", "result", "offset", "item", "reject", "reason", "IHubProtocol_1", "ILogger_1", "ITransport_1", "Loggers_1", "TextMessageFormat_1", "JSON_HUB_PROTOCOL_NAME", "JsonHubProtocol", "input", "logger", "messages", "hubMessages", "message", "parsedMessage", "value", "errorMessage", "exports", "DefaultReconnectPolicy_1", "HttpConnection_1", "HubConnection_1", "ILogger_1", "JsonHubProtocol_1", "Loggers_1", "Utils_1", "LogLevelNameMapping", "parseLogLevel", "name", "mapping", "HubConnectionBuilder", "logging", "isLogger", "logLevel", "url", "transportTypeOrOptions", "protocol", "retryDelaysOrReconnectPolicy", "milliseconds", "options", "httpConnectionOptions", "connection", "exports", "logger", "Errors_1", "exports", "HttpClient_1", "DefaultHttpClient_1", "HubConnection_1", "HubConnectionBuilder_1", "IHubProtocol_1", "ILogger_1", "ITransport_1", "Loggers_1", "JsonHubProtocol_1", "Subject_1", "Utils_1", "extension_exports", "__export", "activate", "deactivate", "log", "__toCommonJS", "vscode", "path", "fs", "import_child_process", "import_events", "path", "WorkspaceDetector", "createWatcher", "readFile", "workspacePaths", "wsPath", "configPath", "filePath", "workspaceFolderPath", "raw", "config", "normalised", "ws", "normWs", "BackendProcessManager", "options", "spawner", "fetcher", "delay", "ms", "resolve", "fileExists", "p", "healthUrl", "attempt", "vscode", "StatusBarManager", "StudioApiClient", "baseUrl", "fetcher", "url", "init", "projectSlug", "enc", "agentSlug", "processed", "agents", "a", "msgs", "m", "fileName", "status", "decisionId", "resolution", "path", "res", "ApiError", "body", "value", "statusCode", "vscode", "import_signalr", "defaultFactory", "url", "ctx", "StudioSignalRClient", "hubUrl", "factory", "projectSlug", "msg", "kinds", "k", "state", "vscode", "crypto", "BasePanelProvider", "viewId", "extensionUri", "webviewScript", "webviewView", "projectSlug", "api", "signalR", "d", "message", "view", "webview", "nonce", "scriptUri", "AgentsPanelProvider", "BasePanelProvider", "extensionUri", "view", "disposables", "msg", "e", "data", "MessagesPanelProvider", "BasePanelProvider", "extensionUri", "view", "disposables", "msg", "e", "data", "DecisionsPanelProvider", "BasePanelProvider", "extensionUri", "view", "disposables", "msg", "e", "data", "backendManager", "signalRClient", "statusBar", "log", "activate", "context", "StatusBarManager", "agentsProvider", "AgentsPanelProvider", "messagesProvider", "MessagesPanelProvider", "decisionsProvider", "DecisionsPanelProvider", "detector", "WorkspaceDetector", "glob", "watcher", "handler", "uri", "filePath", "config", "workspaceFolderPath", "connectBackend", "wsPath", "teardown", "scanWorkspace", "e", "f", "folders", "binaryName", "binaryPath", "BackendProcessManager", "binary", "args", "options", "url", "r", "baseUrl", "api", "StudioApiClient", "StudioSignalRClient", "state", "deactivate"] +} diff --git a/ai-dev-vscode/dist/webviews/agents/main.js b/ai-dev-vscode/dist/webviews/agents/main.js new file mode 100644 index 0000000..36fd766 --- /dev/null +++ b/ai-dev-vscode/dist/webviews/agents/main.js @@ -0,0 +1,67 @@ +"use strict";(()=>{var Rm=Object.create;var Bi=Object.defineProperty;var Bm=Object.getOwnPropertyDescriptor;var Cm=Object.getOwnPropertyNames;var Ym=Object.getPrototypeOf,Gm=Object.prototype.hasOwnProperty;var $l=(l,t)=>()=>(t||l((t={exports:{}}).exports,t),t.exports);var Xm=(l,t,u,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Cm(t))!Gm.call(l,n)&&n!==u&&Bi(l,n,{get:()=>t[n],enumerable:!(a=Bm(t,n))||a.enumerable});return l};var hn=(l,t,u)=>(u=l!=null?Rm(Ym(l)):{},Xm(t||!l||!l.__esModule?Bi(u,"default",{value:l,enumerable:!0}):u,l));var ri=$l(_=>{"use strict";var We=Symbol.for("react.transitional.element"),Qm=Symbol.for("react.portal"),jm=Symbol.for("react.fragment"),Zm=Symbol.for("react.strict_mode"),Vm=Symbol.for("react.profiler"),xm=Symbol.for("react.consumer"),Lm=Symbol.for("react.context"),rm=Symbol.for("react.forward_ref"),Km=Symbol.for("react.suspense"),Jm=Symbol.for("react.memo"),Qi=Symbol.for("react.lazy"),wm=Symbol.for("react.activity"),Ci=Symbol.iterator;function Wm(l){return l===null||typeof l!="object"?null:(l=Ci&&l[Ci]||l["@@iterator"],typeof l=="function"?l:null)}var ji={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Zi=Object.assign,Vi={};function Eu(l,t,u){this.props=l,this.context=t,this.refs=Vi,this.updater=u||ji}Eu.prototype.isReactComponent={};Eu.prototype.setState=function(l,t){if(typeof l!="object"&&typeof l!="function"&&l!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,l,t,"setState")};Eu.prototype.forceUpdate=function(l){this.updater.enqueueForceUpdate(this,l,"forceUpdate")};function xi(){}xi.prototype=Eu.prototype;function $e(l,t,u){this.props=l,this.context=t,this.refs=Vi,this.updater=u||ji}var Fe=$e.prototype=new xi;Fe.constructor=$e;Zi(Fe,Eu.prototype);Fe.isPureReactComponent=!0;var Yi=Array.isArray;function we(){}var L={H:null,A:null,T:null,S:null},Li=Object.prototype.hasOwnProperty;function ke(l,t,u){var a=u.ref;return{$$typeof:We,type:l,key:t,ref:a!==void 0?a:null,props:u}}function $m(l,t){return ke(l.type,t,l.props)}function Ie(l){return typeof l=="object"&&l!==null&&l.$$typeof===We}function Fm(l){var t={"=":"=0",":":"=2"};return"$"+l.replace(/[=:]/g,function(u){return t[u]})}var Gi=/\/+/g;function Je(l,t){return typeof l=="object"&&l!==null&&l.key!=null?Fm(""+l.key):t.toString(36)}function km(l){switch(l.status){case"fulfilled":return l.value;case"rejected":throw l.reason;default:switch(typeof l.status=="string"?l.then(we,we):(l.status="pending",l.then(function(t){l.status==="pending"&&(l.status="fulfilled",l.value=t)},function(t){l.status==="pending"&&(l.status="rejected",l.reason=t)})),l.status){case"fulfilled":return l.value;case"rejected":throw l.reason}}throw l}function zu(l,t,u,a,n){var e=typeof l;(e==="undefined"||e==="boolean")&&(l=null);var f=!1;if(l===null)f=!0;else switch(e){case"bigint":case"string":case"number":f=!0;break;case"object":switch(l.$$typeof){case We:case Qm:f=!0;break;case Qi:return f=l._init,zu(f(l._payload),t,u,a,n)}}if(f)return n=n(l),f=a===""?"."+Je(l,0):a,Yi(n)?(u="",f!=null&&(u=f.replace(Gi,"$&/")+"/"),zu(n,t,u,"",function(m){return m})):n!=null&&(Ie(n)&&(n=$m(n,u+(n.key==null||l&&l.key===n.key?"":(""+n.key).replace(Gi,"$&/")+"/")+f)),t.push(n)),1;f=0;var c=a===""?".":a+":";if(Yi(l))for(var i=0;i{"use strict";Ki.exports=ri()});var t0=$l(w=>{"use strict";function uf(l,t){var u=l.length;l.push(t);l:for(;0>>1,n=l[a];if(0>>1;aSn(c,u))iSn(m,c)?(l[a]=m,l[i]=u,a=i):(l[a]=c,l[f]=u,a=f);else if(iSn(m,u))l[a]=m,l[i]=u,a=i;else break l}}return t}function Sn(l,t){var u=l.sortIndex-t.sortIndex;return u!==0?u:l.id-t.id}w.unstable_now=void 0;typeof performance=="object"&&typeof performance.now=="function"?(Ji=performance,w.unstable_now=function(){return Ji.now()}):(Pe=Date,wi=Pe.now(),w.unstable_now=function(){return Pe.now()-wi});var Ji,Pe,wi,at=[],_t=[],ld=1,Yl=null,hl=3,af=!1,ma=!1,da=!1,nf=!1,Fi=typeof setTimeout=="function"?setTimeout:null,ki=typeof clearTimeout=="function"?clearTimeout:null,Wi=typeof setImmediate<"u"?setImmediate:null;function gn(l){for(var t=Fl(_t);t!==null;){if(t.callback===null)bn(_t);else if(t.startTime<=l)bn(_t),t.sortIndex=t.expirationTime,uf(at,t);else break;t=Fl(_t)}}function ef(l){if(da=!1,gn(l),!ma)if(Fl(at)!==null)ma=!0,Au||(Au=!0,Tu());else{var t=Fl(_t);t!==null&&ff(ef,t.startTime-l)}}var Au=!1,ha=-1,Ii=5,Pi=-1;function l0(){return nf?!0:!(w.unstable_now()-Pil&&l0());){var a=Yl.callback;if(typeof a=="function"){Yl.callback=null,hl=Yl.priorityLevel;var n=a(Yl.expirationTime<=l);if(l=w.unstable_now(),typeof n=="function"){Yl.callback=n,gn(l),t=!0;break t}Yl===Fl(at)&&bn(at),gn(l)}else bn(at);Yl=Fl(at)}if(Yl!==null)t=!0;else{var e=Fl(_t);e!==null&&ff(ef,e.startTime-l),t=!1}}break l}finally{Yl=null,hl=u,af=!1}t=void 0}}finally{t?Tu():Au=!1}}}var Tu;typeof Wi=="function"?Tu=function(){Wi(lf)}:typeof MessageChannel<"u"?(tf=new MessageChannel,$i=tf.port2,tf.port1.onmessage=lf,Tu=function(){$i.postMessage(null)}):Tu=function(){Fi(lf,0)};var tf,$i;function ff(l,t){ha=Fi(function(){l(w.unstable_now())},t)}w.unstable_IdlePriority=5;w.unstable_ImmediatePriority=1;w.unstable_LowPriority=4;w.unstable_NormalPriority=3;w.unstable_Profiling=null;w.unstable_UserBlockingPriority=2;w.unstable_cancelCallback=function(l){l.callback=null};w.unstable_forceFrameRate=function(l){0>l||125a?(l.sortIndex=u,uf(_t,l),Fl(at)===null&&l===Fl(_t)&&(da?(ki(ha),ha=-1):da=!0,ff(ef,u-a))):(l.sortIndex=n,uf(at,l),ma||af||(ma=!0,Au||(Au=!0,Tu()))),l};w.unstable_shouldYield=l0;w.unstable_wrapCallback=function(l){var t=hl;return function(){var u=hl;hl=t;try{return l.apply(this,arguments)}finally{hl=u}}}});var a0=$l((Qs,u0)=>{"use strict";u0.exports=t0()});var e0=$l(ol=>{"use strict";var td=on();function n0(l){var t="https://react.dev/errors/"+l;if(1{"use strict";function f0(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f0)}catch(l){console.error(l)}}f0(),c0.exports=e0()});var Em=$l(re=>{"use strict";var nl=a0(),C1=on(),nd=i0();function b(l){var t="https://react.dev/errors/"+l;if(1pu||(l.current=Jf[pu],Jf[pu]=null,pu--)}function x(l,t){pu++,Jf[pu]=l.current,l.current=t}var lt=tt(null),Za=tt(null),Xt=tt(null),Pn=tt(null);function le(l,t){switch(x(Xt,t),x(Za,l),x(lt,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?g1(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=g1(t),l=fm(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}cl(lt),x(lt,l)}function wu(){cl(lt),cl(Za),cl(Xt)}function wf(l){l.memoizedState!==null&&x(Pn,l);var t=lt.current,u=fm(t,l.type);t!==u&&(x(Za,l),x(lt,u))}function te(l){Za.current===l&&(cl(lt),cl(Za)),Pn.current===l&&(cl(Pn),ka._currentValue=au)}var cf,m0;function Pt(l){if(cf===void 0)try{throw Error()}catch(u){var t=u.stack.trim().match(/\n( *(at )?)/);cf=t&&t[1]||"",m0=-1)":-1n||i[a]!==m[n]){var o=` +`+i[a].replace(" at new "," at ");return l.displayName&&o.includes("")&&(o=o.replace("",l.displayName)),o}while(1<=a&&0<=n);break}}}finally{yf=!1,Error.prepareStackTrace=u}return(u=l?l.displayName||l.name:"")?Pt(u):""}function yd(l,t){switch(l.tag){case 26:case 27:case 5:return Pt(l.type);case 16:return Pt("Lazy");case 13:return l.child!==t&&t!==null?Pt("Suspense Fallback"):Pt("Suspense");case 19:return Pt("SuspenseList");case 0:case 15:return vf(l.type,!1);case 11:return vf(l.type.render,!1);case 1:return vf(l.type,!0);case 31:return Pt("Activity");default:return""}}function d0(l){try{var t="",u=null;do t+=yd(l,u),u=l,l=l.return;while(l);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var Wf=Object.prototype.hasOwnProperty,Qc=nl.unstable_scheduleCallback,mf=nl.unstable_cancelCallback,vd=nl.unstable_shouldYield,md=nl.unstable_requestPaint,pl=nl.unstable_now,dd=nl.unstable_getCurrentPriorityLevel,V1=nl.unstable_ImmediatePriority,x1=nl.unstable_UserBlockingPriority,ue=nl.unstable_NormalPriority,hd=nl.unstable_LowPriority,L1=nl.unstable_IdlePriority,sd=nl.log,od=nl.unstable_setDisableYieldValue,tn=null,Hl=null;function Rt(l){if(typeof sd=="function"&&od(l),Hl&&typeof Hl.setStrictMode=="function")try{Hl.setStrictMode(tn,l)}catch{}}var ql=Math.clz32?Math.clz32:bd,Sd=Math.log,gd=Math.LN2;function bd(l){return l>>>=0,l===0?32:31-(Sd(l)/gd|0)|0}var Tn=256,An=262144,On=4194304;function lu(l){var t=l&42;if(t!==0)return t;switch(l&-l){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Ne(l,t,u){var a=l.pendingLanes;if(a===0)return 0;var n=0,e=l.suspendedLanes,f=l.pingedLanes;l=l.warmLanes;var c=a&134217727;return c!==0?(a=c&~e,a!==0?n=lu(a):(f&=c,f!==0?n=lu(f):u||(u=c&~l,u!==0&&(n=lu(u))))):(c=a&~e,c!==0?n=lu(c):f!==0?n=lu(f):u||(u=a&~l,u!==0&&(n=lu(u)))),n===0?0:t!==0&&t!==n&&(t&e)===0&&(e=n&-n,u=t&-t,e>=u||e===32&&(u&4194048)!==0)?t:n}function un(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function zd(l,t){switch(l){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function r1(){var l=On;return On<<=1,(On&62914560)===0&&(On=4194304),l}function df(l){for(var t=[],u=0;31>u;u++)t.push(l);return t}function an(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Ed(l,t,u,a,n,e){var f=l.pendingLanes;l.pendingLanes=u,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=u,l.entangledLanes&=u,l.errorRecoveryDisabledLanes&=u,l.shellSuspendCounter=0;var c=l.entanglements,i=l.expirationTimes,m=l.hiddenUpdates;for(u=f&~u;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var Dd=/[\n"\\]/g;function Zl(l){return l.replace(Dd,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function kf(l,t,u,a,n,e,f,c){l.name="",f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"?l.type=f:l.removeAttribute("type"),t!=null?f==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+Xl(t)):l.value!==""+Xl(t)&&(l.value=""+Xl(t)):f!=="submit"&&f!=="reset"||l.removeAttribute("value"),t!=null?If(l,f,Xl(t)):u!=null?If(l,f,Xl(u)):a!=null&&l.removeAttribute("value"),n==null&&e!=null&&(l.defaultChecked=!!e),n!=null&&(l.checked=n&&typeof n!="function"&&typeof n!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+Xl(c):l.removeAttribute("name")}function P1(l,t,u,a,n,e,f,c){if(e!=null&&typeof e!="function"&&typeof e!="symbol"&&typeof e!="boolean"&&(l.type=e),t!=null||u!=null){if(!(e!=="submit"&&e!=="reset"||t!=null)){Ff(l);return}u=u!=null?""+Xl(u):"",t=t!=null?""+Xl(t):u,c||t===l.value||(l.value=t),l.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,l.checked=c?l.checked:!!a,l.defaultChecked=!!a,f!=null&&typeof f!="function"&&typeof f!="symbol"&&typeof f!="boolean"&&(l.name=f),Ff(l)}function If(l,t,u){t==="number"&&ae(l.ownerDocument)===l||l.defaultValue===""+u||(l.defaultValue=""+u)}function Vu(l,t,u,a){if(l=l.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),lc=!1;if(gt)try{Ou={},Object.defineProperty(Ou,"passive",{get:function(){lc=!0}}),window.addEventListener("test",Ou,Ou),window.removeEventListener("test",Ou,Ou)}catch{lc=!1}var Ou,Bt=null,rc=null,Zn=null;function ny(){if(Zn)return Zn;var l,t=rc,u=t.length,a,n="value"in Bt?Bt.value:Bt.textContent,e=n.length;for(l=0;l=Ua),O0=" ",_0=!1;function fy(l,t){switch(l){case"keyup":return lh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function cy(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Ru=!1;function uh(l,t){switch(l){case"compositionend":return cy(t);case"keypress":return t.which!==32?null:(_0=!0,O0);case"textInput":return l=t.data,l===O0&&_0?null:l;default:return null}}function ah(l,t){if(Ru)return l==="compositionend"||!Jc&&fy(l,t)?(l=ny(),Zn=rc=Bt=null,Ru=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:u,offset:t-l};l=a}l:{for(;u;){if(u.nextSibling){u=u.nextSibling;break l}u=u.parentNode}u=void 0}u=N0(u)}}function my(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?my(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function dy(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=ae(l.document);t instanceof l.HTMLIFrameElement;){try{var u=typeof t.contentWindow.location.href=="string"}catch{u=!1}if(u)l=t.contentWindow;else break;t=ae(l.document)}return t}function wc(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var mh=gt&&"documentMode"in document&&11>=document.documentMode,Bu=null,tc=null,pa=null,uc=!1;function H0(l,t,u){var a=u.window===u?u.document:u.nodeType===9?u:u.ownerDocument;uc||Bu==null||Bu!==ae(a)||(a=Bu,"selectionStart"in a&&wc(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),pa&&La(pa,a)||(pa=a,a=Te(tc,"onSelect"),0>=f,n-=f,kl=1<<32-ql(t)+n|u<D?(p=E,E=null):p=E.sibling;var B=h(v,E,d[D],S);if(B===null){E===null&&(E=p);break}l&&E&&B.alternate===null&&t(v,E),y=e(B,y,D),R===null?T=B:R.sibling=B,R=B,E=p}if(D===d.length)return u(v,E),q&&yt(v,D),T;if(E===null){for(;DD?(p=E,E=null):p=E.sibling;var Ot=h(v,E,B.value,S);if(Ot===null){E===null&&(E=p);break}l&&E&&Ot.alternate===null&&t(v,E),y=e(Ot,y,D),R===null?T=Ot:R.sibling=Ot,R=Ot,E=p}if(B.done)return u(v,E),q&&yt(v,D),T;if(E===null){for(;!B.done;D++,B=d.next())B=g(v,B.value,S),B!==null&&(y=e(B,y,D),R===null?T=B:R.sibling=B,R=B);return q&&yt(v,D),T}for(E=a(E);!B.done;D++,B=d.next())B=s(E,v,D,B.value,S),B!==null&&(l&&B.alternate!==null&&E.delete(B.key===null?D:B.key),y=e(B,y,D),R===null?T=B:R.sibling=B,R=B);return l&&E.forEach(function(qm){return t(v,qm)}),q&&yt(v,D),T}function Q(v,y,d,S){if(typeof d=="object"&&d!==null&&d.type===Nu&&d.key===null&&(d=d.props.children),typeof d=="object"&&d!==null){switch(d.$$typeof){case En:l:{for(var T=d.key;y!==null;){if(y.key===T){if(T=d.type,T===Nu){if(y.tag===7){u(v,y.sibling),S=n(y,d.props.children),S.return=v,v=S;break l}}else if(y.elementType===T||typeof T=="object"&&T!==null&&T.$$typeof===Dt&&tu(T)===y.type){u(v,y.sibling),S=n(y,d.props),ga(S,d),S.return=v,v=S;break l}u(v,y);break}else t(v,y);y=y.sibling}d.type===Nu?(S=nu(d.props.children,v.mode,S,d.key),S.return=v,v=S):(S=xn(d.type,d.key,d.props,null,v.mode,S),ga(S,d),S.return=v,v=S)}return f(v);case Aa:l:{for(T=d.key;y!==null;){if(y.key===T)if(y.tag===4&&y.stateNode.containerInfo===d.containerInfo&&y.stateNode.implementation===d.implementation){u(v,y.sibling),S=n(y,d.children||[]),S.return=v,v=S;break l}else{u(v,y);break}else t(v,y);y=y.sibling}S=Ef(d,v.mode,S),S.return=v,v=S}return f(v);case Dt:return d=tu(d),Q(v,y,d,S)}if(Oa(d))return z(v,y,d,S);if(oa(d)){if(T=oa(d),typeof T!="function")throw Error(b(150));return d=T.call(d),A(v,y,d,S)}if(typeof d.then=="function")return Q(v,y,pn(d),S);if(d.$$typeof===mt)return Q(v,y,Nn(v,d),S);Hn(v,d)}return typeof d=="string"&&d!==""||typeof d=="number"||typeof d=="bigint"?(d=""+d,y!==null&&y.tag===6?(u(v,y.sibling),S=n(y,d),S.return=v,v=S):(u(v,y),S=zf(d,v.mode,S),S.return=v,v=S),f(v)):u(v,y)}return function(v,y,d,S){try{Ja=0;var T=Q(v,y,d,S);return ru=null,T}catch(E){if(E===ca||E===Ce)throw E;var R=Ul(29,E,null,v.mode);return R.lanes=S,R.return=v,R}finally{}}}var vu=Uy(!0),Ny=Uy(!1),Ut=!1;function ui(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function yc(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function jt(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function Zt(l,t,u){var a=l.updateQueue;if(a===null)return null;if(a=a.shared,(C&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=ee(l),zy(l,null,u),t}return Be(l,a,t,u),ee(l)}function qa(l,t,u){if(t=t.updateQueue,t!==null&&(t=t.shared,(u&4194048)!==0)){var a=t.lanes;a&=l.pendingLanes,u|=a,t.lanes=u,J1(l,u)}}function Af(l,t){var u=l.updateQueue,a=l.alternate;if(a!==null&&(a=a.updateQueue,u===a)){var n=null,e=null;if(u=u.firstBaseUpdate,u!==null){do{var f={lane:u.lane,tag:u.tag,payload:u.payload,callback:null,next:null};e===null?n=e=f:e=e.next=f,u=u.next}while(u!==null);e===null?n=e=t:e=e.next=t}else n=e=t;u={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:e,shared:a.shared,callbacks:a.callbacks},l.updateQueue=u;return}l=u.lastBaseUpdate,l===null?u.firstBaseUpdate=t:l.next=t,u.lastBaseUpdate=t}var vc=!1;function Ra(){if(vc){var l=Lu;if(l!==null)throw l}}function Ba(l,t,u,a){vc=!1;var n=l.updateQueue;Ut=!1;var e=n.firstBaseUpdate,f=n.lastBaseUpdate,c=n.shared.pending;if(c!==null){n.shared.pending=null;var i=c,m=i.next;i.next=null,f===null?e=m:f.next=m,f=i;var o=l.alternate;o!==null&&(o=o.updateQueue,c=o.lastBaseUpdate,c!==f&&(c===null?o.firstBaseUpdate=m:c.next=m,o.lastBaseUpdate=i))}if(e!==null){var g=n.baseState;f=0,o=m=i=null,c=e;do{var h=c.lane&-536870913,s=h!==c.lane;if(s?(H&h)===h:(a&h)===h){h!==0&&h===Fu&&(vc=!0),o!==null&&(o=o.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var z=l,A=c;h=t;var Q=u;switch(A.tag){case 1:if(z=A.payload,typeof z=="function"){g=z.call(Q,g,h);break l}g=z;break l;case 3:z.flags=z.flags&-65537|128;case 0:if(z=A.payload,h=typeof z=="function"?z.call(Q,g,h):z,h==null)break l;g=J({},g,h);break l;case 2:Ut=!0}}h=c.callback,h!==null&&(l.flags|=64,s&&(l.flags|=8192),s=n.callbacks,s===null?n.callbacks=[h]:s.push(h))}else s={lane:h,tag:c.tag,payload:c.payload,callback:c.callback,next:null},o===null?(m=o=s,i=g):o=o.next=s,f|=h;if(c=c.next,c===null){if(c=n.shared.pending,c===null)break;s=c,c=s.next,s.next=null,n.lastBaseUpdate=s,n.shared.pending=null}}while(!0);o===null&&(i=g),n.baseState=i,n.firstBaseUpdate=m,n.lastBaseUpdate=o,e===null&&(n.shared.lanes=0),$t|=f,l.lanes=f,l.memoizedState=g}}function py(l,t){if(typeof l!="function")throw Error(b(191,l));l.call(t)}function Hy(l,t){var u=l.callbacks;if(u!==null)for(l.callbacks=null,l=0;le?e:8;var f=O.T,c={};O.T=c,oi(l,!1,t,u);try{var i=n(),m=O.S;if(m!==null&&m(c,i),i!==null&&typeof i=="object"&&typeof i.then=="function"){var o=Eh(i,a);Ca(l,t,o,Rl(l))}else Ca(l,t,a,Rl(l))}catch(g){Ca(l,t,{then:function(){},status:"rejected",reason:g},Rl())}finally{Y.p=e,f!==null&&c.types!==null&&(f.types=c.types),O.T=f}}function Dh(){}function oc(l,t,u,a){if(l.tag!==5)throw Error(b(476));var n=tv(l).queue;lv(l,n,t,au,u===null?Dh:function(){return uv(l),u(a)})}function tv(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:au,baseState:au,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:zt,lastRenderedState:au},next:null};var u={};return t.next={memoizedState:u,baseState:u,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:zt,lastRenderedState:u},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function uv(l){var t=tv(l);t.next===null&&(t=l.alternate.memoizedState),Ca(l,t.next.queue,{},Rl())}function si(){return ml(ka)}function av(){return I().memoizedState}function nv(){return I().memoizedState}function Uh(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var u=Rl();l=jt(u);var a=Zt(t,l,u);a!==null&&(Al(a,t,u),qa(a,t,u)),t={cache:Pc()},l.payload=t;return}t=t.return}}function Nh(l,t,u){var a=Rl();u={lane:a,revertLane:0,gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},Qe(l)?fv(t,u):(u=$c(l,t,u,a),u!==null&&(Al(u,l,a),cv(u,t,a)))}function ev(l,t,u){var a=Rl();Ca(l,t,u,a)}function Ca(l,t,u,a){var n={lane:a,revertLane:0,gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null};if(Qe(l))fv(t,n);else{var e=l.alternate;if(l.lanes===0&&(e===null||e.lanes===0)&&(e=t.lastRenderedReducer,e!==null))try{var f=t.lastRenderedState,c=e(f,u);if(n.hasEagerState=!0,n.eagerState=c,Bl(c,f))return Be(l,t,n,0),V===null&&Re(),!1}catch{}finally{}if(u=$c(l,t,n,a),u!==null)return Al(u,l,a),cv(u,t,a),!0}return!1}function oi(l,t,u,a){if(a={lane:2,revertLane:_i(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Qe(l)){if(t)throw Error(b(479))}else t=$c(l,u,a,2),t!==null&&Al(t,l,2)}function Qe(l){var t=l.alternate;return l===M||t!==null&&t===M}function fv(l,t){Ku=me=!0;var u=l.pending;u===null?t.next=t:(t.next=u.next,u.next=t),l.pending=t}function cv(l,t,u){if((u&4194048)!==0){var a=t.lanes;a&=l.pendingLanes,u|=a,t.lanes=u,J1(l,u)}}var Wa={readContext:ml,use:Ge,useCallback:$,useContext:$,useEffect:$,useImperativeHandle:$,useLayoutEffect:$,useInsertionEffect:$,useMemo:$,useReducer:$,useRef:$,useState:$,useDebugValue:$,useDeferredValue:$,useTransition:$,useSyncExternalStore:$,useId:$,useHostTransitionStatus:$,useFormState:$,useActionState:$,useOptimistic:$,useMemoCache:$,useCacheRefresh:$};Wa.useEffectEvent=$;var iv={readContext:ml,use:Ge,useCallback:function(l,t){return Sl().memoizedState=[l,t===void 0?null:t],l},useContext:ml,useEffect:K0,useImperativeHandle:function(l,t,u){u=u!=null?u.concat([l]):null,Kn(4194308,4,$y.bind(null,t,l),u)},useLayoutEffect:function(l,t){return Kn(4194308,4,l,t)},useInsertionEffect:function(l,t){Kn(4,2,l,t)},useMemo:function(l,t){var u=Sl();t=t===void 0?null:t;var a=l();if(mu){Rt(!0);try{l()}finally{Rt(!1)}}return u.memoizedState=[a,t],a},useReducer:function(l,t,u){var a=Sl();if(u!==void 0){var n=u(t);if(mu){Rt(!0);try{u(t)}finally{Rt(!1)}}}else n=t;return a.memoizedState=a.baseState=n,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:n},a.queue=l,l=l.dispatch=Nh.bind(null,M,l),[a.memoizedState,l]},useRef:function(l){var t=Sl();return l={current:l},t.memoizedState=l},useState:function(l){l=hc(l);var t=l.queue,u=ev.bind(null,M,t);return t.dispatch=u,[l.memoizedState,u]},useDebugValue:di,useDeferredValue:function(l,t){var u=Sl();return hi(u,l,t)},useTransition:function(){var l=hc(!1);return l=lv.bind(null,M,l.queue,!0,!1),Sl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,u){var a=M,n=Sl();if(q){if(u===void 0)throw Error(b(407));u=u()}else{if(u=t(),V===null)throw Error(b(349));(H&127)!==0||Yy(a,t,u)}n.memoizedState=u;var e={value:u,getSnapshot:t};return n.queue=e,K0(Xy.bind(null,a,e,l),[l]),a.flags|=2048,Iu(9,{destroy:void 0},Gy.bind(null,a,e,u,t),null),u},useId:function(){var l=Sl(),t=V.identifierPrefix;if(q){var u=Il,a=kl;u=(a&~(1<<32-ql(a)-1)).toString(32)+u,t="_"+t+"R_"+u,u=de++,0<\/script>",e=e.removeChild(e.firstChild);break;case"select":e=typeof a.is=="string"?f.createElement("select",{is:a.is}):f.createElement("select"),a.multiple?e.multiple=!0:a.size&&(e.size=a.size);break;default:e=typeof a.is=="string"?f.createElement(n,{is:a.is}):f.createElement(n)}}e[yl]=t,e[Ol]=a;l:for(f=t.child;f!==null;){if(f.tag===5||f.tag===6)e.appendChild(f.stateNode);else if(f.tag!==4&&f.tag!==27&&f.child!==null){f.child.return=f,f=f.child;continue}if(f===t)break l;for(;f.sibling===null;){if(f.return===null||f.return===t)break l;f=f.return}f.sibling.return=f.return,f=f.sibling}t.stateNode=e;l:switch(dl(e,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break l;case"img":a=!0;break l;default:a=!1}a&&et(t)}}return r(t),Hf(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,u),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==a&&et(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(b(166));if(l=Xt.current,_u(t)){if(l=t.stateNode,u=t.memoizedProps,a=null,n=vl,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}l[yl]=t,l=!!(l.nodeValue===u||a!==null&&a.suppressHydrationWarning===!0||em(l.nodeValue,u)),l||wt(t,!0)}else l=Ae(l).createTextNode(a),l[yl]=t,t.stateNode=l}return r(t),null;case 31:if(u=t.memoizedState,l===null||l.memoizedState!==null){if(a=_u(t),u!==null){if(l===null){if(!a)throw Error(b(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(b(557));l[yl]=t}else iu(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;r(t),l=!1}else u=Tf(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=u),l=!0;if(!l)return t.flags&256?(Dl(t),t):(Dl(t),null);if((t.flags&128)!==0)throw Error(b(558))}return r(t),null;case 13:if(a=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(n=_u(t),a!==null&&a.dehydrated!==null){if(l===null){if(!n)throw Error(b(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(b(317));n[yl]=t}else iu(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;r(t),n=!1}else n=Tf(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(Dl(t),t):(Dl(t),null)}return Dl(t),(t.flags&128)!==0?(t.lanes=u,t):(u=a!==null,l=l!==null&&l.memoizedState!==null,u&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),e=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(e=a.memoizedState.cachePool.pool),e!==n&&(a.flags|=2048)),u!==l&&u&&(t.child.flags|=8192),qn(t,t.updateQueue),r(t),null);case 4:return wu(),l===null&&Mi(t.stateNode.containerInfo),r(t),null;case 10:return ot(t.type),r(t),null;case 19:if(cl(k),a=t.memoizedState,a===null)return r(t),null;if(n=(t.flags&128)!==0,e=a.rendering,e===null)if(n)ba(a,!1);else{if(F!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(e=ve(l),e!==null){for(t.flags|=128,ba(a,!1),l=e.updateQueue,t.updateQueue=l,qn(t,l),t.subtreeFlags=0,l=u,u=t.child;u!==null;)Ey(u,l),u=u.sibling;return x(k,k.current&1|2),q&&yt(t,a.treeForkCount),t.child}l=l.sibling}a.tail!==null&&pl()>Se&&(t.flags|=128,n=!0,ba(a,!1),t.lanes=4194304)}else{if(!n)if(l=ve(e),l!==null){if(t.flags|=128,n=!0,l=l.updateQueue,t.updateQueue=l,qn(t,l),ba(a,!0),a.tail===null&&a.tailMode==="hidden"&&!e.alternate&&!q)return r(t),null}else 2*pl()-a.renderingStartTime>Se&&u!==536870912&&(t.flags|=128,n=!0,ba(a,!1),t.lanes=4194304);a.isBackwards?(e.sibling=t.child,t.child=e):(l=a.last,l!==null?l.sibling=e:t.child=e,a.last=e)}return a.tail!==null?(l=a.tail,a.rendering=l,a.tail=l.sibling,a.renderingStartTime=pl(),l.sibling=null,u=k.current,x(k,n?u&1|2:u&1),q&&yt(t,a.treeForkCount),l):(r(t),null);case 22:case 23:return Dl(t),ai(),a=t.memoizedState!==null,l!==null?l.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(u&536870912)!==0&&(t.flags&128)===0&&(r(t),t.subtreeFlags&6&&(t.flags|=8192)):r(t),u=t.updateQueue,u!==null&&qn(t,u.retryQueue),u=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(u=l.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==u&&(t.flags|=2048),l!==null&&cl(eu),null;case 24:return u=null,l!==null&&(u=l.memoizedState.cache),t.memoizedState.cache!==u&&(t.flags|=2048),ot(tl),r(t),null;case 25:return null;case 30:return null}throw Error(b(156,t.tag))}function Bh(l,t){switch(Ic(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return ot(tl),wu(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return te(t),null;case 31:if(t.memoizedState!==null){if(Dl(t),t.alternate===null)throw Error(b(340));iu()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(Dl(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(b(340));iu()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return cl(k),null;case 4:return wu(),null;case 10:return ot(t.type),null;case 22:case 23:return Dl(t),ai(),l!==null&&cl(eu),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return ot(tl),null;case 25:return null;default:return null}}function Ev(l,t){switch(Ic(t),t.tag){case 3:ot(tl),wu();break;case 26:case 27:case 5:te(t);break;case 4:wu();break;case 31:t.memoizedState!==null&&Dl(t);break;case 13:Dl(t);break;case 19:cl(k);break;case 10:ot(t.type);break;case 22:case 23:Dl(t),ai(),l!==null&&cl(eu);break;case 24:ot(tl)}}function yn(l,t){try{var u=t.updateQueue,a=u!==null?u.lastEffect:null;if(a!==null){var n=a.next;u=n;do{if((u.tag&l)===l){a=void 0;var e=u.create,f=u.inst;a=e(),f.destroy=a}u=u.next}while(u!==n)}}catch(c){X(t,t.return,c)}}function Wt(l,t,u){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var e=n.next;a=e;do{if((a.tag&l)===l){var f=a.inst,c=f.destroy;if(c!==void 0){f.destroy=void 0,n=t;var i=u,m=c;try{m()}catch(o){X(n,i,o)}}}a=a.next}while(a!==e)}}catch(o){X(t,t.return,o)}}function Tv(l){var t=l.updateQueue;if(t!==null){var u=l.stateNode;try{Hy(t,u)}catch(a){X(l,l.return,a)}}}function Av(l,t,u){u.props=du(l.type,l.memoizedProps),u.state=l.memoizedState;try{u.componentWillUnmount()}catch(a){X(l,t,a)}}function Ya(l,t){try{var u=l.ref;if(u!==null){switch(l.tag){case 26:case 27:case 5:var a=l.stateNode;break;case 30:a=l.stateNode;break;default:a=l.stateNode}typeof u=="function"?l.refCleanup=u(a):u.current=a}}catch(n){X(l,t,n)}}function Pl(l,t){var u=l.ref,a=l.refCleanup;if(u!==null)if(typeof a=="function")try{a()}catch(n){X(l,t,n)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof u=="function")try{u(null)}catch(n){X(l,t,n)}else u.current=null}function Ov(l){var t=l.type,u=l.memoizedProps,a=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":u.autoFocus&&a.focus();break l;case"img":u.src?a.src=u.src:u.srcSet&&(a.srcset=u.srcSet)}}catch(n){X(l,l.return,n)}}function qf(l,t,u){try{var a=l.stateNode;Ph(a,l.type,u,t),a[Ol]=t}catch(n){X(l,l.return,n)}}function _v(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&kt(l.type)||l.tag===4}function Rf(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||_v(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&kt(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function Ec(l,t,u){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?(u.nodeType===9?u.body:u.nodeName==="HTML"?u.ownerDocument.body:u).insertBefore(l,t):(t=u.nodeType===9?u.body:u.nodeName==="HTML"?u.ownerDocument.body:u,t.appendChild(l),u=u._reactRootContainer,u!=null||t.onclick!==null||(t.onclick=dt));else if(a!==4&&(a===27&&kt(l.type)&&(u=l.stateNode,t=null),l=l.child,l!==null))for(Ec(l,t,u),l=l.sibling;l!==null;)Ec(l,t,u),l=l.sibling}function oe(l,t,u){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?u.insertBefore(l,t):u.appendChild(l);else if(a!==4&&(a===27&&kt(l.type)&&(u=l.stateNode),l=l.child,l!==null))for(oe(l,t,u),l=l.sibling;l!==null;)oe(l,t,u),l=l.sibling}function Mv(l){var t=l.stateNode,u=l.memoizedProps;try{for(var a=l.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);dl(t,a,u),t[yl]=l,t[Ol]=u}catch(e){X(l,l.return,e)}}var vt=!1,ll=!1,Bf=!1,n1=typeof WeakSet=="function"?WeakSet:Set,el=null;function Ch(l,t){if(l=l.containerInfo,Uc=De,l=dy(l),wc(l)){if("selectionStart"in l)var u={start:l.selectionStart,end:l.selectionEnd};else l:{u=(u=l.ownerDocument)&&u.defaultView||window;var a=u.getSelection&&u.getSelection();if(a&&a.rangeCount!==0){u=a.anchorNode;var n=a.anchorOffset,e=a.focusNode;a=a.focusOffset;try{u.nodeType,e.nodeType}catch{u=null;break l}var f=0,c=-1,i=-1,m=0,o=0,g=l,h=null;t:for(;;){for(var s;g!==u||n!==0&&g.nodeType!==3||(c=f+n),g!==e||a!==0&&g.nodeType!==3||(i=f+a),g.nodeType===3&&(f+=g.nodeValue.length),(s=g.firstChild)!==null;)h=g,g=s;for(;;){if(g===l)break t;if(h===u&&++m===n&&(c=f),h===e&&++o===a&&(i=f),(s=g.nextSibling)!==null)break;g=h,h=g.parentNode}g=s}u=c===-1||i===-1?null:{start:c,end:i}}else u=null}u=u||{start:0,end:0}}else u=null;for(Nc={focusedElem:l,selectionRange:u},De=!1,el=t;el!==null;)if(t=el,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,el=l;else for(;el!==null;){switch(t=el,e=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(u=0;u title"))),dl(e,a,u),e[yl]=l,fl(e),a=e;break l;case"link":var f=D1("link","href",n).get(a+(u.href||""));if(f){for(var c=0;cQ&&(f=Q,Q=A,A=f);var v=p0(c,A),y=p0(c,Q);if(v&&y&&(s.rangeCount!==1||s.anchorNode!==v.node||s.anchorOffset!==v.offset||s.focusNode!==y.node||s.focusOffset!==y.offset)){var d=g.createRange();d.setStart(v.node,v.offset),s.removeAllRanges(),A>Q?(s.addRange(d),s.extend(y.node,y.offset)):(d.setEnd(y.node,y.offset),s.addRange(d))}}}}for(g=[],s=c;s=s.parentNode;)s.nodeType===1&&g.push({element:s,left:s.scrollLeft,top:s.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;cu?32:u,O.T=null,u=Oc,Oc=null;var e=xt,f=St;if(al=0,la=xt=null,St=0,(C&6)!==0)throw Error(b(331));var c=C;if(C|=4,Gv(e.current),Bv(e,e.current,f,u),C=c,vn(0,!1),Hl&&typeof Hl.onPostCommitFiberRoot=="function")try{Hl.onPostCommitFiberRoot(tn,e)}catch{}return!0}finally{Y.p=n,O.T=a,kv(l,t)}}function i1(l,t,u){t=Vl(u,t),t=gc(l.stateNode,t,2),l=Zt(l,t,2),l!==null&&(an(l,2),ut(l))}function X(l,t,u){if(l.tag===3)i1(l,l,u);else for(;t!==null;){if(t.tag===3){i1(t,l,u);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(Vt===null||!Vt.has(a))){l=Vl(u,l),u=hv(2),a=Zt(t,u,2),a!==null&&(sv(u,a,t,l),an(a,2),ut(a));break}}t=t.return}}function Yf(l,t,u){var a=l.pingCache;if(a===null){a=l.pingCache=new Xh;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(u)||(Ti=!0,n.add(u),l=xh.bind(null,l,t,u),t.then(l,l))}function xh(l,t,u){var a=l.pingCache;a!==null&&a.delete(t),l.pingedLanes|=l.suspendedLanes&u,l.warmLanes&=~u,V===l&&(H&u)===u&&(F===4||F===3&&(H&62914560)===H&&300>pl()-je?(C&2)===0&&ta(l,0):Ai|=u,Pu===H&&(Pu=0)),ut(l)}function Pv(l,t){t===0&&(t=r1()),l=Su(l,t),l!==null&&(an(l,t),ut(l))}function Lh(l){var t=l.memoizedState,u=0;t!==null&&(u=t.retryLane),Pv(l,u)}function rh(l,t){var u=0;switch(l.tag){case 31:case 13:var a=l.stateNode,n=l.memoizedState;n!==null&&(u=n.retryLane);break;case 19:a=l.stateNode;break;case 22:a=l.stateNode._retryCache;break;default:throw Error(b(314))}a!==null&&a.delete(t),Pv(l,u)}function Kh(l,t){return Qc(l,t)}var ze=null,Uu=null,Mc=!1,Ee=!1,Gf=!1,Gt=0;function ut(l){l!==Uu&&l.next===null&&(Uu===null?ze=Uu=l:Uu=Uu.next=l),Ee=!0,Mc||(Mc=!0,wh())}function vn(l,t){if(!Gf&&Ee){Gf=!0;do for(var u=!1,a=ze;a!==null;){if(!t)if(l!==0){var n=a.pendingLanes;if(n===0)var e=0;else{var f=a.suspendedLanes,c=a.pingedLanes;e=(1<<31-ql(42|l)+1)-1,e&=n&~(f&~c),e=e&201326741?e&201326741|1:e?e|2:0}e!==0&&(u=!0,y1(a,e))}else e=H,e=Ne(a,a===V?e:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(e&3)===0||un(a,e)||(u=!0,y1(a,e));a=a.next}while(u);Gf=!1}}function Jh(){lm()}function lm(){Ee=Mc=!1;var l=0;Gt!==0&&ts()&&(l=Gt);for(var t=pl(),u=null,a=ze;a!==null;){var n=a.next,e=tm(a,t);e===0?(a.next=null,u===null?ze=n:u.next=n,n===null&&(Uu=u)):(u=a,(l!==0||(e&3)!==0)&&(Ee=!0)),a=n}al!==0&&al!==5||vn(l,!1),Gt!==0&&(Gt=0)}function tm(l,t){for(var u=l.suspendedLanes,a=l.pingedLanes,n=l.expirationTimes,e=l.pendingLanes&-62914561;0c)break;var o=i.transferSize,g=i.initiatorType;o&&S1(g)&&(i=i.responseEnd,f+=o*(i"u"?null:document;function vm(l,t,u){var a=ya;if(a&&typeof t=="string"&&t){var n=Zl(t);n='link[rel="'+l+'"][href="'+n+'"]',typeof u=="string"&&(n+='[crossorigin="'+u+'"]'),O1.has(n)||(O1.add(n),l={rel:l,crossOrigin:u,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),dl(t,"link",l),fl(t),a.head.appendChild(t)))}}function vs(l){At.D(l),vm("dns-prefetch",l,null)}function ms(l,t){At.C(l,t),vm("preconnect",l,t)}function ds(l,t,u){At.L(l,t,u);var a=ya;if(a&&l&&t){var n='link[rel="preload"][as="'+Zl(t)+'"]';t==="image"&&u&&u.imageSrcSet?(n+='[imagesrcset="'+Zl(u.imageSrcSet)+'"]',typeof u.imageSizes=="string"&&(n+='[imagesizes="'+Zl(u.imageSizes)+'"]')):n+='[href="'+Zl(l)+'"]';var e=n;switch(t){case"style":e=ua(l);break;case"script":e=va(l)}Kl.has(e)||(l=J({rel:"preload",href:t==="image"&&u&&u.imageSrcSet?void 0:l,as:t},u),Kl.set(e,l),a.querySelector(n)!==null||t==="style"&&a.querySelector(mn(e))||t==="script"&&a.querySelector(dn(e))||(t=a.createElement("link"),dl(t,"link",l),fl(t),a.head.appendChild(t)))}}function hs(l,t){At.m(l,t);var u=ya;if(u&&l){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+Zl(a)+'"][href="'+Zl(l)+'"]',e=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":e=va(l)}if(!Kl.has(e)&&(l=J({rel:"modulepreload",href:l},t),Kl.set(e,l),u.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(u.querySelector(dn(e)))return}a=u.createElement("link"),dl(a,"link",l),fl(a),u.head.appendChild(a)}}}function ss(l,t,u){At.S(l,t,u);var a=ya;if(a&&l){var n=Zu(a).hoistableStyles,e=ua(l);t=t||"default";var f=n.get(e);if(!f){var c={loading:0,preload:null};if(f=a.querySelector(mn(e)))c.loading=5;else{l=J({rel:"stylesheet",href:l,"data-precedence":t},u),(u=Kl.get(e))&&Di(l,u);var i=f=a.createElement("link");fl(i),dl(i,"link",l),i._p=new Promise(function(m,o){i.onload=m,i.onerror=o}),i.addEventListener("load",function(){c.loading|=1}),i.addEventListener("error",function(){c.loading|=2}),c.loading|=4,$n(f,t,a)}f={type:"stylesheet",instance:f,count:1,state:c},n.set(e,f)}}}function os(l,t){At.X(l,t);var u=ya;if(u&&l){var a=Zu(u).hoistableScripts,n=va(l),e=a.get(n);e||(e=u.querySelector(dn(n)),e||(l=J({src:l,async:!0},t),(t=Kl.get(n))&&Ui(l,t),e=u.createElement("script"),fl(e),dl(e,"link",l),u.head.appendChild(e)),e={type:"script",instance:e,count:1,state:null},a.set(n,e))}}function Ss(l,t){At.M(l,t);var u=ya;if(u&&l){var a=Zu(u).hoistableScripts,n=va(l),e=a.get(n);e||(e=u.querySelector(dn(n)),e||(l=J({src:l,async:!0,type:"module"},t),(t=Kl.get(n))&&Ui(l,t),e=u.createElement("script"),fl(e),dl(e,"link",l),u.head.appendChild(e)),e={type:"script",instance:e,count:1,state:null},a.set(n,e))}}function _1(l,t,u,a){var n=(n=Xt.current)?Oe(n):null;if(!n)throw Error(b(446));switch(l){case"meta":case"title":return null;case"style":return typeof u.precedence=="string"&&typeof u.href=="string"?(t=ua(u.href),u=Zu(n).hoistableStyles,a=u.get(t),a||(a={type:"style",instance:null,count:0,state:null},u.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(u.rel==="stylesheet"&&typeof u.href=="string"&&typeof u.precedence=="string"){l=ua(u.href);var e=Zu(n).hoistableStyles,f=e.get(l);if(f||(n=n.ownerDocument||n,f={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},e.set(l,f),(e=n.querySelector(mn(l)))&&!e._p&&(f.instance=e,f.state.loading=5),Kl.has(l)||(u={rel:"preload",as:"style",href:u.href,crossOrigin:u.crossOrigin,integrity:u.integrity,media:u.media,hrefLang:u.hrefLang,referrerPolicy:u.referrerPolicy},Kl.set(l,u),e||gs(n,l,u,f.state))),t&&a===null)throw Error(b(528,""));return f}if(t&&a!==null)throw Error(b(529,""));return null;case"script":return t=u.async,u=u.src,typeof u=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=va(u),u=Zu(n).hoistableScripts,a=u.get(t),a||(a={type:"script",instance:null,count:0,state:null},u.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(b(444,l))}}function ua(l){return'href="'+Zl(l)+'"'}function mn(l){return'link[rel="stylesheet"]['+l+"]"}function mm(l){return J({},l,{"data-precedence":l.precedence,precedence:null})}function gs(l,t,u,a){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=l.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),dl(t,"link",u),fl(t),l.head.appendChild(t))}function va(l){return'[src="'+Zl(l)+'"]'}function dn(l){return"script[async]"+l}function M1(l,t,u){if(t.count++,t.instance===null)switch(t.type){case"style":var a=l.querySelector('style[data-href~="'+Zl(u.href)+'"]');if(a)return t.instance=a,fl(a),a;var n=J({},u,{"data-href":u.href,"data-precedence":u.precedence,href:null,precedence:null});return a=(l.ownerDocument||l).createElement("style"),fl(a),dl(a,"style",n),$n(a,u.precedence,l),t.instance=a;case"stylesheet":n=ua(u.href);var e=l.querySelector(mn(n));if(e)return t.state.loading|=4,t.instance=e,fl(e),e;a=mm(u),(n=Kl.get(n))&&Di(a,n),e=(l.ownerDocument||l).createElement("link"),fl(e);var f=e;return f._p=new Promise(function(c,i){f.onload=c,f.onerror=i}),dl(e,"link",a),t.state.loading|=4,$n(e,u.precedence,l),t.instance=e;case"script":return e=va(u.src),(n=l.querySelector(dn(e)))?(t.instance=n,fl(n),n):(a=u,(n=Kl.get(e))&&(a=J({},u),Ui(a,n)),l=l.ownerDocument||l,n=l.createElement("script"),fl(n),dl(n,"link",a),l.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(b(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,$n(a,u.precedence,l));return t.instance}function $n(l,t,u){for(var a=u.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,e=n,f=0;f title"):null)}function bs(l,t,u){if(u===1||t.itemProp!=null)return!1;switch(l){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function dm(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function zs(l,t,u,a){if(u.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(u.state.loading&4)===0){if(u.instance===null){var n=ua(a.href),e=t.querySelector(mn(n));if(e){t=e._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=_e.bind(l),t.then(l,l)),u.state.loading|=4,u.instance=e,fl(e);return}e=t.ownerDocument||t,a=mm(a),(n=Kl.get(n))&&Di(a,n),e=e.createElement("link"),fl(e);var f=e;f._p=new Promise(function(c,i){f.onload=c,f.onerror=i}),dl(e,"link",a),u.instance=e}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(u,t),(t=u.state.preload)&&(u.state.loading&3)===0&&(l.count++,u=_e.bind(l),t.addEventListener("load",u),t.addEventListener("error",u))}}var Zf=0;function Es(l,t){return l.stylesheets&&l.count===0&&kn(l,l.stylesheets),0Zf?50:800)+t);return l.unsuspend=u,function(){l.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function _e(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)kn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Me=null;function kn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Me=new Map,t.forEach(Ts,l),Me=null,_e.call(l))}function Ts(l,t){if(!(t.state.loading&4)){var u=Me.get(l);if(u)var a=u.get(null);else{u=new Map,Me.set(l,u);for(var n=l.querySelectorAll("link[data-precedence],style[data-precedence]"),e=0;e{"use strict";function Tm(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(Tm)}catch(l){console.error(l)}}Tm(),Am.exports=Em()});var Um=$l(Ke=>{"use strict";var ps=Symbol.for("react.transitional.element"),Hs=Symbol.for("react.fragment");function Dm(l,t,u){var a=null;if(u!==void 0&&(a=""+u),t.key!==void 0&&(a=""+t.key),"key"in t){u={};for(var n in t)n!=="key"&&(u[n]=t[n])}else u=t;return t=u.ref,{$$typeof:ps,type:l,key:a,ref:t!==void 0?t:null,props:u}}Ke.Fragment=Hs;Ke.jsx=Dm;Ke.jsxs=Dm});var Ri=$l((Ks,Nm)=>{"use strict";Nm.exports=Um()});var bu=hn(on()),Hm=hn(Om());var _m;function Mm(){return _m??(_m=acquireVsCodeApi()),_m}var gl=hn(Ri()),qs=Mm();function Rs({agent:l}){let[t,u]=(0,bu.useState)(!1);function a(n){u(!0),qs.postMessage({type:n,agentSlug:l.slug})}return(0,gl.jsxs)("div",{style:{padding:"6px 0",borderBottom:"1px solid var(--vscode-widget-border)"},children:[(0,gl.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,gl.jsx)("span",{style:{fontWeight:"bold"},children:l.slug}),(0,gl.jsx)("span",{className:"badge",style:{background:l.isRunning?"var(--vscode-testing-runAction)":"var(--vscode-badge-background)"},children:l.isRateLimited?"rate-limited":l.isRunning?"running":"idle"})]}),(0,gl.jsx)("div",{style:{marginTop:4,display:"flex",gap:4},children:l.isRunning?(0,gl.jsx)("button",{className:"secondary",disabled:t,onClick:()=>a("stop"),children:"Stop"}):(0,gl.jsx)("button",{disabled:t||l.isRateLimited,onClick:()=>a("run"),children:"Run"})})]})}function Bs(){let[l,t]=(0,bu.useState)("loading"),[u,a]=(0,bu.useState)([]),[n,e]=(0,bu.useState)("");return(0,bu.useEffect)(()=>{let f=c=>{let i=c.data;i.type==="loading"?t("loading"):i.type==="error"?(t("error"),e(i.message)):i.type==="agents"&&(a(i.data),t("ready"))};return window.addEventListener("message",f),()=>window.removeEventListener("message",f)},[]),l==="loading"?(0,gl.jsx)("p",{className:"muted",children:"Loading agents\u2026"}):l==="error"?(0,gl.jsx)("p",{className:"error",children:n}):u.length===0?(0,gl.jsx)("p",{className:"muted",children:"No agents found."}):(0,gl.jsx)("div",{children:u.map(f=>(0,gl.jsx)(Rs,{agent:f},f.slug))})}var pm=document.getElementById("root");pm&&(0,Hm.createRoot)(pm).render((0,gl.jsx)(Bs,{}));})(); +/*! Bundled license information: + +react/cjs/react.production.js: + (** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +scheduler/cjs/scheduler.production.js: + (** + * @license React + * scheduler.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +react-dom/cjs/react-dom.production.js: + (** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +react-dom/cjs/react-dom-client.production.js: + (** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +react/cjs/react-jsx-runtime.production.js: + (** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) +*/ +//# sourceMappingURL=main.js.map diff --git a/ai-dev-vscode/dist/webviews/agents/main.js.map b/ai-dev-vscode/dist/webviews/agents/main.js.map new file mode 100644 index 0000000..68150cd --- /dev/null +++ b/ai-dev-vscode/dist/webviews/agents/main.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../../node_modules/react/cjs/react.production.js", "../../../node_modules/react/index.js", "../../../node_modules/scheduler/cjs/scheduler.production.js", "../../../node_modules/scheduler/index.js", "../../../node_modules/react-dom/cjs/react-dom.production.js", "../../../node_modules/react-dom/index.js", "../../../node_modules/react-dom/cjs/react-dom-client.production.js", "../../../node_modules/react-dom/client.js", "../../../node_modules/react/cjs/react-jsx-runtime.production.js", "../../../node_modules/react/jsx-runtime.js", "../../../src/webviews/agents/main.tsx", "../../../src/webviews/shared/vscodeApi.ts"], + "sourcesContent": ["/**\n * @license React\n * react.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nfunction getIteratorFn(maybeIterable) {\n if (null === maybeIterable || \"object\" !== typeof maybeIterable) return null;\n maybeIterable =\n (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||\n maybeIterable[\"@@iterator\"];\n return \"function\" === typeof maybeIterable ? maybeIterable : null;\n}\nvar ReactNoopUpdateQueue = {\n isMounted: function () {\n return !1;\n },\n enqueueForceUpdate: function () {},\n enqueueReplaceState: function () {},\n enqueueSetState: function () {}\n },\n assign = Object.assign,\n emptyObject = {};\nfunction Component(props, context, updater) {\n this.props = props;\n this.context = context;\n this.refs = emptyObject;\n this.updater = updater || ReactNoopUpdateQueue;\n}\nComponent.prototype.isReactComponent = {};\nComponent.prototype.setState = function (partialState, callback) {\n if (\n \"object\" !== typeof partialState &&\n \"function\" !== typeof partialState &&\n null != partialState\n )\n throw Error(\n \"takes an object of state variables to update or a function which returns an object of state variables.\"\n );\n this.updater.enqueueSetState(this, partialState, callback, \"setState\");\n};\nComponent.prototype.forceUpdate = function (callback) {\n this.updater.enqueueForceUpdate(this, callback, \"forceUpdate\");\n};\nfunction ComponentDummy() {}\nComponentDummy.prototype = Component.prototype;\nfunction PureComponent(props, context, updater) {\n this.props = props;\n this.context = context;\n this.refs = emptyObject;\n this.updater = updater || ReactNoopUpdateQueue;\n}\nvar pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());\npureComponentPrototype.constructor = PureComponent;\nassign(pureComponentPrototype, Component.prototype);\npureComponentPrototype.isPureReactComponent = !0;\nvar isArrayImpl = Array.isArray;\nfunction noop() {}\nvar ReactSharedInternals = { H: null, A: null, T: null, S: null },\n hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction ReactElement(type, key, props) {\n var refProp = props.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== refProp ? refProp : null,\n props: props\n };\n}\nfunction cloneAndReplaceKey(oldElement, newKey) {\n return ReactElement(oldElement.type, newKey, oldElement.props);\n}\nfunction isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n}\nfunction escape(key) {\n var escaperLookup = { \"=\": \"=0\", \":\": \"=2\" };\n return (\n \"$\" +\n key.replace(/[=:]/g, function (match) {\n return escaperLookup[match];\n })\n );\n}\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction getElementKey(element, index) {\n return \"object\" === typeof element && null !== element && null != element.key\n ? escape(\"\" + element.key)\n : index.toString(36);\n}\nfunction resolveThenable(thenable) {\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw thenable.reason;\n default:\n switch (\n (\"string\" === typeof thenable.status\n ? thenable.then(noop, noop)\n : ((thenable.status = \"pending\"),\n thenable.then(\n function (fulfilledValue) {\n \"pending\" === thenable.status &&\n ((thenable.status = \"fulfilled\"),\n (thenable.value = fulfilledValue));\n },\n function (error) {\n \"pending\" === thenable.status &&\n ((thenable.status = \"rejected\"), (thenable.reason = error));\n }\n )),\n thenable.status)\n ) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw thenable.reason;\n }\n }\n throw thenable;\n}\nfunction mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) {\n var type = typeof children;\n if (\"undefined\" === type || \"boolean\" === type) children = null;\n var invokeCallback = !1;\n if (null === children) invokeCallback = !0;\n else\n switch (type) {\n case \"bigint\":\n case \"string\":\n case \"number\":\n invokeCallback = !0;\n break;\n case \"object\":\n switch (children.$$typeof) {\n case REACT_ELEMENT_TYPE:\n case REACT_PORTAL_TYPE:\n invokeCallback = !0;\n break;\n case REACT_LAZY_TYPE:\n return (\n (invokeCallback = children._init),\n mapIntoArray(\n invokeCallback(children._payload),\n array,\n escapedPrefix,\n nameSoFar,\n callback\n )\n );\n }\n }\n if (invokeCallback)\n return (\n (callback = callback(children)),\n (invokeCallback =\n \"\" === nameSoFar ? \".\" + getElementKey(children, 0) : nameSoFar),\n isArrayImpl(callback)\n ? ((escapedPrefix = \"\"),\n null != invokeCallback &&\n (escapedPrefix =\n invokeCallback.replace(userProvidedKeyEscapeRegex, \"$&/\") + \"/\"),\n mapIntoArray(callback, array, escapedPrefix, \"\", function (c) {\n return c;\n }))\n : null != callback &&\n (isValidElement(callback) &&\n (callback = cloneAndReplaceKey(\n callback,\n escapedPrefix +\n (null == callback.key ||\n (children && children.key === callback.key)\n ? \"\"\n : (\"\" + callback.key).replace(\n userProvidedKeyEscapeRegex,\n \"$&/\"\n ) + \"/\") +\n invokeCallback\n )),\n array.push(callback)),\n 1\n );\n invokeCallback = 0;\n var nextNamePrefix = \"\" === nameSoFar ? \".\" : nameSoFar + \":\";\n if (isArrayImpl(children))\n for (var i = 0; i < children.length; i++)\n (nameSoFar = children[i]),\n (type = nextNamePrefix + getElementKey(nameSoFar, i)),\n (invokeCallback += mapIntoArray(\n nameSoFar,\n array,\n escapedPrefix,\n type,\n callback\n ));\n else if (((i = getIteratorFn(children)), \"function\" === typeof i))\n for (\n children = i.call(children), i = 0;\n !(nameSoFar = children.next()).done;\n\n )\n (nameSoFar = nameSoFar.value),\n (type = nextNamePrefix + getElementKey(nameSoFar, i++)),\n (invokeCallback += mapIntoArray(\n nameSoFar,\n array,\n escapedPrefix,\n type,\n callback\n ));\n else if (\"object\" === type) {\n if (\"function\" === typeof children.then)\n return mapIntoArray(\n resolveThenable(children),\n array,\n escapedPrefix,\n nameSoFar,\n callback\n );\n array = String(children);\n throw Error(\n \"Objects are not valid as a React child (found: \" +\n (\"[object Object]\" === array\n ? \"object with keys {\" + Object.keys(children).join(\", \") + \"}\"\n : array) +\n \"). If you meant to render a collection of children, use an array instead.\"\n );\n }\n return invokeCallback;\n}\nfunction mapChildren(children, func, context) {\n if (null == children) return children;\n var result = [],\n count = 0;\n mapIntoArray(children, result, \"\", \"\", function (child) {\n return func.call(context, child, count++);\n });\n return result;\n}\nfunction lazyInitializer(payload) {\n if (-1 === payload._status) {\n var ctor = payload._result;\n ctor = ctor();\n ctor.then(\n function (moduleObject) {\n if (0 === payload._status || -1 === payload._status)\n (payload._status = 1), (payload._result = moduleObject);\n },\n function (error) {\n if (0 === payload._status || -1 === payload._status)\n (payload._status = 2), (payload._result = error);\n }\n );\n -1 === payload._status && ((payload._status = 0), (payload._result = ctor));\n }\n if (1 === payload._status) return payload._result.default;\n throw payload._result;\n}\nvar reportGlobalError =\n \"function\" === typeof reportError\n ? reportError\n : function (error) {\n if (\n \"object\" === typeof window &&\n \"function\" === typeof window.ErrorEvent\n ) {\n var event = new window.ErrorEvent(\"error\", {\n bubbles: !0,\n cancelable: !0,\n message:\n \"object\" === typeof error &&\n null !== error &&\n \"string\" === typeof error.message\n ? String(error.message)\n : String(error),\n error: error\n });\n if (!window.dispatchEvent(event)) return;\n } else if (\n \"object\" === typeof process &&\n \"function\" === typeof process.emit\n ) {\n process.emit(\"uncaughtException\", error);\n return;\n }\n console.error(error);\n },\n Children = {\n map: mapChildren,\n forEach: function (children, forEachFunc, forEachContext) {\n mapChildren(\n children,\n function () {\n forEachFunc.apply(this, arguments);\n },\n forEachContext\n );\n },\n count: function (children) {\n var n = 0;\n mapChildren(children, function () {\n n++;\n });\n return n;\n },\n toArray: function (children) {\n return (\n mapChildren(children, function (child) {\n return child;\n }) || []\n );\n },\n only: function (children) {\n if (!isValidElement(children))\n throw Error(\n \"React.Children.only expected to receive a single React element child.\"\n );\n return children;\n }\n };\nexports.Activity = REACT_ACTIVITY_TYPE;\nexports.Children = Children;\nexports.Component = Component;\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.Profiler = REACT_PROFILER_TYPE;\nexports.PureComponent = PureComponent;\nexports.StrictMode = REACT_STRICT_MODE_TYPE;\nexports.Suspense = REACT_SUSPENSE_TYPE;\nexports.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =\n ReactSharedInternals;\nexports.__COMPILER_RUNTIME = {\n __proto__: null,\n c: function (size) {\n return ReactSharedInternals.H.useMemoCache(size);\n }\n};\nexports.cache = function (fn) {\n return function () {\n return fn.apply(null, arguments);\n };\n};\nexports.cacheSignal = function () {\n return null;\n};\nexports.cloneElement = function (element, config, children) {\n if (null === element || void 0 === element)\n throw Error(\n \"The argument must be a React element, but you passed \" + element + \".\"\n );\n var props = assign({}, element.props),\n key = element.key;\n if (null != config)\n for (propName in (void 0 !== config.key && (key = \"\" + config.key), config))\n !hasOwnProperty.call(config, propName) ||\n \"key\" === propName ||\n \"__self\" === propName ||\n \"__source\" === propName ||\n (\"ref\" === propName && void 0 === config.ref) ||\n (props[propName] = config[propName]);\n var propName = arguments.length - 2;\n if (1 === propName) props.children = children;\n else if (1 < propName) {\n for (var childArray = Array(propName), i = 0; i < propName; i++)\n childArray[i] = arguments[i + 2];\n props.children = childArray;\n }\n return ReactElement(element.type, key, props);\n};\nexports.createContext = function (defaultValue) {\n defaultValue = {\n $$typeof: REACT_CONTEXT_TYPE,\n _currentValue: defaultValue,\n _currentValue2: defaultValue,\n _threadCount: 0,\n Provider: null,\n Consumer: null\n };\n defaultValue.Provider = defaultValue;\n defaultValue.Consumer = {\n $$typeof: REACT_CONSUMER_TYPE,\n _context: defaultValue\n };\n return defaultValue;\n};\nexports.createElement = function (type, config, children) {\n var propName,\n props = {},\n key = null;\n if (null != config)\n for (propName in (void 0 !== config.key && (key = \"\" + config.key), config))\n hasOwnProperty.call(config, propName) &&\n \"key\" !== propName &&\n \"__self\" !== propName &&\n \"__source\" !== propName &&\n (props[propName] = config[propName]);\n var childrenLength = arguments.length - 2;\n if (1 === childrenLength) props.children = children;\n else if (1 < childrenLength) {\n for (var childArray = Array(childrenLength), i = 0; i < childrenLength; i++)\n childArray[i] = arguments[i + 2];\n props.children = childArray;\n }\n if (type && type.defaultProps)\n for (propName in ((childrenLength = type.defaultProps), childrenLength))\n void 0 === props[propName] &&\n (props[propName] = childrenLength[propName]);\n return ReactElement(type, key, props);\n};\nexports.createRef = function () {\n return { current: null };\n};\nexports.forwardRef = function (render) {\n return { $$typeof: REACT_FORWARD_REF_TYPE, render: render };\n};\nexports.isValidElement = isValidElement;\nexports.lazy = function (ctor) {\n return {\n $$typeof: REACT_LAZY_TYPE,\n _payload: { _status: -1, _result: ctor },\n _init: lazyInitializer\n };\n};\nexports.memo = function (type, compare) {\n return {\n $$typeof: REACT_MEMO_TYPE,\n type: type,\n compare: void 0 === compare ? null : compare\n };\n};\nexports.startTransition = function (scope) {\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n try {\n var returnValue = scope(),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n \"object\" === typeof returnValue &&\n null !== returnValue &&\n \"function\" === typeof returnValue.then &&\n returnValue.then(noop, reportGlobalError);\n } catch (error) {\n reportGlobalError(error);\n } finally {\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n};\nexports.unstable_useCacheRefresh = function () {\n return ReactSharedInternals.H.useCacheRefresh();\n};\nexports.use = function (usable) {\n return ReactSharedInternals.H.use(usable);\n};\nexports.useActionState = function (action, initialState, permalink) {\n return ReactSharedInternals.H.useActionState(action, initialState, permalink);\n};\nexports.useCallback = function (callback, deps) {\n return ReactSharedInternals.H.useCallback(callback, deps);\n};\nexports.useContext = function (Context) {\n return ReactSharedInternals.H.useContext(Context);\n};\nexports.useDebugValue = function () {};\nexports.useDeferredValue = function (value, initialValue) {\n return ReactSharedInternals.H.useDeferredValue(value, initialValue);\n};\nexports.useEffect = function (create, deps) {\n return ReactSharedInternals.H.useEffect(create, deps);\n};\nexports.useEffectEvent = function (callback) {\n return ReactSharedInternals.H.useEffectEvent(callback);\n};\nexports.useId = function () {\n return ReactSharedInternals.H.useId();\n};\nexports.useImperativeHandle = function (ref, create, deps) {\n return ReactSharedInternals.H.useImperativeHandle(ref, create, deps);\n};\nexports.useInsertionEffect = function (create, deps) {\n return ReactSharedInternals.H.useInsertionEffect(create, deps);\n};\nexports.useLayoutEffect = function (create, deps) {\n return ReactSharedInternals.H.useLayoutEffect(create, deps);\n};\nexports.useMemo = function (create, deps) {\n return ReactSharedInternals.H.useMemo(create, deps);\n};\nexports.useOptimistic = function (passthrough, reducer) {\n return ReactSharedInternals.H.useOptimistic(passthrough, reducer);\n};\nexports.useReducer = function (reducer, initialArg, init) {\n return ReactSharedInternals.H.useReducer(reducer, initialArg, init);\n};\nexports.useRef = function (initialValue) {\n return ReactSharedInternals.H.useRef(initialValue);\n};\nexports.useState = function (initialState) {\n return ReactSharedInternals.H.useState(initialState);\n};\nexports.useSyncExternalStore = function (\n subscribe,\n getSnapshot,\n getServerSnapshot\n) {\n return ReactSharedInternals.H.useSyncExternalStore(\n subscribe,\n getSnapshot,\n getServerSnapshot\n );\n};\nexports.useTransition = function () {\n return ReactSharedInternals.H.useTransition();\n};\nexports.version = \"19.2.6\";\n", "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react.production.js');\n} else {\n module.exports = require('./cjs/react.development.js');\n}\n", "/**\n * @license React\n * scheduler.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nfunction push(heap, node) {\n var index = heap.length;\n heap.push(node);\n a: for (; 0 < index; ) {\n var parentIndex = (index - 1) >>> 1,\n parent = heap[parentIndex];\n if (0 < compare(parent, node))\n (heap[parentIndex] = node), (heap[index] = parent), (index = parentIndex);\n else break a;\n }\n}\nfunction peek(heap) {\n return 0 === heap.length ? null : heap[0];\n}\nfunction pop(heap) {\n if (0 === heap.length) return null;\n var first = heap[0],\n last = heap.pop();\n if (last !== first) {\n heap[0] = last;\n a: for (\n var index = 0, length = heap.length, halfLength = length >>> 1;\n index < halfLength;\n\n ) {\n var leftIndex = 2 * (index + 1) - 1,\n left = heap[leftIndex],\n rightIndex = leftIndex + 1,\n right = heap[rightIndex];\n if (0 > compare(left, last))\n rightIndex < length && 0 > compare(right, left)\n ? ((heap[index] = right),\n (heap[rightIndex] = last),\n (index = rightIndex))\n : ((heap[index] = left),\n (heap[leftIndex] = last),\n (index = leftIndex));\n else if (rightIndex < length && 0 > compare(right, last))\n (heap[index] = right), (heap[rightIndex] = last), (index = rightIndex);\n else break a;\n }\n }\n return first;\n}\nfunction compare(a, b) {\n var diff = a.sortIndex - b.sortIndex;\n return 0 !== diff ? diff : a.id - b.id;\n}\nexports.unstable_now = void 0;\nif (\"object\" === typeof performance && \"function\" === typeof performance.now) {\n var localPerformance = performance;\n exports.unstable_now = function () {\n return localPerformance.now();\n };\n} else {\n var localDate = Date,\n initialTime = localDate.now();\n exports.unstable_now = function () {\n return localDate.now() - initialTime;\n };\n}\nvar taskQueue = [],\n timerQueue = [],\n taskIdCounter = 1,\n currentTask = null,\n currentPriorityLevel = 3,\n isPerformingWork = !1,\n isHostCallbackScheduled = !1,\n isHostTimeoutScheduled = !1,\n needsPaint = !1,\n localSetTimeout = \"function\" === typeof setTimeout ? setTimeout : null,\n localClearTimeout = \"function\" === typeof clearTimeout ? clearTimeout : null,\n localSetImmediate = \"undefined\" !== typeof setImmediate ? setImmediate : null;\nfunction advanceTimers(currentTime) {\n for (var timer = peek(timerQueue); null !== timer; ) {\n if (null === timer.callback) pop(timerQueue);\n else if (timer.startTime <= currentTime)\n pop(timerQueue),\n (timer.sortIndex = timer.expirationTime),\n push(taskQueue, timer);\n else break;\n timer = peek(timerQueue);\n }\n}\nfunction handleTimeout(currentTime) {\n isHostTimeoutScheduled = !1;\n advanceTimers(currentTime);\n if (!isHostCallbackScheduled)\n if (null !== peek(taskQueue))\n (isHostCallbackScheduled = !0),\n isMessageLoopRunning ||\n ((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline());\n else {\n var firstTimer = peek(timerQueue);\n null !== firstTimer &&\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n }\n}\nvar isMessageLoopRunning = !1,\n taskTimeoutID = -1,\n frameInterval = 5,\n startTime = -1;\nfunction shouldYieldToHost() {\n return needsPaint\n ? !0\n : exports.unstable_now() - startTime < frameInterval\n ? !1\n : !0;\n}\nfunction performWorkUntilDeadline() {\n needsPaint = !1;\n if (isMessageLoopRunning) {\n var currentTime = exports.unstable_now();\n startTime = currentTime;\n var hasMoreWork = !0;\n try {\n a: {\n isHostCallbackScheduled = !1;\n isHostTimeoutScheduled &&\n ((isHostTimeoutScheduled = !1),\n localClearTimeout(taskTimeoutID),\n (taskTimeoutID = -1));\n isPerformingWork = !0;\n var previousPriorityLevel = currentPriorityLevel;\n try {\n b: {\n advanceTimers(currentTime);\n for (\n currentTask = peek(taskQueue);\n null !== currentTask &&\n !(\n currentTask.expirationTime > currentTime && shouldYieldToHost()\n );\n\n ) {\n var callback = currentTask.callback;\n if (\"function\" === typeof callback) {\n currentTask.callback = null;\n currentPriorityLevel = currentTask.priorityLevel;\n var continuationCallback = callback(\n currentTask.expirationTime <= currentTime\n );\n currentTime = exports.unstable_now();\n if (\"function\" === typeof continuationCallback) {\n currentTask.callback = continuationCallback;\n advanceTimers(currentTime);\n hasMoreWork = !0;\n break b;\n }\n currentTask === peek(taskQueue) && pop(taskQueue);\n advanceTimers(currentTime);\n } else pop(taskQueue);\n currentTask = peek(taskQueue);\n }\n if (null !== currentTask) hasMoreWork = !0;\n else {\n var firstTimer = peek(timerQueue);\n null !== firstTimer &&\n requestHostTimeout(\n handleTimeout,\n firstTimer.startTime - currentTime\n );\n hasMoreWork = !1;\n }\n }\n break a;\n } finally {\n (currentTask = null),\n (currentPriorityLevel = previousPriorityLevel),\n (isPerformingWork = !1);\n }\n hasMoreWork = void 0;\n }\n } finally {\n hasMoreWork\n ? schedulePerformWorkUntilDeadline()\n : (isMessageLoopRunning = !1);\n }\n }\n}\nvar schedulePerformWorkUntilDeadline;\nif (\"function\" === typeof localSetImmediate)\n schedulePerformWorkUntilDeadline = function () {\n localSetImmediate(performWorkUntilDeadline);\n };\nelse if (\"undefined\" !== typeof MessageChannel) {\n var channel = new MessageChannel(),\n port = channel.port2;\n channel.port1.onmessage = performWorkUntilDeadline;\n schedulePerformWorkUntilDeadline = function () {\n port.postMessage(null);\n };\n} else\n schedulePerformWorkUntilDeadline = function () {\n localSetTimeout(performWorkUntilDeadline, 0);\n };\nfunction requestHostTimeout(callback, ms) {\n taskTimeoutID = localSetTimeout(function () {\n callback(exports.unstable_now());\n }, ms);\n}\nexports.unstable_IdlePriority = 5;\nexports.unstable_ImmediatePriority = 1;\nexports.unstable_LowPriority = 4;\nexports.unstable_NormalPriority = 3;\nexports.unstable_Profiling = null;\nexports.unstable_UserBlockingPriority = 2;\nexports.unstable_cancelCallback = function (task) {\n task.callback = null;\n};\nexports.unstable_forceFrameRate = function (fps) {\n 0 > fps || 125 < fps\n ? console.error(\n \"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported\"\n )\n : (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);\n};\nexports.unstable_getCurrentPriorityLevel = function () {\n return currentPriorityLevel;\n};\nexports.unstable_next = function (eventHandler) {\n switch (currentPriorityLevel) {\n case 1:\n case 2:\n case 3:\n var priorityLevel = 3;\n break;\n default:\n priorityLevel = currentPriorityLevel;\n }\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n};\nexports.unstable_requestPaint = function () {\n needsPaint = !0;\n};\nexports.unstable_runWithPriority = function (priorityLevel, eventHandler) {\n switch (priorityLevel) {\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n break;\n default:\n priorityLevel = 3;\n }\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n};\nexports.unstable_scheduleCallback = function (\n priorityLevel,\n callback,\n options\n) {\n var currentTime = exports.unstable_now();\n \"object\" === typeof options && null !== options\n ? ((options = options.delay),\n (options =\n \"number\" === typeof options && 0 < options\n ? currentTime + options\n : currentTime))\n : (options = currentTime);\n switch (priorityLevel) {\n case 1:\n var timeout = -1;\n break;\n case 2:\n timeout = 250;\n break;\n case 5:\n timeout = 1073741823;\n break;\n case 4:\n timeout = 1e4;\n break;\n default:\n timeout = 5e3;\n }\n timeout = options + timeout;\n priorityLevel = {\n id: taskIdCounter++,\n callback: callback,\n priorityLevel: priorityLevel,\n startTime: options,\n expirationTime: timeout,\n sortIndex: -1\n };\n options > currentTime\n ? ((priorityLevel.sortIndex = options),\n push(timerQueue, priorityLevel),\n null === peek(taskQueue) &&\n priorityLevel === peek(timerQueue) &&\n (isHostTimeoutScheduled\n ? (localClearTimeout(taskTimeoutID), (taskTimeoutID = -1))\n : (isHostTimeoutScheduled = !0),\n requestHostTimeout(handleTimeout, options - currentTime)))\n : ((priorityLevel.sortIndex = timeout),\n push(taskQueue, priorityLevel),\n isHostCallbackScheduled ||\n isPerformingWork ||\n ((isHostCallbackScheduled = !0),\n isMessageLoopRunning ||\n ((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline())));\n return priorityLevel;\n};\nexports.unstable_shouldYield = shouldYieldToHost;\nexports.unstable_wrapCallback = function (callback) {\n var parentPriorityLevel = currentPriorityLevel;\n return function () {\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = parentPriorityLevel;\n try {\n return callback.apply(this, arguments);\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n };\n};\n", "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n", "/**\n * @license React\n * react-dom.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar React = require(\"react\");\nfunction formatProdErrorMessage(code) {\n var url = \"https://react.dev/errors/\" + code;\n if (1 < arguments.length) {\n url += \"?args[]=\" + encodeURIComponent(arguments[1]);\n for (var i = 2; i < arguments.length; i++)\n url += \"&args[]=\" + encodeURIComponent(arguments[i]);\n }\n return (\n \"Minified React error #\" +\n code +\n \"; visit \" +\n url +\n \" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"\n );\n}\nfunction noop() {}\nvar Internals = {\n d: {\n f: noop,\n r: function () {\n throw Error(formatProdErrorMessage(522));\n },\n D: noop,\n C: noop,\n L: noop,\n m: noop,\n X: noop,\n S: noop,\n M: noop\n },\n p: 0,\n findDOMNode: null\n },\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\");\nfunction createPortal$1(children, containerInfo, implementation) {\n var key =\n 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;\n return {\n $$typeof: REACT_PORTAL_TYPE,\n key: null == key ? null : \"\" + key,\n children: children,\n containerInfo: containerInfo,\n implementation: implementation\n };\n}\nvar ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\nfunction getCrossOriginStringAs(as, input) {\n if (\"font\" === as) return \"\";\n if (\"string\" === typeof input)\n return \"use-credentials\" === input ? input : \"\";\n}\nexports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =\n Internals;\nexports.createPortal = function (children, container) {\n var key =\n 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;\n if (\n !container ||\n (1 !== container.nodeType &&\n 9 !== container.nodeType &&\n 11 !== container.nodeType)\n )\n throw Error(formatProdErrorMessage(299));\n return createPortal$1(children, container, null, key);\n};\nexports.flushSync = function (fn) {\n var previousTransition = ReactSharedInternals.T,\n previousUpdatePriority = Internals.p;\n try {\n if (((ReactSharedInternals.T = null), (Internals.p = 2), fn)) return fn();\n } finally {\n (ReactSharedInternals.T = previousTransition),\n (Internals.p = previousUpdatePriority),\n Internals.d.f();\n }\n};\nexports.preconnect = function (href, options) {\n \"string\" === typeof href &&\n (options\n ? ((options = options.crossOrigin),\n (options =\n \"string\" === typeof options\n ? \"use-credentials\" === options\n ? options\n : \"\"\n : void 0))\n : (options = null),\n Internals.d.C(href, options));\n};\nexports.prefetchDNS = function (href) {\n \"string\" === typeof href && Internals.d.D(href);\n};\nexports.preinit = function (href, options) {\n if (\"string\" === typeof href && options && \"string\" === typeof options.as) {\n var as = options.as,\n crossOrigin = getCrossOriginStringAs(as, options.crossOrigin),\n integrity =\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n fetchPriority =\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0;\n \"style\" === as\n ? Internals.d.S(\n href,\n \"string\" === typeof options.precedence ? options.precedence : void 0,\n {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority\n }\n )\n : \"script\" === as &&\n Internals.d.X(href, {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n }\n};\nexports.preinitModule = function (href, options) {\n if (\"string\" === typeof href)\n if (\"object\" === typeof options && null !== options) {\n if (null == options.as || \"script\" === options.as) {\n var crossOrigin = getCrossOriginStringAs(\n options.as,\n options.crossOrigin\n );\n Internals.d.M(href, {\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n }\n } else null == options && Internals.d.M(href);\n};\nexports.preload = function (href, options) {\n if (\n \"string\" === typeof href &&\n \"object\" === typeof options &&\n null !== options &&\n \"string\" === typeof options.as\n ) {\n var as = options.as,\n crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);\n Internals.d.L(href, as, {\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0,\n type: \"string\" === typeof options.type ? options.type : void 0,\n fetchPriority:\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0,\n referrerPolicy:\n \"string\" === typeof options.referrerPolicy\n ? options.referrerPolicy\n : void 0,\n imageSrcSet:\n \"string\" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,\n imageSizes:\n \"string\" === typeof options.imageSizes ? options.imageSizes : void 0,\n media: \"string\" === typeof options.media ? options.media : void 0\n });\n }\n};\nexports.preloadModule = function (href, options) {\n if (\"string\" === typeof href)\n if (options) {\n var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin);\n Internals.d.m(href, {\n as:\n \"string\" === typeof options.as && \"script\" !== options.as\n ? options.as\n : void 0,\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0\n });\n } else Internals.d.m(href);\n};\nexports.requestFormReset = function (form) {\n Internals.d.r(form);\n};\nexports.unstable_batchedUpdates = function (fn, a) {\n return fn(a);\n};\nexports.useFormState = function (action, initialState, permalink) {\n return ReactSharedInternals.H.useFormState(action, initialState, permalink);\n};\nexports.useFormStatus = function () {\n return ReactSharedInternals.H.useHostTransitionStatus();\n};\nexports.version = \"19.2.6\";\n", "'use strict';\n\nfunction checkDCE() {\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n if (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n ) {\n return;\n }\n if (process.env.NODE_ENV !== 'production') {\n // This branch is unreachable because this function is only called\n // in production, but the condition is true only in development.\n // Therefore if the branch is still here, dead code elimination wasn't\n // properly applied.\n // Don't change the message. React DevTools relies on it. Also make sure\n // this message doesn't occur elsewhere in this function, or it will cause\n // a false positive.\n throw new Error('^_^');\n }\n try {\n // Verify that the code above has been dead code eliminated (DCE'd).\n __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n } catch (err) {\n // DevTools shouldn't crash React, no matter what.\n // We should still report in case we break this code.\n console.error(err);\n }\n}\n\nif (process.env.NODE_ENV === 'production') {\n // DCE check should happen before ReactDOM bundle executes so that\n // DevTools can report bad minification during injection.\n checkDCE();\n module.exports = require('./cjs/react-dom.production.js');\n} else {\n module.exports = require('./cjs/react-dom.development.js');\n}\n", "/**\n * @license React\n * react-dom-client.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*\n Modernizr 3.0.0pre (Custom Build) | MIT\n*/\n\"use strict\";\nvar Scheduler = require(\"scheduler\"),\n React = require(\"react\"),\n ReactDOM = require(\"react-dom\");\nfunction formatProdErrorMessage(code) {\n var url = \"https://react.dev/errors/\" + code;\n if (1 < arguments.length) {\n url += \"?args[]=\" + encodeURIComponent(arguments[1]);\n for (var i = 2; i < arguments.length; i++)\n url += \"&args[]=\" + encodeURIComponent(arguments[i]);\n }\n return (\n \"Minified React error #\" +\n code +\n \"; visit \" +\n url +\n \" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"\n );\n}\nfunction isValidContainer(node) {\n return !(\n !node ||\n (1 !== node.nodeType && 9 !== node.nodeType && 11 !== node.nodeType)\n );\n}\nfunction getNearestMountedFiber(fiber) {\n var node = fiber,\n nearestMounted = fiber;\n if (fiber.alternate) for (; node.return; ) node = node.return;\n else {\n fiber = node;\n do\n (node = fiber),\n 0 !== (node.flags & 4098) && (nearestMounted = node.return),\n (fiber = node.return);\n while (fiber);\n }\n return 3 === node.tag ? nearestMounted : null;\n}\nfunction getSuspenseInstanceFromFiber(fiber) {\n if (13 === fiber.tag) {\n var suspenseState = fiber.memoizedState;\n null === suspenseState &&\n ((fiber = fiber.alternate),\n null !== fiber && (suspenseState = fiber.memoizedState));\n if (null !== suspenseState) return suspenseState.dehydrated;\n }\n return null;\n}\nfunction getActivityInstanceFromFiber(fiber) {\n if (31 === fiber.tag) {\n var activityState = fiber.memoizedState;\n null === activityState &&\n ((fiber = fiber.alternate),\n null !== fiber && (activityState = fiber.memoizedState));\n if (null !== activityState) return activityState.dehydrated;\n }\n return null;\n}\nfunction assertIsMounted(fiber) {\n if (getNearestMountedFiber(fiber) !== fiber)\n throw Error(formatProdErrorMessage(188));\n}\nfunction findCurrentFiberUsingSlowPath(fiber) {\n var alternate = fiber.alternate;\n if (!alternate) {\n alternate = getNearestMountedFiber(fiber);\n if (null === alternate) throw Error(formatProdErrorMessage(188));\n return alternate !== fiber ? null : fiber;\n }\n for (var a = fiber, b = alternate; ; ) {\n var parentA = a.return;\n if (null === parentA) break;\n var parentB = parentA.alternate;\n if (null === parentB) {\n b = parentA.return;\n if (null !== b) {\n a = b;\n continue;\n }\n break;\n }\n if (parentA.child === parentB.child) {\n for (parentB = parentA.child; parentB; ) {\n if (parentB === a) return assertIsMounted(parentA), fiber;\n if (parentB === b) return assertIsMounted(parentA), alternate;\n parentB = parentB.sibling;\n }\n throw Error(formatProdErrorMessage(188));\n }\n if (a.return !== b.return) (a = parentA), (b = parentB);\n else {\n for (var didFindChild = !1, child$0 = parentA.child; child$0; ) {\n if (child$0 === a) {\n didFindChild = !0;\n a = parentA;\n b = parentB;\n break;\n }\n if (child$0 === b) {\n didFindChild = !0;\n b = parentA;\n a = parentB;\n break;\n }\n child$0 = child$0.sibling;\n }\n if (!didFindChild) {\n for (child$0 = parentB.child; child$0; ) {\n if (child$0 === a) {\n didFindChild = !0;\n a = parentB;\n b = parentA;\n break;\n }\n if (child$0 === b) {\n didFindChild = !0;\n b = parentB;\n a = parentA;\n break;\n }\n child$0 = child$0.sibling;\n }\n if (!didFindChild) throw Error(formatProdErrorMessage(189));\n }\n }\n if (a.alternate !== b) throw Error(formatProdErrorMessage(190));\n }\n if (3 !== a.tag) throw Error(formatProdErrorMessage(188));\n return a.stateNode.current === a ? fiber : alternate;\n}\nfunction findCurrentHostFiberImpl(node) {\n var tag = node.tag;\n if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return node;\n for (node = node.child; null !== node; ) {\n tag = findCurrentHostFiberImpl(node);\n if (null !== tag) return tag;\n node = node.sibling;\n }\n return null;\n}\nvar assign = Object.assign,\n REACT_LEGACY_ELEMENT_TYPE = Symbol.for(\"react.element\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\");\nSymbol.for(\"react.scope\");\nvar REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\");\nSymbol.for(\"react.legacy_hidden\");\nSymbol.for(\"react.tracing_marker\");\nvar REACT_MEMO_CACHE_SENTINEL = Symbol.for(\"react.memo_cache_sentinel\");\nSymbol.for(\"react.view_transition\");\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nfunction getIteratorFn(maybeIterable) {\n if (null === maybeIterable || \"object\" !== typeof maybeIterable) return null;\n maybeIterable =\n (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||\n maybeIterable[\"@@iterator\"];\n return \"function\" === typeof maybeIterable ? maybeIterable : null;\n}\nvar REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\");\nfunction getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (type.$$typeof) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n}\nvar isArrayImpl = Array.isArray,\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n ReactDOMSharedInternals =\n ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n sharedNotPendingObject = {\n pending: !1,\n data: null,\n method: null,\n action: null\n },\n valueStack = [],\n index = -1;\nfunction createCursor(defaultValue) {\n return { current: defaultValue };\n}\nfunction pop(cursor) {\n 0 > index ||\n ((cursor.current = valueStack[index]), (valueStack[index] = null), index--);\n}\nfunction push(cursor, value) {\n index++;\n valueStack[index] = cursor.current;\n cursor.current = value;\n}\nvar contextStackCursor = createCursor(null),\n contextFiberStackCursor = createCursor(null),\n rootInstanceStackCursor = createCursor(null),\n hostTransitionProviderCursor = createCursor(null);\nfunction pushHostContainer(fiber, nextRootInstance) {\n push(rootInstanceStackCursor, nextRootInstance);\n push(contextFiberStackCursor, fiber);\n push(contextStackCursor, null);\n switch (nextRootInstance.nodeType) {\n case 9:\n case 11:\n fiber = (fiber = nextRootInstance.documentElement)\n ? (fiber = fiber.namespaceURI)\n ? getOwnHostContext(fiber)\n : 0\n : 0;\n break;\n default:\n if (\n ((fiber = nextRootInstance.tagName),\n (nextRootInstance = nextRootInstance.namespaceURI))\n )\n (nextRootInstance = getOwnHostContext(nextRootInstance)),\n (fiber = getChildHostContextProd(nextRootInstance, fiber));\n else\n switch (fiber) {\n case \"svg\":\n fiber = 1;\n break;\n case \"math\":\n fiber = 2;\n break;\n default:\n fiber = 0;\n }\n }\n pop(contextStackCursor);\n push(contextStackCursor, fiber);\n}\nfunction popHostContainer() {\n pop(contextStackCursor);\n pop(contextFiberStackCursor);\n pop(rootInstanceStackCursor);\n}\nfunction pushHostContext(fiber) {\n null !== fiber.memoizedState && push(hostTransitionProviderCursor, fiber);\n var context = contextStackCursor.current;\n var JSCompiler_inline_result = getChildHostContextProd(context, fiber.type);\n context !== JSCompiler_inline_result &&\n (push(contextFiberStackCursor, fiber),\n push(contextStackCursor, JSCompiler_inline_result));\n}\nfunction popHostContext(fiber) {\n contextFiberStackCursor.current === fiber &&\n (pop(contextStackCursor), pop(contextFiberStackCursor));\n hostTransitionProviderCursor.current === fiber &&\n (pop(hostTransitionProviderCursor),\n (HostTransitionContext._currentValue = sharedNotPendingObject));\n}\nvar prefix, suffix;\nfunction describeBuiltInComponentFrame(name) {\n if (void 0 === prefix)\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = (match && match[1]) || \"\";\n suffix =\n -1 < x.stack.indexOf(\"\\n at\")\n ? \" ()\"\n : -1 < x.stack.indexOf(\"@\")\n ? \"@unknown:0:0\"\n : \"\";\n }\n return \"\\n\" + prefix + name + suffix;\n}\nvar reentry = !1;\nfunction describeNativeComponentFrame(fn, construct) {\n if (!fn || reentry) return \"\";\n reentry = !0;\n var previousPrepareStackTrace = Error.prepareStackTrace;\n Error.prepareStackTrace = void 0;\n try {\n var RunInRootFrame = {\n DetermineComponentFrameRoot: function () {\n try {\n if (construct) {\n var Fake = function () {\n throw Error();\n };\n Object.defineProperty(Fake.prototype, \"props\", {\n set: function () {\n throw Error();\n }\n });\n if (\"object\" === typeof Reflect && Reflect.construct) {\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n var control = x;\n }\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x$1) {\n control = x$1;\n }\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x$2) {\n control = x$2;\n }\n (Fake = fn()) &&\n \"function\" === typeof Fake.catch &&\n Fake.catch(function () {});\n }\n } catch (sample) {\n if (sample && control && \"string\" === typeof sample.stack)\n return [sample.stack, control.stack];\n }\n return [null, null];\n }\n };\n RunInRootFrame.DetermineComponentFrameRoot.displayName =\n \"DetermineComponentFrameRoot\";\n var namePropDescriptor = Object.getOwnPropertyDescriptor(\n RunInRootFrame.DetermineComponentFrameRoot,\n \"name\"\n );\n namePropDescriptor &&\n namePropDescriptor.configurable &&\n Object.defineProperty(\n RunInRootFrame.DetermineComponentFrameRoot,\n \"name\",\n { value: \"DetermineComponentFrameRoot\" }\n );\n var _RunInRootFrame$Deter = RunInRootFrame.DetermineComponentFrameRoot(),\n sampleStack = _RunInRootFrame$Deter[0],\n controlStack = _RunInRootFrame$Deter[1];\n if (sampleStack && controlStack) {\n var sampleLines = sampleStack.split(\"\\n\"),\n controlLines = controlStack.split(\"\\n\");\n for (\n namePropDescriptor = RunInRootFrame = 0;\n RunInRootFrame < sampleLines.length &&\n !sampleLines[RunInRootFrame].includes(\"DetermineComponentFrameRoot\");\n\n )\n RunInRootFrame++;\n for (\n ;\n namePropDescriptor < controlLines.length &&\n !controlLines[namePropDescriptor].includes(\n \"DetermineComponentFrameRoot\"\n );\n\n )\n namePropDescriptor++;\n if (\n RunInRootFrame === sampleLines.length ||\n namePropDescriptor === controlLines.length\n )\n for (\n RunInRootFrame = sampleLines.length - 1,\n namePropDescriptor = controlLines.length - 1;\n 1 <= RunInRootFrame &&\n 0 <= namePropDescriptor &&\n sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor];\n\n )\n namePropDescriptor--;\n for (\n ;\n 1 <= RunInRootFrame && 0 <= namePropDescriptor;\n RunInRootFrame--, namePropDescriptor--\n )\n if (sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor]) {\n if (1 !== RunInRootFrame || 1 !== namePropDescriptor) {\n do\n if (\n (RunInRootFrame--,\n namePropDescriptor--,\n 0 > namePropDescriptor ||\n sampleLines[RunInRootFrame] !==\n controlLines[namePropDescriptor])\n ) {\n var frame =\n \"\\n\" +\n sampleLines[RunInRootFrame].replace(\" at new \", \" at \");\n fn.displayName &&\n frame.includes(\"\") &&\n (frame = frame.replace(\"\", fn.displayName));\n return frame;\n }\n while (1 <= RunInRootFrame && 0 <= namePropDescriptor);\n }\n break;\n }\n }\n } finally {\n (reentry = !1), (Error.prepareStackTrace = previousPrepareStackTrace);\n }\n return (previousPrepareStackTrace = fn ? fn.displayName || fn.name : \"\")\n ? describeBuiltInComponentFrame(previousPrepareStackTrace)\n : \"\";\n}\nfunction describeFiber(fiber, childFiber) {\n switch (fiber.tag) {\n case 26:\n case 27:\n case 5:\n return describeBuiltInComponentFrame(fiber.type);\n case 16:\n return describeBuiltInComponentFrame(\"Lazy\");\n case 13:\n return fiber.child !== childFiber && null !== childFiber\n ? describeBuiltInComponentFrame(\"Suspense Fallback\")\n : describeBuiltInComponentFrame(\"Suspense\");\n case 19:\n return describeBuiltInComponentFrame(\"SuspenseList\");\n case 0:\n case 15:\n return describeNativeComponentFrame(fiber.type, !1);\n case 11:\n return describeNativeComponentFrame(fiber.type.render, !1);\n case 1:\n return describeNativeComponentFrame(fiber.type, !0);\n case 31:\n return describeBuiltInComponentFrame(\"Activity\");\n default:\n return \"\";\n }\n}\nfunction getStackByFiberInDevAndProd(workInProgress) {\n try {\n var info = \"\",\n previous = null;\n do\n (info += describeFiber(workInProgress, previous)),\n (previous = workInProgress),\n (workInProgress = workInProgress.return);\n while (workInProgress);\n return info;\n } catch (x) {\n return \"\\nError generating stack: \" + x.message + \"\\n\" + x.stack;\n }\n}\nvar hasOwnProperty = Object.prototype.hasOwnProperty,\n scheduleCallback$3 = Scheduler.unstable_scheduleCallback,\n cancelCallback$1 = Scheduler.unstable_cancelCallback,\n shouldYield = Scheduler.unstable_shouldYield,\n requestPaint = Scheduler.unstable_requestPaint,\n now = Scheduler.unstable_now,\n getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel,\n ImmediatePriority = Scheduler.unstable_ImmediatePriority,\n UserBlockingPriority = Scheduler.unstable_UserBlockingPriority,\n NormalPriority$1 = Scheduler.unstable_NormalPriority,\n LowPriority = Scheduler.unstable_LowPriority,\n IdlePriority = Scheduler.unstable_IdlePriority,\n log$1 = Scheduler.log,\n unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue,\n rendererID = null,\n injectedHook = null;\nfunction setIsStrictModeForDevtools(newIsStrictMode) {\n \"function\" === typeof log$1 && unstable_setDisableYieldValue(newIsStrictMode);\n if (injectedHook && \"function\" === typeof injectedHook.setStrictMode)\n try {\n injectedHook.setStrictMode(rendererID, newIsStrictMode);\n } catch (err) {}\n}\nvar clz32 = Math.clz32 ? Math.clz32 : clz32Fallback,\n log = Math.log,\n LN2 = Math.LN2;\nfunction clz32Fallback(x) {\n x >>>= 0;\n return 0 === x ? 32 : (31 - ((log(x) / LN2) | 0)) | 0;\n}\nvar nextTransitionUpdateLane = 256,\n nextTransitionDeferredLane = 262144,\n nextRetryLane = 4194304;\nfunction getHighestPriorityLanes(lanes) {\n var pendingSyncLanes = lanes & 42;\n if (0 !== pendingSyncLanes) return pendingSyncLanes;\n switch (lanes & -lanes) {\n case 1:\n return 1;\n case 2:\n return 2;\n case 4:\n return 4;\n case 8:\n return 8;\n case 16:\n return 16;\n case 32:\n return 32;\n case 64:\n return 64;\n case 128:\n return 128;\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n return lanes & 261888;\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n return lanes & 3932160;\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n return lanes & 62914560;\n case 67108864:\n return 67108864;\n case 134217728:\n return 134217728;\n case 268435456:\n return 268435456;\n case 536870912:\n return 536870912;\n case 1073741824:\n return 0;\n default:\n return lanes;\n }\n}\nfunction getNextLanes(root, wipLanes, rootHasPendingCommit) {\n var pendingLanes = root.pendingLanes;\n if (0 === pendingLanes) return 0;\n var nextLanes = 0,\n suspendedLanes = root.suspendedLanes,\n pingedLanes = root.pingedLanes;\n root = root.warmLanes;\n var nonIdlePendingLanes = pendingLanes & 134217727;\n 0 !== nonIdlePendingLanes\n ? ((pendingLanes = nonIdlePendingLanes & ~suspendedLanes),\n 0 !== pendingLanes\n ? (nextLanes = getHighestPriorityLanes(pendingLanes))\n : ((pingedLanes &= nonIdlePendingLanes),\n 0 !== pingedLanes\n ? (nextLanes = getHighestPriorityLanes(pingedLanes))\n : rootHasPendingCommit ||\n ((rootHasPendingCommit = nonIdlePendingLanes & ~root),\n 0 !== rootHasPendingCommit &&\n (nextLanes = getHighestPriorityLanes(rootHasPendingCommit)))))\n : ((nonIdlePendingLanes = pendingLanes & ~suspendedLanes),\n 0 !== nonIdlePendingLanes\n ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes))\n : 0 !== pingedLanes\n ? (nextLanes = getHighestPriorityLanes(pingedLanes))\n : rootHasPendingCommit ||\n ((rootHasPendingCommit = pendingLanes & ~root),\n 0 !== rootHasPendingCommit &&\n (nextLanes = getHighestPriorityLanes(rootHasPendingCommit))));\n return 0 === nextLanes\n ? 0\n : 0 !== wipLanes &&\n wipLanes !== nextLanes &&\n 0 === (wipLanes & suspendedLanes) &&\n ((suspendedLanes = nextLanes & -nextLanes),\n (rootHasPendingCommit = wipLanes & -wipLanes),\n suspendedLanes >= rootHasPendingCommit ||\n (32 === suspendedLanes && 0 !== (rootHasPendingCommit & 4194048)))\n ? wipLanes\n : nextLanes;\n}\nfunction checkIfRootIsPrerendering(root, renderLanes) {\n return (\n 0 ===\n (root.pendingLanes &\n ~(root.suspendedLanes & ~root.pingedLanes) &\n renderLanes)\n );\n}\nfunction computeExpirationTime(lane, currentTime) {\n switch (lane) {\n case 1:\n case 2:\n case 4:\n case 8:\n case 64:\n return currentTime + 250;\n case 16:\n case 32:\n case 128:\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n return currentTime + 5e3;\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n return -1;\n case 67108864:\n case 134217728:\n case 268435456:\n case 536870912:\n case 1073741824:\n return -1;\n default:\n return -1;\n }\n}\nfunction claimNextRetryLane() {\n var lane = nextRetryLane;\n nextRetryLane <<= 1;\n 0 === (nextRetryLane & 62914560) && (nextRetryLane = 4194304);\n return lane;\n}\nfunction createLaneMap(initial) {\n for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);\n return laneMap;\n}\nfunction markRootUpdated$1(root, updateLane) {\n root.pendingLanes |= updateLane;\n 268435456 !== updateLane &&\n ((root.suspendedLanes = 0), (root.pingedLanes = 0), (root.warmLanes = 0));\n}\nfunction markRootFinished(\n root,\n finishedLanes,\n remainingLanes,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes\n) {\n var previouslyPendingLanes = root.pendingLanes;\n root.pendingLanes = remainingLanes;\n root.suspendedLanes = 0;\n root.pingedLanes = 0;\n root.warmLanes = 0;\n root.expiredLanes &= remainingLanes;\n root.entangledLanes &= remainingLanes;\n root.errorRecoveryDisabledLanes &= remainingLanes;\n root.shellSuspendCounter = 0;\n var entanglements = root.entanglements,\n expirationTimes = root.expirationTimes,\n hiddenUpdates = root.hiddenUpdates;\n for (\n remainingLanes = previouslyPendingLanes & ~remainingLanes;\n 0 < remainingLanes;\n\n ) {\n var index$7 = 31 - clz32(remainingLanes),\n lane = 1 << index$7;\n entanglements[index$7] = 0;\n expirationTimes[index$7] = -1;\n var hiddenUpdatesForLane = hiddenUpdates[index$7];\n if (null !== hiddenUpdatesForLane)\n for (\n hiddenUpdates[index$7] = null, index$7 = 0;\n index$7 < hiddenUpdatesForLane.length;\n index$7++\n ) {\n var update = hiddenUpdatesForLane[index$7];\n null !== update && (update.lane &= -536870913);\n }\n remainingLanes &= ~lane;\n }\n 0 !== spawnedLane && markSpawnedDeferredLane(root, spawnedLane, 0);\n 0 !== suspendedRetryLanes &&\n 0 === updatedLanes &&\n 0 !== root.tag &&\n (root.suspendedLanes |=\n suspendedRetryLanes & ~(previouslyPendingLanes & ~finishedLanes));\n}\nfunction markSpawnedDeferredLane(root, spawnedLane, entangledLanes) {\n root.pendingLanes |= spawnedLane;\n root.suspendedLanes &= ~spawnedLane;\n var spawnedLaneIndex = 31 - clz32(spawnedLane);\n root.entangledLanes |= spawnedLane;\n root.entanglements[spawnedLaneIndex] =\n root.entanglements[spawnedLaneIndex] |\n 1073741824 |\n (entangledLanes & 261930);\n}\nfunction markRootEntangled(root, entangledLanes) {\n var rootEntangledLanes = (root.entangledLanes |= entangledLanes);\n for (root = root.entanglements; rootEntangledLanes; ) {\n var index$8 = 31 - clz32(rootEntangledLanes),\n lane = 1 << index$8;\n (lane & entangledLanes) | (root[index$8] & entangledLanes) &&\n (root[index$8] |= entangledLanes);\n rootEntangledLanes &= ~lane;\n }\n}\nfunction getBumpedLaneForHydration(root, renderLanes) {\n var renderLane = renderLanes & -renderLanes;\n renderLane =\n 0 !== (renderLane & 42) ? 1 : getBumpedLaneForHydrationByLane(renderLane);\n return 0 !== (renderLane & (root.suspendedLanes | renderLanes))\n ? 0\n : renderLane;\n}\nfunction getBumpedLaneForHydrationByLane(lane) {\n switch (lane) {\n case 2:\n lane = 1;\n break;\n case 8:\n lane = 4;\n break;\n case 32:\n lane = 16;\n break;\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n lane = 128;\n break;\n case 268435456:\n lane = 134217728;\n break;\n default:\n lane = 0;\n }\n return lane;\n}\nfunction lanesToEventPriority(lanes) {\n lanes &= -lanes;\n return 2 < lanes\n ? 8 < lanes\n ? 0 !== (lanes & 134217727)\n ? 32\n : 268435456\n : 8\n : 2;\n}\nfunction resolveUpdatePriority() {\n var updatePriority = ReactDOMSharedInternals.p;\n if (0 !== updatePriority) return updatePriority;\n updatePriority = window.event;\n return void 0 === updatePriority ? 32 : getEventPriority(updatePriority.type);\n}\nfunction runWithPriority(priority, fn) {\n var previousPriority = ReactDOMSharedInternals.p;\n try {\n return (ReactDOMSharedInternals.p = priority), fn();\n } finally {\n ReactDOMSharedInternals.p = previousPriority;\n }\n}\nvar randomKey = Math.random().toString(36).slice(2),\n internalInstanceKey = \"__reactFiber$\" + randomKey,\n internalPropsKey = \"__reactProps$\" + randomKey,\n internalContainerInstanceKey = \"__reactContainer$\" + randomKey,\n internalEventHandlersKey = \"__reactEvents$\" + randomKey,\n internalEventHandlerListenersKey = \"__reactListeners$\" + randomKey,\n internalEventHandlesSetKey = \"__reactHandles$\" + randomKey,\n internalRootNodeResourcesKey = \"__reactResources$\" + randomKey,\n internalHoistableMarker = \"__reactMarker$\" + randomKey;\nfunction detachDeletedInstance(node) {\n delete node[internalInstanceKey];\n delete node[internalPropsKey];\n delete node[internalEventHandlersKey];\n delete node[internalEventHandlerListenersKey];\n delete node[internalEventHandlesSetKey];\n}\nfunction getClosestInstanceFromNode(targetNode) {\n var targetInst = targetNode[internalInstanceKey];\n if (targetInst) return targetInst;\n for (var parentNode = targetNode.parentNode; parentNode; ) {\n if (\n (targetInst =\n parentNode[internalContainerInstanceKey] ||\n parentNode[internalInstanceKey])\n ) {\n parentNode = targetInst.alternate;\n if (\n null !== targetInst.child ||\n (null !== parentNode && null !== parentNode.child)\n )\n for (\n targetNode = getParentHydrationBoundary(targetNode);\n null !== targetNode;\n\n ) {\n if ((parentNode = targetNode[internalInstanceKey])) return parentNode;\n targetNode = getParentHydrationBoundary(targetNode);\n }\n return targetInst;\n }\n targetNode = parentNode;\n parentNode = targetNode.parentNode;\n }\n return null;\n}\nfunction getInstanceFromNode(node) {\n if (\n (node = node[internalInstanceKey] || node[internalContainerInstanceKey])\n ) {\n var tag = node.tag;\n if (\n 5 === tag ||\n 6 === tag ||\n 13 === tag ||\n 31 === tag ||\n 26 === tag ||\n 27 === tag ||\n 3 === tag\n )\n return node;\n }\n return null;\n}\nfunction getNodeFromInstance(inst) {\n var tag = inst.tag;\n if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return inst.stateNode;\n throw Error(formatProdErrorMessage(33));\n}\nfunction getResourcesFromRoot(root) {\n var resources = root[internalRootNodeResourcesKey];\n resources ||\n (resources = root[internalRootNodeResourcesKey] =\n { hoistableStyles: new Map(), hoistableScripts: new Map() });\n return resources;\n}\nfunction markNodeAsHoistable(node) {\n node[internalHoistableMarker] = !0;\n}\nvar allNativeEvents = new Set(),\n registrationNameDependencies = {};\nfunction registerTwoPhaseEvent(registrationName, dependencies) {\n registerDirectEvent(registrationName, dependencies);\n registerDirectEvent(registrationName + \"Capture\", dependencies);\n}\nfunction registerDirectEvent(registrationName, dependencies) {\n registrationNameDependencies[registrationName] = dependencies;\n for (\n registrationName = 0;\n registrationName < dependencies.length;\n registrationName++\n )\n allNativeEvents.add(dependencies[registrationName]);\n}\nvar VALID_ATTRIBUTE_NAME_REGEX = RegExp(\n \"^[:A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD][:A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040]*$\"\n ),\n illegalAttributeNameCache = {},\n validatedAttributeNameCache = {};\nfunction isAttributeNameSafe(attributeName) {\n if (hasOwnProperty.call(validatedAttributeNameCache, attributeName))\n return !0;\n if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) return !1;\n if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName))\n return (validatedAttributeNameCache[attributeName] = !0);\n illegalAttributeNameCache[attributeName] = !0;\n return !1;\n}\nfunction setValueForAttribute(node, name, value) {\n if (isAttributeNameSafe(name))\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n node.removeAttribute(name);\n return;\n case \"boolean\":\n var prefix$10 = name.toLowerCase().slice(0, 5);\n if (\"data-\" !== prefix$10 && \"aria-\" !== prefix$10) {\n node.removeAttribute(name);\n return;\n }\n }\n node.setAttribute(name, \"\" + value);\n }\n}\nfunction setValueForKnownAttribute(node, name, value) {\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n case \"boolean\":\n node.removeAttribute(name);\n return;\n }\n node.setAttribute(name, \"\" + value);\n }\n}\nfunction setValueForNamespacedAttribute(node, namespace, name, value) {\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n case \"boolean\":\n node.removeAttribute(name);\n return;\n }\n node.setAttributeNS(namespace, name, \"\" + value);\n }\n}\nfunction getToStringValue(value) {\n switch (typeof value) {\n case \"bigint\":\n case \"boolean\":\n case \"number\":\n case \"string\":\n case \"undefined\":\n return value;\n case \"object\":\n return value;\n default:\n return \"\";\n }\n}\nfunction isCheckable(elem) {\n var type = elem.type;\n return (\n (elem = elem.nodeName) &&\n \"input\" === elem.toLowerCase() &&\n (\"checkbox\" === type || \"radio\" === type)\n );\n}\nfunction trackValueOnNode(node, valueField, currentValue) {\n var descriptor = Object.getOwnPropertyDescriptor(\n node.constructor.prototype,\n valueField\n );\n if (\n !node.hasOwnProperty(valueField) &&\n \"undefined\" !== typeof descriptor &&\n \"function\" === typeof descriptor.get &&\n \"function\" === typeof descriptor.set\n ) {\n var get = descriptor.get,\n set = descriptor.set;\n Object.defineProperty(node, valueField, {\n configurable: !0,\n get: function () {\n return get.call(this);\n },\n set: function (value) {\n currentValue = \"\" + value;\n set.call(this, value);\n }\n });\n Object.defineProperty(node, valueField, {\n enumerable: descriptor.enumerable\n });\n return {\n getValue: function () {\n return currentValue;\n },\n setValue: function (value) {\n currentValue = \"\" + value;\n },\n stopTracking: function () {\n node._valueTracker = null;\n delete node[valueField];\n }\n };\n }\n}\nfunction track(node) {\n if (!node._valueTracker) {\n var valueField = isCheckable(node) ? \"checked\" : \"value\";\n node._valueTracker = trackValueOnNode(\n node,\n valueField,\n \"\" + node[valueField]\n );\n }\n}\nfunction updateValueIfChanged(node) {\n if (!node) return !1;\n var tracker = node._valueTracker;\n if (!tracker) return !0;\n var lastValue = tracker.getValue();\n var value = \"\";\n node &&\n (value = isCheckable(node)\n ? node.checked\n ? \"true\"\n : \"false\"\n : node.value);\n node = value;\n return node !== lastValue ? (tracker.setValue(node), !0) : !1;\n}\nfunction getActiveElement(doc) {\n doc = doc || (\"undefined\" !== typeof document ? document : void 0);\n if (\"undefined\" === typeof doc) return null;\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\nvar escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\\n\"\\\\]/g;\nfunction escapeSelectorAttributeValueInsideDoubleQuotes(value) {\n return value.replace(\n escapeSelectorAttributeValueInsideDoubleQuotesRegex,\n function (ch) {\n return \"\\\\\" + ch.charCodeAt(0).toString(16) + \" \";\n }\n );\n}\nfunction updateInput(\n element,\n value,\n defaultValue,\n lastDefaultValue,\n checked,\n defaultChecked,\n type,\n name\n) {\n element.name = \"\";\n null != type &&\n \"function\" !== typeof type &&\n \"symbol\" !== typeof type &&\n \"boolean\" !== typeof type\n ? (element.type = type)\n : element.removeAttribute(\"type\");\n if (null != value)\n if (\"number\" === type) {\n if ((0 === value && \"\" === element.value) || element.value != value)\n element.value = \"\" + getToStringValue(value);\n } else\n element.value !== \"\" + getToStringValue(value) &&\n (element.value = \"\" + getToStringValue(value));\n else\n (\"submit\" !== type && \"reset\" !== type) || element.removeAttribute(\"value\");\n null != value\n ? setDefaultValue(element, type, getToStringValue(value))\n : null != defaultValue\n ? setDefaultValue(element, type, getToStringValue(defaultValue))\n : null != lastDefaultValue && element.removeAttribute(\"value\");\n null == checked &&\n null != defaultChecked &&\n (element.defaultChecked = !!defaultChecked);\n null != checked &&\n (element.checked =\n checked && \"function\" !== typeof checked && \"symbol\" !== typeof checked);\n null != name &&\n \"function\" !== typeof name &&\n \"symbol\" !== typeof name &&\n \"boolean\" !== typeof name\n ? (element.name = \"\" + getToStringValue(name))\n : element.removeAttribute(\"name\");\n}\nfunction initInput(\n element,\n value,\n defaultValue,\n checked,\n defaultChecked,\n type,\n name,\n isHydrating\n) {\n null != type &&\n \"function\" !== typeof type &&\n \"symbol\" !== typeof type &&\n \"boolean\" !== typeof type &&\n (element.type = type);\n if (null != value || null != defaultValue) {\n if (\n !(\n (\"submit\" !== type && \"reset\" !== type) ||\n (void 0 !== value && null !== value)\n )\n ) {\n track(element);\n return;\n }\n defaultValue =\n null != defaultValue ? \"\" + getToStringValue(defaultValue) : \"\";\n value = null != value ? \"\" + getToStringValue(value) : defaultValue;\n isHydrating || value === element.value || (element.value = value);\n element.defaultValue = value;\n }\n checked = null != checked ? checked : defaultChecked;\n checked =\n \"function\" !== typeof checked && \"symbol\" !== typeof checked && !!checked;\n element.checked = isHydrating ? element.checked : !!checked;\n element.defaultChecked = !!checked;\n null != name &&\n \"function\" !== typeof name &&\n \"symbol\" !== typeof name &&\n \"boolean\" !== typeof name &&\n (element.name = name);\n track(element);\n}\nfunction setDefaultValue(node, type, value) {\n (\"number\" === type && getActiveElement(node.ownerDocument) === node) ||\n node.defaultValue === \"\" + value ||\n (node.defaultValue = \"\" + value);\n}\nfunction updateOptions(node, multiple, propValue, setDefaultSelected) {\n node = node.options;\n if (multiple) {\n multiple = {};\n for (var i = 0; i < propValue.length; i++)\n multiple[\"$\" + propValue[i]] = !0;\n for (propValue = 0; propValue < node.length; propValue++)\n (i = multiple.hasOwnProperty(\"$\" + node[propValue].value)),\n node[propValue].selected !== i && (node[propValue].selected = i),\n i && setDefaultSelected && (node[propValue].defaultSelected = !0);\n } else {\n propValue = \"\" + getToStringValue(propValue);\n multiple = null;\n for (i = 0; i < node.length; i++) {\n if (node[i].value === propValue) {\n node[i].selected = !0;\n setDefaultSelected && (node[i].defaultSelected = !0);\n return;\n }\n null !== multiple || node[i].disabled || (multiple = node[i]);\n }\n null !== multiple && (multiple.selected = !0);\n }\n}\nfunction updateTextarea(element, value, defaultValue) {\n if (\n null != value &&\n ((value = \"\" + getToStringValue(value)),\n value !== element.value && (element.value = value),\n null == defaultValue)\n ) {\n element.defaultValue !== value && (element.defaultValue = value);\n return;\n }\n element.defaultValue =\n null != defaultValue ? \"\" + getToStringValue(defaultValue) : \"\";\n}\nfunction initTextarea(element, value, defaultValue, children) {\n if (null == value) {\n if (null != children) {\n if (null != defaultValue) throw Error(formatProdErrorMessage(92));\n if (isArrayImpl(children)) {\n if (1 < children.length) throw Error(formatProdErrorMessage(93));\n children = children[0];\n }\n defaultValue = children;\n }\n null == defaultValue && (defaultValue = \"\");\n value = defaultValue;\n }\n defaultValue = getToStringValue(value);\n element.defaultValue = defaultValue;\n children = element.textContent;\n children === defaultValue &&\n \"\" !== children &&\n null !== children &&\n (element.value = children);\n track(element);\n}\nfunction setTextContent(node, text) {\n if (text) {\n var firstChild = node.firstChild;\n if (\n firstChild &&\n firstChild === node.lastChild &&\n 3 === firstChild.nodeType\n ) {\n firstChild.nodeValue = text;\n return;\n }\n }\n node.textContent = text;\n}\nvar unitlessNumbers = new Set(\n \"animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp\".split(\n \" \"\n )\n);\nfunction setValueForStyle(style, styleName, value) {\n var isCustomProperty = 0 === styleName.indexOf(\"--\");\n null == value || \"boolean\" === typeof value || \"\" === value\n ? isCustomProperty\n ? style.setProperty(styleName, \"\")\n : \"float\" === styleName\n ? (style.cssFloat = \"\")\n : (style[styleName] = \"\")\n : isCustomProperty\n ? style.setProperty(styleName, value)\n : \"number\" !== typeof value ||\n 0 === value ||\n unitlessNumbers.has(styleName)\n ? \"float\" === styleName\n ? (style.cssFloat = value)\n : (style[styleName] = (\"\" + value).trim())\n : (style[styleName] = value + \"px\");\n}\nfunction setValueForStyles(node, styles, prevStyles) {\n if (null != styles && \"object\" !== typeof styles)\n throw Error(formatProdErrorMessage(62));\n node = node.style;\n if (null != prevStyles) {\n for (var styleName in prevStyles)\n !prevStyles.hasOwnProperty(styleName) ||\n (null != styles && styles.hasOwnProperty(styleName)) ||\n (0 === styleName.indexOf(\"--\")\n ? node.setProperty(styleName, \"\")\n : \"float\" === styleName\n ? (node.cssFloat = \"\")\n : (node[styleName] = \"\"));\n for (var styleName$16 in styles)\n (styleName = styles[styleName$16]),\n styles.hasOwnProperty(styleName$16) &&\n prevStyles[styleName$16] !== styleName &&\n setValueForStyle(node, styleName$16, styleName);\n } else\n for (var styleName$17 in styles)\n styles.hasOwnProperty(styleName$17) &&\n setValueForStyle(node, styleName$17, styles[styleName$17]);\n}\nfunction isCustomElement(tagName) {\n if (-1 === tagName.indexOf(\"-\")) return !1;\n switch (tagName) {\n case \"annotation-xml\":\n case \"color-profile\":\n case \"font-face\":\n case \"font-face-src\":\n case \"font-face-uri\":\n case \"font-face-format\":\n case \"font-face-name\":\n case \"missing-glyph\":\n return !1;\n default:\n return !0;\n }\n}\nvar aliases = new Map([\n [\"acceptCharset\", \"accept-charset\"],\n [\"htmlFor\", \"for\"],\n [\"httpEquiv\", \"http-equiv\"],\n [\"crossOrigin\", \"crossorigin\"],\n [\"accentHeight\", \"accent-height\"],\n [\"alignmentBaseline\", \"alignment-baseline\"],\n [\"arabicForm\", \"arabic-form\"],\n [\"baselineShift\", \"baseline-shift\"],\n [\"capHeight\", \"cap-height\"],\n [\"clipPath\", \"clip-path\"],\n [\"clipRule\", \"clip-rule\"],\n [\"colorInterpolation\", \"color-interpolation\"],\n [\"colorInterpolationFilters\", \"color-interpolation-filters\"],\n [\"colorProfile\", \"color-profile\"],\n [\"colorRendering\", \"color-rendering\"],\n [\"dominantBaseline\", \"dominant-baseline\"],\n [\"enableBackground\", \"enable-background\"],\n [\"fillOpacity\", \"fill-opacity\"],\n [\"fillRule\", \"fill-rule\"],\n [\"floodColor\", \"flood-color\"],\n [\"floodOpacity\", \"flood-opacity\"],\n [\"fontFamily\", \"font-family\"],\n [\"fontSize\", \"font-size\"],\n [\"fontSizeAdjust\", \"font-size-adjust\"],\n [\"fontStretch\", \"font-stretch\"],\n [\"fontStyle\", \"font-style\"],\n [\"fontVariant\", \"font-variant\"],\n [\"fontWeight\", \"font-weight\"],\n [\"glyphName\", \"glyph-name\"],\n [\"glyphOrientationHorizontal\", \"glyph-orientation-horizontal\"],\n [\"glyphOrientationVertical\", \"glyph-orientation-vertical\"],\n [\"horizAdvX\", \"horiz-adv-x\"],\n [\"horizOriginX\", \"horiz-origin-x\"],\n [\"imageRendering\", \"image-rendering\"],\n [\"letterSpacing\", \"letter-spacing\"],\n [\"lightingColor\", \"lighting-color\"],\n [\"markerEnd\", \"marker-end\"],\n [\"markerMid\", \"marker-mid\"],\n [\"markerStart\", \"marker-start\"],\n [\"overlinePosition\", \"overline-position\"],\n [\"overlineThickness\", \"overline-thickness\"],\n [\"paintOrder\", \"paint-order\"],\n [\"panose-1\", \"panose-1\"],\n [\"pointerEvents\", \"pointer-events\"],\n [\"renderingIntent\", \"rendering-intent\"],\n [\"shapeRendering\", \"shape-rendering\"],\n [\"stopColor\", \"stop-color\"],\n [\"stopOpacity\", \"stop-opacity\"],\n [\"strikethroughPosition\", \"strikethrough-position\"],\n [\"strikethroughThickness\", \"strikethrough-thickness\"],\n [\"strokeDasharray\", \"stroke-dasharray\"],\n [\"strokeDashoffset\", \"stroke-dashoffset\"],\n [\"strokeLinecap\", \"stroke-linecap\"],\n [\"strokeLinejoin\", \"stroke-linejoin\"],\n [\"strokeMiterlimit\", \"stroke-miterlimit\"],\n [\"strokeOpacity\", \"stroke-opacity\"],\n [\"strokeWidth\", \"stroke-width\"],\n [\"textAnchor\", \"text-anchor\"],\n [\"textDecoration\", \"text-decoration\"],\n [\"textRendering\", \"text-rendering\"],\n [\"transformOrigin\", \"transform-origin\"],\n [\"underlinePosition\", \"underline-position\"],\n [\"underlineThickness\", \"underline-thickness\"],\n [\"unicodeBidi\", \"unicode-bidi\"],\n [\"unicodeRange\", \"unicode-range\"],\n [\"unitsPerEm\", \"units-per-em\"],\n [\"vAlphabetic\", \"v-alphabetic\"],\n [\"vHanging\", \"v-hanging\"],\n [\"vIdeographic\", \"v-ideographic\"],\n [\"vMathematical\", \"v-mathematical\"],\n [\"vectorEffect\", \"vector-effect\"],\n [\"vertAdvY\", \"vert-adv-y\"],\n [\"vertOriginX\", \"vert-origin-x\"],\n [\"vertOriginY\", \"vert-origin-y\"],\n [\"wordSpacing\", \"word-spacing\"],\n [\"writingMode\", \"writing-mode\"],\n [\"xmlnsXlink\", \"xmlns:xlink\"],\n [\"xHeight\", \"x-height\"]\n ]),\n isJavaScriptProtocol =\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*:/i;\nfunction sanitizeURL(url) {\n return isJavaScriptProtocol.test(\"\" + url)\n ? \"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')\"\n : url;\n}\nfunction noop$1() {}\nvar currentReplayingEvent = null;\nfunction getEventTarget(nativeEvent) {\n nativeEvent = nativeEvent.target || nativeEvent.srcElement || window;\n nativeEvent.correspondingUseElement &&\n (nativeEvent = nativeEvent.correspondingUseElement);\n return 3 === nativeEvent.nodeType ? nativeEvent.parentNode : nativeEvent;\n}\nvar restoreTarget = null,\n restoreQueue = null;\nfunction restoreStateOfTarget(target) {\n var internalInstance = getInstanceFromNode(target);\n if (internalInstance && (target = internalInstance.stateNode)) {\n var props = target[internalPropsKey] || null;\n a: switch (((target = internalInstance.stateNode), internalInstance.type)) {\n case \"input\":\n updateInput(\n target,\n props.value,\n props.defaultValue,\n props.defaultValue,\n props.checked,\n props.defaultChecked,\n props.type,\n props.name\n );\n internalInstance = props.name;\n if (\"radio\" === props.type && null != internalInstance) {\n for (props = target; props.parentNode; ) props = props.parentNode;\n props = props.querySelectorAll(\n 'input[name=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(\n \"\" + internalInstance\n ) +\n '\"][type=\"radio\"]'\n );\n for (\n internalInstance = 0;\n internalInstance < props.length;\n internalInstance++\n ) {\n var otherNode = props[internalInstance];\n if (otherNode !== target && otherNode.form === target.form) {\n var otherProps = otherNode[internalPropsKey] || null;\n if (!otherProps) throw Error(formatProdErrorMessage(90));\n updateInput(\n otherNode,\n otherProps.value,\n otherProps.defaultValue,\n otherProps.defaultValue,\n otherProps.checked,\n otherProps.defaultChecked,\n otherProps.type,\n otherProps.name\n );\n }\n }\n for (\n internalInstance = 0;\n internalInstance < props.length;\n internalInstance++\n )\n (otherNode = props[internalInstance]),\n otherNode.form === target.form && updateValueIfChanged(otherNode);\n }\n break a;\n case \"textarea\":\n updateTextarea(target, props.value, props.defaultValue);\n break a;\n case \"select\":\n (internalInstance = props.value),\n null != internalInstance &&\n updateOptions(target, !!props.multiple, internalInstance, !1);\n }\n }\n}\nvar isInsideEventHandler = !1;\nfunction batchedUpdates$1(fn, a, b) {\n if (isInsideEventHandler) return fn(a, b);\n isInsideEventHandler = !0;\n try {\n var JSCompiler_inline_result = fn(a);\n return JSCompiler_inline_result;\n } finally {\n if (\n ((isInsideEventHandler = !1),\n null !== restoreTarget || null !== restoreQueue)\n )\n if (\n (flushSyncWork$1(),\n restoreTarget &&\n ((a = restoreTarget),\n (fn = restoreQueue),\n (restoreQueue = restoreTarget = null),\n restoreStateOfTarget(a),\n fn))\n )\n for (a = 0; a < fn.length; a++) restoreStateOfTarget(fn[a]);\n }\n}\nfunction getListener(inst, registrationName) {\n var stateNode = inst.stateNode;\n if (null === stateNode) return null;\n var props = stateNode[internalPropsKey] || null;\n if (null === props) return null;\n stateNode = props[registrationName];\n a: switch (registrationName) {\n case \"onClick\":\n case \"onClickCapture\":\n case \"onDoubleClick\":\n case \"onDoubleClickCapture\":\n case \"onMouseDown\":\n case \"onMouseDownCapture\":\n case \"onMouseMove\":\n case \"onMouseMoveCapture\":\n case \"onMouseUp\":\n case \"onMouseUpCapture\":\n case \"onMouseEnter\":\n (props = !props.disabled) ||\n ((inst = inst.type),\n (props = !(\n \"button\" === inst ||\n \"input\" === inst ||\n \"select\" === inst ||\n \"textarea\" === inst\n )));\n inst = !props;\n break a;\n default:\n inst = !1;\n }\n if (inst) return null;\n if (stateNode && \"function\" !== typeof stateNode)\n throw Error(\n formatProdErrorMessage(231, registrationName, typeof stateNode)\n );\n return stateNode;\n}\nvar canUseDOM = !(\n \"undefined\" === typeof window ||\n \"undefined\" === typeof window.document ||\n \"undefined\" === typeof window.document.createElement\n ),\n passiveBrowserEventsSupported = !1;\nif (canUseDOM)\n try {\n var options = {};\n Object.defineProperty(options, \"passive\", {\n get: function () {\n passiveBrowserEventsSupported = !0;\n }\n });\n window.addEventListener(\"test\", options, options);\n window.removeEventListener(\"test\", options, options);\n } catch (e) {\n passiveBrowserEventsSupported = !1;\n }\nvar root = null,\n startText = null,\n fallbackText = null;\nfunction getData() {\n if (fallbackText) return fallbackText;\n var start,\n startValue = startText,\n startLength = startValue.length,\n end,\n endValue = \"value\" in root ? root.value : root.textContent,\n endLength = endValue.length;\n for (\n start = 0;\n start < startLength && startValue[start] === endValue[start];\n start++\n );\n var minEnd = startLength - start;\n for (\n end = 1;\n end <= minEnd &&\n startValue[startLength - end] === endValue[endLength - end];\n end++\n );\n return (fallbackText = endValue.slice(start, 1 < end ? 1 - end : void 0));\n}\nfunction getEventCharCode(nativeEvent) {\n var keyCode = nativeEvent.keyCode;\n \"charCode\" in nativeEvent\n ? ((nativeEvent = nativeEvent.charCode),\n 0 === nativeEvent && 13 === keyCode && (nativeEvent = 13))\n : (nativeEvent = keyCode);\n 10 === nativeEvent && (nativeEvent = 13);\n return 32 <= nativeEvent || 13 === nativeEvent ? nativeEvent : 0;\n}\nfunction functionThatReturnsTrue() {\n return !0;\n}\nfunction functionThatReturnsFalse() {\n return !1;\n}\nfunction createSyntheticEvent(Interface) {\n function SyntheticBaseEvent(\n reactName,\n reactEventType,\n targetInst,\n nativeEvent,\n nativeEventTarget\n ) {\n this._reactName = reactName;\n this._targetInst = targetInst;\n this.type = reactEventType;\n this.nativeEvent = nativeEvent;\n this.target = nativeEventTarget;\n this.currentTarget = null;\n for (var propName in Interface)\n Interface.hasOwnProperty(propName) &&\n ((reactName = Interface[propName]),\n (this[propName] = reactName\n ? reactName(nativeEvent)\n : nativeEvent[propName]));\n this.isDefaultPrevented = (\n null != nativeEvent.defaultPrevented\n ? nativeEvent.defaultPrevented\n : !1 === nativeEvent.returnValue\n )\n ? functionThatReturnsTrue\n : functionThatReturnsFalse;\n this.isPropagationStopped = functionThatReturnsFalse;\n return this;\n }\n assign(SyntheticBaseEvent.prototype, {\n preventDefault: function () {\n this.defaultPrevented = !0;\n var event = this.nativeEvent;\n event &&\n (event.preventDefault\n ? event.preventDefault()\n : \"unknown\" !== typeof event.returnValue && (event.returnValue = !1),\n (this.isDefaultPrevented = functionThatReturnsTrue));\n },\n stopPropagation: function () {\n var event = this.nativeEvent;\n event &&\n (event.stopPropagation\n ? event.stopPropagation()\n : \"unknown\" !== typeof event.cancelBubble &&\n (event.cancelBubble = !0),\n (this.isPropagationStopped = functionThatReturnsTrue));\n },\n persist: function () {},\n isPersistent: functionThatReturnsTrue\n });\n return SyntheticBaseEvent;\n}\nvar EventInterface = {\n eventPhase: 0,\n bubbles: 0,\n cancelable: 0,\n timeStamp: function (event) {\n return event.timeStamp || Date.now();\n },\n defaultPrevented: 0,\n isTrusted: 0\n },\n SyntheticEvent = createSyntheticEvent(EventInterface),\n UIEventInterface = assign({}, EventInterface, { view: 0, detail: 0 }),\n SyntheticUIEvent = createSyntheticEvent(UIEventInterface),\n lastMovementX,\n lastMovementY,\n lastMouseEvent,\n MouseEventInterface = assign({}, UIEventInterface, {\n screenX: 0,\n screenY: 0,\n clientX: 0,\n clientY: 0,\n pageX: 0,\n pageY: 0,\n ctrlKey: 0,\n shiftKey: 0,\n altKey: 0,\n metaKey: 0,\n getModifierState: getEventModifierState,\n button: 0,\n buttons: 0,\n relatedTarget: function (event) {\n return void 0 === event.relatedTarget\n ? event.fromElement === event.srcElement\n ? event.toElement\n : event.fromElement\n : event.relatedTarget;\n },\n movementX: function (event) {\n if (\"movementX\" in event) return event.movementX;\n event !== lastMouseEvent &&\n (lastMouseEvent && \"mousemove\" === event.type\n ? ((lastMovementX = event.screenX - lastMouseEvent.screenX),\n (lastMovementY = event.screenY - lastMouseEvent.screenY))\n : (lastMovementY = lastMovementX = 0),\n (lastMouseEvent = event));\n return lastMovementX;\n },\n movementY: function (event) {\n return \"movementY\" in event ? event.movementY : lastMovementY;\n }\n }),\n SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface),\n DragEventInterface = assign({}, MouseEventInterface, { dataTransfer: 0 }),\n SyntheticDragEvent = createSyntheticEvent(DragEventInterface),\n FocusEventInterface = assign({}, UIEventInterface, { relatedTarget: 0 }),\n SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface),\n AnimationEventInterface = assign({}, EventInterface, {\n animationName: 0,\n elapsedTime: 0,\n pseudoElement: 0\n }),\n SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface),\n ClipboardEventInterface = assign({}, EventInterface, {\n clipboardData: function (event) {\n return \"clipboardData\" in event\n ? event.clipboardData\n : window.clipboardData;\n }\n }),\n SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface),\n CompositionEventInterface = assign({}, EventInterface, { data: 0 }),\n SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface),\n normalizeKey = {\n Esc: \"Escape\",\n Spacebar: \" \",\n Left: \"ArrowLeft\",\n Up: \"ArrowUp\",\n Right: \"ArrowRight\",\n Down: \"ArrowDown\",\n Del: \"Delete\",\n Win: \"OS\",\n Menu: \"ContextMenu\",\n Apps: \"ContextMenu\",\n Scroll: \"ScrollLock\",\n MozPrintableKey: \"Unidentified\"\n },\n translateToKey = {\n 8: \"Backspace\",\n 9: \"Tab\",\n 12: \"Clear\",\n 13: \"Enter\",\n 16: \"Shift\",\n 17: \"Control\",\n 18: \"Alt\",\n 19: \"Pause\",\n 20: \"CapsLock\",\n 27: \"Escape\",\n 32: \" \",\n 33: \"PageUp\",\n 34: \"PageDown\",\n 35: \"End\",\n 36: \"Home\",\n 37: \"ArrowLeft\",\n 38: \"ArrowUp\",\n 39: \"ArrowRight\",\n 40: \"ArrowDown\",\n 45: \"Insert\",\n 46: \"Delete\",\n 112: \"F1\",\n 113: \"F2\",\n 114: \"F3\",\n 115: \"F4\",\n 116: \"F5\",\n 117: \"F6\",\n 118: \"F7\",\n 119: \"F8\",\n 120: \"F9\",\n 121: \"F10\",\n 122: \"F11\",\n 123: \"F12\",\n 144: \"NumLock\",\n 145: \"ScrollLock\",\n 224: \"Meta\"\n },\n modifierKeyToProp = {\n Alt: \"altKey\",\n Control: \"ctrlKey\",\n Meta: \"metaKey\",\n Shift: \"shiftKey\"\n };\nfunction modifierStateGetter(keyArg) {\n var nativeEvent = this.nativeEvent;\n return nativeEvent.getModifierState\n ? nativeEvent.getModifierState(keyArg)\n : (keyArg = modifierKeyToProp[keyArg])\n ? !!nativeEvent[keyArg]\n : !1;\n}\nfunction getEventModifierState() {\n return modifierStateGetter;\n}\nvar KeyboardEventInterface = assign({}, UIEventInterface, {\n key: function (nativeEvent) {\n if (nativeEvent.key) {\n var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n if (\"Unidentified\" !== key) return key;\n }\n return \"keypress\" === nativeEvent.type\n ? ((nativeEvent = getEventCharCode(nativeEvent)),\n 13 === nativeEvent ? \"Enter\" : String.fromCharCode(nativeEvent))\n : \"keydown\" === nativeEvent.type || \"keyup\" === nativeEvent.type\n ? translateToKey[nativeEvent.keyCode] || \"Unidentified\"\n : \"\";\n },\n code: 0,\n location: 0,\n ctrlKey: 0,\n shiftKey: 0,\n altKey: 0,\n metaKey: 0,\n repeat: 0,\n locale: 0,\n getModifierState: getEventModifierState,\n charCode: function (event) {\n return \"keypress\" === event.type ? getEventCharCode(event) : 0;\n },\n keyCode: function (event) {\n return \"keydown\" === event.type || \"keyup\" === event.type\n ? event.keyCode\n : 0;\n },\n which: function (event) {\n return \"keypress\" === event.type\n ? getEventCharCode(event)\n : \"keydown\" === event.type || \"keyup\" === event.type\n ? event.keyCode\n : 0;\n }\n }),\n SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface),\n PointerEventInterface = assign({}, MouseEventInterface, {\n pointerId: 0,\n width: 0,\n height: 0,\n pressure: 0,\n tangentialPressure: 0,\n tiltX: 0,\n tiltY: 0,\n twist: 0,\n pointerType: 0,\n isPrimary: 0\n }),\n SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface),\n TouchEventInterface = assign({}, UIEventInterface, {\n touches: 0,\n targetTouches: 0,\n changedTouches: 0,\n altKey: 0,\n metaKey: 0,\n ctrlKey: 0,\n shiftKey: 0,\n getModifierState: getEventModifierState\n }),\n SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface),\n TransitionEventInterface = assign({}, EventInterface, {\n propertyName: 0,\n elapsedTime: 0,\n pseudoElement: 0\n }),\n SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface),\n WheelEventInterface = assign({}, MouseEventInterface, {\n deltaX: function (event) {\n return \"deltaX\" in event\n ? event.deltaX\n : \"wheelDeltaX\" in event\n ? -event.wheelDeltaX\n : 0;\n },\n deltaY: function (event) {\n return \"deltaY\" in event\n ? event.deltaY\n : \"wheelDeltaY\" in event\n ? -event.wheelDeltaY\n : \"wheelDelta\" in event\n ? -event.wheelDelta\n : 0;\n },\n deltaZ: 0,\n deltaMode: 0\n }),\n SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface),\n ToggleEventInterface = assign({}, EventInterface, {\n newState: 0,\n oldState: 0\n }),\n SyntheticToggleEvent = createSyntheticEvent(ToggleEventInterface),\n END_KEYCODES = [9, 13, 27, 32],\n canUseCompositionEvent = canUseDOM && \"CompositionEvent\" in window,\n documentMode = null;\ncanUseDOM &&\n \"documentMode\" in document &&\n (documentMode = document.documentMode);\nvar canUseTextInputEvent = canUseDOM && \"TextEvent\" in window && !documentMode,\n useFallbackCompositionData =\n canUseDOM &&\n (!canUseCompositionEvent ||\n (documentMode && 8 < documentMode && 11 >= documentMode)),\n SPACEBAR_CHAR = String.fromCharCode(32),\n hasSpaceKeypress = !1;\nfunction isFallbackCompositionEnd(domEventName, nativeEvent) {\n switch (domEventName) {\n case \"keyup\":\n return -1 !== END_KEYCODES.indexOf(nativeEvent.keyCode);\n case \"keydown\":\n return 229 !== nativeEvent.keyCode;\n case \"keypress\":\n case \"mousedown\":\n case \"focusout\":\n return !0;\n default:\n return !1;\n }\n}\nfunction getDataFromCustomEvent(nativeEvent) {\n nativeEvent = nativeEvent.detail;\n return \"object\" === typeof nativeEvent && \"data\" in nativeEvent\n ? nativeEvent.data\n : null;\n}\nvar isComposing = !1;\nfunction getNativeBeforeInputChars(domEventName, nativeEvent) {\n switch (domEventName) {\n case \"compositionend\":\n return getDataFromCustomEvent(nativeEvent);\n case \"keypress\":\n if (32 !== nativeEvent.which) return null;\n hasSpaceKeypress = !0;\n return SPACEBAR_CHAR;\n case \"textInput\":\n return (\n (domEventName = nativeEvent.data),\n domEventName === SPACEBAR_CHAR && hasSpaceKeypress ? null : domEventName\n );\n default:\n return null;\n }\n}\nfunction getFallbackBeforeInputChars(domEventName, nativeEvent) {\n if (isComposing)\n return \"compositionend\" === domEventName ||\n (!canUseCompositionEvent &&\n isFallbackCompositionEnd(domEventName, nativeEvent))\n ? ((domEventName = getData()),\n (fallbackText = startText = root = null),\n (isComposing = !1),\n domEventName)\n : null;\n switch (domEventName) {\n case \"paste\":\n return null;\n case \"keypress\":\n if (\n !(nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) ||\n (nativeEvent.ctrlKey && nativeEvent.altKey)\n ) {\n if (nativeEvent.char && 1 < nativeEvent.char.length)\n return nativeEvent.char;\n if (nativeEvent.which) return String.fromCharCode(nativeEvent.which);\n }\n return null;\n case \"compositionend\":\n return useFallbackCompositionData && \"ko\" !== nativeEvent.locale\n ? null\n : nativeEvent.data;\n default:\n return null;\n }\n}\nvar supportedInputTypes = {\n color: !0,\n date: !0,\n datetime: !0,\n \"datetime-local\": !0,\n email: !0,\n month: !0,\n number: !0,\n password: !0,\n range: !0,\n search: !0,\n tel: !0,\n text: !0,\n time: !0,\n url: !0,\n week: !0\n};\nfunction isTextInputElement(elem) {\n var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n return \"input\" === nodeName\n ? !!supportedInputTypes[elem.type]\n : \"textarea\" === nodeName\n ? !0\n : !1;\n}\nfunction createAndAccumulateChangeEvent(\n dispatchQueue,\n inst,\n nativeEvent,\n target\n) {\n restoreTarget\n ? restoreQueue\n ? restoreQueue.push(target)\n : (restoreQueue = [target])\n : (restoreTarget = target);\n inst = accumulateTwoPhaseListeners(inst, \"onChange\");\n 0 < inst.length &&\n ((nativeEvent = new SyntheticEvent(\n \"onChange\",\n \"change\",\n null,\n nativeEvent,\n target\n )),\n dispatchQueue.push({ event: nativeEvent, listeners: inst }));\n}\nvar activeElement$1 = null,\n activeElementInst$1 = null;\nfunction runEventInBatch(dispatchQueue) {\n processDispatchQueue(dispatchQueue, 0);\n}\nfunction getInstIfValueChanged(targetInst) {\n var targetNode = getNodeFromInstance(targetInst);\n if (updateValueIfChanged(targetNode)) return targetInst;\n}\nfunction getTargetInstForChangeEvent(domEventName, targetInst) {\n if (\"change\" === domEventName) return targetInst;\n}\nvar isInputEventSupported = !1;\nif (canUseDOM) {\n var JSCompiler_inline_result$jscomp$286;\n if (canUseDOM) {\n var isSupported$jscomp$inline_427 = \"oninput\" in document;\n if (!isSupported$jscomp$inline_427) {\n var element$jscomp$inline_428 = document.createElement(\"div\");\n element$jscomp$inline_428.setAttribute(\"oninput\", \"return;\");\n isSupported$jscomp$inline_427 =\n \"function\" === typeof element$jscomp$inline_428.oninput;\n }\n JSCompiler_inline_result$jscomp$286 = isSupported$jscomp$inline_427;\n } else JSCompiler_inline_result$jscomp$286 = !1;\n isInputEventSupported =\n JSCompiler_inline_result$jscomp$286 &&\n (!document.documentMode || 9 < document.documentMode);\n}\nfunction stopWatchingForValueChange() {\n activeElement$1 &&\n (activeElement$1.detachEvent(\"onpropertychange\", handlePropertyChange),\n (activeElementInst$1 = activeElement$1 = null));\n}\nfunction handlePropertyChange(nativeEvent) {\n if (\n \"value\" === nativeEvent.propertyName &&\n getInstIfValueChanged(activeElementInst$1)\n ) {\n var dispatchQueue = [];\n createAndAccumulateChangeEvent(\n dispatchQueue,\n activeElementInst$1,\n nativeEvent,\n getEventTarget(nativeEvent)\n );\n batchedUpdates$1(runEventInBatch, dispatchQueue);\n }\n}\nfunction handleEventsForInputEventPolyfill(domEventName, target, targetInst) {\n \"focusin\" === domEventName\n ? (stopWatchingForValueChange(),\n (activeElement$1 = target),\n (activeElementInst$1 = targetInst),\n activeElement$1.attachEvent(\"onpropertychange\", handlePropertyChange))\n : \"focusout\" === domEventName && stopWatchingForValueChange();\n}\nfunction getTargetInstForInputEventPolyfill(domEventName) {\n if (\n \"selectionchange\" === domEventName ||\n \"keyup\" === domEventName ||\n \"keydown\" === domEventName\n )\n return getInstIfValueChanged(activeElementInst$1);\n}\nfunction getTargetInstForClickEvent(domEventName, targetInst) {\n if (\"click\" === domEventName) return getInstIfValueChanged(targetInst);\n}\nfunction getTargetInstForInputOrChangeEvent(domEventName, targetInst) {\n if (\"input\" === domEventName || \"change\" === domEventName)\n return getInstIfValueChanged(targetInst);\n}\nfunction is(x, y) {\n return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);\n}\nvar objectIs = \"function\" === typeof Object.is ? Object.is : is;\nfunction shallowEqual(objA, objB) {\n if (objectIs(objA, objB)) return !0;\n if (\n \"object\" !== typeof objA ||\n null === objA ||\n \"object\" !== typeof objB ||\n null === objB\n )\n return !1;\n var keysA = Object.keys(objA),\n keysB = Object.keys(objB);\n if (keysA.length !== keysB.length) return !1;\n for (keysB = 0; keysB < keysA.length; keysB++) {\n var currentKey = keysA[keysB];\n if (\n !hasOwnProperty.call(objB, currentKey) ||\n !objectIs(objA[currentKey], objB[currentKey])\n )\n return !1;\n }\n return !0;\n}\nfunction getLeafNode(node) {\n for (; node && node.firstChild; ) node = node.firstChild;\n return node;\n}\nfunction getNodeForCharacterOffset(root, offset) {\n var node = getLeafNode(root);\n root = 0;\n for (var nodeEnd; node; ) {\n if (3 === node.nodeType) {\n nodeEnd = root + node.textContent.length;\n if (root <= offset && nodeEnd >= offset)\n return { node: node, offset: offset - root };\n root = nodeEnd;\n }\n a: {\n for (; node; ) {\n if (node.nextSibling) {\n node = node.nextSibling;\n break a;\n }\n node = node.parentNode;\n }\n node = void 0;\n }\n node = getLeafNode(node);\n }\n}\nfunction containsNode(outerNode, innerNode) {\n return outerNode && innerNode\n ? outerNode === innerNode\n ? !0\n : outerNode && 3 === outerNode.nodeType\n ? !1\n : innerNode && 3 === innerNode.nodeType\n ? containsNode(outerNode, innerNode.parentNode)\n : \"contains\" in outerNode\n ? outerNode.contains(innerNode)\n : outerNode.compareDocumentPosition\n ? !!(outerNode.compareDocumentPosition(innerNode) & 16)\n : !1\n : !1;\n}\nfunction getActiveElementDeep(containerInfo) {\n containerInfo =\n null != containerInfo &&\n null != containerInfo.ownerDocument &&\n null != containerInfo.ownerDocument.defaultView\n ? containerInfo.ownerDocument.defaultView\n : window;\n for (\n var element = getActiveElement(containerInfo.document);\n element instanceof containerInfo.HTMLIFrameElement;\n\n ) {\n try {\n var JSCompiler_inline_result =\n \"string\" === typeof element.contentWindow.location.href;\n } catch (err) {\n JSCompiler_inline_result = !1;\n }\n if (JSCompiler_inline_result) containerInfo = element.contentWindow;\n else break;\n element = getActiveElement(containerInfo.document);\n }\n return element;\n}\nfunction hasSelectionCapabilities(elem) {\n var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n return (\n nodeName &&\n ((\"input\" === nodeName &&\n (\"text\" === elem.type ||\n \"search\" === elem.type ||\n \"tel\" === elem.type ||\n \"url\" === elem.type ||\n \"password\" === elem.type)) ||\n \"textarea\" === nodeName ||\n \"true\" === elem.contentEditable)\n );\n}\nvar skipSelectionChangeEvent =\n canUseDOM && \"documentMode\" in document && 11 >= document.documentMode,\n activeElement = null,\n activeElementInst = null,\n lastSelection = null,\n mouseDown = !1;\nfunction constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {\n var doc =\n nativeEventTarget.window === nativeEventTarget\n ? nativeEventTarget.document\n : 9 === nativeEventTarget.nodeType\n ? nativeEventTarget\n : nativeEventTarget.ownerDocument;\n mouseDown ||\n null == activeElement ||\n activeElement !== getActiveElement(doc) ||\n ((doc = activeElement),\n \"selectionStart\" in doc && hasSelectionCapabilities(doc)\n ? (doc = { start: doc.selectionStart, end: doc.selectionEnd })\n : ((doc = (\n (doc.ownerDocument && doc.ownerDocument.defaultView) ||\n window\n ).getSelection()),\n (doc = {\n anchorNode: doc.anchorNode,\n anchorOffset: doc.anchorOffset,\n focusNode: doc.focusNode,\n focusOffset: doc.focusOffset\n })),\n (lastSelection && shallowEqual(lastSelection, doc)) ||\n ((lastSelection = doc),\n (doc = accumulateTwoPhaseListeners(activeElementInst, \"onSelect\")),\n 0 < doc.length &&\n ((nativeEvent = new SyntheticEvent(\n \"onSelect\",\n \"select\",\n null,\n nativeEvent,\n nativeEventTarget\n )),\n dispatchQueue.push({ event: nativeEvent, listeners: doc }),\n (nativeEvent.target = activeElement))));\n}\nfunction makePrefixMap(styleProp, eventName) {\n var prefixes = {};\n prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n prefixes[\"Webkit\" + styleProp] = \"webkit\" + eventName;\n prefixes[\"Moz\" + styleProp] = \"moz\" + eventName;\n return prefixes;\n}\nvar vendorPrefixes = {\n animationend: makePrefixMap(\"Animation\", \"AnimationEnd\"),\n animationiteration: makePrefixMap(\"Animation\", \"AnimationIteration\"),\n animationstart: makePrefixMap(\"Animation\", \"AnimationStart\"),\n transitionrun: makePrefixMap(\"Transition\", \"TransitionRun\"),\n transitionstart: makePrefixMap(\"Transition\", \"TransitionStart\"),\n transitioncancel: makePrefixMap(\"Transition\", \"TransitionCancel\"),\n transitionend: makePrefixMap(\"Transition\", \"TransitionEnd\")\n },\n prefixedEventNames = {},\n style = {};\ncanUseDOM &&\n ((style = document.createElement(\"div\").style),\n \"AnimationEvent\" in window ||\n (delete vendorPrefixes.animationend.animation,\n delete vendorPrefixes.animationiteration.animation,\n delete vendorPrefixes.animationstart.animation),\n \"TransitionEvent\" in window ||\n delete vendorPrefixes.transitionend.transition);\nfunction getVendorPrefixedEventName(eventName) {\n if (prefixedEventNames[eventName]) return prefixedEventNames[eventName];\n if (!vendorPrefixes[eventName]) return eventName;\n var prefixMap = vendorPrefixes[eventName],\n styleProp;\n for (styleProp in prefixMap)\n if (prefixMap.hasOwnProperty(styleProp) && styleProp in style)\n return (prefixedEventNames[eventName] = prefixMap[styleProp]);\n return eventName;\n}\nvar ANIMATION_END = getVendorPrefixedEventName(\"animationend\"),\n ANIMATION_ITERATION = getVendorPrefixedEventName(\"animationiteration\"),\n ANIMATION_START = getVendorPrefixedEventName(\"animationstart\"),\n TRANSITION_RUN = getVendorPrefixedEventName(\"transitionrun\"),\n TRANSITION_START = getVendorPrefixedEventName(\"transitionstart\"),\n TRANSITION_CANCEL = getVendorPrefixedEventName(\"transitioncancel\"),\n TRANSITION_END = getVendorPrefixedEventName(\"transitionend\"),\n topLevelEventsToReactNames = new Map(),\n simpleEventPluginEvents =\n \"abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel\".split(\n \" \"\n );\nsimpleEventPluginEvents.push(\"scrollEnd\");\nfunction registerSimpleEvent(domEventName, reactName) {\n topLevelEventsToReactNames.set(domEventName, reactName);\n registerTwoPhaseEvent(reactName, [domEventName]);\n}\nvar reportGlobalError =\n \"function\" === typeof reportError\n ? reportError\n : function (error) {\n if (\n \"object\" === typeof window &&\n \"function\" === typeof window.ErrorEvent\n ) {\n var event = new window.ErrorEvent(\"error\", {\n bubbles: !0,\n cancelable: !0,\n message:\n \"object\" === typeof error &&\n null !== error &&\n \"string\" === typeof error.message\n ? String(error.message)\n : String(error),\n error: error\n });\n if (!window.dispatchEvent(event)) return;\n } else if (\n \"object\" === typeof process &&\n \"function\" === typeof process.emit\n ) {\n process.emit(\"uncaughtException\", error);\n return;\n }\n console.error(error);\n },\n concurrentQueues = [],\n concurrentQueuesIndex = 0,\n concurrentlyUpdatedLanes = 0;\nfunction finishQueueingConcurrentUpdates() {\n for (\n var endIndex = concurrentQueuesIndex,\n i = (concurrentlyUpdatedLanes = concurrentQueuesIndex = 0);\n i < endIndex;\n\n ) {\n var fiber = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var queue = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var update = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var lane = concurrentQueues[i];\n concurrentQueues[i++] = null;\n if (null !== queue && null !== update) {\n var pending = queue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n queue.pending = update;\n }\n 0 !== lane && markUpdateLaneFromFiberToRoot(fiber, update, lane);\n }\n}\nfunction enqueueUpdate$1(fiber, queue, update, lane) {\n concurrentQueues[concurrentQueuesIndex++] = fiber;\n concurrentQueues[concurrentQueuesIndex++] = queue;\n concurrentQueues[concurrentQueuesIndex++] = update;\n concurrentQueues[concurrentQueuesIndex++] = lane;\n concurrentlyUpdatedLanes |= lane;\n fiber.lanes |= lane;\n fiber = fiber.alternate;\n null !== fiber && (fiber.lanes |= lane);\n}\nfunction enqueueConcurrentHookUpdate(fiber, queue, update, lane) {\n enqueueUpdate$1(fiber, queue, update, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction enqueueConcurrentRenderForLane(fiber, lane) {\n enqueueUpdate$1(fiber, null, null, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) {\n sourceFiber.lanes |= lane;\n var alternate = sourceFiber.alternate;\n null !== alternate && (alternate.lanes |= lane);\n for (var isHidden = !1, parent = sourceFiber.return; null !== parent; )\n (parent.childLanes |= lane),\n (alternate = parent.alternate),\n null !== alternate && (alternate.childLanes |= lane),\n 22 === parent.tag &&\n ((sourceFiber = parent.stateNode),\n null === sourceFiber || sourceFiber._visibility & 1 || (isHidden = !0)),\n (sourceFiber = parent),\n (parent = parent.return);\n return 3 === sourceFiber.tag\n ? ((parent = sourceFiber.stateNode),\n isHidden &&\n null !== update &&\n ((isHidden = 31 - clz32(lane)),\n (sourceFiber = parent.hiddenUpdates),\n (alternate = sourceFiber[isHidden]),\n null === alternate\n ? (sourceFiber[isHidden] = [update])\n : alternate.push(update),\n (update.lane = lane | 536870912)),\n parent)\n : null;\n}\nfunction getRootForUpdatedFiber(sourceFiber) {\n if (50 < nestedUpdateCount)\n throw (\n ((nestedUpdateCount = 0),\n (rootWithNestedUpdates = null),\n Error(formatProdErrorMessage(185)))\n );\n for (var parent = sourceFiber.return; null !== parent; )\n (sourceFiber = parent), (parent = sourceFiber.return);\n return 3 === sourceFiber.tag ? sourceFiber.stateNode : null;\n}\nvar emptyContextObject = {};\nfunction FiberNode(tag, pendingProps, key, mode) {\n this.tag = tag;\n this.key = key;\n this.sibling =\n this.child =\n this.return =\n this.stateNode =\n this.type =\n this.elementType =\n null;\n this.index = 0;\n this.refCleanup = this.ref = null;\n this.pendingProps = pendingProps;\n this.dependencies =\n this.memoizedState =\n this.updateQueue =\n this.memoizedProps =\n null;\n this.mode = mode;\n this.subtreeFlags = this.flags = 0;\n this.deletions = null;\n this.childLanes = this.lanes = 0;\n this.alternate = null;\n}\nfunction createFiberImplClass(tag, pendingProps, key, mode) {\n return new FiberNode(tag, pendingProps, key, mode);\n}\nfunction shouldConstruct(Component) {\n Component = Component.prototype;\n return !(!Component || !Component.isReactComponent);\n}\nfunction createWorkInProgress(current, pendingProps) {\n var workInProgress = current.alternate;\n null === workInProgress\n ? ((workInProgress = createFiberImplClass(\n current.tag,\n pendingProps,\n current.key,\n current.mode\n )),\n (workInProgress.elementType = current.elementType),\n (workInProgress.type = current.type),\n (workInProgress.stateNode = current.stateNode),\n (workInProgress.alternate = current),\n (current.alternate = workInProgress))\n : ((workInProgress.pendingProps = pendingProps),\n (workInProgress.type = current.type),\n (workInProgress.flags = 0),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.deletions = null));\n workInProgress.flags = current.flags & 65011712;\n workInProgress.childLanes = current.childLanes;\n workInProgress.lanes = current.lanes;\n workInProgress.child = current.child;\n workInProgress.memoizedProps = current.memoizedProps;\n workInProgress.memoizedState = current.memoizedState;\n workInProgress.updateQueue = current.updateQueue;\n pendingProps = current.dependencies;\n workInProgress.dependencies =\n null === pendingProps\n ? null\n : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext };\n workInProgress.sibling = current.sibling;\n workInProgress.index = current.index;\n workInProgress.ref = current.ref;\n workInProgress.refCleanup = current.refCleanup;\n return workInProgress;\n}\nfunction resetWorkInProgress(workInProgress, renderLanes) {\n workInProgress.flags &= 65011714;\n var current = workInProgress.alternate;\n null === current\n ? ((workInProgress.childLanes = 0),\n (workInProgress.lanes = renderLanes),\n (workInProgress.child = null),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.memoizedProps = null),\n (workInProgress.memoizedState = null),\n (workInProgress.updateQueue = null),\n (workInProgress.dependencies = null),\n (workInProgress.stateNode = null))\n : ((workInProgress.childLanes = current.childLanes),\n (workInProgress.lanes = current.lanes),\n (workInProgress.child = current.child),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.deletions = null),\n (workInProgress.memoizedProps = current.memoizedProps),\n (workInProgress.memoizedState = current.memoizedState),\n (workInProgress.updateQueue = current.updateQueue),\n (workInProgress.type = current.type),\n (renderLanes = current.dependencies),\n (workInProgress.dependencies =\n null === renderLanes\n ? null\n : {\n lanes: renderLanes.lanes,\n firstContext: renderLanes.firstContext\n }));\n return workInProgress;\n}\nfunction createFiberFromTypeAndProps(\n type,\n key,\n pendingProps,\n owner,\n mode,\n lanes\n) {\n var fiberTag = 0;\n owner = type;\n if (\"function\" === typeof type) shouldConstruct(type) && (fiberTag = 1);\n else if (\"string\" === typeof type)\n fiberTag = isHostHoistableType(\n type,\n pendingProps,\n contextStackCursor.current\n )\n ? 26\n : \"html\" === type || \"head\" === type || \"body\" === type\n ? 27\n : 5;\n else\n a: switch (type) {\n case REACT_ACTIVITY_TYPE:\n return (\n (type = createFiberImplClass(31, pendingProps, key, mode)),\n (type.elementType = REACT_ACTIVITY_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_FRAGMENT_TYPE:\n return createFiberFromFragment(pendingProps.children, mode, lanes, key);\n case REACT_STRICT_MODE_TYPE:\n fiberTag = 8;\n mode |= 24;\n break;\n case REACT_PROFILER_TYPE:\n return (\n (type = createFiberImplClass(12, pendingProps, key, mode | 2)),\n (type.elementType = REACT_PROFILER_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_SUSPENSE_TYPE:\n return (\n (type = createFiberImplClass(13, pendingProps, key, mode)),\n (type.elementType = REACT_SUSPENSE_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_SUSPENSE_LIST_TYPE:\n return (\n (type = createFiberImplClass(19, pendingProps, key, mode)),\n (type.elementType = REACT_SUSPENSE_LIST_TYPE),\n (type.lanes = lanes),\n type\n );\n default:\n if (\"object\" === typeof type && null !== type)\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n fiberTag = 10;\n break a;\n case REACT_CONSUMER_TYPE:\n fiberTag = 9;\n break a;\n case REACT_FORWARD_REF_TYPE:\n fiberTag = 11;\n break a;\n case REACT_MEMO_TYPE:\n fiberTag = 14;\n break a;\n case REACT_LAZY_TYPE:\n fiberTag = 16;\n owner = null;\n break a;\n }\n fiberTag = 29;\n pendingProps = Error(\n formatProdErrorMessage(130, null === type ? \"null\" : typeof type, \"\")\n );\n owner = null;\n }\n key = createFiberImplClass(fiberTag, pendingProps, key, mode);\n key.elementType = type;\n key.type = owner;\n key.lanes = lanes;\n return key;\n}\nfunction createFiberFromFragment(elements, mode, lanes, key) {\n elements = createFiberImplClass(7, elements, key, mode);\n elements.lanes = lanes;\n return elements;\n}\nfunction createFiberFromText(content, mode, lanes) {\n content = createFiberImplClass(6, content, null, mode);\n content.lanes = lanes;\n return content;\n}\nfunction createFiberFromDehydratedFragment(dehydratedNode) {\n var fiber = createFiberImplClass(18, null, null, 0);\n fiber.stateNode = dehydratedNode;\n return fiber;\n}\nfunction createFiberFromPortal(portal, mode, lanes) {\n mode = createFiberImplClass(\n 4,\n null !== portal.children ? portal.children : [],\n portal.key,\n mode\n );\n mode.lanes = lanes;\n mode.stateNode = {\n containerInfo: portal.containerInfo,\n pendingChildren: null,\n implementation: portal.implementation\n };\n return mode;\n}\nvar CapturedStacks = new WeakMap();\nfunction createCapturedValueAtFiber(value, source) {\n if (\"object\" === typeof value && null !== value) {\n var existing = CapturedStacks.get(value);\n if (void 0 !== existing) return existing;\n source = {\n value: value,\n source: source,\n stack: getStackByFiberInDevAndProd(source)\n };\n CapturedStacks.set(value, source);\n return source;\n }\n return {\n value: value,\n source: source,\n stack: getStackByFiberInDevAndProd(source)\n };\n}\nvar forkStack = [],\n forkStackIndex = 0,\n treeForkProvider = null,\n treeForkCount = 0,\n idStack = [],\n idStackIndex = 0,\n treeContextProvider = null,\n treeContextId = 1,\n treeContextOverflow = \"\";\nfunction pushTreeFork(workInProgress, totalChildren) {\n forkStack[forkStackIndex++] = treeForkCount;\n forkStack[forkStackIndex++] = treeForkProvider;\n treeForkProvider = workInProgress;\n treeForkCount = totalChildren;\n}\nfunction pushTreeId(workInProgress, totalChildren, index) {\n idStack[idStackIndex++] = treeContextId;\n idStack[idStackIndex++] = treeContextOverflow;\n idStack[idStackIndex++] = treeContextProvider;\n treeContextProvider = workInProgress;\n var baseIdWithLeadingBit = treeContextId;\n workInProgress = treeContextOverflow;\n var baseLength = 32 - clz32(baseIdWithLeadingBit) - 1;\n baseIdWithLeadingBit &= ~(1 << baseLength);\n index += 1;\n var length = 32 - clz32(totalChildren) + baseLength;\n if (30 < length) {\n var numberOfOverflowBits = baseLength - (baseLength % 5);\n length = (\n baseIdWithLeadingBit &\n ((1 << numberOfOverflowBits) - 1)\n ).toString(32);\n baseIdWithLeadingBit >>= numberOfOverflowBits;\n baseLength -= numberOfOverflowBits;\n treeContextId =\n (1 << (32 - clz32(totalChildren) + baseLength)) |\n (index << baseLength) |\n baseIdWithLeadingBit;\n treeContextOverflow = length + workInProgress;\n } else\n (treeContextId =\n (1 << length) | (index << baseLength) | baseIdWithLeadingBit),\n (treeContextOverflow = workInProgress);\n}\nfunction pushMaterializedTreeId(workInProgress) {\n null !== workInProgress.return &&\n (pushTreeFork(workInProgress, 1), pushTreeId(workInProgress, 1, 0));\n}\nfunction popTreeContext(workInProgress) {\n for (; workInProgress === treeForkProvider; )\n (treeForkProvider = forkStack[--forkStackIndex]),\n (forkStack[forkStackIndex] = null),\n (treeForkCount = forkStack[--forkStackIndex]),\n (forkStack[forkStackIndex] = null);\n for (; workInProgress === treeContextProvider; )\n (treeContextProvider = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null),\n (treeContextOverflow = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null),\n (treeContextId = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null);\n}\nfunction restoreSuspendedTreeContext(workInProgress, suspendedContext) {\n idStack[idStackIndex++] = treeContextId;\n idStack[idStackIndex++] = treeContextOverflow;\n idStack[idStackIndex++] = treeContextProvider;\n treeContextId = suspendedContext.id;\n treeContextOverflow = suspendedContext.overflow;\n treeContextProvider = workInProgress;\n}\nvar hydrationParentFiber = null,\n nextHydratableInstance = null,\n isHydrating = !1,\n hydrationErrors = null,\n rootOrSingletonContext = !1,\n HydrationMismatchException = Error(formatProdErrorMessage(519));\nfunction throwOnHydrationMismatch(fiber) {\n var error = Error(\n formatProdErrorMessage(\n 418,\n 1 < arguments.length && void 0 !== arguments[1] && arguments[1]\n ? \"text\"\n : \"HTML\",\n \"\"\n )\n );\n queueHydrationError(createCapturedValueAtFiber(error, fiber));\n throw HydrationMismatchException;\n}\nfunction prepareToHydrateHostInstance(fiber) {\n var instance = fiber.stateNode,\n type = fiber.type,\n props = fiber.memoizedProps;\n instance[internalInstanceKey] = fiber;\n instance[internalPropsKey] = props;\n switch (type) {\n case \"dialog\":\n listenToNonDelegatedEvent(\"cancel\", instance);\n listenToNonDelegatedEvent(\"close\", instance);\n break;\n case \"iframe\":\n case \"object\":\n case \"embed\":\n listenToNonDelegatedEvent(\"load\", instance);\n break;\n case \"video\":\n case \"audio\":\n for (type = 0; type < mediaEventTypes.length; type++)\n listenToNonDelegatedEvent(mediaEventTypes[type], instance);\n break;\n case \"source\":\n listenToNonDelegatedEvent(\"error\", instance);\n break;\n case \"img\":\n case \"image\":\n case \"link\":\n listenToNonDelegatedEvent(\"error\", instance);\n listenToNonDelegatedEvent(\"load\", instance);\n break;\n case \"details\":\n listenToNonDelegatedEvent(\"toggle\", instance);\n break;\n case \"input\":\n listenToNonDelegatedEvent(\"invalid\", instance);\n initInput(\n instance,\n props.value,\n props.defaultValue,\n props.checked,\n props.defaultChecked,\n props.type,\n props.name,\n !0\n );\n break;\n case \"select\":\n listenToNonDelegatedEvent(\"invalid\", instance);\n break;\n case \"textarea\":\n listenToNonDelegatedEvent(\"invalid\", instance),\n initTextarea(instance, props.value, props.defaultValue, props.children);\n }\n type = props.children;\n (\"string\" !== typeof type &&\n \"number\" !== typeof type &&\n \"bigint\" !== typeof type) ||\n instance.textContent === \"\" + type ||\n !0 === props.suppressHydrationWarning ||\n checkForUnmatchedText(instance.textContent, type)\n ? (null != props.popover &&\n (listenToNonDelegatedEvent(\"beforetoggle\", instance),\n listenToNonDelegatedEvent(\"toggle\", instance)),\n null != props.onScroll && listenToNonDelegatedEvent(\"scroll\", instance),\n null != props.onScrollEnd &&\n listenToNonDelegatedEvent(\"scrollend\", instance),\n null != props.onClick && (instance.onclick = noop$1),\n (instance = !0))\n : (instance = !1);\n instance || throwOnHydrationMismatch(fiber, !0);\n}\nfunction popToNextHostParent(fiber) {\n for (hydrationParentFiber = fiber.return; hydrationParentFiber; )\n switch (hydrationParentFiber.tag) {\n case 5:\n case 31:\n case 13:\n rootOrSingletonContext = !1;\n return;\n case 27:\n case 3:\n rootOrSingletonContext = !0;\n return;\n default:\n hydrationParentFiber = hydrationParentFiber.return;\n }\n}\nfunction popHydrationState(fiber) {\n if (fiber !== hydrationParentFiber) return !1;\n if (!isHydrating) return popToNextHostParent(fiber), (isHydrating = !0), !1;\n var tag = fiber.tag,\n JSCompiler_temp;\n if ((JSCompiler_temp = 3 !== tag && 27 !== tag)) {\n if ((JSCompiler_temp = 5 === tag))\n (JSCompiler_temp = fiber.type),\n (JSCompiler_temp =\n !(\"form\" !== JSCompiler_temp && \"button\" !== JSCompiler_temp) ||\n shouldSetTextContent(fiber.type, fiber.memoizedProps));\n JSCompiler_temp = !JSCompiler_temp;\n }\n JSCompiler_temp && nextHydratableInstance && throwOnHydrationMismatch(fiber);\n popToNextHostParent(fiber);\n if (13 === tag) {\n fiber = fiber.memoizedState;\n fiber = null !== fiber ? fiber.dehydrated : null;\n if (!fiber) throw Error(formatProdErrorMessage(317));\n nextHydratableInstance =\n getNextHydratableInstanceAfterHydrationBoundary(fiber);\n } else if (31 === tag) {\n fiber = fiber.memoizedState;\n fiber = null !== fiber ? fiber.dehydrated : null;\n if (!fiber) throw Error(formatProdErrorMessage(317));\n nextHydratableInstance =\n getNextHydratableInstanceAfterHydrationBoundary(fiber);\n } else\n 27 === tag\n ? ((tag = nextHydratableInstance),\n isSingletonScope(fiber.type)\n ? ((fiber = previousHydratableOnEnteringScopedSingleton),\n (previousHydratableOnEnteringScopedSingleton = null),\n (nextHydratableInstance = fiber))\n : (nextHydratableInstance = tag))\n : (nextHydratableInstance = hydrationParentFiber\n ? getNextHydratable(fiber.stateNode.nextSibling)\n : null);\n return !0;\n}\nfunction resetHydrationState() {\n nextHydratableInstance = hydrationParentFiber = null;\n isHydrating = !1;\n}\nfunction upgradeHydrationErrorsToRecoverable() {\n var queuedErrors = hydrationErrors;\n null !== queuedErrors &&\n (null === workInProgressRootRecoverableErrors\n ? (workInProgressRootRecoverableErrors = queuedErrors)\n : workInProgressRootRecoverableErrors.push.apply(\n workInProgressRootRecoverableErrors,\n queuedErrors\n ),\n (hydrationErrors = null));\n return queuedErrors;\n}\nfunction queueHydrationError(error) {\n null === hydrationErrors\n ? (hydrationErrors = [error])\n : hydrationErrors.push(error);\n}\nvar valueCursor = createCursor(null),\n currentlyRenderingFiber$1 = null,\n lastContextDependency = null;\nfunction pushProvider(providerFiber, context, nextValue) {\n push(valueCursor, context._currentValue);\n context._currentValue = nextValue;\n}\nfunction popProvider(context) {\n context._currentValue = valueCursor.current;\n pop(valueCursor);\n}\nfunction scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) {\n for (; null !== parent; ) {\n var alternate = parent.alternate;\n (parent.childLanes & renderLanes) !== renderLanes\n ? ((parent.childLanes |= renderLanes),\n null !== alternate && (alternate.childLanes |= renderLanes))\n : null !== alternate &&\n (alternate.childLanes & renderLanes) !== renderLanes &&\n (alternate.childLanes |= renderLanes);\n if (parent === propagationRoot) break;\n parent = parent.return;\n }\n}\nfunction propagateContextChanges(\n workInProgress,\n contexts,\n renderLanes,\n forcePropagateEntireTree\n) {\n var fiber = workInProgress.child;\n null !== fiber && (fiber.return = workInProgress);\n for (; null !== fiber; ) {\n var list = fiber.dependencies;\n if (null !== list) {\n var nextFiber = fiber.child;\n list = list.firstContext;\n a: for (; null !== list; ) {\n var dependency = list;\n list = fiber;\n for (var i = 0; i < contexts.length; i++)\n if (dependency.context === contexts[i]) {\n list.lanes |= renderLanes;\n dependency = list.alternate;\n null !== dependency && (dependency.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(\n list.return,\n renderLanes,\n workInProgress\n );\n forcePropagateEntireTree || (nextFiber = null);\n break a;\n }\n list = dependency.next;\n }\n } else if (18 === fiber.tag) {\n nextFiber = fiber.return;\n if (null === nextFiber) throw Error(formatProdErrorMessage(341));\n nextFiber.lanes |= renderLanes;\n list = nextFiber.alternate;\n null !== list && (list.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(nextFiber, renderLanes, workInProgress);\n nextFiber = null;\n } else nextFiber = fiber.child;\n if (null !== nextFiber) nextFiber.return = fiber;\n else\n for (nextFiber = fiber; null !== nextFiber; ) {\n if (nextFiber === workInProgress) {\n nextFiber = null;\n break;\n }\n fiber = nextFiber.sibling;\n if (null !== fiber) {\n fiber.return = nextFiber.return;\n nextFiber = fiber;\n break;\n }\n nextFiber = nextFiber.return;\n }\n fiber = nextFiber;\n }\n}\nfunction propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n forcePropagateEntireTree\n) {\n current = null;\n for (\n var parent = workInProgress, isInsidePropagationBailout = !1;\n null !== parent;\n\n ) {\n if (!isInsidePropagationBailout)\n if (0 !== (parent.flags & 524288)) isInsidePropagationBailout = !0;\n else if (0 !== (parent.flags & 262144)) break;\n if (10 === parent.tag) {\n var currentParent = parent.alternate;\n if (null === currentParent) throw Error(formatProdErrorMessage(387));\n currentParent = currentParent.memoizedProps;\n if (null !== currentParent) {\n var context = parent.type;\n objectIs(parent.pendingProps.value, currentParent.value) ||\n (null !== current ? current.push(context) : (current = [context]));\n }\n } else if (parent === hostTransitionProviderCursor.current) {\n currentParent = parent.alternate;\n if (null === currentParent) throw Error(formatProdErrorMessage(387));\n currentParent.memoizedState.memoizedState !==\n parent.memoizedState.memoizedState &&\n (null !== current\n ? current.push(HostTransitionContext)\n : (current = [HostTransitionContext]));\n }\n parent = parent.return;\n }\n null !== current &&\n propagateContextChanges(\n workInProgress,\n current,\n renderLanes,\n forcePropagateEntireTree\n );\n workInProgress.flags |= 262144;\n}\nfunction checkIfContextChanged(currentDependencies) {\n for (\n currentDependencies = currentDependencies.firstContext;\n null !== currentDependencies;\n\n ) {\n if (\n !objectIs(\n currentDependencies.context._currentValue,\n currentDependencies.memoizedValue\n )\n )\n return !0;\n currentDependencies = currentDependencies.next;\n }\n return !1;\n}\nfunction prepareToReadContext(workInProgress) {\n currentlyRenderingFiber$1 = workInProgress;\n lastContextDependency = null;\n workInProgress = workInProgress.dependencies;\n null !== workInProgress && (workInProgress.firstContext = null);\n}\nfunction readContext(context) {\n return readContextForConsumer(currentlyRenderingFiber$1, context);\n}\nfunction readContextDuringReconciliation(consumer, context) {\n null === currentlyRenderingFiber$1 && prepareToReadContext(consumer);\n return readContextForConsumer(consumer, context);\n}\nfunction readContextForConsumer(consumer, context) {\n var value = context._currentValue;\n context = { context: context, memoizedValue: value, next: null };\n if (null === lastContextDependency) {\n if (null === consumer) throw Error(formatProdErrorMessage(308));\n lastContextDependency = context;\n consumer.dependencies = { lanes: 0, firstContext: context };\n consumer.flags |= 524288;\n } else lastContextDependency = lastContextDependency.next = context;\n return value;\n}\nvar AbortControllerLocal =\n \"undefined\" !== typeof AbortController\n ? AbortController\n : function () {\n var listeners = [],\n signal = (this.signal = {\n aborted: !1,\n addEventListener: function (type, listener) {\n listeners.push(listener);\n }\n });\n this.abort = function () {\n signal.aborted = !0;\n listeners.forEach(function (listener) {\n return listener();\n });\n };\n },\n scheduleCallback$2 = Scheduler.unstable_scheduleCallback,\n NormalPriority = Scheduler.unstable_NormalPriority,\n CacheContext = {\n $$typeof: REACT_CONTEXT_TYPE,\n Consumer: null,\n Provider: null,\n _currentValue: null,\n _currentValue2: null,\n _threadCount: 0\n };\nfunction createCache() {\n return {\n controller: new AbortControllerLocal(),\n data: new Map(),\n refCount: 0\n };\n}\nfunction releaseCache(cache) {\n cache.refCount--;\n 0 === cache.refCount &&\n scheduleCallback$2(NormalPriority, function () {\n cache.controller.abort();\n });\n}\nvar currentEntangledListeners = null,\n currentEntangledPendingCount = 0,\n currentEntangledLane = 0,\n currentEntangledActionThenable = null;\nfunction entangleAsyncAction(transition, thenable) {\n if (null === currentEntangledListeners) {\n var entangledListeners = (currentEntangledListeners = []);\n currentEntangledPendingCount = 0;\n currentEntangledLane = requestTransitionLane();\n currentEntangledActionThenable = {\n status: \"pending\",\n value: void 0,\n then: function (resolve) {\n entangledListeners.push(resolve);\n }\n };\n }\n currentEntangledPendingCount++;\n thenable.then(pingEngtangledActionScope, pingEngtangledActionScope);\n return thenable;\n}\nfunction pingEngtangledActionScope() {\n if (\n 0 === --currentEntangledPendingCount &&\n null !== currentEntangledListeners\n ) {\n null !== currentEntangledActionThenable &&\n (currentEntangledActionThenable.status = \"fulfilled\");\n var listeners = currentEntangledListeners;\n currentEntangledListeners = null;\n currentEntangledLane = 0;\n currentEntangledActionThenable = null;\n for (var i = 0; i < listeners.length; i++) (0, listeners[i])();\n }\n}\nfunction chainThenableValue(thenable, result) {\n var listeners = [],\n thenableWithOverride = {\n status: \"pending\",\n value: null,\n reason: null,\n then: function (resolve) {\n listeners.push(resolve);\n }\n };\n thenable.then(\n function () {\n thenableWithOverride.status = \"fulfilled\";\n thenableWithOverride.value = result;\n for (var i = 0; i < listeners.length; i++) (0, listeners[i])(result);\n },\n function (error) {\n thenableWithOverride.status = \"rejected\";\n thenableWithOverride.reason = error;\n for (error = 0; error < listeners.length; error++)\n (0, listeners[error])(void 0);\n }\n );\n return thenableWithOverride;\n}\nvar prevOnStartTransitionFinish = ReactSharedInternals.S;\nReactSharedInternals.S = function (transition, returnValue) {\n globalMostRecentTransitionTime = now();\n \"object\" === typeof returnValue &&\n null !== returnValue &&\n \"function\" === typeof returnValue.then &&\n entangleAsyncAction(transition, returnValue);\n null !== prevOnStartTransitionFinish &&\n prevOnStartTransitionFinish(transition, returnValue);\n};\nvar resumedCache = createCursor(null);\nfunction peekCacheFromPool() {\n var cacheResumedFromPreviousRender = resumedCache.current;\n return null !== cacheResumedFromPreviousRender\n ? cacheResumedFromPreviousRender\n : workInProgressRoot.pooledCache;\n}\nfunction pushTransition(offscreenWorkInProgress, prevCachePool) {\n null === prevCachePool\n ? push(resumedCache, resumedCache.current)\n : push(resumedCache, prevCachePool.pool);\n}\nfunction getSuspendedCache() {\n var cacheFromPool = peekCacheFromPool();\n return null === cacheFromPool\n ? null\n : { parent: CacheContext._currentValue, pool: cacheFromPool };\n}\nvar SuspenseException = Error(formatProdErrorMessage(460)),\n SuspenseyCommitException = Error(formatProdErrorMessage(474)),\n SuspenseActionException = Error(formatProdErrorMessage(542)),\n noopSuspenseyCommitThenable = { then: function () {} };\nfunction isThenableResolved(thenable) {\n thenable = thenable.status;\n return \"fulfilled\" === thenable || \"rejected\" === thenable;\n}\nfunction trackUsedThenable(thenableState, thenable, index) {\n index = thenableState[index];\n void 0 === index\n ? thenableState.push(thenable)\n : index !== thenable && (thenable.then(noop$1, noop$1), (thenable = index));\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw (\n ((thenableState = thenable.reason),\n checkIfUseWrappedInAsyncCatch(thenableState),\n thenableState)\n );\n default:\n if (\"string\" === typeof thenable.status) thenable.then(noop$1, noop$1);\n else {\n thenableState = workInProgressRoot;\n if (null !== thenableState && 100 < thenableState.shellSuspendCounter)\n throw Error(formatProdErrorMessage(482));\n thenableState = thenable;\n thenableState.status = \"pending\";\n thenableState.then(\n function (fulfilledValue) {\n if (\"pending\" === thenable.status) {\n var fulfilledThenable = thenable;\n fulfilledThenable.status = \"fulfilled\";\n fulfilledThenable.value = fulfilledValue;\n }\n },\n function (error) {\n if (\"pending\" === thenable.status) {\n var rejectedThenable = thenable;\n rejectedThenable.status = \"rejected\";\n rejectedThenable.reason = error;\n }\n }\n );\n }\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw (\n ((thenableState = thenable.reason),\n checkIfUseWrappedInAsyncCatch(thenableState),\n thenableState)\n );\n }\n suspendedThenable = thenable;\n throw SuspenseException;\n }\n}\nfunction resolveLazy(lazyType) {\n try {\n var init = lazyType._init;\n return init(lazyType._payload);\n } catch (x) {\n if (null !== x && \"object\" === typeof x && \"function\" === typeof x.then)\n throw ((suspendedThenable = x), SuspenseException);\n throw x;\n }\n}\nvar suspendedThenable = null;\nfunction getSuspendedThenable() {\n if (null === suspendedThenable) throw Error(formatProdErrorMessage(459));\n var thenable = suspendedThenable;\n suspendedThenable = null;\n return thenable;\n}\nfunction checkIfUseWrappedInAsyncCatch(rejectedReason) {\n if (\n rejectedReason === SuspenseException ||\n rejectedReason === SuspenseActionException\n )\n throw Error(formatProdErrorMessage(483));\n}\nvar thenableState$1 = null,\n thenableIndexCounter$1 = 0;\nfunction unwrapThenable(thenable) {\n var index = thenableIndexCounter$1;\n thenableIndexCounter$1 += 1;\n null === thenableState$1 && (thenableState$1 = []);\n return trackUsedThenable(thenableState$1, thenable, index);\n}\nfunction coerceRef(workInProgress, element) {\n element = element.props.ref;\n workInProgress.ref = void 0 !== element ? element : null;\n}\nfunction throwOnInvalidObjectTypeImpl(returnFiber, newChild) {\n if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE)\n throw Error(formatProdErrorMessage(525));\n returnFiber = Object.prototype.toString.call(newChild);\n throw Error(\n formatProdErrorMessage(\n 31,\n \"[object Object]\" === returnFiber\n ? \"object with keys {\" + Object.keys(newChild).join(\", \") + \"}\"\n : returnFiber\n )\n );\n}\nfunction createChildReconciler(shouldTrackSideEffects) {\n function deleteChild(returnFiber, childToDelete) {\n if (shouldTrackSideEffects) {\n var deletions = returnFiber.deletions;\n null === deletions\n ? ((returnFiber.deletions = [childToDelete]), (returnFiber.flags |= 16))\n : deletions.push(childToDelete);\n }\n }\n function deleteRemainingChildren(returnFiber, currentFirstChild) {\n if (!shouldTrackSideEffects) return null;\n for (; null !== currentFirstChild; )\n deleteChild(returnFiber, currentFirstChild),\n (currentFirstChild = currentFirstChild.sibling);\n return null;\n }\n function mapRemainingChildren(currentFirstChild) {\n for (var existingChildren = new Map(); null !== currentFirstChild; )\n null !== currentFirstChild.key\n ? existingChildren.set(currentFirstChild.key, currentFirstChild)\n : existingChildren.set(currentFirstChild.index, currentFirstChild),\n (currentFirstChild = currentFirstChild.sibling);\n return existingChildren;\n }\n function useFiber(fiber, pendingProps) {\n fiber = createWorkInProgress(fiber, pendingProps);\n fiber.index = 0;\n fiber.sibling = null;\n return fiber;\n }\n function placeChild(newFiber, lastPlacedIndex, newIndex) {\n newFiber.index = newIndex;\n if (!shouldTrackSideEffects)\n return (newFiber.flags |= 1048576), lastPlacedIndex;\n newIndex = newFiber.alternate;\n if (null !== newIndex)\n return (\n (newIndex = newIndex.index),\n newIndex < lastPlacedIndex\n ? ((newFiber.flags |= 67108866), lastPlacedIndex)\n : newIndex\n );\n newFiber.flags |= 67108866;\n return lastPlacedIndex;\n }\n function placeSingleChild(newFiber) {\n shouldTrackSideEffects &&\n null === newFiber.alternate &&\n (newFiber.flags |= 67108866);\n return newFiber;\n }\n function updateTextNode(returnFiber, current, textContent, lanes) {\n if (null === current || 6 !== current.tag)\n return (\n (current = createFiberFromText(textContent, returnFiber.mode, lanes)),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, textContent);\n current.return = returnFiber;\n return current;\n }\n function updateElement(returnFiber, current, element, lanes) {\n var elementType = element.type;\n if (elementType === REACT_FRAGMENT_TYPE)\n return updateFragment(\n returnFiber,\n current,\n element.props.children,\n lanes,\n element.key\n );\n if (\n null !== current &&\n (current.elementType === elementType ||\n (\"object\" === typeof elementType &&\n null !== elementType &&\n elementType.$$typeof === REACT_LAZY_TYPE &&\n resolveLazy(elementType) === current.type))\n )\n return (\n (current = useFiber(current, element.props)),\n coerceRef(current, element),\n (current.return = returnFiber),\n current\n );\n current = createFiberFromTypeAndProps(\n element.type,\n element.key,\n element.props,\n null,\n returnFiber.mode,\n lanes\n );\n coerceRef(current, element);\n current.return = returnFiber;\n return current;\n }\n function updatePortal(returnFiber, current, portal, lanes) {\n if (\n null === current ||\n 4 !== current.tag ||\n current.stateNode.containerInfo !== portal.containerInfo ||\n current.stateNode.implementation !== portal.implementation\n )\n return (\n (current = createFiberFromPortal(portal, returnFiber.mode, lanes)),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, portal.children || []);\n current.return = returnFiber;\n return current;\n }\n function updateFragment(returnFiber, current, fragment, lanes, key) {\n if (null === current || 7 !== current.tag)\n return (\n (current = createFiberFromFragment(\n fragment,\n returnFiber.mode,\n lanes,\n key\n )),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, fragment);\n current.return = returnFiber;\n return current;\n }\n function createChild(returnFiber, newChild, lanes) {\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return (\n (newChild = createFiberFromText(\n \"\" + newChild,\n returnFiber.mode,\n lanes\n )),\n (newChild.return = returnFiber),\n newChild\n );\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return (\n (lanes = createFiberFromTypeAndProps(\n newChild.type,\n newChild.key,\n newChild.props,\n null,\n returnFiber.mode,\n lanes\n )),\n coerceRef(lanes, newChild),\n (lanes.return = returnFiber),\n lanes\n );\n case REACT_PORTAL_TYPE:\n return (\n (newChild = createFiberFromPortal(\n newChild,\n returnFiber.mode,\n lanes\n )),\n (newChild.return = returnFiber),\n newChild\n );\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n createChild(returnFiber, newChild, lanes)\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return (\n (newChild = createFiberFromFragment(\n newChild,\n returnFiber.mode,\n lanes,\n null\n )),\n (newChild.return = returnFiber),\n newChild\n );\n if (\"function\" === typeof newChild.then)\n return createChild(returnFiber, unwrapThenable(newChild), lanes);\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return createChild(\n returnFiber,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function updateSlot(returnFiber, oldFiber, newChild, lanes) {\n var key = null !== oldFiber ? oldFiber.key : null;\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return null !== key\n ? null\n : updateTextNode(returnFiber, oldFiber, \"\" + newChild, lanes);\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return newChild.key === key\n ? updateElement(returnFiber, oldFiber, newChild, lanes)\n : null;\n case REACT_PORTAL_TYPE:\n return newChild.key === key\n ? updatePortal(returnFiber, oldFiber, newChild, lanes)\n : null;\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n updateSlot(returnFiber, oldFiber, newChild, lanes)\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return null !== key\n ? null\n : updateFragment(returnFiber, oldFiber, newChild, lanes, null);\n if (\"function\" === typeof newChild.then)\n return updateSlot(\n returnFiber,\n oldFiber,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return updateSlot(\n returnFiber,\n oldFiber,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n newChild,\n lanes\n ) {\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return (\n (existingChildren = existingChildren.get(newIdx) || null),\n updateTextNode(returnFiber, existingChildren, \"\" + newChild, lanes)\n );\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return (\n (existingChildren =\n existingChildren.get(\n null === newChild.key ? newIdx : newChild.key\n ) || null),\n updateElement(returnFiber, existingChildren, newChild, lanes)\n );\n case REACT_PORTAL_TYPE:\n return (\n (existingChildren =\n existingChildren.get(\n null === newChild.key ? newIdx : newChild.key\n ) || null),\n updatePortal(returnFiber, existingChildren, newChild, lanes)\n );\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n newChild,\n lanes\n )\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return (\n (existingChildren = existingChildren.get(newIdx) || null),\n updateFragment(returnFiber, existingChildren, newChild, lanes, null)\n );\n if (\"function\" === typeof newChild.then)\n return updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function reconcileChildrenArray(\n returnFiber,\n currentFirstChild,\n newChildren,\n lanes\n ) {\n for (\n var resultingFirstChild = null,\n previousNewFiber = null,\n oldFiber = currentFirstChild,\n newIdx = (currentFirstChild = 0),\n nextOldFiber = null;\n null !== oldFiber && newIdx < newChildren.length;\n newIdx++\n ) {\n oldFiber.index > newIdx\n ? ((nextOldFiber = oldFiber), (oldFiber = null))\n : (nextOldFiber = oldFiber.sibling);\n var newFiber = updateSlot(\n returnFiber,\n oldFiber,\n newChildren[newIdx],\n lanes\n );\n if (null === newFiber) {\n null === oldFiber && (oldFiber = nextOldFiber);\n break;\n }\n shouldTrackSideEffects &&\n oldFiber &&\n null === newFiber.alternate &&\n deleteChild(returnFiber, oldFiber);\n currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx);\n null === previousNewFiber\n ? (resultingFirstChild = newFiber)\n : (previousNewFiber.sibling = newFiber);\n previousNewFiber = newFiber;\n oldFiber = nextOldFiber;\n }\n if (newIdx === newChildren.length)\n return (\n deleteRemainingChildren(returnFiber, oldFiber),\n isHydrating && pushTreeFork(returnFiber, newIdx),\n resultingFirstChild\n );\n if (null === oldFiber) {\n for (; newIdx < newChildren.length; newIdx++)\n (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)),\n null !== oldFiber &&\n ((currentFirstChild = placeChild(\n oldFiber,\n currentFirstChild,\n newIdx\n )),\n null === previousNewFiber\n ? (resultingFirstChild = oldFiber)\n : (previousNewFiber.sibling = oldFiber),\n (previousNewFiber = oldFiber));\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n for (\n oldFiber = mapRemainingChildren(oldFiber);\n newIdx < newChildren.length;\n newIdx++\n )\n (nextOldFiber = updateFromMap(\n oldFiber,\n returnFiber,\n newIdx,\n newChildren[newIdx],\n lanes\n )),\n null !== nextOldFiber &&\n (shouldTrackSideEffects &&\n null !== nextOldFiber.alternate &&\n oldFiber.delete(\n null === nextOldFiber.key ? newIdx : nextOldFiber.key\n ),\n (currentFirstChild = placeChild(\n nextOldFiber,\n currentFirstChild,\n newIdx\n )),\n null === previousNewFiber\n ? (resultingFirstChild = nextOldFiber)\n : (previousNewFiber.sibling = nextOldFiber),\n (previousNewFiber = nextOldFiber));\n shouldTrackSideEffects &&\n oldFiber.forEach(function (child) {\n return deleteChild(returnFiber, child);\n });\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n function reconcileChildrenIterator(\n returnFiber,\n currentFirstChild,\n newChildren,\n lanes\n ) {\n if (null == newChildren) throw Error(formatProdErrorMessage(151));\n for (\n var resultingFirstChild = null,\n previousNewFiber = null,\n oldFiber = currentFirstChild,\n newIdx = (currentFirstChild = 0),\n nextOldFiber = null,\n step = newChildren.next();\n null !== oldFiber && !step.done;\n newIdx++, step = newChildren.next()\n ) {\n oldFiber.index > newIdx\n ? ((nextOldFiber = oldFiber), (oldFiber = null))\n : (nextOldFiber = oldFiber.sibling);\n var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);\n if (null === newFiber) {\n null === oldFiber && (oldFiber = nextOldFiber);\n break;\n }\n shouldTrackSideEffects &&\n oldFiber &&\n null === newFiber.alternate &&\n deleteChild(returnFiber, oldFiber);\n currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx);\n null === previousNewFiber\n ? (resultingFirstChild = newFiber)\n : (previousNewFiber.sibling = newFiber);\n previousNewFiber = newFiber;\n oldFiber = nextOldFiber;\n }\n if (step.done)\n return (\n deleteRemainingChildren(returnFiber, oldFiber),\n isHydrating && pushTreeFork(returnFiber, newIdx),\n resultingFirstChild\n );\n if (null === oldFiber) {\n for (; !step.done; newIdx++, step = newChildren.next())\n (step = createChild(returnFiber, step.value, lanes)),\n null !== step &&\n ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)),\n null === previousNewFiber\n ? (resultingFirstChild = step)\n : (previousNewFiber.sibling = step),\n (previousNewFiber = step));\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n for (\n oldFiber = mapRemainingChildren(oldFiber);\n !step.done;\n newIdx++, step = newChildren.next()\n )\n (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)),\n null !== step &&\n (shouldTrackSideEffects &&\n null !== step.alternate &&\n oldFiber.delete(null === step.key ? newIdx : step.key),\n (currentFirstChild = placeChild(step, currentFirstChild, newIdx)),\n null === previousNewFiber\n ? (resultingFirstChild = step)\n : (previousNewFiber.sibling = step),\n (previousNewFiber = step));\n shouldTrackSideEffects &&\n oldFiber.forEach(function (child) {\n return deleteChild(returnFiber, child);\n });\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n function reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n ) {\n \"object\" === typeof newChild &&\n null !== newChild &&\n newChild.type === REACT_FRAGMENT_TYPE &&\n null === newChild.key &&\n (newChild = newChild.props.children);\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n a: {\n for (var key = newChild.key; null !== currentFirstChild; ) {\n if (currentFirstChild.key === key) {\n key = newChild.type;\n if (key === REACT_FRAGMENT_TYPE) {\n if (7 === currentFirstChild.tag) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(\n currentFirstChild,\n newChild.props.children\n );\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n }\n } else if (\n currentFirstChild.elementType === key ||\n (\"object\" === typeof key &&\n null !== key &&\n key.$$typeof === REACT_LAZY_TYPE &&\n resolveLazy(key) === currentFirstChild.type)\n ) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(currentFirstChild, newChild.props);\n coerceRef(lanes, newChild);\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n }\n deleteRemainingChildren(returnFiber, currentFirstChild);\n break;\n } else deleteChild(returnFiber, currentFirstChild);\n currentFirstChild = currentFirstChild.sibling;\n }\n newChild.type === REACT_FRAGMENT_TYPE\n ? ((lanes = createFiberFromFragment(\n newChild.props.children,\n returnFiber.mode,\n lanes,\n newChild.key\n )),\n (lanes.return = returnFiber),\n (returnFiber = lanes))\n : ((lanes = createFiberFromTypeAndProps(\n newChild.type,\n newChild.key,\n newChild.props,\n null,\n returnFiber.mode,\n lanes\n )),\n coerceRef(lanes, newChild),\n (lanes.return = returnFiber),\n (returnFiber = lanes));\n }\n return placeSingleChild(returnFiber);\n case REACT_PORTAL_TYPE:\n a: {\n for (key = newChild.key; null !== currentFirstChild; ) {\n if (currentFirstChild.key === key)\n if (\n 4 === currentFirstChild.tag &&\n currentFirstChild.stateNode.containerInfo ===\n newChild.containerInfo &&\n currentFirstChild.stateNode.implementation ===\n newChild.implementation\n ) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(currentFirstChild, newChild.children || []);\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n } else {\n deleteRemainingChildren(returnFiber, currentFirstChild);\n break;\n }\n else deleteChild(returnFiber, currentFirstChild);\n currentFirstChild = currentFirstChild.sibling;\n }\n lanes = createFiberFromPortal(newChild, returnFiber.mode, lanes);\n lanes.return = returnFiber;\n returnFiber = lanes;\n }\n return placeSingleChild(returnFiber);\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n )\n );\n }\n if (isArrayImpl(newChild))\n return reconcileChildrenArray(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n if (getIteratorFn(newChild)) {\n key = getIteratorFn(newChild);\n if (\"function\" !== typeof key) throw Error(formatProdErrorMessage(150));\n newChild = key.call(newChild);\n return reconcileChildrenIterator(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n }\n if (\"function\" === typeof newChild.then)\n return reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n ? ((newChild = \"\" + newChild),\n null !== currentFirstChild && 6 === currentFirstChild.tag\n ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling),\n (lanes = useFiber(currentFirstChild, newChild)),\n (lanes.return = returnFiber),\n (returnFiber = lanes))\n : (deleteRemainingChildren(returnFiber, currentFirstChild),\n (lanes = createFiberFromText(newChild, returnFiber.mode, lanes)),\n (lanes.return = returnFiber),\n (returnFiber = lanes)),\n placeSingleChild(returnFiber))\n : deleteRemainingChildren(returnFiber, currentFirstChild);\n }\n return function (returnFiber, currentFirstChild, newChild, lanes) {\n try {\n thenableIndexCounter$1 = 0;\n var firstChildFiber = reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n thenableState$1 = null;\n return firstChildFiber;\n } catch (x) {\n if (x === SuspenseException || x === SuspenseActionException) throw x;\n var fiber = createFiberImplClass(29, x, null, returnFiber.mode);\n fiber.lanes = lanes;\n fiber.return = returnFiber;\n return fiber;\n } finally {\n }\n };\n}\nvar reconcileChildFibers = createChildReconciler(!0),\n mountChildFibers = createChildReconciler(!1),\n hasForceUpdate = !1;\nfunction initializeUpdateQueue(fiber) {\n fiber.updateQueue = {\n baseState: fiber.memoizedState,\n firstBaseUpdate: null,\n lastBaseUpdate: null,\n shared: { pending: null, lanes: 0, hiddenCallbacks: null },\n callbacks: null\n };\n}\nfunction cloneUpdateQueue(current, workInProgress) {\n current = current.updateQueue;\n workInProgress.updateQueue === current &&\n (workInProgress.updateQueue = {\n baseState: current.baseState,\n firstBaseUpdate: current.firstBaseUpdate,\n lastBaseUpdate: current.lastBaseUpdate,\n shared: current.shared,\n callbacks: null\n });\n}\nfunction createUpdate(lane) {\n return { lane: lane, tag: 0, payload: null, callback: null, next: null };\n}\nfunction enqueueUpdate(fiber, update, lane) {\n var updateQueue = fiber.updateQueue;\n if (null === updateQueue) return null;\n updateQueue = updateQueue.shared;\n if (0 !== (executionContext & 2)) {\n var pending = updateQueue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n updateQueue.pending = update;\n update = getRootForUpdatedFiber(fiber);\n markUpdateLaneFromFiberToRoot(fiber, null, lane);\n return update;\n }\n enqueueUpdate$1(fiber, updateQueue, update, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction entangleTransitions(root, fiber, lane) {\n fiber = fiber.updateQueue;\n if (null !== fiber && ((fiber = fiber.shared), 0 !== (lane & 4194048))) {\n var queueLanes = fiber.lanes;\n queueLanes &= root.pendingLanes;\n lane |= queueLanes;\n fiber.lanes = lane;\n markRootEntangled(root, lane);\n }\n}\nfunction enqueueCapturedUpdate(workInProgress, capturedUpdate) {\n var queue = workInProgress.updateQueue,\n current = workInProgress.alternate;\n if (\n null !== current &&\n ((current = current.updateQueue), queue === current)\n ) {\n var newFirst = null,\n newLast = null;\n queue = queue.firstBaseUpdate;\n if (null !== queue) {\n do {\n var clone = {\n lane: queue.lane,\n tag: queue.tag,\n payload: queue.payload,\n callback: null,\n next: null\n };\n null === newLast\n ? (newFirst = newLast = clone)\n : (newLast = newLast.next = clone);\n queue = queue.next;\n } while (null !== queue);\n null === newLast\n ? (newFirst = newLast = capturedUpdate)\n : (newLast = newLast.next = capturedUpdate);\n } else newFirst = newLast = capturedUpdate;\n queue = {\n baseState: current.baseState,\n firstBaseUpdate: newFirst,\n lastBaseUpdate: newLast,\n shared: current.shared,\n callbacks: current.callbacks\n };\n workInProgress.updateQueue = queue;\n return;\n }\n workInProgress = queue.lastBaseUpdate;\n null === workInProgress\n ? (queue.firstBaseUpdate = capturedUpdate)\n : (workInProgress.next = capturedUpdate);\n queue.lastBaseUpdate = capturedUpdate;\n}\nvar didReadFromEntangledAsyncAction = !1;\nfunction suspendIfUpdateReadFromEntangledAsyncAction() {\n if (didReadFromEntangledAsyncAction) {\n var entangledActionThenable = currentEntangledActionThenable;\n if (null !== entangledActionThenable) throw entangledActionThenable;\n }\n}\nfunction processUpdateQueue(\n workInProgress$jscomp$0,\n props,\n instance$jscomp$0,\n renderLanes\n) {\n didReadFromEntangledAsyncAction = !1;\n var queue = workInProgress$jscomp$0.updateQueue;\n hasForceUpdate = !1;\n var firstBaseUpdate = queue.firstBaseUpdate,\n lastBaseUpdate = queue.lastBaseUpdate,\n pendingQueue = queue.shared.pending;\n if (null !== pendingQueue) {\n queue.shared.pending = null;\n var lastPendingUpdate = pendingQueue,\n firstPendingUpdate = lastPendingUpdate.next;\n lastPendingUpdate.next = null;\n null === lastBaseUpdate\n ? (firstBaseUpdate = firstPendingUpdate)\n : (lastBaseUpdate.next = firstPendingUpdate);\n lastBaseUpdate = lastPendingUpdate;\n var current = workInProgress$jscomp$0.alternate;\n null !== current &&\n ((current = current.updateQueue),\n (pendingQueue = current.lastBaseUpdate),\n pendingQueue !== lastBaseUpdate &&\n (null === pendingQueue\n ? (current.firstBaseUpdate = firstPendingUpdate)\n : (pendingQueue.next = firstPendingUpdate),\n (current.lastBaseUpdate = lastPendingUpdate)));\n }\n if (null !== firstBaseUpdate) {\n var newState = queue.baseState;\n lastBaseUpdate = 0;\n current = firstPendingUpdate = lastPendingUpdate = null;\n pendingQueue = firstBaseUpdate;\n do {\n var updateLane = pendingQueue.lane & -536870913,\n isHiddenUpdate = updateLane !== pendingQueue.lane;\n if (\n isHiddenUpdate\n ? (workInProgressRootRenderLanes & updateLane) === updateLane\n : (renderLanes & updateLane) === updateLane\n ) {\n 0 !== updateLane &&\n updateLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction = !0);\n null !== current &&\n (current = current.next =\n {\n lane: 0,\n tag: pendingQueue.tag,\n payload: pendingQueue.payload,\n callback: null,\n next: null\n });\n a: {\n var workInProgress = workInProgress$jscomp$0,\n update = pendingQueue;\n updateLane = props;\n var instance = instance$jscomp$0;\n switch (update.tag) {\n case 1:\n workInProgress = update.payload;\n if (\"function\" === typeof workInProgress) {\n newState = workInProgress.call(instance, newState, updateLane);\n break a;\n }\n newState = workInProgress;\n break a;\n case 3:\n workInProgress.flags = (workInProgress.flags & -65537) | 128;\n case 0:\n workInProgress = update.payload;\n updateLane =\n \"function\" === typeof workInProgress\n ? workInProgress.call(instance, newState, updateLane)\n : workInProgress;\n if (null === updateLane || void 0 === updateLane) break a;\n newState = assign({}, newState, updateLane);\n break a;\n case 2:\n hasForceUpdate = !0;\n }\n }\n updateLane = pendingQueue.callback;\n null !== updateLane &&\n ((workInProgress$jscomp$0.flags |= 64),\n isHiddenUpdate && (workInProgress$jscomp$0.flags |= 8192),\n (isHiddenUpdate = queue.callbacks),\n null === isHiddenUpdate\n ? (queue.callbacks = [updateLane])\n : isHiddenUpdate.push(updateLane));\n } else\n (isHiddenUpdate = {\n lane: updateLane,\n tag: pendingQueue.tag,\n payload: pendingQueue.payload,\n callback: pendingQueue.callback,\n next: null\n }),\n null === current\n ? ((firstPendingUpdate = current = isHiddenUpdate),\n (lastPendingUpdate = newState))\n : (current = current.next = isHiddenUpdate),\n (lastBaseUpdate |= updateLane);\n pendingQueue = pendingQueue.next;\n if (null === pendingQueue)\n if (((pendingQueue = queue.shared.pending), null === pendingQueue))\n break;\n else\n (isHiddenUpdate = pendingQueue),\n (pendingQueue = isHiddenUpdate.next),\n (isHiddenUpdate.next = null),\n (queue.lastBaseUpdate = isHiddenUpdate),\n (queue.shared.pending = null);\n } while (1);\n null === current && (lastPendingUpdate = newState);\n queue.baseState = lastPendingUpdate;\n queue.firstBaseUpdate = firstPendingUpdate;\n queue.lastBaseUpdate = current;\n null === firstBaseUpdate && (queue.shared.lanes = 0);\n workInProgressRootSkippedLanes |= lastBaseUpdate;\n workInProgress$jscomp$0.lanes = lastBaseUpdate;\n workInProgress$jscomp$0.memoizedState = newState;\n }\n}\nfunction callCallback(callback, context) {\n if (\"function\" !== typeof callback)\n throw Error(formatProdErrorMessage(191, callback));\n callback.call(context);\n}\nfunction commitCallbacks(updateQueue, context) {\n var callbacks = updateQueue.callbacks;\n if (null !== callbacks)\n for (\n updateQueue.callbacks = null, updateQueue = 0;\n updateQueue < callbacks.length;\n updateQueue++\n )\n callCallback(callbacks[updateQueue], context);\n}\nvar currentTreeHiddenStackCursor = createCursor(null),\n prevEntangledRenderLanesCursor = createCursor(0);\nfunction pushHiddenContext(fiber, context) {\n fiber = entangledRenderLanes;\n push(prevEntangledRenderLanesCursor, fiber);\n push(currentTreeHiddenStackCursor, context);\n entangledRenderLanes = fiber | context.baseLanes;\n}\nfunction reuseHiddenContextOnStack() {\n push(prevEntangledRenderLanesCursor, entangledRenderLanes);\n push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current);\n}\nfunction popHiddenContext() {\n entangledRenderLanes = prevEntangledRenderLanesCursor.current;\n pop(currentTreeHiddenStackCursor);\n pop(prevEntangledRenderLanesCursor);\n}\nvar suspenseHandlerStackCursor = createCursor(null),\n shellBoundary = null;\nfunction pushPrimaryTreeSuspenseHandler(handler) {\n var current = handler.alternate;\n push(suspenseStackCursor, suspenseStackCursor.current & 1);\n push(suspenseHandlerStackCursor, handler);\n null === shellBoundary &&\n (null === current || null !== currentTreeHiddenStackCursor.current\n ? (shellBoundary = handler)\n : null !== current.memoizedState && (shellBoundary = handler));\n}\nfunction pushDehydratedActivitySuspenseHandler(fiber) {\n push(suspenseStackCursor, suspenseStackCursor.current);\n push(suspenseHandlerStackCursor, fiber);\n null === shellBoundary && (shellBoundary = fiber);\n}\nfunction pushOffscreenSuspenseHandler(fiber) {\n 22 === fiber.tag\n ? (push(suspenseStackCursor, suspenseStackCursor.current),\n push(suspenseHandlerStackCursor, fiber),\n null === shellBoundary && (shellBoundary = fiber))\n : reuseSuspenseHandlerOnStack(fiber);\n}\nfunction reuseSuspenseHandlerOnStack() {\n push(suspenseStackCursor, suspenseStackCursor.current);\n push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current);\n}\nfunction popSuspenseHandler(fiber) {\n pop(suspenseHandlerStackCursor);\n shellBoundary === fiber && (shellBoundary = null);\n pop(suspenseStackCursor);\n}\nvar suspenseStackCursor = createCursor(0);\nfunction findFirstSuspended(row) {\n for (var node = row; null !== node; ) {\n if (13 === node.tag) {\n var state = node.memoizedState;\n if (\n null !== state &&\n ((state = state.dehydrated),\n null === state ||\n isSuspenseInstancePending(state) ||\n isSuspenseInstanceFallback(state))\n )\n return node;\n } else if (\n 19 === node.tag &&\n (\"forwards\" === node.memoizedProps.revealOrder ||\n \"backwards\" === node.memoizedProps.revealOrder ||\n \"unstable_legacy-backwards\" === node.memoizedProps.revealOrder ||\n \"together\" === node.memoizedProps.revealOrder)\n ) {\n if (0 !== (node.flags & 128)) return node;\n } else if (null !== node.child) {\n node.child.return = node;\n node = node.child;\n continue;\n }\n if (node === row) break;\n for (; null === node.sibling; ) {\n if (null === node.return || node.return === row) return null;\n node = node.return;\n }\n node.sibling.return = node.return;\n node = node.sibling;\n }\n return null;\n}\nvar renderLanes = 0,\n currentlyRenderingFiber = null,\n currentHook = null,\n workInProgressHook = null,\n didScheduleRenderPhaseUpdate = !1,\n didScheduleRenderPhaseUpdateDuringThisPass = !1,\n shouldDoubleInvokeUserFnsInHooksDEV = !1,\n localIdCounter = 0,\n thenableIndexCounter = 0,\n thenableState = null,\n globalClientIdCounter = 0;\nfunction throwInvalidHookError() {\n throw Error(formatProdErrorMessage(321));\n}\nfunction areHookInputsEqual(nextDeps, prevDeps) {\n if (null === prevDeps) return !1;\n for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++)\n if (!objectIs(nextDeps[i], prevDeps[i])) return !1;\n return !0;\n}\nfunction renderWithHooks(\n current,\n workInProgress,\n Component,\n props,\n secondArg,\n nextRenderLanes\n) {\n renderLanes = nextRenderLanes;\n currentlyRenderingFiber = workInProgress;\n workInProgress.memoizedState = null;\n workInProgress.updateQueue = null;\n workInProgress.lanes = 0;\n ReactSharedInternals.H =\n null === current || null === current.memoizedState\n ? HooksDispatcherOnMount\n : HooksDispatcherOnUpdate;\n shouldDoubleInvokeUserFnsInHooksDEV = !1;\n nextRenderLanes = Component(props, secondArg);\n shouldDoubleInvokeUserFnsInHooksDEV = !1;\n didScheduleRenderPhaseUpdateDuringThisPass &&\n (nextRenderLanes = renderWithHooksAgain(\n workInProgress,\n Component,\n props,\n secondArg\n ));\n finishRenderingHooks(current);\n return nextRenderLanes;\n}\nfunction finishRenderingHooks(current) {\n ReactSharedInternals.H = ContextOnlyDispatcher;\n var didRenderTooFewHooks = null !== currentHook && null !== currentHook.next;\n renderLanes = 0;\n workInProgressHook = currentHook = currentlyRenderingFiber = null;\n didScheduleRenderPhaseUpdate = !1;\n thenableIndexCounter = 0;\n thenableState = null;\n if (didRenderTooFewHooks) throw Error(formatProdErrorMessage(300));\n null === current ||\n didReceiveUpdate ||\n ((current = current.dependencies),\n null !== current &&\n checkIfContextChanged(current) &&\n (didReceiveUpdate = !0));\n}\nfunction renderWithHooksAgain(workInProgress, Component, props, secondArg) {\n currentlyRenderingFiber = workInProgress;\n var numberOfReRenders = 0;\n do {\n didScheduleRenderPhaseUpdateDuringThisPass && (thenableState = null);\n thenableIndexCounter = 0;\n didScheduleRenderPhaseUpdateDuringThisPass = !1;\n if (25 <= numberOfReRenders) throw Error(formatProdErrorMessage(301));\n numberOfReRenders += 1;\n workInProgressHook = currentHook = null;\n if (null != workInProgress.updateQueue) {\n var children = workInProgress.updateQueue;\n children.lastEffect = null;\n children.events = null;\n children.stores = null;\n null != children.memoCache && (children.memoCache.index = 0);\n }\n ReactSharedInternals.H = HooksDispatcherOnRerender;\n children = Component(props, secondArg);\n } while (didScheduleRenderPhaseUpdateDuringThisPass);\n return children;\n}\nfunction TransitionAwareHostComponent() {\n var dispatcher = ReactSharedInternals.H,\n maybeThenable = dispatcher.useState()[0];\n maybeThenable =\n \"function\" === typeof maybeThenable.then\n ? useThenable(maybeThenable)\n : maybeThenable;\n dispatcher = dispatcher.useState()[0];\n (null !== currentHook ? currentHook.memoizedState : null) !== dispatcher &&\n (currentlyRenderingFiber.flags |= 1024);\n return maybeThenable;\n}\nfunction checkDidRenderIdHook() {\n var didRenderIdHook = 0 !== localIdCounter;\n localIdCounter = 0;\n return didRenderIdHook;\n}\nfunction bailoutHooks(current, workInProgress, lanes) {\n workInProgress.updateQueue = current.updateQueue;\n workInProgress.flags &= -2053;\n current.lanes &= ~lanes;\n}\nfunction resetHooksOnUnwind(workInProgress) {\n if (didScheduleRenderPhaseUpdate) {\n for (\n workInProgress = workInProgress.memoizedState;\n null !== workInProgress;\n\n ) {\n var queue = workInProgress.queue;\n null !== queue && (queue.pending = null);\n workInProgress = workInProgress.next;\n }\n didScheduleRenderPhaseUpdate = !1;\n }\n renderLanes = 0;\n workInProgressHook = currentHook = currentlyRenderingFiber = null;\n didScheduleRenderPhaseUpdateDuringThisPass = !1;\n thenableIndexCounter = localIdCounter = 0;\n thenableState = null;\n}\nfunction mountWorkInProgressHook() {\n var hook = {\n memoizedState: null,\n baseState: null,\n baseQueue: null,\n queue: null,\n next: null\n };\n null === workInProgressHook\n ? (currentlyRenderingFiber.memoizedState = workInProgressHook = hook)\n : (workInProgressHook = workInProgressHook.next = hook);\n return workInProgressHook;\n}\nfunction updateWorkInProgressHook() {\n if (null === currentHook) {\n var nextCurrentHook = currentlyRenderingFiber.alternate;\n nextCurrentHook =\n null !== nextCurrentHook ? nextCurrentHook.memoizedState : null;\n } else nextCurrentHook = currentHook.next;\n var nextWorkInProgressHook =\n null === workInProgressHook\n ? currentlyRenderingFiber.memoizedState\n : workInProgressHook.next;\n if (null !== nextWorkInProgressHook)\n (workInProgressHook = nextWorkInProgressHook),\n (currentHook = nextCurrentHook);\n else {\n if (null === nextCurrentHook) {\n if (null === currentlyRenderingFiber.alternate)\n throw Error(formatProdErrorMessage(467));\n throw Error(formatProdErrorMessage(310));\n }\n currentHook = nextCurrentHook;\n nextCurrentHook = {\n memoizedState: currentHook.memoizedState,\n baseState: currentHook.baseState,\n baseQueue: currentHook.baseQueue,\n queue: currentHook.queue,\n next: null\n };\n null === workInProgressHook\n ? (currentlyRenderingFiber.memoizedState = workInProgressHook =\n nextCurrentHook)\n : (workInProgressHook = workInProgressHook.next = nextCurrentHook);\n }\n return workInProgressHook;\n}\nfunction createFunctionComponentUpdateQueue() {\n return { lastEffect: null, events: null, stores: null, memoCache: null };\n}\nfunction useThenable(thenable) {\n var index = thenableIndexCounter;\n thenableIndexCounter += 1;\n null === thenableState && (thenableState = []);\n thenable = trackUsedThenable(thenableState, thenable, index);\n index = currentlyRenderingFiber;\n null ===\n (null === workInProgressHook\n ? index.memoizedState\n : workInProgressHook.next) &&\n ((index = index.alternate),\n (ReactSharedInternals.H =\n null === index || null === index.memoizedState\n ? HooksDispatcherOnMount\n : HooksDispatcherOnUpdate));\n return thenable;\n}\nfunction use(usable) {\n if (null !== usable && \"object\" === typeof usable) {\n if (\"function\" === typeof usable.then) return useThenable(usable);\n if (usable.$$typeof === REACT_CONTEXT_TYPE) return readContext(usable);\n }\n throw Error(formatProdErrorMessage(438, String(usable)));\n}\nfunction useMemoCache(size) {\n var memoCache = null,\n updateQueue = currentlyRenderingFiber.updateQueue;\n null !== updateQueue && (memoCache = updateQueue.memoCache);\n if (null == memoCache) {\n var current = currentlyRenderingFiber.alternate;\n null !== current &&\n ((current = current.updateQueue),\n null !== current &&\n ((current = current.memoCache),\n null != current &&\n (memoCache = {\n data: current.data.map(function (array) {\n return array.slice();\n }),\n index: 0\n })));\n }\n null == memoCache && (memoCache = { data: [], index: 0 });\n null === updateQueue &&\n ((updateQueue = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = updateQueue));\n updateQueue.memoCache = memoCache;\n updateQueue = memoCache.data[memoCache.index];\n if (void 0 === updateQueue)\n for (\n updateQueue = memoCache.data[memoCache.index] = Array(size), current = 0;\n current < size;\n current++\n )\n updateQueue[current] = REACT_MEMO_CACHE_SENTINEL;\n memoCache.index++;\n return updateQueue;\n}\nfunction basicStateReducer(state, action) {\n return \"function\" === typeof action ? action(state) : action;\n}\nfunction updateReducer(reducer) {\n var hook = updateWorkInProgressHook();\n return updateReducerImpl(hook, currentHook, reducer);\n}\nfunction updateReducerImpl(hook, current, reducer) {\n var queue = hook.queue;\n if (null === queue) throw Error(formatProdErrorMessage(311));\n queue.lastRenderedReducer = reducer;\n var baseQueue = hook.baseQueue,\n pendingQueue = queue.pending;\n if (null !== pendingQueue) {\n if (null !== baseQueue) {\n var baseFirst = baseQueue.next;\n baseQueue.next = pendingQueue.next;\n pendingQueue.next = baseFirst;\n }\n current.baseQueue = baseQueue = pendingQueue;\n queue.pending = null;\n }\n pendingQueue = hook.baseState;\n if (null === baseQueue) hook.memoizedState = pendingQueue;\n else {\n current = baseQueue.next;\n var newBaseQueueFirst = (baseFirst = null),\n newBaseQueueLast = null,\n update = current,\n didReadFromEntangledAsyncAction$60 = !1;\n do {\n var updateLane = update.lane & -536870913;\n if (\n updateLane !== update.lane\n ? (workInProgressRootRenderLanes & updateLane) === updateLane\n : (renderLanes & updateLane) === updateLane\n ) {\n var revertLane = update.revertLane;\n if (0 === revertLane)\n null !== newBaseQueueLast &&\n (newBaseQueueLast = newBaseQueueLast.next =\n {\n lane: 0,\n revertLane: 0,\n gesture: null,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n updateLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction$60 = !0);\n else if ((renderLanes & revertLane) === revertLane) {\n update = update.next;\n revertLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction$60 = !0);\n continue;\n } else\n (updateLane = {\n lane: 0,\n revertLane: update.revertLane,\n gesture: null,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n null === newBaseQueueLast\n ? ((newBaseQueueFirst = newBaseQueueLast = updateLane),\n (baseFirst = pendingQueue))\n : (newBaseQueueLast = newBaseQueueLast.next = updateLane),\n (currentlyRenderingFiber.lanes |= revertLane),\n (workInProgressRootSkippedLanes |= revertLane);\n updateLane = update.action;\n shouldDoubleInvokeUserFnsInHooksDEV &&\n reducer(pendingQueue, updateLane);\n pendingQueue = update.hasEagerState\n ? update.eagerState\n : reducer(pendingQueue, updateLane);\n } else\n (revertLane = {\n lane: updateLane,\n revertLane: update.revertLane,\n gesture: update.gesture,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n null === newBaseQueueLast\n ? ((newBaseQueueFirst = newBaseQueueLast = revertLane),\n (baseFirst = pendingQueue))\n : (newBaseQueueLast = newBaseQueueLast.next = revertLane),\n (currentlyRenderingFiber.lanes |= updateLane),\n (workInProgressRootSkippedLanes |= updateLane);\n update = update.next;\n } while (null !== update && update !== current);\n null === newBaseQueueLast\n ? (baseFirst = pendingQueue)\n : (newBaseQueueLast.next = newBaseQueueFirst);\n if (\n !objectIs(pendingQueue, hook.memoizedState) &&\n ((didReceiveUpdate = !0),\n didReadFromEntangledAsyncAction$60 &&\n ((reducer = currentEntangledActionThenable), null !== reducer))\n )\n throw reducer;\n hook.memoizedState = pendingQueue;\n hook.baseState = baseFirst;\n hook.baseQueue = newBaseQueueLast;\n queue.lastRenderedState = pendingQueue;\n }\n null === baseQueue && (queue.lanes = 0);\n return [hook.memoizedState, queue.dispatch];\n}\nfunction rerenderReducer(reducer) {\n var hook = updateWorkInProgressHook(),\n queue = hook.queue;\n if (null === queue) throw Error(formatProdErrorMessage(311));\n queue.lastRenderedReducer = reducer;\n var dispatch = queue.dispatch,\n lastRenderPhaseUpdate = queue.pending,\n newState = hook.memoizedState;\n if (null !== lastRenderPhaseUpdate) {\n queue.pending = null;\n var update = (lastRenderPhaseUpdate = lastRenderPhaseUpdate.next);\n do (newState = reducer(newState, update.action)), (update = update.next);\n while (update !== lastRenderPhaseUpdate);\n objectIs(newState, hook.memoizedState) || (didReceiveUpdate = !0);\n hook.memoizedState = newState;\n null === hook.baseQueue && (hook.baseState = newState);\n queue.lastRenderedState = newState;\n }\n return [newState, dispatch];\n}\nfunction updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {\n var fiber = currentlyRenderingFiber,\n hook = updateWorkInProgressHook(),\n isHydrating$jscomp$0 = isHydrating;\n if (isHydrating$jscomp$0) {\n if (void 0 === getServerSnapshot) throw Error(formatProdErrorMessage(407));\n getServerSnapshot = getServerSnapshot();\n } else getServerSnapshot = getSnapshot();\n var snapshotChanged = !objectIs(\n (currentHook || hook).memoizedState,\n getServerSnapshot\n );\n snapshotChanged &&\n ((hook.memoizedState = getServerSnapshot), (didReceiveUpdate = !0));\n hook = hook.queue;\n updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [\n subscribe\n ]);\n if (\n hook.getSnapshot !== getSnapshot ||\n snapshotChanged ||\n (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1)\n ) {\n fiber.flags |= 2048;\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n updateStoreInstance.bind(\n null,\n fiber,\n hook,\n getServerSnapshot,\n getSnapshot\n ),\n null\n );\n if (null === workInProgressRoot) throw Error(formatProdErrorMessage(349));\n isHydrating$jscomp$0 ||\n 0 !== (renderLanes & 127) ||\n pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot);\n }\n return getServerSnapshot;\n}\nfunction pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {\n fiber.flags |= 16384;\n fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };\n getSnapshot = currentlyRenderingFiber.updateQueue;\n null === getSnapshot\n ? ((getSnapshot = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = getSnapshot),\n (getSnapshot.stores = [fiber]))\n : ((renderedSnapshot = getSnapshot.stores),\n null === renderedSnapshot\n ? (getSnapshot.stores = [fiber])\n : renderedSnapshot.push(fiber));\n}\nfunction updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {\n inst.value = nextSnapshot;\n inst.getSnapshot = getSnapshot;\n checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);\n}\nfunction subscribeToStore(fiber, inst, subscribe) {\n return subscribe(function () {\n checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);\n });\n}\nfunction checkIfSnapshotChanged(inst) {\n var latestGetSnapshot = inst.getSnapshot;\n inst = inst.value;\n try {\n var nextValue = latestGetSnapshot();\n return !objectIs(inst, nextValue);\n } catch (error) {\n return !0;\n }\n}\nfunction forceStoreRerender(fiber) {\n var root = enqueueConcurrentRenderForLane(fiber, 2);\n null !== root && scheduleUpdateOnFiber(root, fiber, 2);\n}\nfunction mountStateImpl(initialState) {\n var hook = mountWorkInProgressHook();\n if (\"function\" === typeof initialState) {\n var initialStateInitializer = initialState;\n initialState = initialStateInitializer();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n initialStateInitializer();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n }\n hook.memoizedState = hook.baseState = initialState;\n hook.queue = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: initialState\n };\n return hook;\n}\nfunction updateOptimisticImpl(hook, current, passthrough, reducer) {\n hook.baseState = passthrough;\n return updateReducerImpl(\n hook,\n currentHook,\n \"function\" === typeof reducer ? reducer : basicStateReducer\n );\n}\nfunction dispatchActionState(\n fiber,\n actionQueue,\n setPendingState,\n setState,\n payload\n) {\n if (isRenderPhaseUpdate(fiber)) throw Error(formatProdErrorMessage(485));\n fiber = actionQueue.action;\n if (null !== fiber) {\n var actionNode = {\n payload: payload,\n action: fiber,\n next: null,\n isTransition: !0,\n status: \"pending\",\n value: null,\n reason: null,\n listeners: [],\n then: function (listener) {\n actionNode.listeners.push(listener);\n }\n };\n null !== ReactSharedInternals.T\n ? setPendingState(!0)\n : (actionNode.isTransition = !1);\n setState(actionNode);\n setPendingState = actionQueue.pending;\n null === setPendingState\n ? ((actionNode.next = actionQueue.pending = actionNode),\n runActionStateAction(actionQueue, actionNode))\n : ((actionNode.next = setPendingState.next),\n (actionQueue.pending = setPendingState.next = actionNode));\n }\n}\nfunction runActionStateAction(actionQueue, node) {\n var action = node.action,\n payload = node.payload,\n prevState = actionQueue.state;\n if (node.isTransition) {\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n try {\n var returnValue = action(prevState, payload),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n handleActionReturnValue(actionQueue, node, returnValue);\n } catch (error) {\n onActionError(actionQueue, node, error);\n } finally {\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n } else\n try {\n (prevTransition = action(prevState, payload)),\n handleActionReturnValue(actionQueue, node, prevTransition);\n } catch (error$66) {\n onActionError(actionQueue, node, error$66);\n }\n}\nfunction handleActionReturnValue(actionQueue, node, returnValue) {\n null !== returnValue &&\n \"object\" === typeof returnValue &&\n \"function\" === typeof returnValue.then\n ? returnValue.then(\n function (nextState) {\n onActionSuccess(actionQueue, node, nextState);\n },\n function (error) {\n return onActionError(actionQueue, node, error);\n }\n )\n : onActionSuccess(actionQueue, node, returnValue);\n}\nfunction onActionSuccess(actionQueue, actionNode, nextState) {\n actionNode.status = \"fulfilled\";\n actionNode.value = nextState;\n notifyActionListeners(actionNode);\n actionQueue.state = nextState;\n actionNode = actionQueue.pending;\n null !== actionNode &&\n ((nextState = actionNode.next),\n nextState === actionNode\n ? (actionQueue.pending = null)\n : ((nextState = nextState.next),\n (actionNode.next = nextState),\n runActionStateAction(actionQueue, nextState)));\n}\nfunction onActionError(actionQueue, actionNode, error) {\n var last = actionQueue.pending;\n actionQueue.pending = null;\n if (null !== last) {\n last = last.next;\n do\n (actionNode.status = \"rejected\"),\n (actionNode.reason = error),\n notifyActionListeners(actionNode),\n (actionNode = actionNode.next);\n while (actionNode !== last);\n }\n actionQueue.action = null;\n}\nfunction notifyActionListeners(actionNode) {\n actionNode = actionNode.listeners;\n for (var i = 0; i < actionNode.length; i++) (0, actionNode[i])();\n}\nfunction actionStateReducer(oldState, newState) {\n return newState;\n}\nfunction mountActionState(action, initialStateProp) {\n if (isHydrating) {\n var ssrFormState = workInProgressRoot.formState;\n if (null !== ssrFormState) {\n a: {\n var JSCompiler_inline_result = currentlyRenderingFiber;\n if (isHydrating) {\n if (nextHydratableInstance) {\n b: {\n var JSCompiler_inline_result$jscomp$0 = nextHydratableInstance;\n for (\n var inRootOrSingleton = rootOrSingletonContext;\n 8 !== JSCompiler_inline_result$jscomp$0.nodeType;\n\n ) {\n if (!inRootOrSingleton) {\n JSCompiler_inline_result$jscomp$0 = null;\n break b;\n }\n JSCompiler_inline_result$jscomp$0 = getNextHydratable(\n JSCompiler_inline_result$jscomp$0.nextSibling\n );\n if (null === JSCompiler_inline_result$jscomp$0) {\n JSCompiler_inline_result$jscomp$0 = null;\n break b;\n }\n }\n inRootOrSingleton = JSCompiler_inline_result$jscomp$0.data;\n JSCompiler_inline_result$jscomp$0 =\n \"F!\" === inRootOrSingleton || \"F\" === inRootOrSingleton\n ? JSCompiler_inline_result$jscomp$0\n : null;\n }\n if (JSCompiler_inline_result$jscomp$0) {\n nextHydratableInstance = getNextHydratable(\n JSCompiler_inline_result$jscomp$0.nextSibling\n );\n JSCompiler_inline_result =\n \"F!\" === JSCompiler_inline_result$jscomp$0.data;\n break a;\n }\n }\n throwOnHydrationMismatch(JSCompiler_inline_result);\n }\n JSCompiler_inline_result = !1;\n }\n JSCompiler_inline_result && (initialStateProp = ssrFormState[0]);\n }\n }\n ssrFormState = mountWorkInProgressHook();\n ssrFormState.memoizedState = ssrFormState.baseState = initialStateProp;\n JSCompiler_inline_result = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: actionStateReducer,\n lastRenderedState: initialStateProp\n };\n ssrFormState.queue = JSCompiler_inline_result;\n ssrFormState = dispatchSetState.bind(\n null,\n currentlyRenderingFiber,\n JSCompiler_inline_result\n );\n JSCompiler_inline_result.dispatch = ssrFormState;\n JSCompiler_inline_result = mountStateImpl(!1);\n inRootOrSingleton = dispatchOptimisticSetState.bind(\n null,\n currentlyRenderingFiber,\n !1,\n JSCompiler_inline_result.queue\n );\n JSCompiler_inline_result = mountWorkInProgressHook();\n JSCompiler_inline_result$jscomp$0 = {\n state: initialStateProp,\n dispatch: null,\n action: action,\n pending: null\n };\n JSCompiler_inline_result.queue = JSCompiler_inline_result$jscomp$0;\n ssrFormState = dispatchActionState.bind(\n null,\n currentlyRenderingFiber,\n JSCompiler_inline_result$jscomp$0,\n inRootOrSingleton,\n ssrFormState\n );\n JSCompiler_inline_result$jscomp$0.dispatch = ssrFormState;\n JSCompiler_inline_result.memoizedState = action;\n return [initialStateProp, ssrFormState, !1];\n}\nfunction updateActionState(action) {\n var stateHook = updateWorkInProgressHook();\n return updateActionStateImpl(stateHook, currentHook, action);\n}\nfunction updateActionStateImpl(stateHook, currentStateHook, action) {\n currentStateHook = updateReducerImpl(\n stateHook,\n currentStateHook,\n actionStateReducer\n )[0];\n stateHook = updateReducer(basicStateReducer)[0];\n if (\n \"object\" === typeof currentStateHook &&\n null !== currentStateHook &&\n \"function\" === typeof currentStateHook.then\n )\n try {\n var state = useThenable(currentStateHook);\n } catch (x) {\n if (x === SuspenseException) throw SuspenseActionException;\n throw x;\n }\n else state = currentStateHook;\n currentStateHook = updateWorkInProgressHook();\n var actionQueue = currentStateHook.queue,\n dispatch = actionQueue.dispatch;\n action !== currentStateHook.memoizedState &&\n ((currentlyRenderingFiber.flags |= 2048),\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n actionStateActionEffect.bind(null, actionQueue, action),\n null\n ));\n return [state, dispatch, stateHook];\n}\nfunction actionStateActionEffect(actionQueue, action) {\n actionQueue.action = action;\n}\nfunction rerenderActionState(action) {\n var stateHook = updateWorkInProgressHook(),\n currentStateHook = currentHook;\n if (null !== currentStateHook)\n return updateActionStateImpl(stateHook, currentStateHook, action);\n updateWorkInProgressHook();\n stateHook = stateHook.memoizedState;\n currentStateHook = updateWorkInProgressHook();\n var dispatch = currentStateHook.queue.dispatch;\n currentStateHook.memoizedState = action;\n return [stateHook, dispatch, !1];\n}\nfunction pushSimpleEffect(tag, inst, create, deps) {\n tag = { tag: tag, create: create, deps: deps, inst: inst, next: null };\n inst = currentlyRenderingFiber.updateQueue;\n null === inst &&\n ((inst = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = inst));\n create = inst.lastEffect;\n null === create\n ? (inst.lastEffect = tag.next = tag)\n : ((deps = create.next),\n (create.next = tag),\n (tag.next = deps),\n (inst.lastEffect = tag));\n return tag;\n}\nfunction updateRef() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction mountEffectImpl(fiberFlags, hookFlags, create, deps) {\n var hook = mountWorkInProgressHook();\n currentlyRenderingFiber.flags |= fiberFlags;\n hook.memoizedState = pushSimpleEffect(\n 1 | hookFlags,\n { destroy: void 0 },\n create,\n void 0 === deps ? null : deps\n );\n}\nfunction updateEffectImpl(fiberFlags, hookFlags, create, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var inst = hook.memoizedState.inst;\n null !== currentHook &&\n null !== deps &&\n areHookInputsEqual(deps, currentHook.memoizedState.deps)\n ? (hook.memoizedState = pushSimpleEffect(hookFlags, inst, create, deps))\n : ((currentlyRenderingFiber.flags |= fiberFlags),\n (hook.memoizedState = pushSimpleEffect(\n 1 | hookFlags,\n inst,\n create,\n deps\n )));\n}\nfunction mountEffect(create, deps) {\n mountEffectImpl(8390656, 8, create, deps);\n}\nfunction updateEffect(create, deps) {\n updateEffectImpl(2048, 8, create, deps);\n}\nfunction useEffectEventImpl(payload) {\n currentlyRenderingFiber.flags |= 4;\n var componentUpdateQueue = currentlyRenderingFiber.updateQueue;\n if (null === componentUpdateQueue)\n (componentUpdateQueue = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = componentUpdateQueue),\n (componentUpdateQueue.events = [payload]);\n else {\n var events = componentUpdateQueue.events;\n null === events\n ? (componentUpdateQueue.events = [payload])\n : events.push(payload);\n }\n}\nfunction updateEvent(callback) {\n var ref = updateWorkInProgressHook().memoizedState;\n useEffectEventImpl({ ref: ref, nextImpl: callback });\n return function () {\n if (0 !== (executionContext & 2)) throw Error(formatProdErrorMessage(440));\n return ref.impl.apply(void 0, arguments);\n };\n}\nfunction updateInsertionEffect(create, deps) {\n return updateEffectImpl(4, 2, create, deps);\n}\nfunction updateLayoutEffect(create, deps) {\n return updateEffectImpl(4, 4, create, deps);\n}\nfunction imperativeHandleEffect(create, ref) {\n if (\"function\" === typeof ref) {\n create = create();\n var refCleanup = ref(create);\n return function () {\n \"function\" === typeof refCleanup ? refCleanup() : ref(null);\n };\n }\n if (null !== ref && void 0 !== ref)\n return (\n (create = create()),\n (ref.current = create),\n function () {\n ref.current = null;\n }\n );\n}\nfunction updateImperativeHandle(ref, create, deps) {\n deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;\n updateEffectImpl(4, 4, imperativeHandleEffect.bind(null, create, ref), deps);\n}\nfunction mountDebugValue() {}\nfunction updateCallback(callback, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var prevState = hook.memoizedState;\n if (null !== deps && areHookInputsEqual(deps, prevState[1]))\n return prevState[0];\n hook.memoizedState = [callback, deps];\n return callback;\n}\nfunction updateMemo(nextCreate, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var prevState = hook.memoizedState;\n if (null !== deps && areHookInputsEqual(deps, prevState[1]))\n return prevState[0];\n prevState = nextCreate();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n nextCreate();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n hook.memoizedState = [prevState, deps];\n return prevState;\n}\nfunction mountDeferredValueImpl(hook, value, initialValue) {\n if (\n void 0 === initialValue ||\n (0 !== (renderLanes & 1073741824) &&\n 0 === (workInProgressRootRenderLanes & 261930))\n )\n return (hook.memoizedState = value);\n hook.memoizedState = initialValue;\n hook = requestDeferredLane();\n currentlyRenderingFiber.lanes |= hook;\n workInProgressRootSkippedLanes |= hook;\n return initialValue;\n}\nfunction updateDeferredValueImpl(hook, prevValue, value, initialValue) {\n if (objectIs(value, prevValue)) return value;\n if (null !== currentTreeHiddenStackCursor.current)\n return (\n (hook = mountDeferredValueImpl(hook, value, initialValue)),\n objectIs(hook, prevValue) || (didReceiveUpdate = !0),\n hook\n );\n if (\n 0 === (renderLanes & 42) ||\n (0 !== (renderLanes & 1073741824) &&\n 0 === (workInProgressRootRenderLanes & 261930))\n )\n return (didReceiveUpdate = !0), (hook.memoizedState = value);\n hook = requestDeferredLane();\n currentlyRenderingFiber.lanes |= hook;\n workInProgressRootSkippedLanes |= hook;\n return prevValue;\n}\nfunction startTransition(fiber, queue, pendingState, finishedState, callback) {\n var previousPriority = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p =\n 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8;\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n dispatchOptimisticSetState(fiber, !1, queue, pendingState);\n try {\n var returnValue = callback(),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n if (\n null !== returnValue &&\n \"object\" === typeof returnValue &&\n \"function\" === typeof returnValue.then\n ) {\n var thenableForFinishedState = chainThenableValue(\n returnValue,\n finishedState\n );\n dispatchSetStateInternal(\n fiber,\n queue,\n thenableForFinishedState,\n requestUpdateLane(fiber)\n );\n } else\n dispatchSetStateInternal(\n fiber,\n queue,\n finishedState,\n requestUpdateLane(fiber)\n );\n } catch (error) {\n dispatchSetStateInternal(\n fiber,\n queue,\n { then: function () {}, status: \"rejected\", reason: error },\n requestUpdateLane()\n );\n } finally {\n (ReactDOMSharedInternals.p = previousPriority),\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n}\nfunction noop() {}\nfunction startHostTransition(formFiber, pendingState, action, formData) {\n if (5 !== formFiber.tag) throw Error(formatProdErrorMessage(476));\n var queue = ensureFormComponentIsStateful(formFiber).queue;\n startTransition(\n formFiber,\n queue,\n pendingState,\n sharedNotPendingObject,\n null === action\n ? noop\n : function () {\n requestFormReset$1(formFiber);\n return action(formData);\n }\n );\n}\nfunction ensureFormComponentIsStateful(formFiber) {\n var existingStateHook = formFiber.memoizedState;\n if (null !== existingStateHook) return existingStateHook;\n existingStateHook = {\n memoizedState: sharedNotPendingObject,\n baseState: sharedNotPendingObject,\n baseQueue: null,\n queue: {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: sharedNotPendingObject\n },\n next: null\n };\n var initialResetState = {};\n existingStateHook.next = {\n memoizedState: initialResetState,\n baseState: initialResetState,\n baseQueue: null,\n queue: {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: initialResetState\n },\n next: null\n };\n formFiber.memoizedState = existingStateHook;\n formFiber = formFiber.alternate;\n null !== formFiber && (formFiber.memoizedState = existingStateHook);\n return existingStateHook;\n}\nfunction requestFormReset$1(formFiber) {\n var stateHook = ensureFormComponentIsStateful(formFiber);\n null === stateHook.next && (stateHook = formFiber.alternate.memoizedState);\n dispatchSetStateInternal(\n formFiber,\n stateHook.next.queue,\n {},\n requestUpdateLane()\n );\n}\nfunction useHostTransitionStatus() {\n return readContext(HostTransitionContext);\n}\nfunction updateId() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction updateRefresh() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction refreshCache(fiber) {\n for (var provider = fiber.return; null !== provider; ) {\n switch (provider.tag) {\n case 24:\n case 3:\n var lane = requestUpdateLane();\n fiber = createUpdate(lane);\n var root$69 = enqueueUpdate(provider, fiber, lane);\n null !== root$69 &&\n (scheduleUpdateOnFiber(root$69, provider, lane),\n entangleTransitions(root$69, provider, lane));\n provider = { cache: createCache() };\n fiber.payload = provider;\n return;\n }\n provider = provider.return;\n }\n}\nfunction dispatchReducerAction(fiber, queue, action) {\n var lane = requestUpdateLane();\n action = {\n lane: lane,\n revertLane: 0,\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n isRenderPhaseUpdate(fiber)\n ? enqueueRenderPhaseUpdate(queue, action)\n : ((action = enqueueConcurrentHookUpdate(fiber, queue, action, lane)),\n null !== action &&\n (scheduleUpdateOnFiber(action, fiber, lane),\n entangleTransitionUpdate(action, queue, lane)));\n}\nfunction dispatchSetState(fiber, queue, action) {\n var lane = requestUpdateLane();\n dispatchSetStateInternal(fiber, queue, action, lane);\n}\nfunction dispatchSetStateInternal(fiber, queue, action, lane) {\n var update = {\n lane: lane,\n revertLane: 0,\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, update);\n else {\n var alternate = fiber.alternate;\n if (\n 0 === fiber.lanes &&\n (null === alternate || 0 === alternate.lanes) &&\n ((alternate = queue.lastRenderedReducer), null !== alternate)\n )\n try {\n var currentState = queue.lastRenderedState,\n eagerState = alternate(currentState, action);\n update.hasEagerState = !0;\n update.eagerState = eagerState;\n if (objectIs(eagerState, currentState))\n return (\n enqueueUpdate$1(fiber, queue, update, 0),\n null === workInProgressRoot && finishQueueingConcurrentUpdates(),\n !1\n );\n } catch (error) {\n } finally {\n }\n action = enqueueConcurrentHookUpdate(fiber, queue, update, lane);\n if (null !== action)\n return (\n scheduleUpdateOnFiber(action, fiber, lane),\n entangleTransitionUpdate(action, queue, lane),\n !0\n );\n }\n return !1;\n}\nfunction dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) {\n action = {\n lane: 2,\n revertLane: requestTransitionLane(),\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n if (isRenderPhaseUpdate(fiber)) {\n if (throwIfDuringRender) throw Error(formatProdErrorMessage(479));\n } else\n (throwIfDuringRender = enqueueConcurrentHookUpdate(\n fiber,\n queue,\n action,\n 2\n )),\n null !== throwIfDuringRender &&\n scheduleUpdateOnFiber(throwIfDuringRender, fiber, 2);\n}\nfunction isRenderPhaseUpdate(fiber) {\n var alternate = fiber.alternate;\n return (\n fiber === currentlyRenderingFiber ||\n (null !== alternate && alternate === currentlyRenderingFiber)\n );\n}\nfunction enqueueRenderPhaseUpdate(queue, update) {\n didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate =\n !0;\n var pending = queue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n queue.pending = update;\n}\nfunction entangleTransitionUpdate(root, queue, lane) {\n if (0 !== (lane & 4194048)) {\n var queueLanes = queue.lanes;\n queueLanes &= root.pendingLanes;\n lane |= queueLanes;\n queue.lanes = lane;\n markRootEntangled(root, lane);\n }\n}\nvar ContextOnlyDispatcher = {\n readContext: readContext,\n use: use,\n useCallback: throwInvalidHookError,\n useContext: throwInvalidHookError,\n useEffect: throwInvalidHookError,\n useImperativeHandle: throwInvalidHookError,\n useLayoutEffect: throwInvalidHookError,\n useInsertionEffect: throwInvalidHookError,\n useMemo: throwInvalidHookError,\n useReducer: throwInvalidHookError,\n useRef: throwInvalidHookError,\n useState: throwInvalidHookError,\n useDebugValue: throwInvalidHookError,\n useDeferredValue: throwInvalidHookError,\n useTransition: throwInvalidHookError,\n useSyncExternalStore: throwInvalidHookError,\n useId: throwInvalidHookError,\n useHostTransitionStatus: throwInvalidHookError,\n useFormState: throwInvalidHookError,\n useActionState: throwInvalidHookError,\n useOptimistic: throwInvalidHookError,\n useMemoCache: throwInvalidHookError,\n useCacheRefresh: throwInvalidHookError\n};\nContextOnlyDispatcher.useEffectEvent = throwInvalidHookError;\nvar HooksDispatcherOnMount = {\n readContext: readContext,\n use: use,\n useCallback: function (callback, deps) {\n mountWorkInProgressHook().memoizedState = [\n callback,\n void 0 === deps ? null : deps\n ];\n return callback;\n },\n useContext: readContext,\n useEffect: mountEffect,\n useImperativeHandle: function (ref, create, deps) {\n deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;\n mountEffectImpl(\n 4194308,\n 4,\n imperativeHandleEffect.bind(null, create, ref),\n deps\n );\n },\n useLayoutEffect: function (create, deps) {\n return mountEffectImpl(4194308, 4, create, deps);\n },\n useInsertionEffect: function (create, deps) {\n mountEffectImpl(4, 2, create, deps);\n },\n useMemo: function (nextCreate, deps) {\n var hook = mountWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var nextValue = nextCreate();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n nextCreate();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n hook.memoizedState = [nextValue, deps];\n return nextValue;\n },\n useReducer: function (reducer, initialArg, init) {\n var hook = mountWorkInProgressHook();\n if (void 0 !== init) {\n var initialState = init(initialArg);\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n init(initialArg);\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n } else initialState = initialArg;\n hook.memoizedState = hook.baseState = initialState;\n reducer = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: reducer,\n lastRenderedState: initialState\n };\n hook.queue = reducer;\n reducer = reducer.dispatch = dispatchReducerAction.bind(\n null,\n currentlyRenderingFiber,\n reducer\n );\n return [hook.memoizedState, reducer];\n },\n useRef: function (initialValue) {\n var hook = mountWorkInProgressHook();\n initialValue = { current: initialValue };\n return (hook.memoizedState = initialValue);\n },\n useState: function (initialState) {\n initialState = mountStateImpl(initialState);\n var queue = initialState.queue,\n dispatch = dispatchSetState.bind(null, currentlyRenderingFiber, queue);\n queue.dispatch = dispatch;\n return [initialState.memoizedState, dispatch];\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = mountWorkInProgressHook();\n return mountDeferredValueImpl(hook, value, initialValue);\n },\n useTransition: function () {\n var stateHook = mountStateImpl(!1);\n stateHook = startTransition.bind(\n null,\n currentlyRenderingFiber,\n stateHook.queue,\n !0,\n !1\n );\n mountWorkInProgressHook().memoizedState = stateHook;\n return [!1, stateHook];\n },\n useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {\n var fiber = currentlyRenderingFiber,\n hook = mountWorkInProgressHook();\n if (isHydrating) {\n if (void 0 === getServerSnapshot)\n throw Error(formatProdErrorMessage(407));\n getServerSnapshot = getServerSnapshot();\n } else {\n getServerSnapshot = getSnapshot();\n if (null === workInProgressRoot)\n throw Error(formatProdErrorMessage(349));\n 0 !== (workInProgressRootRenderLanes & 127) ||\n pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot);\n }\n hook.memoizedState = getServerSnapshot;\n var inst = { value: getServerSnapshot, getSnapshot: getSnapshot };\n hook.queue = inst;\n mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [\n subscribe\n ]);\n fiber.flags |= 2048;\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n updateStoreInstance.bind(\n null,\n fiber,\n inst,\n getServerSnapshot,\n getSnapshot\n ),\n null\n );\n return getServerSnapshot;\n },\n useId: function () {\n var hook = mountWorkInProgressHook(),\n identifierPrefix = workInProgressRoot.identifierPrefix;\n if (isHydrating) {\n var JSCompiler_inline_result = treeContextOverflow;\n var idWithLeadingBit = treeContextId;\n JSCompiler_inline_result =\n (\n idWithLeadingBit & ~(1 << (32 - clz32(idWithLeadingBit) - 1))\n ).toString(32) + JSCompiler_inline_result;\n identifierPrefix =\n \"_\" + identifierPrefix + \"R_\" + JSCompiler_inline_result;\n JSCompiler_inline_result = localIdCounter++;\n 0 < JSCompiler_inline_result &&\n (identifierPrefix += \"H\" + JSCompiler_inline_result.toString(32));\n identifierPrefix += \"_\";\n } else\n (JSCompiler_inline_result = globalClientIdCounter++),\n (identifierPrefix =\n \"_\" +\n identifierPrefix +\n \"r_\" +\n JSCompiler_inline_result.toString(32) +\n \"_\");\n return (hook.memoizedState = identifierPrefix);\n },\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: mountActionState,\n useActionState: mountActionState,\n useOptimistic: function (passthrough) {\n var hook = mountWorkInProgressHook();\n hook.memoizedState = hook.baseState = passthrough;\n var queue = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: null,\n lastRenderedState: null\n };\n hook.queue = queue;\n hook = dispatchOptimisticSetState.bind(\n null,\n currentlyRenderingFiber,\n !0,\n queue\n );\n queue.dispatch = hook;\n return [passthrough, hook];\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: function () {\n return (mountWorkInProgressHook().memoizedState = refreshCache.bind(\n null,\n currentlyRenderingFiber\n ));\n },\n useEffectEvent: function (callback) {\n var hook = mountWorkInProgressHook(),\n ref = { impl: callback };\n hook.memoizedState = ref;\n return function () {\n if (0 !== (executionContext & 2))\n throw Error(formatProdErrorMessage(440));\n return ref.impl.apply(void 0, arguments);\n };\n }\n },\n HooksDispatcherOnUpdate = {\n readContext: readContext,\n use: use,\n useCallback: updateCallback,\n useContext: readContext,\n useEffect: updateEffect,\n useImperativeHandle: updateImperativeHandle,\n useInsertionEffect: updateInsertionEffect,\n useLayoutEffect: updateLayoutEffect,\n useMemo: updateMemo,\n useReducer: updateReducer,\n useRef: updateRef,\n useState: function () {\n return updateReducer(basicStateReducer);\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = updateWorkInProgressHook();\n return updateDeferredValueImpl(\n hook,\n currentHook.memoizedState,\n value,\n initialValue\n );\n },\n useTransition: function () {\n var booleanOrThenable = updateReducer(basicStateReducer)[0],\n start = updateWorkInProgressHook().memoizedState;\n return [\n \"boolean\" === typeof booleanOrThenable\n ? booleanOrThenable\n : useThenable(booleanOrThenable),\n start\n ];\n },\n useSyncExternalStore: updateSyncExternalStore,\n useId: updateId,\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: updateActionState,\n useActionState: updateActionState,\n useOptimistic: function (passthrough, reducer) {\n var hook = updateWorkInProgressHook();\n return updateOptimisticImpl(hook, currentHook, passthrough, reducer);\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: updateRefresh\n };\nHooksDispatcherOnUpdate.useEffectEvent = updateEvent;\nvar HooksDispatcherOnRerender = {\n readContext: readContext,\n use: use,\n useCallback: updateCallback,\n useContext: readContext,\n useEffect: updateEffect,\n useImperativeHandle: updateImperativeHandle,\n useInsertionEffect: updateInsertionEffect,\n useLayoutEffect: updateLayoutEffect,\n useMemo: updateMemo,\n useReducer: rerenderReducer,\n useRef: updateRef,\n useState: function () {\n return rerenderReducer(basicStateReducer);\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = updateWorkInProgressHook();\n return null === currentHook\n ? mountDeferredValueImpl(hook, value, initialValue)\n : updateDeferredValueImpl(\n hook,\n currentHook.memoizedState,\n value,\n initialValue\n );\n },\n useTransition: function () {\n var booleanOrThenable = rerenderReducer(basicStateReducer)[0],\n start = updateWorkInProgressHook().memoizedState;\n return [\n \"boolean\" === typeof booleanOrThenable\n ? booleanOrThenable\n : useThenable(booleanOrThenable),\n start\n ];\n },\n useSyncExternalStore: updateSyncExternalStore,\n useId: updateId,\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: rerenderActionState,\n useActionState: rerenderActionState,\n useOptimistic: function (passthrough, reducer) {\n var hook = updateWorkInProgressHook();\n if (null !== currentHook)\n return updateOptimisticImpl(hook, currentHook, passthrough, reducer);\n hook.baseState = passthrough;\n return [passthrough, hook.queue.dispatch];\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: updateRefresh\n};\nHooksDispatcherOnRerender.useEffectEvent = updateEvent;\nfunction applyDerivedStateFromProps(\n workInProgress,\n ctor,\n getDerivedStateFromProps,\n nextProps\n) {\n ctor = workInProgress.memoizedState;\n getDerivedStateFromProps = getDerivedStateFromProps(nextProps, ctor);\n getDerivedStateFromProps =\n null === getDerivedStateFromProps || void 0 === getDerivedStateFromProps\n ? ctor\n : assign({}, ctor, getDerivedStateFromProps);\n workInProgress.memoizedState = getDerivedStateFromProps;\n 0 === workInProgress.lanes &&\n (workInProgress.updateQueue.baseState = getDerivedStateFromProps);\n}\nvar classComponentUpdater = {\n enqueueSetState: function (inst, payload, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.payload = payload;\n void 0 !== callback && null !== callback && (update.callback = callback);\n payload = enqueueUpdate(inst, update, lane);\n null !== payload &&\n (scheduleUpdateOnFiber(payload, inst, lane),\n entangleTransitions(payload, inst, lane));\n },\n enqueueReplaceState: function (inst, payload, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.tag = 1;\n update.payload = payload;\n void 0 !== callback && null !== callback && (update.callback = callback);\n payload = enqueueUpdate(inst, update, lane);\n null !== payload &&\n (scheduleUpdateOnFiber(payload, inst, lane),\n entangleTransitions(payload, inst, lane));\n },\n enqueueForceUpdate: function (inst, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.tag = 2;\n void 0 !== callback && null !== callback && (update.callback = callback);\n callback = enqueueUpdate(inst, update, lane);\n null !== callback &&\n (scheduleUpdateOnFiber(callback, inst, lane),\n entangleTransitions(callback, inst, lane));\n }\n};\nfunction checkShouldComponentUpdate(\n workInProgress,\n ctor,\n oldProps,\n newProps,\n oldState,\n newState,\n nextContext\n) {\n workInProgress = workInProgress.stateNode;\n return \"function\" === typeof workInProgress.shouldComponentUpdate\n ? workInProgress.shouldComponentUpdate(newProps, newState, nextContext)\n : ctor.prototype && ctor.prototype.isPureReactComponent\n ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)\n : !0;\n}\nfunction callComponentWillReceiveProps(\n workInProgress,\n instance,\n newProps,\n nextContext\n) {\n workInProgress = instance.state;\n \"function\" === typeof instance.componentWillReceiveProps &&\n instance.componentWillReceiveProps(newProps, nextContext);\n \"function\" === typeof instance.UNSAFE_componentWillReceiveProps &&\n instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);\n instance.state !== workInProgress &&\n classComponentUpdater.enqueueReplaceState(instance, instance.state, null);\n}\nfunction resolveClassComponentProps(Component, baseProps) {\n var newProps = baseProps;\n if (\"ref\" in baseProps) {\n newProps = {};\n for (var propName in baseProps)\n \"ref\" !== propName && (newProps[propName] = baseProps[propName]);\n }\n if ((Component = Component.defaultProps)) {\n newProps === baseProps && (newProps = assign({}, newProps));\n for (var propName$73 in Component)\n void 0 === newProps[propName$73] &&\n (newProps[propName$73] = Component[propName$73]);\n }\n return newProps;\n}\nfunction defaultOnUncaughtError(error) {\n reportGlobalError(error);\n}\nfunction defaultOnCaughtError(error) {\n console.error(error);\n}\nfunction defaultOnRecoverableError(error) {\n reportGlobalError(error);\n}\nfunction logUncaughtError(root, errorInfo) {\n try {\n var onUncaughtError = root.onUncaughtError;\n onUncaughtError(errorInfo.value, { componentStack: errorInfo.stack });\n } catch (e$74) {\n setTimeout(function () {\n throw e$74;\n });\n }\n}\nfunction logCaughtError(root, boundary, errorInfo) {\n try {\n var onCaughtError = root.onCaughtError;\n onCaughtError(errorInfo.value, {\n componentStack: errorInfo.stack,\n errorBoundary: 1 === boundary.tag ? boundary.stateNode : null\n });\n } catch (e$75) {\n setTimeout(function () {\n throw e$75;\n });\n }\n}\nfunction createRootErrorUpdate(root, errorInfo, lane) {\n lane = createUpdate(lane);\n lane.tag = 3;\n lane.payload = { element: null };\n lane.callback = function () {\n logUncaughtError(root, errorInfo);\n };\n return lane;\n}\nfunction createClassErrorUpdate(lane) {\n lane = createUpdate(lane);\n lane.tag = 3;\n return lane;\n}\nfunction initializeClassErrorUpdate(update, root, fiber, errorInfo) {\n var getDerivedStateFromError = fiber.type.getDerivedStateFromError;\n if (\"function\" === typeof getDerivedStateFromError) {\n var error = errorInfo.value;\n update.payload = function () {\n return getDerivedStateFromError(error);\n };\n update.callback = function () {\n logCaughtError(root, fiber, errorInfo);\n };\n }\n var inst = fiber.stateNode;\n null !== inst &&\n \"function\" === typeof inst.componentDidCatch &&\n (update.callback = function () {\n logCaughtError(root, fiber, errorInfo);\n \"function\" !== typeof getDerivedStateFromError &&\n (null === legacyErrorBoundariesThatAlreadyFailed\n ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this]))\n : legacyErrorBoundariesThatAlreadyFailed.add(this));\n var stack = errorInfo.stack;\n this.componentDidCatch(errorInfo.value, {\n componentStack: null !== stack ? stack : \"\"\n });\n });\n}\nfunction throwException(\n root,\n returnFiber,\n sourceFiber,\n value,\n rootRenderLanes\n) {\n sourceFiber.flags |= 32768;\n if (\n null !== value &&\n \"object\" === typeof value &&\n \"function\" === typeof value.then\n ) {\n returnFiber = sourceFiber.alternate;\n null !== returnFiber &&\n propagateParentContextChanges(\n returnFiber,\n sourceFiber,\n rootRenderLanes,\n !0\n );\n sourceFiber = suspenseHandlerStackCursor.current;\n if (null !== sourceFiber) {\n switch (sourceFiber.tag) {\n case 31:\n case 13:\n return (\n null === shellBoundary\n ? renderDidSuspendDelayIfPossible()\n : null === sourceFiber.alternate &&\n 0 === workInProgressRootExitStatus &&\n (workInProgressRootExitStatus = 3),\n (sourceFiber.flags &= -257),\n (sourceFiber.flags |= 65536),\n (sourceFiber.lanes = rootRenderLanes),\n value === noopSuspenseyCommitThenable\n ? (sourceFiber.flags |= 16384)\n : ((returnFiber = sourceFiber.updateQueue),\n null === returnFiber\n ? (sourceFiber.updateQueue = new Set([value]))\n : returnFiber.add(value),\n attachPingListener(root, value, rootRenderLanes)),\n !1\n );\n case 22:\n return (\n (sourceFiber.flags |= 65536),\n value === noopSuspenseyCommitThenable\n ? (sourceFiber.flags |= 16384)\n : ((returnFiber = sourceFiber.updateQueue),\n null === returnFiber\n ? ((returnFiber = {\n transitions: null,\n markerInstances: null,\n retryQueue: new Set([value])\n }),\n (sourceFiber.updateQueue = returnFiber))\n : ((sourceFiber = returnFiber.retryQueue),\n null === sourceFiber\n ? (returnFiber.retryQueue = new Set([value]))\n : sourceFiber.add(value)),\n attachPingListener(root, value, rootRenderLanes)),\n !1\n );\n }\n throw Error(formatProdErrorMessage(435, sourceFiber.tag));\n }\n attachPingListener(root, value, rootRenderLanes);\n renderDidSuspendDelayIfPossible();\n return !1;\n }\n if (isHydrating)\n return (\n (returnFiber = suspenseHandlerStackCursor.current),\n null !== returnFiber\n ? (0 === (returnFiber.flags & 65536) && (returnFiber.flags |= 256),\n (returnFiber.flags |= 65536),\n (returnFiber.lanes = rootRenderLanes),\n value !== HydrationMismatchException &&\n ((root = Error(formatProdErrorMessage(422), { cause: value })),\n queueHydrationError(createCapturedValueAtFiber(root, sourceFiber))))\n : (value !== HydrationMismatchException &&\n ((returnFiber = Error(formatProdErrorMessage(423), {\n cause: value\n })),\n queueHydrationError(\n createCapturedValueAtFiber(returnFiber, sourceFiber)\n )),\n (root = root.current.alternate),\n (root.flags |= 65536),\n (rootRenderLanes &= -rootRenderLanes),\n (root.lanes |= rootRenderLanes),\n (value = createCapturedValueAtFiber(value, sourceFiber)),\n (rootRenderLanes = createRootErrorUpdate(\n root.stateNode,\n value,\n rootRenderLanes\n )),\n enqueueCapturedUpdate(root, rootRenderLanes),\n 4 !== workInProgressRootExitStatus &&\n (workInProgressRootExitStatus = 2)),\n !1\n );\n var wrapperError = Error(formatProdErrorMessage(520), { cause: value });\n wrapperError = createCapturedValueAtFiber(wrapperError, sourceFiber);\n null === workInProgressRootConcurrentErrors\n ? (workInProgressRootConcurrentErrors = [wrapperError])\n : workInProgressRootConcurrentErrors.push(wrapperError);\n 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2);\n if (null === returnFiber) return !0;\n value = createCapturedValueAtFiber(value, sourceFiber);\n sourceFiber = returnFiber;\n do {\n switch (sourceFiber.tag) {\n case 3:\n return (\n (sourceFiber.flags |= 65536),\n (root = rootRenderLanes & -rootRenderLanes),\n (sourceFiber.lanes |= root),\n (root = createRootErrorUpdate(sourceFiber.stateNode, value, root)),\n enqueueCapturedUpdate(sourceFiber, root),\n !1\n );\n case 1:\n if (\n ((returnFiber = sourceFiber.type),\n (wrapperError = sourceFiber.stateNode),\n 0 === (sourceFiber.flags & 128) &&\n (\"function\" === typeof returnFiber.getDerivedStateFromError ||\n (null !== wrapperError &&\n \"function\" === typeof wrapperError.componentDidCatch &&\n (null === legacyErrorBoundariesThatAlreadyFailed ||\n !legacyErrorBoundariesThatAlreadyFailed.has(wrapperError)))))\n )\n return (\n (sourceFiber.flags |= 65536),\n (rootRenderLanes &= -rootRenderLanes),\n (sourceFiber.lanes |= rootRenderLanes),\n (rootRenderLanes = createClassErrorUpdate(rootRenderLanes)),\n initializeClassErrorUpdate(\n rootRenderLanes,\n root,\n sourceFiber,\n value\n ),\n enqueueCapturedUpdate(sourceFiber, rootRenderLanes),\n !1\n );\n }\n sourceFiber = sourceFiber.return;\n } while (null !== sourceFiber);\n return !1;\n}\nvar SelectiveHydrationException = Error(formatProdErrorMessage(461)),\n didReceiveUpdate = !1;\nfunction reconcileChildren(current, workInProgress, nextChildren, renderLanes) {\n workInProgress.child =\n null === current\n ? mountChildFibers(workInProgress, null, nextChildren, renderLanes)\n : reconcileChildFibers(\n workInProgress,\n current.child,\n nextChildren,\n renderLanes\n );\n}\nfunction updateForwardRef(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n Component = Component.render;\n var ref = workInProgress.ref;\n if (\"ref\" in nextProps) {\n var propsWithoutRef = {};\n for (var key in nextProps)\n \"ref\" !== key && (propsWithoutRef[key] = nextProps[key]);\n } else propsWithoutRef = nextProps;\n prepareToReadContext(workInProgress);\n nextProps = renderWithHooks(\n current,\n workInProgress,\n Component,\n propsWithoutRef,\n ref,\n renderLanes\n );\n key = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && key && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n return workInProgress.child;\n}\nfunction updateMemoComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n if (null === current) {\n var type = Component.type;\n if (\n \"function\" === typeof type &&\n !shouldConstruct(type) &&\n void 0 === type.defaultProps &&\n null === Component.compare\n )\n return (\n (workInProgress.tag = 15),\n (workInProgress.type = type),\n updateSimpleMemoComponent(\n current,\n workInProgress,\n type,\n nextProps,\n renderLanes\n )\n );\n current = createFiberFromTypeAndProps(\n Component.type,\n null,\n nextProps,\n workInProgress,\n workInProgress.mode,\n renderLanes\n );\n current.ref = workInProgress.ref;\n current.return = workInProgress;\n return (workInProgress.child = current);\n }\n type = current.child;\n if (!checkScheduledUpdateOrContext(current, renderLanes)) {\n var prevProps = type.memoizedProps;\n Component = Component.compare;\n Component = null !== Component ? Component : shallowEqual;\n if (Component(prevProps, nextProps) && current.ref === workInProgress.ref)\n return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n }\n workInProgress.flags |= 1;\n current = createWorkInProgress(type, nextProps);\n current.ref = workInProgress.ref;\n current.return = workInProgress;\n return (workInProgress.child = current);\n}\nfunction updateSimpleMemoComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n if (null !== current) {\n var prevProps = current.memoizedProps;\n if (\n shallowEqual(prevProps, nextProps) &&\n current.ref === workInProgress.ref\n )\n if (\n ((didReceiveUpdate = !1),\n (workInProgress.pendingProps = nextProps = prevProps),\n checkScheduledUpdateOrContext(current, renderLanes))\n )\n 0 !== (current.flags & 131072) && (didReceiveUpdate = !0);\n else\n return (\n (workInProgress.lanes = current.lanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n }\n return updateFunctionComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n );\n}\nfunction updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n nextProps\n) {\n var nextChildren = nextProps.children,\n prevState = null !== current ? current.memoizedState : null;\n null === current &&\n null === workInProgress.stateNode &&\n (workInProgress.stateNode = {\n _visibility: 1,\n _pendingMarkers: null,\n _retryCache: null,\n _transitions: null\n });\n if (\"hidden\" === nextProps.mode) {\n if (0 !== (workInProgress.flags & 128)) {\n prevState =\n null !== prevState ? prevState.baseLanes | renderLanes : renderLanes;\n if (null !== current) {\n nextProps = workInProgress.child = current.child;\n for (nextChildren = 0; null !== nextProps; )\n (nextChildren =\n nextChildren | nextProps.lanes | nextProps.childLanes),\n (nextProps = nextProps.sibling);\n nextProps = nextChildren & ~prevState;\n } else (nextProps = 0), (workInProgress.child = null);\n return deferHiddenOffscreenComponent(\n current,\n workInProgress,\n prevState,\n renderLanes,\n nextProps\n );\n }\n if (0 !== (renderLanes & 536870912))\n (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }),\n null !== current &&\n pushTransition(\n workInProgress,\n null !== prevState ? prevState.cachePool : null\n ),\n null !== prevState\n ? pushHiddenContext(workInProgress, prevState)\n : reuseHiddenContextOnStack(),\n pushOffscreenSuspenseHandler(workInProgress);\n else\n return (\n (nextProps = workInProgress.lanes = 536870912),\n deferHiddenOffscreenComponent(\n current,\n workInProgress,\n null !== prevState ? prevState.baseLanes | renderLanes : renderLanes,\n renderLanes,\n nextProps\n )\n );\n } else\n null !== prevState\n ? (pushTransition(workInProgress, prevState.cachePool),\n pushHiddenContext(workInProgress, prevState),\n reuseSuspenseHandlerOnStack(workInProgress),\n (workInProgress.memoizedState = null))\n : (null !== current && pushTransition(workInProgress, null),\n reuseHiddenContextOnStack(),\n reuseSuspenseHandlerOnStack(workInProgress));\n reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n return workInProgress.child;\n}\nfunction bailoutOffscreenComponent(current, workInProgress) {\n (null !== current && 22 === current.tag) ||\n null !== workInProgress.stateNode ||\n (workInProgress.stateNode = {\n _visibility: 1,\n _pendingMarkers: null,\n _retryCache: null,\n _transitions: null\n });\n return workInProgress.sibling;\n}\nfunction deferHiddenOffscreenComponent(\n current,\n workInProgress,\n nextBaseLanes,\n renderLanes,\n remainingChildLanes\n) {\n var JSCompiler_inline_result = peekCacheFromPool();\n JSCompiler_inline_result =\n null === JSCompiler_inline_result\n ? null\n : { parent: CacheContext._currentValue, pool: JSCompiler_inline_result };\n workInProgress.memoizedState = {\n baseLanes: nextBaseLanes,\n cachePool: JSCompiler_inline_result\n };\n null !== current && pushTransition(workInProgress, null);\n reuseHiddenContextOnStack();\n pushOffscreenSuspenseHandler(workInProgress);\n null !== current &&\n propagateParentContextChanges(current, workInProgress, renderLanes, !0);\n workInProgress.childLanes = remainingChildLanes;\n return null;\n}\nfunction mountActivityChildren(workInProgress, nextProps) {\n nextProps = mountWorkInProgressOffscreenFiber(\n { mode: nextProps.mode, children: nextProps.children },\n workInProgress.mode\n );\n nextProps.ref = workInProgress.ref;\n workInProgress.child = nextProps;\n nextProps.return = workInProgress;\n return nextProps;\n}\nfunction retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n) {\n reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n current = mountActivityChildren(workInProgress, workInProgress.pendingProps);\n current.flags |= 2;\n popSuspenseHandler(workInProgress);\n workInProgress.memoizedState = null;\n return current;\n}\nfunction updateActivityComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n didSuspend = 0 !== (workInProgress.flags & 128);\n workInProgress.flags &= -129;\n if (null === current) {\n if (isHydrating) {\n if (\"hidden\" === nextProps.mode)\n return (\n (current = mountActivityChildren(workInProgress, nextProps)),\n (workInProgress.lanes = 536870912),\n bailoutOffscreenComponent(null, current)\n );\n pushDehydratedActivitySuspenseHandler(workInProgress);\n (current = nextHydratableInstance)\n ? ((current = canHydrateHydrationBoundary(\n current,\n rootOrSingletonContext\n )),\n (current = null !== current && \"&\" === current.data ? current : null),\n null !== current &&\n ((workInProgress.memoizedState = {\n dehydrated: current,\n treeContext:\n null !== treeContextProvider\n ? { id: treeContextId, overflow: treeContextOverflow }\n : null,\n retryLane: 536870912,\n hydrationErrors: null\n }),\n (renderLanes = createFiberFromDehydratedFragment(current)),\n (renderLanes.return = workInProgress),\n (workInProgress.child = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null)))\n : (current = null);\n if (null === current) throw throwOnHydrationMismatch(workInProgress);\n workInProgress.lanes = 536870912;\n return null;\n }\n return mountActivityChildren(workInProgress, nextProps);\n }\n var prevState = current.memoizedState;\n if (null !== prevState) {\n var dehydrated = prevState.dehydrated;\n pushDehydratedActivitySuspenseHandler(workInProgress);\n if (didSuspend)\n if (workInProgress.flags & 256)\n (workInProgress.flags &= -257),\n (workInProgress = retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n ));\n else if (null !== workInProgress.memoizedState)\n (workInProgress.child = current.child),\n (workInProgress.flags |= 128),\n (workInProgress = null);\n else throw Error(formatProdErrorMessage(558));\n else if (\n (didReceiveUpdate ||\n propagateParentContextChanges(current, workInProgress, renderLanes, !1),\n (didSuspend = 0 !== (renderLanes & current.childLanes)),\n didReceiveUpdate || didSuspend)\n ) {\n nextProps = workInProgressRoot;\n if (\n null !== nextProps &&\n ((dehydrated = getBumpedLaneForHydration(nextProps, renderLanes)),\n 0 !== dehydrated && dehydrated !== prevState.retryLane)\n )\n throw (\n ((prevState.retryLane = dehydrated),\n enqueueConcurrentRenderForLane(current, dehydrated),\n scheduleUpdateOnFiber(nextProps, current, dehydrated),\n SelectiveHydrationException)\n );\n renderDidSuspendDelayIfPossible();\n workInProgress = retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else\n (current = prevState.treeContext),\n (nextHydratableInstance = getNextHydratable(dehydrated.nextSibling)),\n (hydrationParentFiber = workInProgress),\n (isHydrating = !0),\n (hydrationErrors = null),\n (rootOrSingletonContext = !1),\n null !== current &&\n restoreSuspendedTreeContext(workInProgress, current),\n (workInProgress = mountActivityChildren(workInProgress, nextProps)),\n (workInProgress.flags |= 4096);\n return workInProgress;\n }\n current = createWorkInProgress(current.child, {\n mode: nextProps.mode,\n children: nextProps.children\n });\n current.ref = workInProgress.ref;\n workInProgress.child = current;\n current.return = workInProgress;\n return current;\n}\nfunction markRef(current, workInProgress) {\n var ref = workInProgress.ref;\n if (null === ref)\n null !== current &&\n null !== current.ref &&\n (workInProgress.flags |= 4194816);\n else {\n if (\"function\" !== typeof ref && \"object\" !== typeof ref)\n throw Error(formatProdErrorMessage(284));\n if (null === current || current.ref !== ref)\n workInProgress.flags |= 4194816;\n }\n}\nfunction updateFunctionComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n Component = renderWithHooks(\n current,\n workInProgress,\n Component,\n nextProps,\n void 0,\n renderLanes\n );\n nextProps = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && nextProps && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, Component, renderLanes);\n return workInProgress.child;\n}\nfunction replayFunctionComponent(\n current,\n workInProgress,\n nextProps,\n Component,\n secondArg,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n workInProgress.updateQueue = null;\n nextProps = renderWithHooksAgain(\n workInProgress,\n Component,\n nextProps,\n secondArg\n );\n finishRenderingHooks(current);\n Component = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && Component && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n return workInProgress.child;\n}\nfunction updateClassComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n if (null === workInProgress.stateNode) {\n var context = emptyContextObject,\n contextType = Component.contextType;\n \"object\" === typeof contextType &&\n null !== contextType &&\n (context = readContext(contextType));\n context = new Component(nextProps, context);\n workInProgress.memoizedState =\n null !== context.state && void 0 !== context.state ? context.state : null;\n context.updater = classComponentUpdater;\n workInProgress.stateNode = context;\n context._reactInternals = workInProgress;\n context = workInProgress.stateNode;\n context.props = nextProps;\n context.state = workInProgress.memoizedState;\n context.refs = {};\n initializeUpdateQueue(workInProgress);\n contextType = Component.contextType;\n context.context =\n \"object\" === typeof contextType && null !== contextType\n ? readContext(contextType)\n : emptyContextObject;\n context.state = workInProgress.memoizedState;\n contextType = Component.getDerivedStateFromProps;\n \"function\" === typeof contextType &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n contextType,\n nextProps\n ),\n (context.state = workInProgress.memoizedState));\n \"function\" === typeof Component.getDerivedStateFromProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate ||\n (\"function\" !== typeof context.UNSAFE_componentWillMount &&\n \"function\" !== typeof context.componentWillMount) ||\n ((contextType = context.state),\n \"function\" === typeof context.componentWillMount &&\n context.componentWillMount(),\n \"function\" === typeof context.UNSAFE_componentWillMount &&\n context.UNSAFE_componentWillMount(),\n contextType !== context.state &&\n classComponentUpdater.enqueueReplaceState(context, context.state, null),\n processUpdateQueue(workInProgress, nextProps, context, renderLanes),\n suspendIfUpdateReadFromEntangledAsyncAction(),\n (context.state = workInProgress.memoizedState));\n \"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308);\n nextProps = !0;\n } else if (null === current) {\n context = workInProgress.stateNode;\n var unresolvedOldProps = workInProgress.memoizedProps,\n oldProps = resolveClassComponentProps(Component, unresolvedOldProps);\n context.props = oldProps;\n var oldContext = context.context,\n contextType$jscomp$0 = Component.contextType;\n contextType = emptyContextObject;\n \"object\" === typeof contextType$jscomp$0 &&\n null !== contextType$jscomp$0 &&\n (contextType = readContext(contextType$jscomp$0));\n var getDerivedStateFromProps = Component.getDerivedStateFromProps;\n contextType$jscomp$0 =\n \"function\" === typeof getDerivedStateFromProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate;\n unresolvedOldProps = workInProgress.pendingProps !== unresolvedOldProps;\n contextType$jscomp$0 ||\n (\"function\" !== typeof context.UNSAFE_componentWillReceiveProps &&\n \"function\" !== typeof context.componentWillReceiveProps) ||\n ((unresolvedOldProps || oldContext !== contextType) &&\n callComponentWillReceiveProps(\n workInProgress,\n context,\n nextProps,\n contextType\n ));\n hasForceUpdate = !1;\n var oldState = workInProgress.memoizedState;\n context.state = oldState;\n processUpdateQueue(workInProgress, nextProps, context, renderLanes);\n suspendIfUpdateReadFromEntangledAsyncAction();\n oldContext = workInProgress.memoizedState;\n unresolvedOldProps || oldState !== oldContext || hasForceUpdate\n ? (\"function\" === typeof getDerivedStateFromProps &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n getDerivedStateFromProps,\n nextProps\n ),\n (oldContext = workInProgress.memoizedState)),\n (oldProps =\n hasForceUpdate ||\n checkShouldComponentUpdate(\n workInProgress,\n Component,\n oldProps,\n nextProps,\n oldState,\n oldContext,\n contextType\n ))\n ? (contextType$jscomp$0 ||\n (\"function\" !== typeof context.UNSAFE_componentWillMount &&\n \"function\" !== typeof context.componentWillMount) ||\n (\"function\" === typeof context.componentWillMount &&\n context.componentWillMount(),\n \"function\" === typeof context.UNSAFE_componentWillMount &&\n context.UNSAFE_componentWillMount()),\n \"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308))\n : (\"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308),\n (workInProgress.memoizedProps = nextProps),\n (workInProgress.memoizedState = oldContext)),\n (context.props = nextProps),\n (context.state = oldContext),\n (context.context = contextType),\n (nextProps = oldProps))\n : (\"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308),\n (nextProps = !1));\n } else {\n context = workInProgress.stateNode;\n cloneUpdateQueue(current, workInProgress);\n contextType = workInProgress.memoizedProps;\n contextType$jscomp$0 = resolveClassComponentProps(Component, contextType);\n context.props = contextType$jscomp$0;\n getDerivedStateFromProps = workInProgress.pendingProps;\n oldState = context.context;\n oldContext = Component.contextType;\n oldProps = emptyContextObject;\n \"object\" === typeof oldContext &&\n null !== oldContext &&\n (oldProps = readContext(oldContext));\n unresolvedOldProps = Component.getDerivedStateFromProps;\n (oldContext =\n \"function\" === typeof unresolvedOldProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate) ||\n (\"function\" !== typeof context.UNSAFE_componentWillReceiveProps &&\n \"function\" !== typeof context.componentWillReceiveProps) ||\n ((contextType !== getDerivedStateFromProps || oldState !== oldProps) &&\n callComponentWillReceiveProps(\n workInProgress,\n context,\n nextProps,\n oldProps\n ));\n hasForceUpdate = !1;\n oldState = workInProgress.memoizedState;\n context.state = oldState;\n processUpdateQueue(workInProgress, nextProps, context, renderLanes);\n suspendIfUpdateReadFromEntangledAsyncAction();\n var newState = workInProgress.memoizedState;\n contextType !== getDerivedStateFromProps ||\n oldState !== newState ||\n hasForceUpdate ||\n (null !== current &&\n null !== current.dependencies &&\n checkIfContextChanged(current.dependencies))\n ? (\"function\" === typeof unresolvedOldProps &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n unresolvedOldProps,\n nextProps\n ),\n (newState = workInProgress.memoizedState)),\n (contextType$jscomp$0 =\n hasForceUpdate ||\n checkShouldComponentUpdate(\n workInProgress,\n Component,\n contextType$jscomp$0,\n nextProps,\n oldState,\n newState,\n oldProps\n ) ||\n (null !== current &&\n null !== current.dependencies &&\n checkIfContextChanged(current.dependencies)))\n ? (oldContext ||\n (\"function\" !== typeof context.UNSAFE_componentWillUpdate &&\n \"function\" !== typeof context.componentWillUpdate) ||\n (\"function\" === typeof context.componentWillUpdate &&\n context.componentWillUpdate(nextProps, newState, oldProps),\n \"function\" === typeof context.UNSAFE_componentWillUpdate &&\n context.UNSAFE_componentWillUpdate(\n nextProps,\n newState,\n oldProps\n )),\n \"function\" === typeof context.componentDidUpdate &&\n (workInProgress.flags |= 4),\n \"function\" === typeof context.getSnapshotBeforeUpdate &&\n (workInProgress.flags |= 1024))\n : (\"function\" !== typeof context.componentDidUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 4),\n \"function\" !== typeof context.getSnapshotBeforeUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 1024),\n (workInProgress.memoizedProps = nextProps),\n (workInProgress.memoizedState = newState)),\n (context.props = nextProps),\n (context.state = newState),\n (context.context = oldProps),\n (nextProps = contextType$jscomp$0))\n : (\"function\" !== typeof context.componentDidUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 4),\n \"function\" !== typeof context.getSnapshotBeforeUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 1024),\n (nextProps = !1));\n }\n context = nextProps;\n markRef(current, workInProgress);\n nextProps = 0 !== (workInProgress.flags & 128);\n context || nextProps\n ? ((context = workInProgress.stateNode),\n (Component =\n nextProps && \"function\" !== typeof Component.getDerivedStateFromError\n ? null\n : context.render()),\n (workInProgress.flags |= 1),\n null !== current && nextProps\n ? ((workInProgress.child = reconcileChildFibers(\n workInProgress,\n current.child,\n null,\n renderLanes\n )),\n (workInProgress.child = reconcileChildFibers(\n workInProgress,\n null,\n Component,\n renderLanes\n )))\n : reconcileChildren(current, workInProgress, Component, renderLanes),\n (workInProgress.memoizedState = context.state),\n (current = workInProgress.child))\n : (current = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n ));\n return current;\n}\nfunction mountHostRootWithoutHydrating(\n current,\n workInProgress,\n nextChildren,\n renderLanes\n) {\n resetHydrationState();\n workInProgress.flags |= 256;\n reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n return workInProgress.child;\n}\nvar SUSPENDED_MARKER = {\n dehydrated: null,\n treeContext: null,\n retryLane: 0,\n hydrationErrors: null\n};\nfunction mountSuspenseOffscreenState(renderLanes) {\n return { baseLanes: renderLanes, cachePool: getSuspendedCache() };\n}\nfunction getRemainingWorkInPrimaryTree(\n current,\n primaryTreeDidDefer,\n renderLanes\n) {\n current = null !== current ? current.childLanes & ~renderLanes : 0;\n primaryTreeDidDefer && (current |= workInProgressDeferredLane);\n return current;\n}\nfunction updateSuspenseComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n showFallback = !1,\n didSuspend = 0 !== (workInProgress.flags & 128),\n JSCompiler_temp;\n (JSCompiler_temp = didSuspend) ||\n (JSCompiler_temp =\n null !== current && null === current.memoizedState\n ? !1\n : 0 !== (suspenseStackCursor.current & 2));\n JSCompiler_temp && ((showFallback = !0), (workInProgress.flags &= -129));\n JSCompiler_temp = 0 !== (workInProgress.flags & 32);\n workInProgress.flags &= -33;\n if (null === current) {\n if (isHydrating) {\n showFallback\n ? pushPrimaryTreeSuspenseHandler(workInProgress)\n : reuseSuspenseHandlerOnStack(workInProgress);\n (current = nextHydratableInstance)\n ? ((current = canHydrateHydrationBoundary(\n current,\n rootOrSingletonContext\n )),\n (current = null !== current && \"&\" !== current.data ? current : null),\n null !== current &&\n ((workInProgress.memoizedState = {\n dehydrated: current,\n treeContext:\n null !== treeContextProvider\n ? { id: treeContextId, overflow: treeContextOverflow }\n : null,\n retryLane: 536870912,\n hydrationErrors: null\n }),\n (renderLanes = createFiberFromDehydratedFragment(current)),\n (renderLanes.return = workInProgress),\n (workInProgress.child = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null)))\n : (current = null);\n if (null === current) throw throwOnHydrationMismatch(workInProgress);\n isSuspenseInstanceFallback(current)\n ? (workInProgress.lanes = 32)\n : (workInProgress.lanes = 536870912);\n return null;\n }\n var nextPrimaryChildren = nextProps.children;\n nextProps = nextProps.fallback;\n if (showFallback)\n return (\n reuseSuspenseHandlerOnStack(workInProgress),\n (showFallback = workInProgress.mode),\n (nextPrimaryChildren = mountWorkInProgressOffscreenFiber(\n { mode: \"hidden\", children: nextPrimaryChildren },\n showFallback\n )),\n (nextProps = createFiberFromFragment(\n nextProps,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.return = workInProgress),\n (nextPrimaryChildren.sibling = nextProps),\n (workInProgress.child = nextPrimaryChildren),\n (nextProps = workInProgress.child),\n (nextProps.memoizedState = mountSuspenseOffscreenState(renderLanes)),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n bailoutOffscreenComponent(null, nextProps)\n );\n pushPrimaryTreeSuspenseHandler(workInProgress);\n return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren);\n }\n var prevState = current.memoizedState;\n if (\n null !== prevState &&\n ((nextPrimaryChildren = prevState.dehydrated), null !== nextPrimaryChildren)\n ) {\n if (didSuspend)\n workInProgress.flags & 256\n ? (pushPrimaryTreeSuspenseHandler(workInProgress),\n (workInProgress.flags &= -257),\n (workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n )))\n : null !== workInProgress.memoizedState\n ? (reuseSuspenseHandlerOnStack(workInProgress),\n (workInProgress.child = current.child),\n (workInProgress.flags |= 128),\n (workInProgress = null))\n : (reuseSuspenseHandlerOnStack(workInProgress),\n (nextPrimaryChildren = nextProps.fallback),\n (showFallback = workInProgress.mode),\n (nextProps = mountWorkInProgressOffscreenFiber(\n { mode: \"visible\", children: nextProps.children },\n showFallback\n )),\n (nextPrimaryChildren = createFiberFromFragment(\n nextPrimaryChildren,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.flags |= 2),\n (nextProps.return = workInProgress),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.sibling = nextPrimaryChildren),\n (workInProgress.child = nextProps),\n reconcileChildFibers(\n workInProgress,\n current.child,\n null,\n renderLanes\n ),\n (nextProps = workInProgress.child),\n (nextProps.memoizedState =\n mountSuspenseOffscreenState(renderLanes)),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n (workInProgress = bailoutOffscreenComponent(null, nextProps)));\n else if (\n (pushPrimaryTreeSuspenseHandler(workInProgress),\n isSuspenseInstanceFallback(nextPrimaryChildren))\n ) {\n JSCompiler_temp =\n nextPrimaryChildren.nextSibling &&\n nextPrimaryChildren.nextSibling.dataset;\n if (JSCompiler_temp) var digest = JSCompiler_temp.dgst;\n JSCompiler_temp = digest;\n nextProps = Error(formatProdErrorMessage(419));\n nextProps.stack = \"\";\n nextProps.digest = JSCompiler_temp;\n queueHydrationError({ value: nextProps, source: null, stack: null });\n workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else if (\n (didReceiveUpdate ||\n propagateParentContextChanges(current, workInProgress, renderLanes, !1),\n (JSCompiler_temp = 0 !== (renderLanes & current.childLanes)),\n didReceiveUpdate || JSCompiler_temp)\n ) {\n JSCompiler_temp = workInProgressRoot;\n if (\n null !== JSCompiler_temp &&\n ((nextProps = getBumpedLaneForHydration(JSCompiler_temp, renderLanes)),\n 0 !== nextProps && nextProps !== prevState.retryLane)\n )\n throw (\n ((prevState.retryLane = nextProps),\n enqueueConcurrentRenderForLane(current, nextProps),\n scheduleUpdateOnFiber(JSCompiler_temp, current, nextProps),\n SelectiveHydrationException)\n );\n isSuspenseInstancePending(nextPrimaryChildren) ||\n renderDidSuspendDelayIfPossible();\n workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else\n isSuspenseInstancePending(nextPrimaryChildren)\n ? ((workInProgress.flags |= 192),\n (workInProgress.child = current.child),\n (workInProgress = null))\n : ((current = prevState.treeContext),\n (nextHydratableInstance = getNextHydratable(\n nextPrimaryChildren.nextSibling\n )),\n (hydrationParentFiber = workInProgress),\n (isHydrating = !0),\n (hydrationErrors = null),\n (rootOrSingletonContext = !1),\n null !== current &&\n restoreSuspendedTreeContext(workInProgress, current),\n (workInProgress = mountSuspensePrimaryChildren(\n workInProgress,\n nextProps.children\n )),\n (workInProgress.flags |= 4096));\n return workInProgress;\n }\n if (showFallback)\n return (\n reuseSuspenseHandlerOnStack(workInProgress),\n (nextPrimaryChildren = nextProps.fallback),\n (showFallback = workInProgress.mode),\n (prevState = current.child),\n (digest = prevState.sibling),\n (nextProps = createWorkInProgress(prevState, {\n mode: \"hidden\",\n children: nextProps.children\n })),\n (nextProps.subtreeFlags = prevState.subtreeFlags & 65011712),\n null !== digest\n ? (nextPrimaryChildren = createWorkInProgress(\n digest,\n nextPrimaryChildren\n ))\n : ((nextPrimaryChildren = createFiberFromFragment(\n nextPrimaryChildren,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.flags |= 2)),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.return = workInProgress),\n (nextProps.sibling = nextPrimaryChildren),\n (workInProgress.child = nextProps),\n bailoutOffscreenComponent(null, nextProps),\n (nextProps = workInProgress.child),\n (nextPrimaryChildren = current.child.memoizedState),\n null === nextPrimaryChildren\n ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes))\n : ((showFallback = nextPrimaryChildren.cachePool),\n null !== showFallback\n ? ((prevState = CacheContext._currentValue),\n (showFallback =\n showFallback.parent !== prevState\n ? { parent: prevState, pool: prevState }\n : showFallback))\n : (showFallback = getSuspendedCache()),\n (nextPrimaryChildren = {\n baseLanes: nextPrimaryChildren.baseLanes | renderLanes,\n cachePool: showFallback\n })),\n (nextProps.memoizedState = nextPrimaryChildren),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n bailoutOffscreenComponent(current.child, nextProps)\n );\n pushPrimaryTreeSuspenseHandler(workInProgress);\n renderLanes = current.child;\n current = renderLanes.sibling;\n renderLanes = createWorkInProgress(renderLanes, {\n mode: \"visible\",\n children: nextProps.children\n });\n renderLanes.return = workInProgress;\n renderLanes.sibling = null;\n null !== current &&\n ((JSCompiler_temp = workInProgress.deletions),\n null === JSCompiler_temp\n ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16))\n : JSCompiler_temp.push(current));\n workInProgress.child = renderLanes;\n workInProgress.memoizedState = null;\n return renderLanes;\n}\nfunction mountSuspensePrimaryChildren(workInProgress, primaryChildren) {\n primaryChildren = mountWorkInProgressOffscreenFiber(\n { mode: \"visible\", children: primaryChildren },\n workInProgress.mode\n );\n primaryChildren.return = workInProgress;\n return (workInProgress.child = primaryChildren);\n}\nfunction mountWorkInProgressOffscreenFiber(offscreenProps, mode) {\n offscreenProps = createFiberImplClass(22, offscreenProps, null, mode);\n offscreenProps.lanes = 0;\n return offscreenProps;\n}\nfunction retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n) {\n reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n current = mountSuspensePrimaryChildren(\n workInProgress,\n workInProgress.pendingProps.children\n );\n current.flags |= 2;\n workInProgress.memoizedState = null;\n return current;\n}\nfunction scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) {\n fiber.lanes |= renderLanes;\n var alternate = fiber.alternate;\n null !== alternate && (alternate.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot);\n}\nfunction initSuspenseListRenderState(\n workInProgress,\n isBackwards,\n tail,\n lastContentRow,\n tailMode,\n treeForkCount\n) {\n var renderState = workInProgress.memoizedState;\n null === renderState\n ? (workInProgress.memoizedState = {\n isBackwards: isBackwards,\n rendering: null,\n renderingStartTime: 0,\n last: lastContentRow,\n tail: tail,\n tailMode: tailMode,\n treeForkCount: treeForkCount\n })\n : ((renderState.isBackwards = isBackwards),\n (renderState.rendering = null),\n (renderState.renderingStartTime = 0),\n (renderState.last = lastContentRow),\n (renderState.tail = tail),\n (renderState.tailMode = tailMode),\n (renderState.treeForkCount = treeForkCount));\n}\nfunction updateSuspenseListComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n revealOrder = nextProps.revealOrder,\n tailMode = nextProps.tail;\n nextProps = nextProps.children;\n var suspenseContext = suspenseStackCursor.current,\n shouldForceFallback = 0 !== (suspenseContext & 2);\n shouldForceFallback\n ? ((suspenseContext = (suspenseContext & 1) | 2),\n (workInProgress.flags |= 128))\n : (suspenseContext &= 1);\n push(suspenseStackCursor, suspenseContext);\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n nextProps = isHydrating ? treeForkCount : 0;\n if (!shouldForceFallback && null !== current && 0 !== (current.flags & 128))\n a: for (current = workInProgress.child; null !== current; ) {\n if (13 === current.tag)\n null !== current.memoizedState &&\n scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress);\n else if (19 === current.tag)\n scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress);\n else if (null !== current.child) {\n current.child.return = current;\n current = current.child;\n continue;\n }\n if (current === workInProgress) break a;\n for (; null === current.sibling; ) {\n if (null === current.return || current.return === workInProgress)\n break a;\n current = current.return;\n }\n current.sibling.return = current.return;\n current = current.sibling;\n }\n switch (revealOrder) {\n case \"forwards\":\n renderLanes = workInProgress.child;\n for (revealOrder = null; null !== renderLanes; )\n (current = renderLanes.alternate),\n null !== current &&\n null === findFirstSuspended(current) &&\n (revealOrder = renderLanes),\n (renderLanes = renderLanes.sibling);\n renderLanes = revealOrder;\n null === renderLanes\n ? ((revealOrder = workInProgress.child), (workInProgress.child = null))\n : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null));\n initSuspenseListRenderState(\n workInProgress,\n !1,\n revealOrder,\n renderLanes,\n tailMode,\n nextProps\n );\n break;\n case \"backwards\":\n case \"unstable_legacy-backwards\":\n renderLanes = null;\n revealOrder = workInProgress.child;\n for (workInProgress.child = null; null !== revealOrder; ) {\n current = revealOrder.alternate;\n if (null !== current && null === findFirstSuspended(current)) {\n workInProgress.child = revealOrder;\n break;\n }\n current = revealOrder.sibling;\n revealOrder.sibling = renderLanes;\n renderLanes = revealOrder;\n revealOrder = current;\n }\n initSuspenseListRenderState(\n workInProgress,\n !0,\n renderLanes,\n null,\n tailMode,\n nextProps\n );\n break;\n case \"together\":\n initSuspenseListRenderState(\n workInProgress,\n !1,\n null,\n null,\n void 0,\n nextProps\n );\n break;\n default:\n workInProgress.memoizedState = null;\n }\n return workInProgress.child;\n}\nfunction bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) {\n null !== current && (workInProgress.dependencies = current.dependencies);\n workInProgressRootSkippedLanes |= workInProgress.lanes;\n if (0 === (renderLanes & workInProgress.childLanes))\n if (null !== current) {\n if (\n (propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n !1\n ),\n 0 === (renderLanes & workInProgress.childLanes))\n )\n return null;\n } else return null;\n if (null !== current && workInProgress.child !== current.child)\n throw Error(formatProdErrorMessage(153));\n if (null !== workInProgress.child) {\n current = workInProgress.child;\n renderLanes = createWorkInProgress(current, current.pendingProps);\n workInProgress.child = renderLanes;\n for (renderLanes.return = workInProgress; null !== current.sibling; )\n (current = current.sibling),\n (renderLanes = renderLanes.sibling =\n createWorkInProgress(current, current.pendingProps)),\n (renderLanes.return = workInProgress);\n renderLanes.sibling = null;\n }\n return workInProgress.child;\n}\nfunction checkScheduledUpdateOrContext(current, renderLanes) {\n if (0 !== (current.lanes & renderLanes)) return !0;\n current = current.dependencies;\n return null !== current && checkIfContextChanged(current) ? !0 : !1;\n}\nfunction attemptEarlyBailoutIfNoScheduledUpdate(\n current,\n workInProgress,\n renderLanes\n) {\n switch (workInProgress.tag) {\n case 3:\n pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n pushProvider(workInProgress, CacheContext, current.memoizedState.cache);\n resetHydrationState();\n break;\n case 27:\n case 5:\n pushHostContext(workInProgress);\n break;\n case 4:\n pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n break;\n case 10:\n pushProvider(\n workInProgress,\n workInProgress.type,\n workInProgress.memoizedProps.value\n );\n break;\n case 31:\n if (null !== workInProgress.memoizedState)\n return (\n (workInProgress.flags |= 128),\n pushDehydratedActivitySuspenseHandler(workInProgress),\n null\n );\n break;\n case 13:\n var state$102 = workInProgress.memoizedState;\n if (null !== state$102) {\n if (null !== state$102.dehydrated)\n return (\n pushPrimaryTreeSuspenseHandler(workInProgress),\n (workInProgress.flags |= 128),\n null\n );\n if (0 !== (renderLanes & workInProgress.child.childLanes))\n return updateSuspenseComponent(current, workInProgress, renderLanes);\n pushPrimaryTreeSuspenseHandler(workInProgress);\n current = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n );\n return null !== current ? current.sibling : null;\n }\n pushPrimaryTreeSuspenseHandler(workInProgress);\n break;\n case 19:\n var didSuspendBefore = 0 !== (current.flags & 128);\n state$102 = 0 !== (renderLanes & workInProgress.childLanes);\n state$102 ||\n (propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n !1\n ),\n (state$102 = 0 !== (renderLanes & workInProgress.childLanes)));\n if (didSuspendBefore) {\n if (state$102)\n return updateSuspenseListComponent(\n current,\n workInProgress,\n renderLanes\n );\n workInProgress.flags |= 128;\n }\n didSuspendBefore = workInProgress.memoizedState;\n null !== didSuspendBefore &&\n ((didSuspendBefore.rendering = null),\n (didSuspendBefore.tail = null),\n (didSuspendBefore.lastEffect = null));\n push(suspenseStackCursor, suspenseStackCursor.current);\n if (state$102) break;\n else return null;\n case 22:\n return (\n (workInProgress.lanes = 0),\n updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n workInProgress.pendingProps\n )\n );\n case 24:\n pushProvider(workInProgress, CacheContext, current.memoizedState.cache);\n }\n return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n}\nfunction beginWork(current, workInProgress, renderLanes) {\n if (null !== current)\n if (current.memoizedProps !== workInProgress.pendingProps)\n didReceiveUpdate = !0;\n else {\n if (\n !checkScheduledUpdateOrContext(current, renderLanes) &&\n 0 === (workInProgress.flags & 128)\n )\n return (\n (didReceiveUpdate = !1),\n attemptEarlyBailoutIfNoScheduledUpdate(\n current,\n workInProgress,\n renderLanes\n )\n );\n didReceiveUpdate = 0 !== (current.flags & 131072) ? !0 : !1;\n }\n else\n (didReceiveUpdate = !1),\n isHydrating &&\n 0 !== (workInProgress.flags & 1048576) &&\n pushTreeId(workInProgress, treeForkCount, workInProgress.index);\n workInProgress.lanes = 0;\n switch (workInProgress.tag) {\n case 16:\n a: {\n var props = workInProgress.pendingProps;\n current = resolveLazy(workInProgress.elementType);\n workInProgress.type = current;\n if (\"function\" === typeof current)\n shouldConstruct(current)\n ? ((props = resolveClassComponentProps(current, props)),\n (workInProgress.tag = 1),\n (workInProgress = updateClassComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n )))\n : ((workInProgress.tag = 0),\n (workInProgress = updateFunctionComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n )));\n else {\n if (void 0 !== current && null !== current) {\n var $$typeof = current.$$typeof;\n if ($$typeof === REACT_FORWARD_REF_TYPE) {\n workInProgress.tag = 11;\n workInProgress = updateForwardRef(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n );\n break a;\n } else if ($$typeof === REACT_MEMO_TYPE) {\n workInProgress.tag = 14;\n workInProgress = updateMemoComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n );\n break a;\n }\n }\n workInProgress = getComponentNameFromType(current) || current;\n throw Error(formatProdErrorMessage(306, workInProgress, \"\"));\n }\n }\n return workInProgress;\n case 0:\n return updateFunctionComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 1:\n return (\n (props = workInProgress.type),\n ($$typeof = resolveClassComponentProps(\n props,\n workInProgress.pendingProps\n )),\n updateClassComponent(\n current,\n workInProgress,\n props,\n $$typeof,\n renderLanes\n )\n );\n case 3:\n a: {\n pushHostContainer(\n workInProgress,\n workInProgress.stateNode.containerInfo\n );\n if (null === current) throw Error(formatProdErrorMessage(387));\n props = workInProgress.pendingProps;\n var prevState = workInProgress.memoizedState;\n $$typeof = prevState.element;\n cloneUpdateQueue(current, workInProgress);\n processUpdateQueue(workInProgress, props, null, renderLanes);\n var nextState = workInProgress.memoizedState;\n props = nextState.cache;\n pushProvider(workInProgress, CacheContext, props);\n props !== prevState.cache &&\n propagateContextChanges(\n workInProgress,\n [CacheContext],\n renderLanes,\n !0\n );\n suspendIfUpdateReadFromEntangledAsyncAction();\n props = nextState.element;\n if (prevState.isDehydrated)\n if (\n ((prevState = {\n element: props,\n isDehydrated: !1,\n cache: nextState.cache\n }),\n (workInProgress.updateQueue.baseState = prevState),\n (workInProgress.memoizedState = prevState),\n workInProgress.flags & 256)\n ) {\n workInProgress = mountHostRootWithoutHydrating(\n current,\n workInProgress,\n props,\n renderLanes\n );\n break a;\n } else if (props !== $$typeof) {\n $$typeof = createCapturedValueAtFiber(\n Error(formatProdErrorMessage(424)),\n workInProgress\n );\n queueHydrationError($$typeof);\n workInProgress = mountHostRootWithoutHydrating(\n current,\n workInProgress,\n props,\n renderLanes\n );\n break a;\n } else {\n current = workInProgress.stateNode.containerInfo;\n switch (current.nodeType) {\n case 9:\n current = current.body;\n break;\n default:\n current =\n \"HTML\" === current.nodeName\n ? current.ownerDocument.body\n : current;\n }\n nextHydratableInstance = getNextHydratable(current.firstChild);\n hydrationParentFiber = workInProgress;\n isHydrating = !0;\n hydrationErrors = null;\n rootOrSingletonContext = !0;\n renderLanes = mountChildFibers(\n workInProgress,\n null,\n props,\n renderLanes\n );\n for (workInProgress.child = renderLanes; renderLanes; )\n (renderLanes.flags = (renderLanes.flags & -3) | 4096),\n (renderLanes = renderLanes.sibling);\n }\n else {\n resetHydrationState();\n if (props === $$typeof) {\n workInProgress = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n );\n break a;\n }\n reconcileChildren(current, workInProgress, props, renderLanes);\n }\n workInProgress = workInProgress.child;\n }\n return workInProgress;\n case 26:\n return (\n markRef(current, workInProgress),\n null === current\n ? (renderLanes = getResource(\n workInProgress.type,\n null,\n workInProgress.pendingProps,\n null\n ))\n ? (workInProgress.memoizedState = renderLanes)\n : isHydrating ||\n ((renderLanes = workInProgress.type),\n (current = workInProgress.pendingProps),\n (props = getOwnerDocumentFromRootContainer(\n rootInstanceStackCursor.current\n ).createElement(renderLanes)),\n (props[internalInstanceKey] = workInProgress),\n (props[internalPropsKey] = current),\n setInitialProperties(props, renderLanes, current),\n markNodeAsHoistable(props),\n (workInProgress.stateNode = props))\n : (workInProgress.memoizedState = getResource(\n workInProgress.type,\n current.memoizedProps,\n workInProgress.pendingProps,\n current.memoizedState\n )),\n null\n );\n case 27:\n return (\n pushHostContext(workInProgress),\n null === current &&\n isHydrating &&\n ((props = workInProgress.stateNode =\n resolveSingletonInstance(\n workInProgress.type,\n workInProgress.pendingProps,\n rootInstanceStackCursor.current\n )),\n (hydrationParentFiber = workInProgress),\n (rootOrSingletonContext = !0),\n ($$typeof = nextHydratableInstance),\n isSingletonScope(workInProgress.type)\n ? ((previousHydratableOnEnteringScopedSingleton = $$typeof),\n (nextHydratableInstance = getNextHydratable(props.firstChild)))\n : (nextHydratableInstance = $$typeof)),\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n markRef(current, workInProgress),\n null === current && (workInProgress.flags |= 4194304),\n workInProgress.child\n );\n case 5:\n if (null === current && isHydrating) {\n if (($$typeof = props = nextHydratableInstance))\n (props = canHydrateInstance(\n props,\n workInProgress.type,\n workInProgress.pendingProps,\n rootOrSingletonContext\n )),\n null !== props\n ? ((workInProgress.stateNode = props),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = getNextHydratable(props.firstChild)),\n (rootOrSingletonContext = !1),\n ($$typeof = !0))\n : ($$typeof = !1);\n $$typeof || throwOnHydrationMismatch(workInProgress);\n }\n pushHostContext(workInProgress);\n $$typeof = workInProgress.type;\n prevState = workInProgress.pendingProps;\n nextState = null !== current ? current.memoizedProps : null;\n props = prevState.children;\n shouldSetTextContent($$typeof, prevState)\n ? (props = null)\n : null !== nextState &&\n shouldSetTextContent($$typeof, nextState) &&\n (workInProgress.flags |= 32);\n null !== workInProgress.memoizedState &&\n (($$typeof = renderWithHooks(\n current,\n workInProgress,\n TransitionAwareHostComponent,\n null,\n null,\n renderLanes\n )),\n (HostTransitionContext._currentValue = $$typeof));\n markRef(current, workInProgress);\n reconcileChildren(current, workInProgress, props, renderLanes);\n return workInProgress.child;\n case 6:\n if (null === current && isHydrating) {\n if ((current = renderLanes = nextHydratableInstance))\n (renderLanes = canHydrateTextInstance(\n renderLanes,\n workInProgress.pendingProps,\n rootOrSingletonContext\n )),\n null !== renderLanes\n ? ((workInProgress.stateNode = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null),\n (current = !0))\n : (current = !1);\n current || throwOnHydrationMismatch(workInProgress);\n }\n return null;\n case 13:\n return updateSuspenseComponent(current, workInProgress, renderLanes);\n case 4:\n return (\n pushHostContainer(\n workInProgress,\n workInProgress.stateNode.containerInfo\n ),\n (props = workInProgress.pendingProps),\n null === current\n ? (workInProgress.child = reconcileChildFibers(\n workInProgress,\n null,\n props,\n renderLanes\n ))\n : reconcileChildren(current, workInProgress, props, renderLanes),\n workInProgress.child\n );\n case 11:\n return updateForwardRef(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 7:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps,\n renderLanes\n ),\n workInProgress.child\n );\n case 8:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 12:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 10:\n return (\n (props = workInProgress.pendingProps),\n pushProvider(workInProgress, workInProgress.type, props.value),\n reconcileChildren(current, workInProgress, props.children, renderLanes),\n workInProgress.child\n );\n case 9:\n return (\n ($$typeof = workInProgress.type._context),\n (props = workInProgress.pendingProps.children),\n prepareToReadContext(workInProgress),\n ($$typeof = readContext($$typeof)),\n (props = props($$typeof)),\n (workInProgress.flags |= 1),\n reconcileChildren(current, workInProgress, props, renderLanes),\n workInProgress.child\n );\n case 14:\n return updateMemoComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 15:\n return updateSimpleMemoComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 19:\n return updateSuspenseListComponent(current, workInProgress, renderLanes);\n case 31:\n return updateActivityComponent(current, workInProgress, renderLanes);\n case 22:\n return updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n workInProgress.pendingProps\n );\n case 24:\n return (\n prepareToReadContext(workInProgress),\n (props = readContext(CacheContext)),\n null === current\n ? (($$typeof = peekCacheFromPool()),\n null === $$typeof &&\n (($$typeof = workInProgressRoot),\n (prevState = createCache()),\n ($$typeof.pooledCache = prevState),\n prevState.refCount++,\n null !== prevState && ($$typeof.pooledCacheLanes |= renderLanes),\n ($$typeof = prevState)),\n (workInProgress.memoizedState = { parent: props, cache: $$typeof }),\n initializeUpdateQueue(workInProgress),\n pushProvider(workInProgress, CacheContext, $$typeof))\n : (0 !== (current.lanes & renderLanes) &&\n (cloneUpdateQueue(current, workInProgress),\n processUpdateQueue(workInProgress, null, null, renderLanes),\n suspendIfUpdateReadFromEntangledAsyncAction()),\n ($$typeof = current.memoizedState),\n (prevState = workInProgress.memoizedState),\n $$typeof.parent !== props\n ? (($$typeof = { parent: props, cache: props }),\n (workInProgress.memoizedState = $$typeof),\n 0 === workInProgress.lanes &&\n (workInProgress.memoizedState =\n workInProgress.updateQueue.baseState =\n $$typeof),\n pushProvider(workInProgress, CacheContext, props))\n : ((props = prevState.cache),\n pushProvider(workInProgress, CacheContext, props),\n props !== $$typeof.cache &&\n propagateContextChanges(\n workInProgress,\n [CacheContext],\n renderLanes,\n !0\n ))),\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 29:\n throw workInProgress.pendingProps;\n }\n throw Error(formatProdErrorMessage(156, workInProgress.tag));\n}\nfunction markUpdate(workInProgress) {\n workInProgress.flags |= 4;\n}\nfunction preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n oldProps,\n newProps,\n renderLanes\n) {\n if ((type = 0 !== (workInProgress.mode & 32))) type = !1;\n if (type) {\n if (\n ((workInProgress.flags |= 16777216),\n (renderLanes & 335544128) === renderLanes)\n )\n if (workInProgress.stateNode.complete) workInProgress.flags |= 8192;\n else if (shouldRemainOnPreviousScreen()) workInProgress.flags |= 8192;\n else\n throw (\n ((suspendedThenable = noopSuspenseyCommitThenable),\n SuspenseyCommitException)\n );\n } else workInProgress.flags &= -16777217;\n}\nfunction preloadResourceAndSuspendIfNeeded(workInProgress, resource) {\n if (\"stylesheet\" !== resource.type || 0 !== (resource.state.loading & 4))\n workInProgress.flags &= -16777217;\n else if (((workInProgress.flags |= 16777216), !preloadResource(resource)))\n if (shouldRemainOnPreviousScreen()) workInProgress.flags |= 8192;\n else\n throw (\n ((suspendedThenable = noopSuspenseyCommitThenable),\n SuspenseyCommitException)\n );\n}\nfunction scheduleRetryEffect(workInProgress, retryQueue) {\n null !== retryQueue && (workInProgress.flags |= 4);\n workInProgress.flags & 16384 &&\n ((retryQueue =\n 22 !== workInProgress.tag ? claimNextRetryLane() : 536870912),\n (workInProgress.lanes |= retryQueue),\n (workInProgressSuspendedRetryLanes |= retryQueue));\n}\nfunction cutOffTailIfNeeded(renderState, hasRenderedATailFallback) {\n if (!isHydrating)\n switch (renderState.tailMode) {\n case \"hidden\":\n hasRenderedATailFallback = renderState.tail;\n for (var lastTailNode = null; null !== hasRenderedATailFallback; )\n null !== hasRenderedATailFallback.alternate &&\n (lastTailNode = hasRenderedATailFallback),\n (hasRenderedATailFallback = hasRenderedATailFallback.sibling);\n null === lastTailNode\n ? (renderState.tail = null)\n : (lastTailNode.sibling = null);\n break;\n case \"collapsed\":\n lastTailNode = renderState.tail;\n for (var lastTailNode$106 = null; null !== lastTailNode; )\n null !== lastTailNode.alternate && (lastTailNode$106 = lastTailNode),\n (lastTailNode = lastTailNode.sibling);\n null === lastTailNode$106\n ? hasRenderedATailFallback || null === renderState.tail\n ? (renderState.tail = null)\n : (renderState.tail.sibling = null)\n : (lastTailNode$106.sibling = null);\n }\n}\nfunction bubbleProperties(completedWork) {\n var didBailout =\n null !== completedWork.alternate &&\n completedWork.alternate.child === completedWork.child,\n newChildLanes = 0,\n subtreeFlags = 0;\n if (didBailout)\n for (var child$107 = completedWork.child; null !== child$107; )\n (newChildLanes |= child$107.lanes | child$107.childLanes),\n (subtreeFlags |= child$107.subtreeFlags & 65011712),\n (subtreeFlags |= child$107.flags & 65011712),\n (child$107.return = completedWork),\n (child$107 = child$107.sibling);\n else\n for (child$107 = completedWork.child; null !== child$107; )\n (newChildLanes |= child$107.lanes | child$107.childLanes),\n (subtreeFlags |= child$107.subtreeFlags),\n (subtreeFlags |= child$107.flags),\n (child$107.return = completedWork),\n (child$107 = child$107.sibling);\n completedWork.subtreeFlags |= subtreeFlags;\n completedWork.childLanes = newChildLanes;\n return didBailout;\n}\nfunction completeWork(current, workInProgress, renderLanes) {\n var newProps = workInProgress.pendingProps;\n popTreeContext(workInProgress);\n switch (workInProgress.tag) {\n case 16:\n case 15:\n case 0:\n case 11:\n case 7:\n case 8:\n case 12:\n case 9:\n case 14:\n return bubbleProperties(workInProgress), null;\n case 1:\n return bubbleProperties(workInProgress), null;\n case 3:\n renderLanes = workInProgress.stateNode;\n newProps = null;\n null !== current && (newProps = current.memoizedState.cache);\n workInProgress.memoizedState.cache !== newProps &&\n (workInProgress.flags |= 2048);\n popProvider(CacheContext);\n popHostContainer();\n renderLanes.pendingContext &&\n ((renderLanes.context = renderLanes.pendingContext),\n (renderLanes.pendingContext = null));\n if (null === current || null === current.child)\n popHydrationState(workInProgress)\n ? markUpdate(workInProgress)\n : null === current ||\n (current.memoizedState.isDehydrated &&\n 0 === (workInProgress.flags & 256)) ||\n ((workInProgress.flags |= 1024),\n upgradeHydrationErrorsToRecoverable());\n bubbleProperties(workInProgress);\n return null;\n case 26:\n var type = workInProgress.type,\n nextResource = workInProgress.memoizedState;\n null === current\n ? (markUpdate(workInProgress),\n null !== nextResource\n ? (bubbleProperties(workInProgress),\n preloadResourceAndSuspendIfNeeded(workInProgress, nextResource))\n : (bubbleProperties(workInProgress),\n preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n null,\n newProps,\n renderLanes\n )))\n : nextResource\n ? nextResource !== current.memoizedState\n ? (markUpdate(workInProgress),\n bubbleProperties(workInProgress),\n preloadResourceAndSuspendIfNeeded(workInProgress, nextResource))\n : (bubbleProperties(workInProgress),\n (workInProgress.flags &= -16777217))\n : ((current = current.memoizedProps),\n current !== newProps && markUpdate(workInProgress),\n bubbleProperties(workInProgress),\n preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n current,\n newProps,\n renderLanes\n ));\n return null;\n case 27:\n popHostContext(workInProgress);\n renderLanes = rootInstanceStackCursor.current;\n type = workInProgress.type;\n if (null !== current && null != workInProgress.stateNode)\n current.memoizedProps !== newProps && markUpdate(workInProgress);\n else {\n if (!newProps) {\n if (null === workInProgress.stateNode)\n throw Error(formatProdErrorMessage(166));\n bubbleProperties(workInProgress);\n return null;\n }\n current = contextStackCursor.current;\n popHydrationState(workInProgress)\n ? prepareToHydrateHostInstance(workInProgress, current)\n : ((current = resolveSingletonInstance(type, newProps, renderLanes)),\n (workInProgress.stateNode = current),\n markUpdate(workInProgress));\n }\n bubbleProperties(workInProgress);\n return null;\n case 5:\n popHostContext(workInProgress);\n type = workInProgress.type;\n if (null !== current && null != workInProgress.stateNode)\n current.memoizedProps !== newProps && markUpdate(workInProgress);\n else {\n if (!newProps) {\n if (null === workInProgress.stateNode)\n throw Error(formatProdErrorMessage(166));\n bubbleProperties(workInProgress);\n return null;\n }\n nextResource = contextStackCursor.current;\n if (popHydrationState(workInProgress))\n prepareToHydrateHostInstance(workInProgress, nextResource);\n else {\n var ownerDocument = getOwnerDocumentFromRootContainer(\n rootInstanceStackCursor.current\n );\n switch (nextResource) {\n case 1:\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/2000/svg\",\n type\n );\n break;\n case 2:\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/1998/Math/MathML\",\n type\n );\n break;\n default:\n switch (type) {\n case \"svg\":\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/2000/svg\",\n type\n );\n break;\n case \"math\":\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/1998/Math/MathML\",\n type\n );\n break;\n case \"script\":\n nextResource = ownerDocument.createElement(\"div\");\n nextResource.innerHTML = \" + +`; + } +} diff --git a/ai-dev-vscode/src/panels/DecisionsPanelProvider.ts b/ai-dev-vscode/src/panels/DecisionsPanelProvider.ts new file mode 100644 index 0000000..98afceb --- /dev/null +++ b/ai-dev-vscode/src/panels/DecisionsPanelProvider.ts @@ -0,0 +1,40 @@ +import * as vscode from 'vscode'; +import { BasePanelProvider } from './BasePanelProvider'; +import type { FromDecisionsWebview } from '../webviews/shared/protocol'; + +export class DecisionsPanelProvider extends BasePanelProvider { + constructor(extensionUri: vscode.Uri) { + super('aidev.decisions', extensionUri, 'decisions/main.js'); + } + + protected onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void { + disposables.push(this.signalR!.onDecisionsChanged(() => void this.refresh(view))); + + disposables.push(view.webview.onDidReceiveMessage(async (msg: FromDecisionsWebview) => { + try { + if (msg.type === 'resolve') { + await this.api!.resolveDecision(this.projectSlug!, msg.decisionId, msg.resolution); + await this.refresh(view); + } + } catch (e) { + this.send({ type: 'error', message: String(e) }); + } + })); + + void this.refresh(view); + } + + private async refresh(view: vscode.WebviewView): Promise { + if (!this.api) return; + this.send({ type: 'loading' }); + try { + const data = await this.api.listDecisions(this.projectSlug!, 'pending'); + this.send({ type: 'decisions', data }); + view.badge = data.length > 0 + ? { value: data.length, tooltip: `${data.length} pending decision(s)` } + : undefined; + } catch (e) { + this.send({ type: 'error', message: `Failed to load decisions: ${e}` }); + } + } +} diff --git a/ai-dev-vscode/src/panels/MessagesPanelProvider.ts b/ai-dev-vscode/src/panels/MessagesPanelProvider.ts new file mode 100644 index 0000000..37b5ed8 --- /dev/null +++ b/ai-dev-vscode/src/panels/MessagesPanelProvider.ts @@ -0,0 +1,40 @@ +import * as vscode from 'vscode'; +import { BasePanelProvider } from './BasePanelProvider'; +import type { FromMessagesWebview } from '../webviews/shared/protocol'; + +export class MessagesPanelProvider extends BasePanelProvider { + constructor(extensionUri: vscode.Uri) { + super('aidev.messages', extensionUri, 'messages/main.js'); + } + + protected onConnected(view: vscode.WebviewView, disposables: vscode.Disposable[]): void { + disposables.push(this.signalR!.onMessagesChanged(() => void this.refresh(view))); + + disposables.push(view.webview.onDidReceiveMessage(async (msg: FromMessagesWebview) => { + try { + if (msg.type === 'process') { + await this.api!.processMessage(this.projectSlug!, msg.agentSlug, msg.fileName); + await this.refresh(view); + } + } catch (e) { + this.send({ type: 'error', message: String(e) }); + } + })); + + void this.refresh(view); + } + + private async refresh(view: vscode.WebviewView): Promise { + if (!this.api) return; + this.send({ type: 'loading' }); + try { + const data = await this.api.listAllMessages(this.projectSlug!); + this.send({ type: 'messages', data }); + view.badge = data.length > 0 + ? { value: data.length, tooltip: `${data.length} unprocessed message(s)` } + : undefined; + } catch (e) { + this.send({ type: 'error', message: `Failed to load messages: ${e}` }); + } + } +} diff --git a/ai-dev-vscode/src/test/BackendProcessManager.test.ts b/ai-dev-vscode/src/test/BackendProcessManager.test.ts new file mode 100644 index 0000000..79039e6 --- /dev/null +++ b/ai-dev-vscode/src/test/BackendProcessManager.test.ts @@ -0,0 +1,134 @@ +import { BackendProcessManager, ProcessLike, Spawner, Fetcher } from '../BackendProcessManager'; + +function makeProcess(): ProcessLike & { triggerExit(code: number | null): void } { + const handlers: Record void)[]> = {}; + return { + kill: jest.fn(), + on: (event, handler) => { + (handlers[event] ??= []).push(handler as (...args: unknown[]) => void); + }, + triggerExit: code => handlers['exit']?.forEach(h => h(code)), + }; +} + +const OPTIONS = { binaryPath: '/bin/ai-dev-api', port: 5100, maxAttempts: 3, retryDelayMs: 0 }; +const noDelay = () => Promise.resolve(); +const binaryExists = () => true; +const binaryAbsent = () => false; + +describe('BackendProcessManager', () => { + it('starts in not-started state', () => { + const mgr = new BackendProcessManager(OPTIONS, jest.fn(), jest.fn(), noDelay, binaryExists); + expect(mgr.state).toBe('not-started'); + }); + + it('transitions not-started → starting → ready on successful health check', async () => { + const proc = makeProcess(); + const spawner: Spawner = jest.fn(() => proc); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: true }); + + const mgr = new BackendProcessManager(OPTIONS, spawner, fetcher, noDelay, binaryExists); + const states: string[] = [mgr.state]; + (spawner as jest.Mock).mockImplementation(() => { + states.push('spawned'); + return proc; + }); + + await mgr.start(); + states.push(mgr.state); + + expect(states).toContain('spawned'); + expect(mgr.state).toBe('ready'); + expect(fetcher).toHaveBeenCalledWith('http://localhost:5100/api/health'); + }); + + it('retries health check until success', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn() + .mockResolvedValueOnce({ ok: false }) + .mockResolvedValueOnce({ ok: false }) + .mockResolvedValueOnce({ ok: true }); + + const mgr = new BackendProcessManager(OPTIONS, () => proc, fetcher, noDelay, binaryExists); + await mgr.start(); + + expect(mgr.state).toBe('ready'); + expect(fetcher).toHaveBeenCalledTimes(3); + }); + + it('transitions to stopped and throws after maxAttempts exhausted', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: false }); + + const mgr = new BackendProcessManager(OPTIONS, () => proc, fetcher, noDelay, binaryExists); + await expect(mgr.start()).rejects.toThrow(/healthy after 3 attempts/); + + expect(mgr.state).toBe('stopped'); + expect(proc.kill).toHaveBeenCalled(); + }); + + it('counts fetch errors as failed attempts', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn().mockRejectedValue(new Error('ECONNREFUSED')); + + const mgr = new BackendProcessManager(OPTIONS, () => proc, fetcher, noDelay, binaryExists); + await expect(mgr.start()).rejects.toThrow(/healthy after 3 attempts/); + expect(fetcher).toHaveBeenCalledTimes(3); + }); + + it('stop() kills the process and transitions to stopped', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: true }); + + const mgr = new BackendProcessManager(OPTIONS, () => proc, fetcher, noDelay, binaryExists); + await mgr.start(); + expect(mgr.state).toBe('ready'); + + mgr.stop(); + expect(mgr.state).toBe('stopped'); + expect(proc.kill).toHaveBeenCalled(); + }); + + it('stop() is a no-op when not-started', () => { + const proc = makeProcess(); + const mgr = new BackendProcessManager(OPTIONS, () => proc, jest.fn(), noDelay, binaryExists); + mgr.stop(); + expect(mgr.state).toBe('not-started'); + expect(proc.kill).not.toHaveBeenCalled(); + }); + + it('start() is idempotent — second call is ignored', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: true }); + const spawner: Spawner = jest.fn(() => proc); + + const mgr = new BackendProcessManager(OPTIONS, spawner, fetcher, noDelay, binaryExists); + await mgr.start(); + await mgr.start(); + + expect(spawner).toHaveBeenCalledTimes(1); + }); + + it('transitions to stopped when spawned process exits unexpectedly', async () => { + const proc = makeProcess(); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: true }); + + const mgr = new BackendProcessManager(OPTIONS, () => proc, fetcher, noDelay, binaryExists); + await mgr.start(); + expect(mgr.state).toBe('ready'); + + proc.triggerExit(1); + expect(mgr.state).toBe('stopped'); + }); + + it('skips spawning when binary is absent (dev mode), still reaches ready via health check', async () => { + const spawner: Spawner = jest.fn(); + const fetcher: Fetcher = jest.fn().mockResolvedValue({ ok: true }); + + const mgr = new BackendProcessManager(OPTIONS, spawner, fetcher, noDelay, binaryAbsent); + await mgr.start(); + + expect(spawner).not.toHaveBeenCalled(); + expect(mgr.state).toBe('ready'); + }); +}); diff --git a/ai-dev-vscode/src/test/StudioSignalRClient.test.ts b/ai-dev-vscode/src/test/StudioSignalRClient.test.ts new file mode 100644 index 0000000..f772cfe --- /dev/null +++ b/ai-dev-vscode/src/test/StudioSignalRClient.test.ts @@ -0,0 +1,147 @@ +import { StudioSignalRClient, ConnectionState, HubConnectionFactory, StateChangedMessage } from '../StudioSignalRClient'; +import { HubConnectionState } from '@microsoft/signalr'; + +function makeConnection() { + const handlers: Record void)> = {}; + const messageHandlers: Record void)> = {}; + + return { + state: HubConnectionState.Disconnected as HubConnectionState, + start: jest.fn(async () => { (conn as { state: HubConnectionState }).state = HubConnectionState.Connected; }), + stop: jest.fn(async () => { (conn as { state: HubConnectionState }).state = HubConnectionState.Disconnected; }), + invoke: jest.fn().mockResolvedValue(undefined), + on: jest.fn((event: string, handler: (...args: unknown[]) => void) => { + messageHandlers[event] = handler; + }), + onreconnecting: jest.fn((h: () => void) => { handlers['reconnecting'] = h; }), + onreconnected: jest.fn((h: () => void) => { handlers['reconnected'] = h; }), + onclose: jest.fn((h: () => void) => { handlers['close'] = h; }), + // test helpers + simulateReconnecting: () => handlers['reconnecting']?.(), + simulateReconnected: () => handlers['reconnected']?.(), + simulateClose: () => handlers['close']?.(), + simulateMessage: (msg: StateChangedMessage) => messageHandlers['StateChanged']?.(msg), + }; +} + +const conn = makeConnection(); + +const factory: HubConnectionFactory = { + build: jest.fn(() => conn as never), +}; + +const PROJECT = 'my-project'; + +describe('StudioSignalRClient', () => { + let client: StudioSignalRClient; + + beforeEach(() => { + jest.clearAllMocks(); + Object.assign(conn, makeConnection()); + (factory.build as jest.Mock).mockReturnValue(conn); + client = new StudioSignalRClient('http://localhost:5100/hubs/project', factory); + }); + + it('starts in disconnected state', () => { + expect(client.connectionState).toBe('disconnected'); + }); + + it('transitions disconnected → connecting → connected on start()', async () => { + const states: ConnectionState[] = []; + client.onConnectionStateChanged(s => states.push(s)); + + await client.start(PROJECT); + + expect(states).toEqual(['connecting', 'connected']); + expect(client.connectionState).toBe('connected'); + }); + + it('joins the project group after connecting', async () => { + await client.start(PROJECT); + expect(conn.invoke).toHaveBeenCalledWith('JoinProject', PROJECT); + }); + + it('transitions to connecting on reconnecting event', async () => { + await client.start(PROJECT); + const states: ConnectionState[] = []; + client.onConnectionStateChanged(s => states.push(s)); + + conn.simulateReconnecting(); + expect(states).toContain('connecting'); + }); + + it('transitions to connected on reconnected event', async () => { + await client.start(PROJECT); + conn.simulateReconnecting(); + const states: ConnectionState[] = []; + client.onConnectionStateChanged(s => states.push(s)); + + conn.simulateReconnected(); + expect(states).toContain('connected'); + }); + + it('transitions to disconnected on close event', async () => { + await client.start(PROJECT); + const states: ConnectionState[] = []; + client.onConnectionStateChanged(s => states.push(s)); + + conn.simulateClose(); + expect(states).toContain('disconnected'); + }); + + it('fires onAgentsChanged when Agents kind received', async () => { + await client.start(PROJECT); + let fired = false; + client.onAgentsChanged(() => { fired = true; }); + + conn.simulateMessage({ projectSlug: PROJECT, kinds: ['Agents'] }); + expect(fired).toBe(true); + }); + + it('fires onMessagesChanged when Messages kind received', async () => { + await client.start(PROJECT); + let fired = false; + client.onMessagesChanged(() => { fired = true; }); + + conn.simulateMessage({ projectSlug: PROJECT, kinds: ['Messages'] }); + expect(fired).toBe(true); + }); + + it('fires onDecisionsChanged when Decisions kind received', async () => { + await client.start(PROJECT); + let fired = false; + client.onDecisionsChanged(() => { fired = true; }); + + conn.simulateMessage({ projectSlug: PROJECT, kinds: ['Decisions'] }); + expect(fired).toBe(true); + }); + + it('ignores StateChanged messages for a different project', async () => { + await client.start(PROJECT); + let fired = false; + client.onAgentsChanged(() => { fired = true; }); + + conn.simulateMessage({ projectSlug: 'other-project', kinds: ['Agents'] }); + expect(fired).toBe(false); + }); + + it('can fire multiple kinds in one message', async () => { + await client.start(PROJECT); + let agentsFired = false, messagesFired = false; + client.onAgentsChanged(() => { agentsFired = true; }); + client.onMessagesChanged(() => { messagesFired = true; }); + + conn.simulateMessage({ projectSlug: PROJECT, kinds: ['Agents', 'Messages'] }); + expect(agentsFired).toBe(true); + expect(messagesFired).toBe(true); + }); + + it('stop() leaves the project group and stops the connection', async () => { + await client.start(PROJECT); + await client.stop(); + + expect(conn.invoke).toHaveBeenCalledWith('LeaveProject', PROJECT); + expect(conn.stop).toHaveBeenCalled(); + expect(client.connectionState).toBe('disconnected'); + }); +}); diff --git a/ai-dev-vscode/src/test/WorkspaceDetector.test.ts b/ai-dev-vscode/src/test/WorkspaceDetector.test.ts new file mode 100644 index 0000000..94b5fd8 --- /dev/null +++ b/ai-dev-vscode/src/test/WorkspaceDetector.test.ts @@ -0,0 +1,120 @@ +import * as path from 'path'; +import { WorkspaceDetector, FileWatcherLike } from '../WorkspaceDetector'; +import { DetectedProject } from '../types'; + +function makeWatcher(): FileWatcherLike & { + fireCreated(p: string): void; + fireDeleted(p: string): void; +} { + let createdHandler: ((p: string) => void) | undefined; + let deletedHandler: ((p: string) => void) | undefined; + return { + onCreated: h => { createdHandler = h; }, + onDeleted: h => { deletedHandler = h; }, + dispose: jest.fn(), + fireCreated: (p) => createdHandler?.(p), + fireDeleted: (p) => deletedHandler?.(p), + }; +} + +const VALID_CONFIG = JSON.stringify({ projectSlug: 'my-project', apiPort: 5100 }); +const WS = '/workspace/my-repo'; + +describe('WorkspaceDetector', () => { + it('emits projectDetected on start when config file exists', () => { + const watcher = makeWatcher(); + const detector = new WorkspaceDetector( + () => watcher, + filePath => (filePath.endsWith('project.json') ? VALID_CONFIG : undefined), + ); + + const events: DetectedProject[] = []; + detector.on('projectDetected', e => events.push(e)); + detector.start([WS]); + + expect(events).toHaveLength(1); + expect(events[0].config.projectSlug).toBe('my-project'); + expect(events[0].config.apiPort).toBe(5100); + expect(events[0].workspaceFolderPath).toBe(WS); + }); + + it('does not emit projectDetected on start when config file absent', () => { + const watcher = makeWatcher(); + const detector = new WorkspaceDetector(() => watcher, () => undefined); + + const events: DetectedProject[] = []; + detector.on('projectDetected', e => events.push(e)); + detector.start([WS]); + + expect(events).toHaveLength(0); + }); + + it('emits projectDetected when watcher fires created for a workspace path', () => { + const watcher = makeWatcher(); + const configPath = path.join(WS, '.ai-dev', 'project.json').replace(/\\/g, '/'); + // readFile returns undefined initially (file absent), then valid JSON after creation + let filePresent = false; + const detector = new WorkspaceDetector( + () => watcher, + filePath => (filePresent && filePath.replace(/\\/g, '/') === configPath ? VALID_CONFIG : undefined), + ); + + const events: DetectedProject[] = []; + detector.on('projectDetected', e => events.push(e)); + detector.start([WS]); + expect(events).toHaveLength(0); // file absent at start + + filePresent = true; + watcher.fireCreated(configPath); + + expect(events).toHaveLength(1); + expect(events[0].config.projectSlug).toBe('my-project'); + }); + + it('emits projectRemoved when watcher fires deleted for a workspace path', () => { + const watcher = makeWatcher(); + const configPath = path.join(WS, '.ai-dev', 'project.json').replace(/\\/g, '/'); + const detector = new WorkspaceDetector(() => watcher, () => undefined); + + const removed: string[] = []; + detector.on('projectRemoved', p => removed.push(p)); + detector.start([WS]); + watcher.fireDeleted(configPath); + + expect(removed).toHaveLength(1); + expect(removed[0]).toBe(WS); + }); + + it('ignores created events for paths outside workspace folders', () => { + const watcher = makeWatcher(); + const detector = new WorkspaceDetector(() => watcher, () => VALID_CONFIG); + + const events: DetectedProject[] = []; + detector.on('projectDetected', e => events.push(e)); + detector.start([WS]); + events.length = 0; // reset after start scan + + watcher.fireCreated('/some/other/path/.ai-dev/project.json'); + + expect(events).toHaveLength(0); + }); + + it('does not emit projectDetected for malformed JSON', () => { + const watcher = makeWatcher(); + const detector = new WorkspaceDetector(() => watcher, () => '{ not valid json }'); + + const events: DetectedProject[] = []; + detector.on('projectDetected', e => events.push(e)); + detector.start([WS]); + + expect(events).toHaveLength(0); + }); + + it('disposes the watcher on dispose()', () => { + const watcher = makeWatcher(); + const detector = new WorkspaceDetector(() => watcher, () => undefined); + detector.start([WS]); + detector.dispose(); + expect(watcher.dispose).toHaveBeenCalled(); + }); +}); diff --git a/ai-dev-vscode/src/types.ts b/ai-dev-vscode/src/types.ts new file mode 100644 index 0000000..a9519d6 --- /dev/null +++ b/ai-dev-vscode/src/types.ts @@ -0,0 +1,39 @@ +export interface ProjectConfig { + projectSlug: string; + apiPort: number; +} + +export interface DetectedProject { + config: ProjectConfig; + workspaceFolderPath: string; +} + +// Shared data shapes used by both extension host and webview apps + +export interface AgentSummary { + slug: string; + isRunning: boolean; + isRateLimited: boolean; +} + +export interface MessageItem { + fileName: string; + from: string; + re: string; + type: string; + priority: string; + createdAt: string; + processed: boolean; + agentSlug?: string; // populated client-side when fetching per-agent +} + +export interface DecisionItem { + id: string; + from: string; + subject: string; + priority: string; + status: string; + createdAt: string; + blocks?: string; + body?: string; +} diff --git a/ai-dev-vscode/src/webviews/agents/main.tsx b/ai-dev-vscode/src/webviews/agents/main.tsx new file mode 100644 index 0000000..345c97a --- /dev/null +++ b/ai-dev-vscode/src/webviews/agents/main.tsx @@ -0,0 +1,63 @@ +import React, { useState, useEffect } from 'react'; +import { createRoot } from 'react-dom/client'; +import { getVsCodeApi } from '../shared/vscodeApi'; +import type { ToAgentsWebview } from '../shared/protocol'; +import type { AgentSummary } from '../../types'; + +const vscode = getVsCodeApi(); + +function AgentRow({ agent }: { agent: AgentSummary }) { + const [busy, setBusy] = useState(false); + + function send(type: 'run' | 'stop') { + setBusy(true); + vscode.postMessage({ type, agentSlug: agent.slug }); + } + + return ( +
+
+ {agent.slug} + + {agent.isRateLimited ? 'rate-limited' : agent.isRunning ? 'running' : 'idle'} + +
+
+ {agent.isRunning ? ( + + ) : ( + + )} +
+
+ ); +} + +function App() { + const [state, setState] = useState<'loading' | 'error' | 'ready'>('loading'); + const [agents, setAgents] = useState([]); + const [errorMsg, setErrorMsg] = useState(''); + + useEffect(() => { + const handler = (event: MessageEvent) => { + const msg = event.data; + if (msg.type === 'loading') { setState('loading'); } + else if (msg.type === 'error') { setState('error'); setErrorMsg(msg.message); } + else if (msg.type === 'agents') { setAgents(msg.data); setState('ready'); } + }; + window.addEventListener('message', handler); + return () => window.removeEventListener('message', handler); + }, []); + + if (state === 'loading') return

Loading agents…

; + if (state === 'error') return

{errorMsg}

; + if (agents.length === 0) return

No agents found.

; + return
{agents.map(a => )}
; +} + +const root = document.getElementById('root'); +if (root) createRoot(root).render(); diff --git a/ai-dev-vscode/src/webviews/decisions/main.tsx b/ai-dev-vscode/src/webviews/decisions/main.tsx new file mode 100644 index 0000000..6a4bc15 --- /dev/null +++ b/ai-dev-vscode/src/webviews/decisions/main.tsx @@ -0,0 +1,70 @@ +import React, { useState, useEffect } from 'react'; +import { createRoot } from 'react-dom/client'; +import { getVsCodeApi } from '../shared/vscodeApi'; +import type { ToDecisionsWebview } from '../shared/protocol'; +import type { DecisionItem } from '../../types'; + +const vscode = getVsCodeApi(); + +function DecisionRow({ decision }: { decision: DecisionItem }) { + const [resolution, setResolution] = useState(''); + const [busy, setBusy] = useState(false); + + function resolve() { + if (!resolution.trim()) return; + setBusy(true); + vscode.postMessage({ type: 'resolve', decisionId: decision.id, resolution: resolution.trim() }); + } + + return ( +
+
{decision.subject}
+
+ from: {decision.from} · {decision.priority} + {decision.blocks && <> · blocks: {decision.blocks}} +
+ {decision.body && ( +
+ {decision.body} +
+ )} +
+ setResolution(e.target.value)} + placeholder="Enter resolution…" + style={{ flex: 1 }} + onKeyDown={e => { if (e.key === 'Enter') resolve(); }} + disabled={busy} + /> + +
+
+ ); +} + +function App() { + const [state, setState] = useState<'loading' | 'error' | 'ready'>('loading'); + const [decisions, setDecisions] = useState([]); + const [errorMsg, setErrorMsg] = useState(''); + + useEffect(() => { + const handler = (event: MessageEvent) => { + const msg = event.data; + if (msg.type === 'loading') { setState('loading'); } + else if (msg.type === 'error') { setState('error'); setErrorMsg(msg.message); } + else if (msg.type === 'decisions') { setDecisions(msg.data); setState('ready'); } + }; + window.addEventListener('message', handler); + return () => window.removeEventListener('message', handler); + }, []); + + if (state === 'loading') return

Loading decisions…

; + if (state === 'error') return

{errorMsg}

; + if (decisions.length === 0) return

No pending decisions.

; + return
{decisions.map(d => )}
; +} + +const root = document.getElementById('root'); +if (root) createRoot(root).render(); diff --git a/ai-dev-vscode/src/webviews/messages/main.tsx b/ai-dev-vscode/src/webviews/messages/main.tsx new file mode 100644 index 0000000..45ca2a0 --- /dev/null +++ b/ai-dev-vscode/src/webviews/messages/main.tsx @@ -0,0 +1,61 @@ +import React, { useState, useEffect } from 'react'; +import { createRoot } from 'react-dom/client'; +import { getVsCodeApi } from '../shared/vscodeApi'; +import type { ToMessagesWebview } from '../shared/protocol'; +import type { MessageItem } from '../../types'; + +const vscode = getVsCodeApi(); + +function priorityColor(priority: string): string { + switch (priority.toLowerCase()) { + case 'urgent': return 'var(--vscode-errorForeground)'; + case 'high': return 'var(--vscode-notificationsWarningIcon-foreground)'; + default: return 'var(--vscode-foreground)'; + } +} + +function MessageRow({ message }: { message: MessageItem }) { + function process() { + vscode.postMessage({ type: 'process', fileName: message.fileName, agentSlug: message.agentSlug ?? message.from }); + } + + return ( +
+
+ {message.re} + + {message.priority} + +
+
from: {message.from}
+ +
+ ); +} + +function App() { + const [state, setState] = useState<'loading' | 'error' | 'ready'>('loading'); + const [messages, setMessages] = useState([]); + const [errorMsg, setErrorMsg] = useState(''); + + useEffect(() => { + const handler = (event: MessageEvent) => { + const msg = event.data; + if (msg.type === 'loading') { setState('loading'); } + else if (msg.type === 'error') { setState('error'); setErrorMsg(msg.message); } + else if (msg.type === 'messages') { setMessages(msg.data); setState('ready'); } + }; + window.addEventListener('message', handler); + return () => window.removeEventListener('message', handler); + }, []); + + if (state === 'loading') return

Loading messages…

; + if (state === 'error') return

{errorMsg}

; + if (messages.length === 0) return

No unprocessed messages.

; + return
{messages.map(m => )}
; +} + +const root = document.getElementById('root'); +if (root) createRoot(root).render(); diff --git a/ai-dev-vscode/src/webviews/shared/protocol.ts b/ai-dev-vscode/src/webviews/shared/protocol.ts new file mode 100644 index 0000000..e666108 --- /dev/null +++ b/ai-dev-vscode/src/webviews/shared/protocol.ts @@ -0,0 +1,28 @@ +import type { AgentSummary, MessageItem, DecisionItem } from '../../types'; + +// Extension host → webview +export type ToAgentsWebview = + | { type: 'loading' } + | { type: 'error'; message: string } + | { type: 'agents'; data: AgentSummary[] }; + +export type ToMessagesWebview = + | { type: 'loading' } + | { type: 'error'; message: string } + | { type: 'messages'; data: MessageItem[] }; + +export type ToDecisionsWebview = + | { type: 'loading' } + | { type: 'error'; message: string } + | { type: 'decisions'; data: DecisionItem[] }; + +// Webview → extension host +export type FromAgentsWebview = + | { type: 'run'; agentSlug: string } + | { type: 'stop'; agentSlug: string }; + +export type FromMessagesWebview = + | { type: 'process'; fileName: string; agentSlug: string }; // agentSlug populated from MessageItem.agentSlug + +export type FromDecisionsWebview = + | { type: 'resolve'; decisionId: string; resolution: string }; diff --git a/ai-dev-vscode/src/webviews/shared/vscodeApi.ts b/ai-dev-vscode/src/webviews/shared/vscodeApi.ts new file mode 100644 index 0000000..fdb9995 --- /dev/null +++ b/ai-dev-vscode/src/webviews/shared/vscodeApi.ts @@ -0,0 +1,13 @@ +declare function acquireVsCodeApi(): { + postMessage(message: unknown): void; + getState(): unknown; + setState(state: unknown): void; +}; + +let _api: ReturnType | undefined; + +export function getVsCodeApi() { + // acquireVsCodeApi() may only be called once per webview session + _api ??= acquireVsCodeApi(); + return _api; +} diff --git a/ai-dev-vscode/tsconfig.json b/ai-dev-vscode/tsconfig.json new file mode 100644 index 0000000..7bad76a --- /dev/null +++ b/ai-dev-vscode/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2022", + "lib": ["ES2022"], + "outDir": "./out", + "rootDir": "./src", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "sourceMap": true, + "declaration": true, + "skipLibCheck": true, + "types": ["node", "jest"] + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "out"] +} diff --git a/ai-dev.api/Hubs/ProjectStateHub.cs b/ai-dev.api/Hubs/ProjectStateHub.cs new file mode 100644 index 0000000..00efb3f --- /dev/null +++ b/ai-dev.api/Hubs/ProjectStateHub.cs @@ -0,0 +1,26 @@ +using AiDev.Models; +using Microsoft.AspNetCore.SignalR; + +namespace AiDev.Api.Hubs; + +/// +/// Broadcasts project state changes to connected VS Code extension and web clients. +/// Clients join a project group by sending JoinProject(projectSlug) on connect. +/// +public class ProjectStateHub : Hub +{ + public async Task JoinProject(string projectSlug) + { + await Groups.AddToGroupAsync(Context.ConnectionId, projectSlug); + } + + public async Task LeaveProject(string projectSlug) + { + await Groups.RemoveFromGroupAsync(Context.ConnectionId, projectSlug); + } +} + +/// +/// Payload sent to clients when project state changes. +/// +public sealed record StateChangedMessage(string ProjectSlug, string[] Kinds); diff --git a/ai-dev.api/Hubs/ProjectStateRelayService.cs b/ai-dev.api/Hubs/ProjectStateRelayService.cs new file mode 100644 index 0000000..0b4f846 --- /dev/null +++ b/ai-dev.api/Hubs/ProjectStateRelayService.cs @@ -0,0 +1,46 @@ +using AiDev.Models; +using AiDev.Services; +using Microsoft.AspNetCore.SignalR; + +namespace AiDev.Api.Hubs; + +/// +/// Bridges ProjectStateChangedNotifier events to SignalR by forwarding each notification +/// to the project's group on ProjectStateHub. Registered as a hosted service so it +/// subscribes on startup and unsubscribes on shutdown. +/// +public sealed class ProjectStateRelayService( + ProjectStateChangedNotifier notifier, + IHubContext hubContext) : IHostedService +{ + public Task StartAsync(CancellationToken cancellationToken) + { + notifier.Changed += OnChanged; + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + notifier.Changed -= OnChanged; + return Task.CompletedTask; + } + + private void OnChanged(ProjectStateChangedEvent e) + { + var kinds = GetKindNames(e.Kind); + var message = new StateChangedMessage(e.ProjectSlug.Value, kinds); + _ = hubContext.Clients + .Group(e.ProjectSlug.Value) + .SendAsync("StateChanged", message); + } + + private static string[] GetKindNames(ProjectStateChangeKind kind) + { + var names = new List(4); + if (kind.HasFlag(ProjectStateChangeKind.Agents)) names.Add("Agents"); + if (kind.HasFlag(ProjectStateChangeKind.Messages)) names.Add("Messages"); + if (kind.HasFlag(ProjectStateChangeKind.Decisions)) names.Add("Decisions"); + if (kind.HasFlag(ProjectStateChangeKind.Board)) names.Add("Board"); + return [.. names]; + } +} diff --git a/ai-dev.api/Program.cs b/ai-dev.api/Program.cs new file mode 100644 index 0000000..390e389 --- /dev/null +++ b/ai-dev.api/Program.cs @@ -0,0 +1,51 @@ +using AiDev; +using AiDev.Api.Hubs; +using AiDev.Api.Routes; +using AiDev.Extensions; +using AiDev.Features.Workspace; + +var builder = WebApplication.CreateBuilder(args); + +builder.AddServiceDefaults(); + +// WORKSPACE_ROOT is the folder opened in VS Code — the extension passes it when spawning +// this process. .ai-dev is always a direct child of that folder. +var workspaceRoot = builder.Configuration["WORKSPACE_ROOT"] + ?? throw new InvalidOperationException( + "WORKSPACE_ROOT is not set. The VS Code extension sets this when spawning the backend, " + + "or add it to launchSettings.json for direct development runs."); + +var workspacePaths = new WorkspacePaths(new RootDir(Path.Combine(workspaceRoot, ".ai-dev"))); + +builder.Services.AddSingleton(workspacePaths); +builder.Services.AddSingleton(workspacePaths.Root); + +builder.Services.AddAiDevCore(); +builder.Services.AddSignalR(); +builder.Services.AddHostedService(); + +builder.Services.AddCors(options => + options.AddDefaultPolicy(policy => + policy.SetIsOriginAllowed(origin => + origin.StartsWith("http://localhost", StringComparison.OrdinalIgnoreCase) || + origin.StartsWith("vscode-webview://", StringComparison.OrdinalIgnoreCase)) + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials())); + +var app = builder.Build(); + +app.MapDefaultEndpoints(); +app.UseCors(); + +app.MapAgentRoutes(); +app.MapMessageRoutes(); +app.MapDecisionRoutes(); + +app.MapGet("/api/health", () => Results.Ok(new { status = "healthy" })); +app.MapHub("/hubs/project"); + +app.Run(); + +// Exposes Program for WebApplicationFactory in integration tests. +public partial class Program { } diff --git a/ai-dev.api/Properties/launchSettings.json b/ai-dev.api/Properties/launchSettings.json new file mode 100644 index 0000000..be588ac --- /dev/null +++ b/ai-dev.api/Properties/launchSettings.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5191", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "WORKSPACE_ROOT": "M:\\ai-dev-net" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7087;http://localhost:5191", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "WORKSPACE_ROOT": "M:\\ai-dev-net" + } + } + } +} diff --git a/ai-dev.api/Routes/AgentRoutes.cs b/ai-dev.api/Routes/AgentRoutes.cs new file mode 100644 index 0000000..ef33f0c --- /dev/null +++ b/ai-dev.api/Routes/AgentRoutes.cs @@ -0,0 +1,41 @@ +using AiDev.Features.Agent; +using AiDev.Models.Types; + +namespace AiDev.Api.Routes; + +public static class AgentRoutes +{ + public static IEndpointRouteBuilder MapAgentRoutes(this IEndpointRouteBuilder app) + { + app.MapGet("/api/agents", (string projectSlug, IAgentRunnerService runner, AgentService agentService) => + { + ProjectSlug project = projectSlug; + var agents = agentService.ListAgents(project); + var result = agents.Select(a => new + { + slug = a.Slug, + isRunning = runner.IsRunning(project, a.Slug), + isRateLimited = runner.IsRateLimited(project, a.Slug), + }); + return Results.Ok(result); + }); + + app.MapPost("/api/agents/{slug}/run", (string slug, string projectSlug, IAgentRunnerService runner) => + { + ProjectSlug project = projectSlug; + AgentSlug agentSlug = slug; + var launched = runner.LaunchAgent(project, agentSlug); + return launched ? Results.Ok() : Results.Conflict(); + }); + + app.MapPost("/api/agents/{slug}/stop", (string slug, string projectSlug, IAgentRunnerService runner) => + { + ProjectSlug project = projectSlug; + AgentSlug agentSlug = slug; + var stopped = runner.StopAgent(project, agentSlug); + return stopped ? Results.Ok() : Results.Conflict(); + }); + + return app; + } +} diff --git a/ai-dev.api/Routes/DecisionRoutes.cs b/ai-dev.api/Routes/DecisionRoutes.cs new file mode 100644 index 0000000..827e873 --- /dev/null +++ b/ai-dev.api/Routes/DecisionRoutes.cs @@ -0,0 +1,42 @@ +using AiDev.Features.Decision; +using AiDev.Models; +using AiDev.Models.Types; + +namespace AiDev.Api.Routes; + +public static class DecisionRoutes +{ + private sealed record ResolveRequest(string Resolution); + + public static IEndpointRouteBuilder MapDecisionRoutes(this IEndpointRouteBuilder app) + { + app.MapGet("/api/decisions", (string projectSlug, string? status, IDecisionsService decisions) => + { + ProjectSlug project = projectSlug; + DecisionStatus statusFilter = status != null ? DecisionStatus.From(status) : DecisionStatus.Pending; + + var result = decisions.ListDecisions(project, statusFilter); + return Results.Ok(result); + }); + + app.MapPost("/api/decisions/{id}/resolve", async (string id, string projectSlug, ResolveRequest body, + IDecisionsService decisions, CancellationToken ct) => + { + ProjectSlug project = projectSlug; + DecisionId decisionId = id; + + var result = await decisions.ResolveDecisionAsync(project, decisionId, body.Resolution, ct); + + return result switch + { + Ok => Results.Ok(), + Err err when err.Error.Code == "DECISION_NOT_FOUND" => Results.NotFound(), + Err err when err.Error.Code == "DECISION_ALREADY_RESOLVED" => Results.Conflict(), + Err err => Results.Problem(err.Error.Message), + _ => Results.Problem("Unexpected result."), + }; + }); + + return app; + } +} diff --git a/ai-dev.api/Routes/MessageRoutes.cs b/ai-dev.api/Routes/MessageRoutes.cs new file mode 100644 index 0000000..ed3161b --- /dev/null +++ b/ai-dev.api/Routes/MessageRoutes.cs @@ -0,0 +1,41 @@ +using AiDev.Models.Types; +using AiDev.Services; + +namespace AiDev.Api.Routes; + +public static class MessageRoutes +{ + public static IEndpointRouteBuilder MapMessageRoutes(this IEndpointRouteBuilder app) + { + app.MapGet("/api/messages", (string projectSlug, string? agentSlug, bool? processed, MessagesService messages) => + { + ProjectSlug project = projectSlug; + AgentSlug? agent = agentSlug != null ? (AgentSlug)agentSlug : null; + + var all = messages.ListMessages(project, agent); + + var result = processed.HasValue + ? all.Where(m => m.IsProcessed == processed.Value).ToList() + : all; + + return Results.Ok(result); + }); + + app.MapPost("/api/messages/{filename}/process", (string filename, string projectSlug, string agentSlug, MessagesService messages) => + { + ProjectSlug project = projectSlug; + AgentSlug agent = agentSlug; + + // Verify the message exists in the inbox (unprocessed) before archiving. + var all = messages.ListMessages(project, agent); + var exists = all.Any(m => m.Filename == filename && !m.IsProcessed); + if (!exists) + return Results.NotFound(); + + messages.MarkProcessed(project, agent, filename); + return Results.Ok(); + }); + + return app; + } +} diff --git a/ai-dev.api/ai-dev.api.csproj b/ai-dev.api/ai-dev.api.csproj new file mode 100644 index 0000000..47274f0 --- /dev/null +++ b/ai-dev.api/ai-dev.api.csproj @@ -0,0 +1,15 @@ + + + + net10.0 + enable + enable + AiDev.Api + + + + + + + + diff --git a/ai-dev.api/ai-dev.api.http b/ai-dev.api/ai-dev.api.http new file mode 100644 index 0000000..8603245 --- /dev/null +++ b/ai-dev.api/ai-dev.api.http @@ -0,0 +1,6 @@ +@ai_dev.api_HostAddress = http://localhost:5191 + +GET {{ai_dev.api_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/ai-dev.api/appsettings.Development.json b/ai-dev.api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/ai-dev.api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/ai-dev.api/appsettings.json b/ai-dev.api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/ai-dev.api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/ai-dev.core/Extensions/CoreServiceExtensions.cs b/ai-dev.core/Extensions/CoreServiceExtensions.cs index 1dc12fe..d39c410 100644 --- a/ai-dev.core/Extensions/CoreServiceExtensions.cs +++ b/ai-dev.core/Extensions/CoreServiceExtensions.cs @@ -24,6 +24,11 @@ public static class CoreServiceExtensions /// public static IServiceCollection AddAiDevCore(this IServiceCollection services) { + // WorkspacePaths is resolved lazily from the active workspace holder so that the holder + // can be populated (by activating a project) before any service first uses it. + services.AddSingleton(); + services.AddSingleton(sp => sp.GetRequiredService().Paths); + services.AddSingleton(); services.AddSingleton, TaskAssignedHandler>(); services.AddSingleton(); @@ -37,9 +42,9 @@ public static IServiceCollection AddAiDevCore(this IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -49,7 +54,7 @@ public static IServiceCollection AddAiDevCore(this IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/ai-dev.core/Extensions/WorkspacePathsExtensions.cs b/ai-dev.core/Extensions/WorkspacePathsExtensions.cs index 8ad4c27..4a6110d 100644 --- a/ai-dev.core/Extensions/WorkspacePathsExtensions.cs +++ b/ai-dev.core/Extensions/WorkspacePathsExtensions.cs @@ -4,10 +4,7 @@ public static class WorkspacePathsExtensions { extension(RootDir dir) { - public RegistryFile RegistryFile() => new(Path.Combine(dir.Value, FilePathConstants.RegistryFileName)); - public StudioSettingFile StudioSettingFile() => new(Path.Combine(dir.Value, FilePathConstants.StudioSettingsFileName)); - public AgentTemplatesFile AgentTemplatesFile() => new(Path.Combine(dir.Value, FilePathConstants.AgentTemplatesDirName)); - public ProjectDir ProjectDir(ProjectSlug slug) => new(Path.Combine(dir.Value, slug.Value)); + public ProjectDir ProjectDir(ProjectSlug slug) => new(dir.Value); } extension(ProjectDir dir) diff --git a/ai-dev.core/Features/Agent/AgentInboxService.cs b/ai-dev.core/Features/Agent/AgentInboxService.cs index a826464..9bcb01e 100644 --- a/ai-dev.core/Features/Agent/AgentInboxService.cs +++ b/ai-dev.core/Features/Agent/AgentInboxService.cs @@ -6,7 +6,7 @@ namespace AiDev.Features.Agent; public partial class AgentInboxService( WorkspacePaths paths, ProjectStateChangedNotifier projectStateChangedNotifier, - ILogger logger) + ILogger logger) : IAgentInboxService { private static readonly ActivitySource ActivitySource = new("AiDevNet.AgentRunner"); diff --git a/ai-dev.core/Features/Agent/AgentRunnerService.cs b/ai-dev.core/Features/Agent/AgentRunnerService.cs index fff1cce..ec25f78 100644 --- a/ai-dev.core/Features/Agent/AgentRunnerService.cs +++ b/ai-dev.core/Features/Agent/AgentRunnerService.cs @@ -19,7 +19,7 @@ public partial class AgentRunnerService( AgentPromptBuilder promptBuilder, SessionCompletionProcessor completionProcessor, SecretsService secretsService, - DecisionsService decisionsService, + IDecisionsService decisionsService, ILogger logger, ProjectStateChangedNotifier projectStateChangedNotifier, FeatureFlagsService featureFlagsService, diff --git a/ai-dev.core/Features/Agent/AgentTemplatesService.cs b/ai-dev.core/Features/Agent/AgentTemplatesService.cs index 4075a19..6baa55e 100644 --- a/ai-dev.core/Features/Agent/AgentTemplatesService.cs +++ b/ai-dev.core/Features/Agent/AgentTemplatesService.cs @@ -1,19 +1,24 @@ namespace AiDev.Features.Agent; /// -/// Loads, saves, creates, and deletes agent templates. +/// Loads, saves, creates, and deletes agent templates from the global templates directory. /// -public class AgentTemplatesService(WorkspacePaths paths) +public class AgentTemplatesService { private readonly TemplateComposer _composer = new(); + private readonly string? _templatesOverride; + + public AgentTemplatesService(string templatesDir) => _templatesOverride = templatesDir; + public AgentTemplatesService() { } + + private AgentTemplatesFile TemplatesDir => new(_templatesOverride ?? GlobalPaths.AgentTemplatesDir); /// /// Lists the available agent templates. /// - /// The available templates ordered by name. public List ListTemplates() { - var dir = paths.AgentTemplatesDir; + var dir = TemplatesDir.Value; if (!Directory.Exists(dir)) return []; return [.. Directory.GetFiles(dir, "*.json") @@ -24,7 +29,7 @@ public List ListTemplates() private IReadOnlyDictionary LoadPartials() { - var sharedDir = Path.Combine(paths.AgentTemplatesDir.Value, "shared"); + var sharedDir = Path.Combine(TemplatesDir.Value, "shared"); if (!Directory.Exists(sharedDir)) return new Dictionary(); return Directory.GetFiles(sharedDir, "*.md") @@ -61,32 +66,28 @@ private IReadOnlyDictionary LoadPartials() /// /// Gets an agent template by slug. /// - /// The template slug. - /// The matching template, or when not found. public AgentTemplate? GetTemplate(string slug) { if (!AgentSlug.TryParse(slug, out _)) return null; - var jsonPath = paths.SafeTemplatePath(slug, ".json"); + var jsonPath = TemplatesDir.SafeTemplateFile(slug, ".json"); return jsonPath != null && File.Exists(jsonPath.Value) ? LoadTemplateFile(jsonPath.Value) : null; } /// /// Saves an agent template. /// - /// The template to persist. public void SaveTemplate(AgentTemplate template) { - var jsonPath = paths.SafeTemplatePath(template.Slug, ".json"); - var mdPath = paths.SafeTemplatePath(template.Slug, ".md"); + var jsonPath = TemplatesDir.SafeTemplateFile(template.Slug, ".json"); + var mdPath = TemplatesDir.SafeTemplateFile(template.Slug, ".md"); if (jsonPath == null || mdPath == null) throw new ArgumentException($"Invalid template slug: '{template.Slug}'"); - Directory.CreateDirectory(paths.AgentTemplatesDir.Value); + Directory.CreateDirectory(TemplatesDir.Value); if (!string.IsNullOrEmpty(template.Content)) File.WriteAllText(mdPath.Value, template.Content); - // Store metadata only in JSON (content lives in .md) var meta = new AgentTemplate { Slug = template.Slug, @@ -105,8 +106,6 @@ public void SaveTemplate(AgentTemplate template) /// /// Creates and saves a new agent template. /// - /// The template to create. - /// The created template. public AgentTemplate CreateTemplate(AgentTemplate template) { if (string.IsNullOrEmpty(template.Model)) @@ -119,11 +118,10 @@ public AgentTemplate CreateTemplate(AgentTemplate template) /// /// Deletes an agent template by slug. /// - /// The template slug. public void DeleteTemplate(string slug) { - var jsonPath = paths.SafeTemplatePath(slug, ".json"); - var mdPath = paths.SafeTemplatePath(slug, ".md"); + var jsonPath = TemplatesDir.SafeTemplateFile(slug, ".json"); + var mdPath = TemplatesDir.SafeTemplateFile(slug, ".md"); if (jsonPath != null && File.Exists(jsonPath.Value)) File.Delete(jsonPath.Value); if (mdPath != null && File.Exists(mdPath.Value)) File.Delete(mdPath.Value); diff --git a/ai-dev.core/Features/Agent/IAgentInboxService.cs b/ai-dev.core/Features/Agent/IAgentInboxService.cs new file mode 100644 index 0000000..0a0f429 --- /dev/null +++ b/ai-dev.core/Features/Agent/IAgentInboxService.cs @@ -0,0 +1,24 @@ +namespace AiDev.Features.Agent; + +/// +/// Writes inbox messages for agents and notifies project state changes. +/// +public interface IAgentInboxService +{ + /// + /// Writes a message into an agent inbox. + /// + /// The project that owns the agent. + /// The target agent slug. + /// The message source. + /// The message subject. + /// The message type. + /// The message priority. + /// The message body. + /// The optional associated task identifier. + /// The optional associated decision identifier. + /// The result of the write operation. + Result WriteInboxMessage(ProjectSlug projectSlug, AgentSlug agentSlug, + MessageSource from, string re, MessageType type, Priority priority, string body, + TaskId? taskId = null, DecisionId? decisionId = null); +} diff --git a/ai-dev.core/Features/Agent/SessionCompletionProcessor.cs b/ai-dev.core/Features/Agent/SessionCompletionProcessor.cs index d91e35f..18d3123 100644 --- a/ai-dev.core/Features/Agent/SessionCompletionProcessor.cs +++ b/ai-dev.core/Features/Agent/SessionCompletionProcessor.cs @@ -10,7 +10,7 @@ namespace AiDev.Features.Agent; /// public partial class SessionCompletionProcessor( WorkspacePaths paths, - BoardService boardService, + IBoardService boardService, InsightsService insightsService, ProjectStateChangedNotifier projectStateChangedNotifier, ILogger logger) diff --git a/ai-dev.core/Features/Agent/TaskAssignedHandler.cs b/ai-dev.core/Features/Agent/TaskAssignedHandler.cs index 8415d26..4020c54 100644 --- a/ai-dev.core/Features/Agent/TaskAssignedHandler.cs +++ b/ai-dev.core/Features/Agent/TaskAssignedHandler.cs @@ -1,7 +1,7 @@ namespace AiDev.Features.Agent; internal sealed partial class TaskAssignedHandler( - AgentInboxService inbox, + IAgentInboxService inbox, IAgentRunnerService runner, ILogger logger) : IDomainEventHandler { diff --git a/ai-dev.core/Features/Board/BoardService.cs b/ai-dev.core/Features/Board/BoardService.cs index 785e63a..7abe13c 100644 --- a/ai-dev.core/Features/Board/BoardService.cs +++ b/ai-dev.core/Features/Board/BoardService.cs @@ -36,7 +36,7 @@ public partial class BoardService( AtomicFileWriter fileWriter, ProjectMutationCoordinator coordinator, ILogger logger, - ProjectStateChangedNotifier projectStateChangedNotifier) + ProjectStateChangedNotifier projectStateChangedNotifier) : IBoardService { private static readonly DomainError InvalidColumnError = new("BOARD_INVALID_COLUMN", "Column id is invalid."); private static readonly TimeSpan DispatchTimeout = TimeSpan.FromSeconds(10); diff --git a/ai-dev.core/Features/Board/IBoardService.cs b/ai-dev.core/Features/Board/IBoardService.cs new file mode 100644 index 0000000..bdafa5a --- /dev/null +++ b/ai-dev.core/Features/Board/IBoardService.cs @@ -0,0 +1,69 @@ +namespace AiDev.Features.Board; + +/// +/// Provides persistence and mutation operations for project boards. +/// +public interface IBoardService +{ + /// + /// Loads the board for a project. + /// + /// The project whose board should be loaded. + /// The loaded board, or a default empty board when none exists. + Board LoadBoard(ProjectSlug projectSlug); + + /// + /// Saves the board for a project. + /// + /// The project whose board should be saved. + /// The board to save. + void SaveBoard(ProjectSlug projectSlug, Board board); + + /// + /// Creates a new task on the board. + /// + Task> CreateTaskAsync(ProjectSlug projectSlug, string columnId, string title, + string? description, string priority, string? assignee, List? tags = null, + CancellationToken cancellationToken = default); + + /// + /// Updates an existing task on the board. + /// + Task> UpdateTaskAsync(ProjectSlug projectSlug, TaskId taskId, string newColumnId, + string title, string? description, string priority, string? assignee, List? tags = null, + CancellationToken cancellationToken = default); + + /// + /// Marks a task as nudged. + /// + void SetTaskNudged(ProjectSlug projectSlug, TaskId taskId); + + /// + /// Deletes a task from the board. + /// + Task> DeleteTaskAsync(ProjectSlug projectSlug, TaskId taskId, + CancellationToken cancellationToken = default); + + /// + /// Clears all tasks from a column. + /// + Task> ClearColumnAsync(ProjectSlug projectSlug, ColumnId columnId, + CancellationToken cancellationToken = default); + + /// + /// Returns the allowed tag strings for a project from allowed-tags.json, or null if no allowlist is configured. + /// + List? GetAllowedTags(ProjectSlug projectSlug); + + /// + /// Merges tags from a result payload onto the specified task and persists. + /// No-ops silently if the task does not exist or tags is null/empty. + /// + void MergeTaskTagsFromResult(ProjectSlug projectSlug, TaskId taskId, IEnumerable? tags); + + /// + /// Automatically moves a board task to Done and merges any tags from the session result. + /// No-ops silently if the task does not exist or is already in Done. + /// + void CompleteTaskFromResult(ProjectSlug projectSlug, TaskId taskId, SessionResult result); +} diff --git a/ai-dev.core/Features/Decision/DecisionChatService.cs b/ai-dev.core/Features/Decision/DecisionChatService.cs index fdacbef..6c04b54 100644 --- a/ai-dev.core/Features/Decision/DecisionChatService.cs +++ b/ai-dev.core/Features/Decision/DecisionChatService.cs @@ -10,7 +10,7 @@ namespace AiDev.Features.Decision; public partial class DecisionChatService( WorkspacePaths paths, IAgentRunnerService runner, - AgentInboxService inbox, + IAgentInboxService inbox, ProjectStateChangedNotifier projectStateNotifier, ILogger logger) { diff --git a/ai-dev.core/Features/Decision/DecisionsService.cs b/ai-dev.core/Features/Decision/DecisionsService.cs index 83a7c73..fd0d929 100644 --- a/ai-dev.core/Features/Decision/DecisionsService.cs +++ b/ai-dev.core/Features/Decision/DecisionsService.cs @@ -8,7 +8,7 @@ public class DecisionsService( IDomainEventDispatcher dispatcher, AtomicFileWriter fileWriter, ProjectMutationCoordinator coordinator, - ILogger logger) + ILogger logger) : IDecisionsService { private const string ResponseSeparator = "\n\n---\n\n## Human Response\n\n"; private static readonly TimeSpan DispatchTimeout = TimeSpan.FromSeconds(10); diff --git a/ai-dev.core/Features/Decision/IDecisionsService.cs b/ai-dev.core/Features/Decision/IDecisionsService.cs new file mode 100644 index 0000000..38026e5 --- /dev/null +++ b/ai-dev.core/Features/Decision/IDecisionsService.cs @@ -0,0 +1,46 @@ +namespace AiDev.Features.Decision; + +/// +/// Provides creation, lookup, and resolution operations for project decisions. +/// +public interface IDecisionsService +{ + /// + /// Creates a new decision request. + /// + /// The project that owns the decision. + /// The decision source. + /// The decision subject. + /// The decision priority. + /// The optional blocker reference. + /// The decision body content. + /// The result of the create operation. + Result CreateDecision(ProjectSlug projectSlug, string from, string subject, + Priority priority, string? blocks, string body); + + /// + /// Lists decisions for a project filtered by status. + /// + /// The project that owns the decisions. + /// The optional status filter. + /// The matching decisions. + List ListDecisions(ProjectSlug projectSlug, DecisionStatus? status = null); + + /// + /// Gets a decision by identifier. + /// + /// The project that owns the decision. + /// The decision identifier. + /// The decision item, or when not found. + DecisionItem? GetDecision(ProjectSlug projectSlug, DecisionId id); + + /// + /// Resolves a decision with a human response. + /// + /// The project that owns the decision. + /// The decision identifier. + /// The response used to resolve the decision. + /// The cancellation token for the operation. + /// The result of the resolve operation. + Task> ResolveDecisionAsync(ProjectSlug projectSlug, DecisionId id, string response, CancellationToken cancellationToken); +} diff --git a/ai-dev.core/Features/Workspace/ActiveWorkspaceHolder.cs b/ai-dev.core/Features/Workspace/ActiveWorkspaceHolder.cs new file mode 100644 index 0000000..58d24f4 --- /dev/null +++ b/ai-dev.core/Features/Workspace/ActiveWorkspaceHolder.cs @@ -0,0 +1,41 @@ +namespace AiDev.Features.Workspace; + +/// +/// Holds the currently active project's . +/// Registered as a singleton; call before any service resolves +/// from DI. +/// +public sealed class ActiveWorkspaceHolder +{ + private WorkspacePaths? _paths; + + /// + /// Gets the for the active project. + /// + /// Thrown when no project has been activated. + public WorkspacePaths Paths => _paths ?? throw new InvalidOperationException( + "No active project. Call ActiveWorkspaceHolder.Activate(codebasePath) before accessing workspace paths."); + + /// Gets a value indicating whether a project is currently active. + public bool HasActiveProject => _paths is not null; + + /// Gets the absolute path to the active codebase root, or when no project is active. + public string? ActiveCodebasePath { get; private set; } + + /// + /// Activates the workspace rooted at /.ai-dev/. + /// + /// Absolute path to the codebase directory. + public void Activate(string codebasePath) + { + ActiveCodebasePath = Path.GetFullPath(codebasePath); + _paths = new WorkspacePaths(new RootDir(Path.Combine(ActiveCodebasePath, ".ai-dev"))); + } + + /// Clears the active project. + public void Deactivate() + { + _paths = null; + ActiveCodebasePath = null; + } +} diff --git a/ai-dev.core/Features/Workspace/GlobalPaths.cs b/ai-dev.core/Features/Workspace/GlobalPaths.cs new file mode 100644 index 0000000..f218f82 --- /dev/null +++ b/ai-dev.core/Features/Workspace/GlobalPaths.cs @@ -0,0 +1,23 @@ +namespace AiDev.Features.Workspace; + +/// +/// Provides paths to the global (per-user, cross-project) AI Dev Studio data directory. +/// These locations are independent of any codebase root. +/// +public static class GlobalPaths +{ + private static readonly string AppDataDir = + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AiDevStudio"); + + /// Path to the global project registry file. + public static string RegistryFile => Path.Combine(AppDataDir, "registry.json"); + + /// Path to the global studio settings file. + public static string StudioSettingsFile => Path.Combine(AppDataDir, "studio-settings.json"); + + /// Path to the global agent templates directory. + public static string AgentTemplatesDir => Path.Combine(AppDataDir, "agent-templates"); + + /// Ensures the global app data directory exists. + public static void EnsureCreated() => Directory.CreateDirectory(AppDataDir); +} diff --git a/ai-dev.core/Features/Workspace/ProjectConfig.cs b/ai-dev.core/Features/Workspace/ProjectConfig.cs new file mode 100644 index 0000000..43fd3ad --- /dev/null +++ b/ai-dev.core/Features/Workspace/ProjectConfig.cs @@ -0,0 +1,13 @@ +namespace AiDev.Features.Workspace; + +/// +/// Represents the contents of a .ai-dev/project.json file. +/// The minimal fields ( and ) are required by the +/// VS Code extension for project discovery. The remaining fields are written by AI Dev Studio. +/// +public sealed record ProjectConfig( + string ProjectSlug, + int ApiPort, + string? Name = null, + string? Description = null, + DateTime? CreatedAt = null); diff --git a/ai-dev.core/Features/Workspace/ProjectConfigReader.cs b/ai-dev.core/Features/Workspace/ProjectConfigReader.cs new file mode 100644 index 0000000..67ed455 --- /dev/null +++ b/ai-dev.core/Features/Workspace/ProjectConfigReader.cs @@ -0,0 +1,89 @@ +namespace AiDev.Features.Workspace; + +/// +/// Reads .ai-dev/project.json from a codebase directory. +/// +public static class ProjectConfigReader +{ + private const string AiDevDirName = ".ai-dev"; + private const string ConfigFileName = "project.json"; + + /// + /// Reads .ai-dev/project.json from . + /// Returns if the file is absent, malformed, or missing + /// projectSlug. + /// + public static ProjectConfig? TryRead(string baseDirectory) + { + var configPath = Path.Combine(baseDirectory, AiDevDirName, ConfigFileName); + if (!File.Exists(configPath)) return null; + + try + { + var json = File.ReadAllText(configPath); + var dto = JsonSerializer.Deserialize(json, JsonDefaults.Read); + if (dto?.ProjectSlug is null or "") return null; + return new ProjectConfig(dto.ProjectSlug, dto.ApiPort); + } + catch { return null; } + } + + /// + /// Reads .ai-dev/project.json from , including the + /// optional display fields written by AI Dev Studio (name, description, + /// createdAt). + /// Returns if the file is absent, malformed, or missing + /// projectSlug. + /// + public static ProjectConfig? TryReadFull(string baseDirectory) + { + var configPath = Path.Combine(baseDirectory, AiDevDirName, ConfigFileName); + if (!File.Exists(configPath)) return null; + + try + { + var json = File.ReadAllText(configPath); + var dto = JsonSerializer.Deserialize(json, JsonDefaults.Read); + if (dto?.ProjectSlug is null or "") return null; + + DateTime? createdAt = DateTime.TryParse(dto.CreatedAt, null, + System.Globalization.DateTimeStyles.RoundtripKind, out var dt) ? dt : null; + + return new ProjectConfig(dto.ProjectSlug, dto.ApiPort, + Name: dto.Name, Description: dto.Description, CreatedAt: createdAt); + } + catch { return null; } + } + + /// + /// Creates by walking up from + /// until a directory containing .ai-dev/project.json is found, otherwise falls back + /// to . + /// + public static WorkspacePaths CreateWorkspacePaths(string baseDirectory, RootDir? fallback) + { + var dir = Path.GetFullPath(baseDirectory); + while (dir is not null) + { + var config = TryRead(dir); + if (config is not null) + return new WorkspacePaths(new RootDir(Path.Combine(dir, AiDevDirName))); + dir = Path.GetDirectoryName(dir); + } + + if (fallback is null) + throw new InvalidOperationException( + $"No .ai-dev/project.json found walking up from '{baseDirectory}' and no fallback RootDir was provided."); + + return new WorkspacePaths(fallback); + } + + private sealed class ProjectConfigDto + { + public string? ProjectSlug { get; set; } + public int ApiPort { get; set; } + public string? Name { get; set; } + public string? Description { get; set; } + public string? CreatedAt { get; set; } + } +} diff --git a/ai-dev.core/Features/Workspace/WorkspaceRegistry.cs b/ai-dev.core/Features/Workspace/WorkspaceRegistry.cs index 54d237b..57d472a 100644 --- a/ai-dev.core/Features/Workspace/WorkspaceRegistry.cs +++ b/ai-dev.core/Features/Workspace/WorkspaceRegistry.cs @@ -1,12 +1,17 @@ namespace AiDev.Features.Workspace; /// -/// Represents the persisted registry of workspace projects. +/// Represents the global registry of known project codebases. /// public class WorkspaceRegistry { /// - /// Gets or sets the registered workspace projects. + /// Gets or sets the registered codebase paths. /// public List Projects { get; set; } = []; + + /// + /// Gets or sets the absolute codebase path of the most recently activated project. + /// + public string? LastActivePath { get; set; } } diff --git a/ai-dev.core/Features/Workspace/WorkspaceRegistryEntry.cs b/ai-dev.core/Features/Workspace/WorkspaceRegistryEntry.cs index 4b5a456..e1d08c1 100644 --- a/ai-dev.core/Features/Workspace/WorkspaceRegistryEntry.cs +++ b/ai-dev.core/Features/Workspace/WorkspaceRegistryEntry.cs @@ -1,22 +1,14 @@ namespace AiDev.Features.Workspace; /// -/// Represents a project entry stored in the workspace registry. +/// Represents a known codebase in the global project registry. +/// The project's slug and display name are read from the codebase's own +/// .ai-dev/project.json at runtime and are not duplicated here. /// public class WorkspaceRegistryEntry { /// - /// Gets or sets the project slug. - /// - public required string Slug { get; set; } - - /// - /// Gets or sets the relative project path. + /// Gets or sets the absolute path to the codebase root directory. /// public required string Path { get; set; } - - /// - /// Gets or sets the display name of the project. - /// - public required string Name { get; set; } } diff --git a/ai-dev.core/Features/Workspace/WorkspaceService.cs b/ai-dev.core/Features/Workspace/WorkspaceService.cs index b78411f..b3d50d9 100644 --- a/ai-dev.core/Features/Workspace/WorkspaceService.cs +++ b/ai-dev.core/Features/Workspace/WorkspaceService.cs @@ -1,114 +1,98 @@ namespace AiDev.Features.Workspace; -file class ProjectJson -{ - public string? Description { get; set; } - public string? CreatedAt { get; set; } -} - /// -/// Provides workspace project management and metadata operations. +/// Manages the global registry of known project codebases and per-project metadata operations. /// -public class WorkspaceService(WorkspacePaths paths, AtomicFileWriter fileWriter, ILogger? logger = null) +public class WorkspaceService(ActiveWorkspaceHolder workspace, AtomicFileWriter fileWriter, ILogger? logger = null) { - private static readonly DomainError InvalidProjectSlugError = new("WORKSPACE_INVALID_SLUG", "Project slug is invalid."); private static readonly DomainError ProjectNotFoundError = new("WORKSPACE_NOT_FOUND", "Project not found."); + // ── Registry ────────────────────────────────────────────────────────────── + /// - /// Lists the registered workspace projects. + /// Lists all registered project codebases by reading each one's .ai-dev/project.json. /// - /// The registered workspace projects. public List ListProjects() { - if (!File.Exists(paths.RegistryPath)) return []; + var registry = ReadRegistry(); + var projects = new List(); - try + foreach (var entry in registry.Projects) { - var json = File.ReadAllText(paths.RegistryPath); - var registry = JsonSerializer.Deserialize(json, JsonDefaults.Read); - if (registry?.Projects == null) return []; - - var projects = new List(); - foreach (var entry in registry.Projects) + try { - if (!ProjectSlug.TryParse(entry.Path, out var entrySlug)) continue; - var projectJsonPath = paths.ProjectJsonPath(entrySlug); + var tempPaths = PathsFor(entry.Path); + var projectJsonPath = tempPaths.ProjectJsonPath(default!); + if (!File.Exists(projectJsonPath)) continue; - string? description = null; - DateTime? createdAt = null; + var raw = JsonSerializer.Deserialize>( + File.ReadAllText(projectJsonPath), JsonDefaults.Read); + if (raw is null) continue; - if (File.Exists(projectJsonPath)) - { - try - { - var pJson = File.ReadAllText(projectJsonPath); - var pData = JsonSerializer.Deserialize(pJson, JsonDefaults.Read); - description = pData?.Description; - createdAt = DateTime.TryParse(pData?.CreatedAt, null, System.Globalization.DateTimeStyles.RoundtripKind, out var caDate) - ? caDate : null; - } - catch (Exception ex) { logger?.LogWarning(ex, "[workspace] Failed to read project.json for {Slug} — using defaults", entrySlug); } - } - - var agentsDir = paths.AgentsDir(entrySlug); - var agentCount = Directory.Exists(agentsDir) - ? Directory.GetDirectories(agentsDir).Length - : 0; - - projects.Add(new WorkspaceProject( - slug: entrySlug, - name: entry.Name, - description: description, - createdAt: createdAt, - agentCount: agentCount)); - } + var slug = ReadString(raw, "projectSlug") ?? ReadString(raw, "slug"); + if (slug is null || !ProjectSlug.TryParse(slug, out var projectSlug)) continue; - return projects; - } - catch (Exception ex) - { - logger?.LogError(ex, "[workspace] Failed to read workspace registry at {Path} — returning empty project list", paths.RegistryPath); - return []; + var name = ReadString(raw, "name") ?? slug; + var description = ReadString(raw, "description"); + var createdAtStr = ReadString(raw, "createdAt"); + var createdAt = DateTime.TryParse(createdAtStr, null, + System.Globalization.DateTimeStyles.RoundtripKind, out var dt) ? dt : (DateTime?)null; + + var agentsDir = tempPaths.AgentsDir(projectSlug); + var agentCount = Directory.Exists(agentsDir) ? Directory.GetDirectories(agentsDir).Length : 0; + + projects.Add(new WorkspaceProject(projectSlug, name, description, createdAt, agentCount)); + } + catch (Exception ex) + { + logger?.LogWarning(ex, "[workspace] Failed to read project at {Path} — skipping", entry.Path); + } } + + return projects; } + // ── Project lifecycle ───────────────────────────────────────────────────── + /// - /// Creates a new project folder structure and registers it in workspaces.json. - /// Returns an error message if validation fails, null on success. + /// Initialises a codebase as an AI Dev project: creates the .ai-dev/ structure, + /// writes a merged project.json, registers the path globally, and activates it. /// - public Result CreateProject(string slug, string name, string? description, string? codebasePath = null) + public Result CreateProject(string codebasePath, string slug, string name, + string? description = null, int apiPort = 0) { if (string.IsNullOrWhiteSpace(name)) return new Err(new DomainError("WORKSPACE_NAME_REQUIRED", "Name is required.")); if (!ProjectSlug.TryParse(slug, out var projectSlug)) - return new Err(new DomainError("WORKSPACE_INVALID_SLUG", "Slug must contain only lowercase letters, digits, and hyphens, and cannot start or end with a hyphen.")); + return new Err(new DomainError("WORKSPACE_INVALID_SLUG", + "Slug must contain only lowercase letters, digits, and hyphens, and cannot start or end with a hyphen.")); + if (!Directory.Exists(codebasePath)) + return new Err(new DomainError("WORKSPACE_INVALID_PATH", + $"Directory not found: {codebasePath}")); - var projectDir = paths.ProjectDir(projectSlug); - if (Directory.Exists(projectDir)) - return new Err(new DomainError("WORKSPACE_ALREADY_EXISTS", $"A project with slug '{slug}' already exists.")); + var absolutePath = Path.GetFullPath(codebasePath); + var tempPaths = PathsFor(absolutePath); try { - // Create folder structure - Directory.CreateDirectory(paths.AgentsDir(projectSlug)); - Directory.CreateDirectory(Path.GetDirectoryName(paths.BoardPath(projectSlug))!); - Directory.CreateDirectory(paths.DecisionsPendingDir(projectSlug)); - Directory.CreateDirectory(paths.DecisionsResolvedDir(projectSlug)); + // Create .ai-dev/ structure + Directory.CreateDirectory(tempPaths.AgentsDir(projectSlug)); + Directory.CreateDirectory(Path.GetDirectoryName(tempPaths.BoardPath(projectSlug))!); + Directory.CreateDirectory(tempPaths.DecisionsPendingDir(projectSlug)); + Directory.CreateDirectory(tempPaths.DecisionsResolvedDir(projectSlug)); - // Write project.json + // Write merged project.json var meta = new Dictionary { - ["slug"] = slug, + ["projectSlug"] = slug, ["name"] = name, ["description"] = description ?? string.Empty, ["createdAt"] = DateTime.UtcNow.ToString("o"), - ["codebaseInitialized"] = false, }; - if (!string.IsNullOrWhiteSpace(codebasePath)) - meta["codebasePath"] = codebasePath; + if (apiPort > 0) meta["apiPort"] = apiPort; fileWriter.WriteAllText( - paths.ProjectJsonPath(projectSlug), + tempPaths.ProjectJsonPath(projectSlug), JsonSerializer.Serialize(meta, JsonDefaults.Write)); // Write default board @@ -124,66 +108,81 @@ public Result CreateProject(string slug, string name, string? description, tasks = new { }, }; fileWriter.WriteAllText( - paths.BoardPath(projectSlug), + tempPaths.BoardPath(projectSlug), JsonSerializer.Serialize(boardJson, JsonDefaults.Write)); - // Register in workspaces.json - WorkspaceRegistry registry; - if (File.Exists(paths.RegistryPath)) - { - var existing = File.ReadAllText(paths.RegistryPath); - registry = JsonSerializer.Deserialize(existing, JsonDefaults.Read) ?? new WorkspaceRegistry(); - } - else - { - registry = new(); - } + // Register in global registry + RegisterPath(absolutePath); - registry.Projects.Add(new() { Slug = slug, Path = slug, Name = name }); - fileWriter.WriteAllText(paths.RegistryPath, JsonSerializer.Serialize(registry, JsonDefaults.Write)); + // Activate + workspace.Activate(absolutePath); return new Ok(Unit.Value); } - catch (JsonException ex) - { - try { if (Directory.Exists(projectDir)) Directory.Delete(projectDir.Value, recursive: true); } catch { } - return new Err(new DomainError("WORKSPACE_INVALID_REGISTRY", ex.Message)); - } catch (IOException ex) { - // Clean up partial directory on failure - try { if (Directory.Exists(projectDir)) Directory.Delete(projectDir.Value, recursive: true); } catch { } return new Err(new DomainError("WORKSPACE_IO_ERROR", $"Failed to create project: {ex.Message}")); } catch (UnauthorizedAccessException ex) { - try { if (Directory.Exists(projectDir)) Directory.Delete(projectDir.Value, recursive: true); } catch { } return new Err(new DomainError("WORKSPACE_IO_ERROR", $"Failed to create project: {ex.Message}")); } } /// - /// Gets detailed metadata for a project. + /// Registers an existing codebase (that already has .ai-dev/project.json) and activates it. + /// + public Result RegisterProject(string codebasePath) + { + var absolutePath = Path.GetFullPath(codebasePath); + var config = ProjectConfigReader.TryRead(absolutePath); + if (config is null) + return new Err(new DomainError("WORKSPACE_INVALID_PATH", + "No valid .ai-dev/project.json found at that path.")); + + RegisterPath(absolutePath); + workspace.Activate(absolutePath); + return new Ok(Unit.Value); + } + + /// + /// Removes a codebase from the global registry. Does not delete any files on disk. + /// + public void RemoveProject(string codebasePath) + { + var absolutePath = Path.GetFullPath(codebasePath); + var registry = ReadRegistry(); + registry.Projects.RemoveAll(e => + string.Equals(Path.GetFullPath(e.Path), absolutePath, StringComparison.OrdinalIgnoreCase)); + if (string.Equals(registry.LastActivePath, absolutePath, StringComparison.OrdinalIgnoreCase)) + registry.LastActivePath = null; + WriteRegistry(registry); + } + + // ── Active project metadata ─────────────────────────────────────────────── + + /// + /// Gets detailed metadata for a project from the active workspace. /// - /// The project slug to read. - /// The project detail, or when the project does not exist. public ProjectDetail? GetProject(ProjectSlug projectSlug) { - var jsonPath = paths.ProjectJsonPath(projectSlug); + var jsonPath = workspace.Paths.ProjectJsonPath(projectSlug); if (!File.Exists(jsonPath)) return null; try { - var raw = JsonSerializer.Deserialize>(File.ReadAllText(jsonPath), JsonDefaults.Read); - if (raw == null) return null; - var caStr = raw.TryGetValue("createdAt", out var ca) ? ca.GetString() : null; + var raw = JsonSerializer.Deserialize>( + File.ReadAllText(jsonPath), JsonDefaults.Read); + if (raw is null) return null; + + var caStr = ReadString(raw, "createdAt"); return new ProjectDetail { Slug = projectSlug, - Name = raw.TryGetValue("name", out var n) ? n.GetString() ?? projectSlug : projectSlug, - Description = raw.TryGetValue("description", out var d) ? d.GetString() ?? string.Empty : string.Empty, - CodebasePath = raw.TryGetValue("codebasePath", out var cp) ? cp.GetString() : null, - CreatedAt = DateTime.TryParse(caStr, null, System.Globalization.DateTimeStyles.RoundtripKind, out var caDate) ? caDate : null, + Name = ReadString(raw, "name") ?? projectSlug, + Description = ReadString(raw, "description") ?? string.Empty, + CreatedAt = DateTime.TryParse(caStr, null, + System.Globalization.DateTimeStyles.RoundtripKind, out var caDate) ? caDate : null, }; } catch (Exception ex) @@ -194,52 +193,71 @@ public Result CreateProject(string slug, string name, string? description, } /// - /// Updates editable metadata for an existing project. + /// Updates editable metadata for the active project. /// - /// The project slug to update. - /// The new project name. - /// The new project description. - /// The optional codebase path associated with the project. - /// The result of the update operation. - public Result UpdateProject(ProjectSlug projectSlug, string name, string? description, string? codebasePath) + public Result UpdateProject(ProjectSlug projectSlug, string name, string? description) { if (string.IsNullOrWhiteSpace(name)) return new Err(new DomainError("WORKSPACE_NAME_REQUIRED", "Name is required.")); - var jsonPath = paths.ProjectJsonPath(projectSlug); + + var jsonPath = workspace.Paths.ProjectJsonPath(projectSlug); if (!File.Exists(jsonPath)) return new Err(ProjectNotFoundError); try { - var raw = JsonSerializer.Deserialize>(File.ReadAllText(jsonPath), JsonDefaults.Read) - ?? []; + var raw = JsonSerializer.Deserialize>( + File.ReadAllText(jsonPath), JsonDefaults.Read) ?? []; var merged = raw.ToDictionary(kv => kv.Key, kv => (object?)kv.Value); merged["name"] = name; merged["description"] = description ?? string.Empty; - if (string.IsNullOrWhiteSpace(codebasePath)) - merged.Remove("codebasePath"); - else - merged["codebasePath"] = codebasePath; - - fileWriter.WriteAllText(jsonPath, JsonSerializer.Serialize(merged, - JsonDefaults.Write)); - - // Keep display name in sync in workspaces.json - if (File.Exists(paths.RegistryPath)) - { - var registry = JsonSerializer.Deserialize(File.ReadAllText(paths.RegistryPath), JsonDefaults.Read); - var entry = registry?.Projects.FirstOrDefault(p => p.Slug == projectSlug); - if (entry != null) - { - entry.Name = name; - fileWriter.WriteAllText(paths.RegistryPath, JsonSerializer.Serialize(registry, - JsonDefaults.Write)); - } - } + fileWriter.WriteAllText(jsonPath, JsonSerializer.Serialize(merged, JsonDefaults.Write)); return new Ok(Unit.Value); } catch (JsonException ex) { return new Err(new DomainError("WORKSPACE_INVALID_METADATA", ex.Message)); } catch (IOException ex) { return new Err(new DomainError("WORKSPACE_IO_ERROR", ex.Message)); } catch (UnauthorizedAccessException ex) { return new Err(new DomainError("WORKSPACE_IO_ERROR", ex.Message)); } } + + // ── Registry helpers ────────────────────────────────────────────────────── + + internal WorkspaceRegistry ReadRegistry() + { + GlobalPaths.EnsureCreated(); + if (!File.Exists(GlobalPaths.RegistryFile)) return new WorkspaceRegistry(); + try + { + var json = File.ReadAllText(GlobalPaths.RegistryFile); + return JsonSerializer.Deserialize(json, JsonDefaults.Read) ?? new WorkspaceRegistry(); + } + catch (Exception ex) + { + logger?.LogError(ex, "[workspace] Failed to read global registry at {Path}", GlobalPaths.RegistryFile); + return new WorkspaceRegistry(); + } + } + + private void WriteRegistry(WorkspaceRegistry registry) + { + GlobalPaths.EnsureCreated(); + fileWriter.WriteAllText(GlobalPaths.RegistryFile, JsonSerializer.Serialize(registry, JsonDefaults.Write)); + } + + private void RegisterPath(string absolutePath) + { + var registry = ReadRegistry(); + if (!registry.Projects.Any(e => + string.Equals(Path.GetFullPath(e.Path), absolutePath, StringComparison.OrdinalIgnoreCase))) + { + registry.Projects.Add(new WorkspaceRegistryEntry { Path = absolutePath }); + } + registry.LastActivePath = absolutePath; + WriteRegistry(registry); + } + + private static WorkspacePaths PathsFor(string codebasePath) => + new(new RootDir(Path.Combine(codebasePath, ".ai-dev"))); + + private static string? ReadString(Dictionary raw, string key) => + raw.TryGetValue(key, out var el) ? el.GetString() : null; } diff --git a/ai-dev.core/GlobalUsings.cs b/ai-dev.core/GlobalUsings.cs index 6116e12..9e499c1 100644 --- a/ai-dev.core/GlobalUsings.cs +++ b/ai-dev.core/GlobalUsings.cs @@ -1,3 +1,5 @@ +global using AiDev.Extensions; +global using AiDev.Features.Workspace; global using AiDev.Models; global using AiDev.Models.Types; global using AiDev.Services; diff --git a/ai-dev.core/Models/ProjectDetail.cs b/ai-dev.core/Models/ProjectDetail.cs index ed36b3d..52114f7 100644 --- a/ai-dev.core/Models/ProjectDetail.cs +++ b/ai-dev.core/Models/ProjectDetail.cs @@ -20,11 +20,6 @@ public class ProjectDetail /// public required string Description { get; set; } - /// - /// Gets or sets the optional codebase path. - /// - public string? CodebasePath { get; set; } - /// /// Gets or sets the project creation timestamp. /// diff --git a/ai-dev.core/Services/ConsistencyCheckService.cs b/ai-dev.core/Services/ConsistencyCheckService.cs index fcf9da7..0191d15 100644 --- a/ai-dev.core/Services/ConsistencyCheckService.cs +++ b/ai-dev.core/Services/ConsistencyCheckService.cs @@ -9,7 +9,7 @@ namespace AiDev.Services; public class ConsistencyCheckService( WorkspacePaths paths, WorkspaceService workspaceService, - BoardService boardService, + IBoardService boardService, ILogger logger) { private sealed class RawBoardState diff --git a/ai-dev.core/Services/DispatcherService.cs b/ai-dev.core/Services/DispatcherService.cs index c06b51c..9a8e8fc 100644 --- a/ai-dev.core/Services/DispatcherService.cs +++ b/ai-dev.core/Services/DispatcherService.cs @@ -69,13 +69,10 @@ public Task StopAsync(CancellationToken cancellationToken) public void Dispose() { _pollTimer?.Dispose(); - foreach (var w in _watchers) + foreach (var w in _watchers.ToArray()) { try { w.Dispose(); } - catch - { - // ignored - } + catch { } } _watchers.Clear(); GC.SuppressFinalize(this); diff --git a/ai-dev.core/Services/OverwatchService.cs b/ai-dev.core/Services/OverwatchService.cs index 40cfa63..e704cf8 100644 --- a/ai-dev.core/Services/OverwatchService.cs +++ b/ai-dev.core/Services/OverwatchService.cs @@ -19,12 +19,12 @@ namespace AiDev.Services; /// public partial class OverwatchService( WorkspaceService workspace, - BoardService boardService, + IBoardService boardService, IAgentRunnerService runner, - AgentInboxService inbox, + IAgentInboxService inbox, AgentService agentService, ExecutorHealthMonitor executorHealth, - DecisionsService decisionsService, + IDecisionsService decisionsService, ILogger logger) : IHostedService, IDisposable { @@ -62,8 +62,9 @@ public async Task StopAsync(CancellationToken cancellationToken) public void Dispose() { - _scanCts?.Cancel(); - _scanCts?.Dispose(); + var cts = Interlocked.Exchange(ref _scanCts, null); + try { cts?.Cancel(); } catch (ObjectDisposedException) { } + cts?.Dispose(); GC.SuppressFinalize(this); } diff --git a/ai-dev.core/Services/ProjectStateSnapshotService.cs b/ai-dev.core/Services/ProjectStateSnapshotService.cs index 2ffa096..6a4b27c 100644 --- a/ai-dev.core/Services/ProjectStateSnapshotService.cs +++ b/ai-dev.core/Services/ProjectStateSnapshotService.cs @@ -11,8 +11,8 @@ namespace AiDev.Services; /// public partial class ProjectStateSnapshotService( MessagesService messagesService, - DecisionsService decisionsService, - BoardService boardService, + IDecisionsService decisionsService, + IBoardService boardService, AgentService agentService, AgentRunnerService agentRunnerService, ILogger logger) diff --git a/ai-dev.core/Services/PromptEnhancerService.cs b/ai-dev.core/Services/PromptEnhancerService.cs index 7fc9199..923b2b9 100644 --- a/ai-dev.core/Services/PromptEnhancerService.cs +++ b/ai-dev.core/Services/PromptEnhancerService.cs @@ -172,8 +172,9 @@ private string BuildContext(ProjectSlug projectSlug) sb.AppendLine($"Project: {project.Name}"); if (!string.IsNullOrWhiteSpace(project.Description)) sb.AppendLine($"Description: {project.Description}"); - if (!string.IsNullOrWhiteSpace(project.CodebasePath)) - sb.AppendLine($"Codebase: {project.CodebasePath}"); + var codebasePath = Path.GetDirectoryName(paths.Root.Value); + if (!string.IsNullOrWhiteSpace(codebasePath)) + sb.AppendLine($"Codebase: {codebasePath}"); } var articles = kbService.ListArticles(projectSlug); diff --git a/ai-dev.core/WorkspacePaths.cs b/ai-dev.core/WorkspacePaths.cs index 84d6d99..b589a31 100644 --- a/ai-dev.core/WorkspacePaths.cs +++ b/ai-dev.core/WorkspacePaths.cs @@ -126,33 +126,22 @@ public record PlaybookArticleFile(string Value) : FilePath(Value); public record TemplateFile(string Value) : FilePath(Value); /// -/// Resolved once at startup; provides every known file-system location within the workspace. -/// Register as a singleton so the workspace root is calculated only once. +/// Resolved per active project; provides every known file-system path within a codebase's +/// .ai-dev/ directory. Consumed as a singleton whose value is set by +/// before first use. /// public class WorkspacePaths { - /// Absolute path to the workspace root directory. + /// Absolute path to the .ai-dev/ directory inside the active codebase. public RootDir Root { get; } - /// Path to workspaces.json (the project registry). - public RegistryFile RegistryPath { get; } - - /// Path to studio-settings.json. - public StudioSettingFile StudioSettingsPath { get; } - - /// Directory containing agent template files. - public AgentTemplatesFile AgentTemplatesDir { get; } - /// - /// Initializes resolved workspace paths from the workspace root. + /// Initializes resolved workspace paths from the codebase's .ai-dev/ root. /// - /// The workspace root directory. + /// The .ai-dev/ directory inside the codebase. public WorkspacePaths(RootDir root) { Root = root; - RegistryPath = Root.RegistryFile(); - StudioSettingsPath = Root.StudioSettingFile(); - AgentTemplatesDir = Root.AgentTemplatesFile(); } /// Gets the project directory path. @@ -229,6 +218,4 @@ public PlanningSessionDslFile PlanningSessionDraftDslPath(ProjectSlug p, Session public KbArticleFile? SafeKbArticlePath(ProjectSlug p, string slug) => KbDir(p).SafeKbArticleFile(slug); /// Gets a safe playbook file path when the slug is valid. public PlaybookArticleFile? SafePlaybookPath(ProjectSlug p, string slug) => PlaybooksDir(p).SafePlaybookFile(slug); - /// Gets a safe template file path when the slug and extension are valid. - public TemplateFile? SafeTemplatePath(string slug, string extension) => AgentTemplatesDir.SafeTemplateFile(slug, extension); } diff --git a/ai-dev.core/ai-dev.core.csproj b/ai-dev.core/ai-dev.core.csproj index d84bc3d..b5cfc9a 100644 --- a/ai-dev.core/ai-dev.core.csproj +++ b/ai-dev.core/ai-dev.core.csproj @@ -5,6 +5,8 @@ AiDev enable enable + + $(NoWarn);CS8602 diff --git a/ai-dev.executor.lmstudio/LmStudioAgentExecutor.cs b/ai-dev.executor.lmstudio/LmStudioAgentExecutor.cs index 3504b57..9193cca 100644 --- a/ai-dev.executor.lmstudio/LmStudioAgentExecutor.cs +++ b/ai-dev.executor.lmstudio/LmStudioAgentExecutor.cs @@ -254,9 +254,9 @@ public async Task RunAsync(ExecutorContext context, ChannelWrite LogSessionTrigger( context.Trigger?.Source, context.Trigger?.Reason, - context.Trigger?.ProjectSlug, - context.Trigger?.TaskId, - context.Trigger?.DecisionId, + context.Trigger?.ProjectSlug?.ToString(), + context.Trigger?.TaskId?.ToString(), + context.Trigger?.DecisionId?.ToString(), context.Trigger?.MessageFile); output.TryWrite($"[{DateTime.UtcNow:o}] [lmstudio] model={context.ModelId} endpoint={requestUri}"); diff --git a/ai-dev.executor.ollama/OllamaAgentExecutor.cs b/ai-dev.executor.ollama/OllamaAgentExecutor.cs index 2278f74..09fdcfd 100644 --- a/ai-dev.executor.ollama/OllamaAgentExecutor.cs +++ b/ai-dev.executor.ollama/OllamaAgentExecutor.cs @@ -212,9 +212,9 @@ public async Task RunAsync(ExecutorContext context, ChannelWrite LogTriggerDetails( context.Trigger?.Source, context.Trigger?.Reason, - context.Trigger?.ProjectSlug, - context.Trigger?.TaskId, - context.Trigger?.DecisionId, + context.Trigger?.ProjectSlug?.ToString(), + context.Trigger?.TaskId?.ToString(), + context.Trigger?.DecisionId?.ToString(), context.Trigger?.MessageFile); output.TryWrite($"[{DateTime.UtcNow:o}] [ollama] model={context.ModelId} endpoint={requestUri}"); diff --git a/ai-dev.ui.winui/App.xaml.cs b/ai-dev.ui.winui/App.xaml.cs index 772e6d8..03eaa4e 100644 --- a/ai-dev.ui.winui/App.xaml.cs +++ b/ai-dev.ui.winui/App.xaml.cs @@ -1,4 +1,5 @@ using AiDev.Core.Local.Extensions; +using AiDev.Features.Workspace; using AiDev.WinUI.ViewModels; using Microsoft.Extensions.Configuration; @@ -46,12 +47,16 @@ protected override async void OnLaunched(LaunchActivatedEventArgs args) private static void ConfigureServices(IConfiguration configuration, IServiceCollection services) { - var configuredPath = configuration["WorkspacesPath"]; - var workspaceRoot = !string.IsNullOrWhiteSpace(configuredPath) - ? Path.GetFullPath(configuredPath) - : DiscoverWorkspacesPath(); + // Activate the last-used project from the global registry (if any) before DI is built, + // so that the lazy WorkspacePaths singleton resolves correctly on first access. + var holder = new ActiveWorkspaceHolder(); + var lastActive = configuration["ActiveProjectPath"] + ?? ReadLastActiveFromRegistry(); + if (!string.IsNullOrWhiteSpace(lastActive) && Directory.Exists(lastActive)) + holder.Activate(lastActive); - services.AddSingleton(new WorkspacePaths(new RootDir(workspaceRoot))); + services.AddSingleton(holder); + services.AddSingleton(sp => sp.GetRequiredService().Paths); // Core domain services services.AddAiDevCore(); @@ -95,18 +100,17 @@ private static void ConfigureServices(IConfiguration configuration, IServiceColl services.AddTransient(); } - /// - /// Walk up from the executable directory looking for a workspaces folder. - /// - private static string DiscoverWorkspacesPath() + private static string? ReadLastActiveFromRegistry() { - var dir = new DirectoryInfo(AppContext.BaseDirectory); - for (int i = 0; i < 8 && dir is not null; i++, dir = dir.Parent) + try { - var candidate = Path.Combine(dir.FullName, "workspaces"); - if (Directory.Exists(candidate)) - return candidate; + if (!File.Exists(GlobalPaths.RegistryFile)) return null; + var json = File.ReadAllText(GlobalPaths.RegistryFile); + using var doc = System.Text.Json.JsonDocument.Parse(json); + if (doc.RootElement.TryGetProperty("lastActivePath", out var prop)) + return prop.GetString(); } - return Path.Combine(AppContext.BaseDirectory, "workspaces"); + catch { } + return null; } } diff --git a/ai-dev.ui.winui/ViewModels/AgentDashboardViewModel.cs b/ai-dev.ui.winui/ViewModels/AgentDashboardViewModel.cs index d9a2092..26c32aa 100644 --- a/ai-dev.ui.winui/ViewModels/AgentDashboardViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/AgentDashboardViewModel.cs @@ -1,3 +1,5 @@ +using AiDev.Services; + using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -14,7 +16,8 @@ public partial class AgentDashboardViewModel : ObservableObject, IDisposable private readonly AgentTemplatesService _templatesService; private readonly MainViewModel _mainViewModel; private readonly DispatcherQueue _dispatcher; - private Timer? _pollTimer; + private readonly ProjectStateChangedNotifier _notifier; + private readonly Action _onStateChanged; [ObservableProperty] public partial bool IsLoading { get; set; } [ObservableProperty] public partial bool HasFailoverAlerts { get; set; } @@ -29,13 +32,17 @@ public AgentDashboardViewModel( AgentService agentService, AgentRunnerService agentRunnerService, AgentTemplatesService templatesService, - MainViewModel mainViewModel) + MainViewModel mainViewModel, + ProjectStateChangedNotifier notifier) { _agentService = agentService; _agentRunnerService = agentRunnerService; _templatesService = templatesService; _mainViewModel = mainViewModel; + _notifier = notifier; _dispatcher = DispatcherQueue.GetForCurrentThread(); + _onStateChanged = OnStateChanged; + _notifier.Changed += _onStateChanged; } private ProjectSlug? CurrentSlug => _mainViewModel.ActiveProject?.Slug; @@ -65,17 +72,6 @@ public Task LoadAsync() Templates.Clear(); foreach (var t in templates) Templates.Add(t); - // Poll every 2 s to update live run state on cards - _pollTimer ??= new Timer(_ => - { - _dispatcher.TryEnqueue(() => - { - if (CurrentSlug is null) return; - foreach (var card in Agents) - card.IsRunning = _agentRunnerService.IsRunning(CurrentSlug, card.Agent.Slug); - }); - }, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2)); - return Task.CompletedTask; } finally @@ -132,9 +128,20 @@ public async Task StopAgentAsync(AgentCardViewModel card) return null; } + private void OnStateChanged(ProjectStateChangedEvent e) + { + if (e.ProjectSlug != CurrentSlug) return; + if (!e.Kind.HasFlag(ProjectStateChangeKind.Agents)) return; + _dispatcher.TryEnqueue(() => + { + if (CurrentSlug is null) return; + foreach (var card in Agents) + card.IsRunning = _agentRunnerService.IsRunning(CurrentSlug, card.Agent.Slug); + }); + } + public void Dispose() { - _pollTimer?.Dispose(); - _pollTimer = null; + _notifier.Changed -= _onStateChanged; } } diff --git a/ai-dev.ui.winui/ViewModels/AgentDetailViewModel.cs b/ai-dev.ui.winui/ViewModels/AgentDetailViewModel.cs index 032e944..376e41e 100644 --- a/ai-dev.ui.winui/ViewModels/AgentDetailViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/AgentDetailViewModel.cs @@ -1,5 +1,6 @@ using AiDev.Executors; using AiDev.Features.Agent; +using AiDev.Services; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -20,7 +21,8 @@ public partial class AgentDetailViewModel : ObservableObject, IDisposable private readonly IModelRegistry _modelRegistry; private readonly MainViewModel _mainViewModel; private readonly DispatcherQueue _dispatcher; - private Timer? _pollTimer; + private readonly ProjectStateChangedNotifier _notifier; + private readonly Action _onStateChanged; // ── Core state ────────────────────────────────────────────────────────── [ObservableProperty] public partial AgentInfo? Agent { get; set; } @@ -62,7 +64,8 @@ public AgentDetailViewModel( MessagesService messagesService, ExecutorHealthMonitor healthMonitor, IModelRegistry modelRegistry, - MainViewModel mainViewModel) + MainViewModel mainViewModel, + ProjectStateChangedNotifier notifier) { _agentService = agentService; _agentRunnerService = agentRunnerService; @@ -71,7 +74,10 @@ public AgentDetailViewModel( _healthMonitor = healthMonitor; _modelRegistry = modelRegistry; _mainViewModel = mainViewModel; + _notifier = notifier; _dispatcher = DispatcherQueue.GetForCurrentThread(); + _onStateChanged = OnStateChanged; + _notifier.Changed += _onStateChanged; } private ProjectSlug? CurrentSlug => _mainViewModel.ActiveProject?.Slug; @@ -99,23 +105,6 @@ public async Task LoadAsync(AgentSlug agentSlug) PopulateSkillsList(); UpdateModelCapabilities(); RefreshInbox(agentSlug); - - // Poll every 2 s for live run-state changes - _pollTimer?.Dispose(); - _pollTimer = new Timer(_ => - { - _dispatcher.TryEnqueue(() => - { - if (Agent is null) return; - var running = _agentRunnerService.IsRunning(CurrentSlug!, Agent.Slug); - if (running != IsRunning) - { - IsRunning = running; - Agent = _agentService.LoadAgent(CurrentSlug!, Agent.Slug); - if (Agent is not null) RefreshInbox(Agent.Slug); - } - }); - }, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2)); } finally { @@ -268,9 +257,30 @@ public void Stop() [RelayCommand] public void ViewTranscript() => NavigateToTranscript?.Invoke(); + private void OnStateChanged(ProjectStateChangedEvent e) + { + if (e.ProjectSlug != CurrentSlug) return; + _dispatcher.TryEnqueue(() => + { + if (Agent is null || CurrentSlug is null) return; + if (e.Kind.HasFlag(ProjectStateChangeKind.Agents)) + { + var running = _agentRunnerService.IsRunning(CurrentSlug, Agent.Slug); + if (running != IsRunning) + { + IsRunning = running; + Agent = _agentService.LoadAgent(CurrentSlug, Agent.Slug); + if (Agent is not null) RefreshInbox(Agent.Slug); + return; + } + } + if (e.Kind.HasFlag(ProjectStateChangeKind.Messages)) + RefreshInbox(Agent.Slug); + }); + } + public void Dispose() { - _pollTimer?.Dispose(); - _pollTimer = null; + _notifier.Changed -= _onStateChanged; } } diff --git a/ai-dev.ui.winui/ViewModels/BoardViewModel.cs b/ai-dev.ui.winui/ViewModels/BoardViewModel.cs index 771466a..9b0b6eb 100644 --- a/ai-dev.ui.winui/ViewModels/BoardViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/BoardViewModel.cs @@ -1,3 +1,5 @@ +using AiDev.Services; + using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -23,12 +25,13 @@ public sealed record AssigneeOption(string DisplayName, string Value); public partial class BoardViewModel : ObservableObject, IDisposable { - private readonly BoardService _boardService; + private readonly IBoardService _boardService; private readonly AgentService _agentService; private readonly PromptEnhancerService _enhancerService; private readonly MainViewModel _mainViewModel; private readonly DispatcherQueue _dispatcher; - private Timer? _pollTimer; + private readonly ProjectStateChangedNotifier _notifier; + private readonly Action _onStateChanged; [ObservableProperty] public partial bool IsLoading { get; set; } @@ -60,17 +63,20 @@ public bool IsClearingCompleted public ObservableCollection AssigneeOptions { get; } = []; public BoardViewModel( - BoardService boardService, + IBoardService boardService, AgentService agentService, PromptEnhancerService enhancerService, - MainViewModel mainViewModel) + MainViewModel mainViewModel, + ProjectStateChangedNotifier notifier) { _boardService = boardService; _agentService = agentService; _enhancerService = enhancerService; _mainViewModel = mainViewModel; - // Capture the dispatcher on the UI thread so background timer callbacks can marshal to it. + _notifier = notifier; _dispatcher = DispatcherQueue.GetForCurrentThread(); + _onStateChanged = OnStateChanged; + _notifier.Changed += _onStateChanged; } private ProjectSlug? CurrentSlug => _mainViewModel.ActiveProject?.Slug; @@ -84,11 +90,6 @@ public async Task LoadAsync() { RefreshAgents(); RefreshBoard(); - - // Poll every 3 s for board changes from running agents - _pollTimer ??= new Timer(_ => - _dispatcher.TryEnqueue(RefreshBoard), - null, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3)); } finally { @@ -310,10 +311,16 @@ private void SyncSelectedAssigneeOption() SelectedAssigneeOption = match; } + private void OnStateChanged(ProjectStateChangedEvent e) + { + if (e.ProjectSlug != CurrentSlug) return; + if (!e.Kind.HasFlag(ProjectStateChangeKind.Board)) return; + _dispatcher.TryEnqueue(RefreshBoard); + } + public void Dispose() { - _pollTimer?.Dispose(); - _pollTimer = null; + _notifier.Changed -= _onStateChanged; _enhanceCts?.Cancel(); _enhanceCts?.Dispose(); diff --git a/ai-dev.ui.winui/ViewModels/CodebaseViewModel.cs b/ai-dev.ui.winui/ViewModels/CodebaseViewModel.cs index 228664b..03b468c 100644 --- a/ai-dev.ui.winui/ViewModels/CodebaseViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/CodebaseViewModel.cs @@ -5,67 +5,37 @@ namespace AiDev.WinUI.ViewModels; +/// +/// Displays the active project's codebase root and its git history. +/// public partial class CodebaseViewModel : ObservableObject { private readonly GitService _gitService; - private readonly WorkspacePaths _paths; - private readonly MainViewModel _mainViewModel; + private readonly ActiveWorkspaceHolder _workspace; [ObservableProperty] public partial bool IsLoading { get; set; } - [ObservableProperty] public partial bool CodebaseInitialized { get; set; } [ObservableProperty] public partial bool IsGitRepo { get; set; } - [ObservableProperty] public partial string ProjectDir { get; set; } = ""; [ObservableProperty] public partial string CodebasePath { get; set; } = ""; - [ObservableProperty] public partial string InitMode { get; set; } = "create"; - [ObservableProperty] public partial string CustomPath { get; set; } = ""; - [ObservableProperty] public partial string InitError { get; set; } = ""; - [ObservableProperty] public partial bool IsInitializing { get; set; } - [ObservableProperty] public partial bool InitDone { get; set; } [ObservableProperty] public partial GitCommitDetail? SelectedCommit { get; set; } - // Change-path state (visible when already initialized) - [ObservableProperty] public partial bool IsChangingPath { get; set; } - [ObservableProperty] public partial string NewCodebasePath { get; set; } = ""; - [ObservableProperty] public partial string ChangePathError { get; set; } = ""; - [ObservableProperty] public partial bool ChangePathDone { get; set; } - - public bool IsLinkMode => InitMode == "link"; - - partial void OnInitModeChanged(string value) => OnPropertyChanged(nameof(IsLinkMode)); - public ObservableCollection Commits { get; } = []; - public CodebaseViewModel(GitService gitService, WorkspacePaths paths, MainViewModel mainViewModel) + public CodebaseViewModel(GitService gitService, ActiveWorkspaceHolder workspace) { _gitService = gitService; - _paths = paths; - _mainViewModel = mainViewModel; + _workspace = workspace; } - private ProjectSlug? CurrentSlug => _mainViewModel.ActiveProject?.Slug; - [RelayCommand] public void Load() { - if (CurrentSlug is null) return; IsLoading = true; - InitDone = false; - InitError = ""; SelectedCommit = null; Commits.Clear(); try { - ProjectDir = _paths.ProjectDir(CurrentSlug).Value; - var jsonPath = Path.Combine(ProjectDir, "project.json"); - if (File.Exists(jsonPath)) - { - using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(jsonPath)); - var root = doc.RootElement; - CodebaseInitialized = root.TryGetProperty("codebaseInitialized", out var ci) && ci.GetBoolean(); - CodebasePath = root.TryGetProperty("codebasePath", out var cp) ? cp.GetString() ?? "" : ""; - } - - if (CodebaseInitialized && !string.IsNullOrEmpty(CodebasePath)) + CodebasePath = _workspace.ActiveCodebasePath ?? ""; + if (!string.IsNullOrEmpty(CodebasePath)) { IsGitRepo = _gitService.IsGitRepo(CodebasePath); if (IsGitRepo) @@ -75,97 +45,10 @@ public void Load() finally { IsLoading = false; } } - [RelayCommand] - public void Initialize() - { - if (CurrentSlug is null) return; - IsInitializing = true; - InitError = ""; - try - { - string cbPath; - if (InitMode == "create") - { - cbPath = Path.Combine(ProjectDir, "codebase"); - Directory.CreateDirectory(cbPath); - } - else - { - cbPath = CustomPath.Trim(); - if (!Directory.Exists(cbPath)) throw new Exception($"Directory not found: {cbPath}"); - } - UpdateProjectJson(cbPath); - CodebasePath = cbPath; - CodebaseInitialized = true; - InitDone = true; - IsGitRepo = _gitService.IsGitRepo(cbPath); - Commits.Clear(); - if (IsGitRepo) - foreach (var c in _gitService.GetLog(cbPath)) Commits.Add(c); - } - catch (Exception ex) { InitError = ex.Message; } - finally { IsInitializing = false; } - } - [RelayCommand] public void SelectCommit(string hash) => SelectedCommit = _gitService.GetCommit(CodebasePath, hash); [RelayCommand] public void CloseDetail() => SelectedCommit = null; - - /// - /// Updates the registered codebase path for an already-initialized project. - /// Used to fix a misconfigured path without reinitializing. - /// - [RelayCommand] - public void ChangePath() - { - if (CurrentSlug is null) return; - ChangePathError = ""; - ChangePathDone = false; - - var path = NewCodebasePath.Trim(); - if (string.IsNullOrWhiteSpace(path)) - { - ChangePathError = "Path is required."; - return; - } - if (!Directory.Exists(path)) - { - ChangePathError = $"Directory not found: {path}"; - return; - } - - try - { - UpdateProjectJson(path); - CodebasePath = path; - IsGitRepo = _gitService.IsGitRepo(path); - Commits.Clear(); - if (IsGitRepo) - foreach (var c in _gitService.GetLog(path)) Commits.Add(c); - NewCodebasePath = ""; - IsChangingPath = false; - ChangePathDone = true; - } - catch (Exception ex) - { - ChangePathError = ex.Message; - } - } - - private void UpdateProjectJson(string cbPath) - { - var path = Path.Combine(ProjectDir, "project.json"); - var json = File.Exists(path) ? File.ReadAllText(path) : "{}"; - using var doc = System.Text.Json.JsonDocument.Parse(json); - var dict = new Dictionary(); - foreach (var prop in doc.RootElement.EnumerateObject()) - dict[prop.Name] = (object?)prop.Value; - dict["codebaseInitialized"] = true; - dict["codebasePath"] = cbPath; - File.WriteAllText(path, System.Text.Json.JsonSerializer.Serialize(dict, - new System.Text.Json.JsonSerializerOptions { WriteIndented = true })); - } } diff --git a/ai-dev.ui.winui/ViewModels/DecisionDetailViewModel.cs b/ai-dev.ui.winui/ViewModels/DecisionDetailViewModel.cs index f6ac0b0..9073ce5 100644 --- a/ai-dev.ui.winui/ViewModels/DecisionDetailViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/DecisionDetailViewModel.cs @@ -7,7 +7,7 @@ namespace AiDev.WinUI.ViewModels; public partial class DecisionDetailViewModel : ObservableObject, IDisposable { - private readonly DecisionsService _decisionsService; + private readonly IDecisionsService _decisionsService; private readonly DecisionChatService _chatService; private readonly AgentRunnerService _runnerService; private readonly MainViewModel _mainViewModel; @@ -30,7 +30,7 @@ public partial class DecisionDetailViewModel : ObservableObject, IDisposable public event Action? NavigateBack; public DecisionDetailViewModel( - DecisionsService decisionsService, + IDecisionsService decisionsService, DecisionChatService chatService, AgentRunnerService runnerService, MainViewModel mainViewModel) @@ -119,7 +119,7 @@ public async Task ConfirmResolveAsync() ResolveError = ""; try { - var result = await _decisionsService.ResolveDecisionAsync(CurrentSlug, Decision.Id, ResolveResponse.Trim()); + var result = await _decisionsService.ResolveDecisionAsync(CurrentSlug, Decision.Id, ResolveResponse.Trim(), CancellationToken.None); if (result is Err err) { ResolveError = err.Error.Message; return; } ShowResolveDialog = false; _pollTimer?.Dispose(); diff --git a/ai-dev.ui.winui/ViewModels/DecisionsViewModel.cs b/ai-dev.ui.winui/ViewModels/DecisionsViewModel.cs index e01c555..ffddc81 100644 --- a/ai-dev.ui.winui/ViewModels/DecisionsViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/DecisionsViewModel.cs @@ -7,7 +7,7 @@ namespace AiDev.WinUI.ViewModels; public partial class DecisionsViewModel : ObservableObject { - private readonly DecisionsService _decisionsService; + private readonly IDecisionsService _decisionsService; private readonly DecisionChatService _chatService; private readonly MainViewModel _mainViewModel; private readonly IUiDispatcher _uiDispatcher; @@ -33,7 +33,7 @@ public partial class DecisionsViewModel : ObservableObject public ObservableCollection ChatMessages { get; } = []; public DecisionsViewModel( - DecisionsService decisionsService, + IDecisionsService decisionsService, DecisionChatService chatService, MainViewModel mainViewModel, IUiDispatcher uiDispatcher) @@ -101,7 +101,7 @@ public async Task ResolveDecisionAsync() { if (CurrentSlug is null || SelectedDecision is null) return; StopPollingDecision(); - await _decisionsService.ResolveDecisionAsync(CurrentSlug, SelectedDecision.Id, ReplyText.Trim()); + await _decisionsService.ResolveDecisionAsync(CurrentSlug, SelectedDecision.Id, ReplyText.Trim(), CancellationToken.None); ReplyText = ""; SelectedDecision = null; ChatMessages.Clear(); diff --git a/ai-dev.ui.winui/ViewModels/MainViewModel.cs b/ai-dev.ui.winui/ViewModels/MainViewModel.cs index 2507e71..ae8b5da 100644 --- a/ai-dev.ui.winui/ViewModels/MainViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/MainViewModel.cs @@ -22,7 +22,7 @@ public partial class MainViewModel : ObservableObject { private readonly ExecutorHealthMonitor _healthMonitor; private readonly MessagesService _messagesService; - private readonly DecisionsService _decisionsService; + private readonly IDecisionsService _decisionsService; private IDisposable? _healthSubscription; [ObservableProperty] public partial ProjectDetail? ActiveProject { get; set; } @@ -46,7 +46,7 @@ public TaskId? PendingTaskId /// The executor health monitor. /// The messages service. /// The decisions service. - public MainViewModel(ExecutorHealthMonitor healthMonitor, MessagesService messagesService, DecisionsService decisionsService) + public MainViewModel(ExecutorHealthMonitor healthMonitor, MessagesService messagesService, IDecisionsService decisionsService) { _healthMonitor = healthMonitor; _messagesService = messagesService; diff --git a/ai-dev.ui.winui/ViewModels/ProjectSettingsViewModel.cs b/ai-dev.ui.winui/ViewModels/ProjectSettingsViewModel.cs index 220b7e9..94ba61f 100644 --- a/ai-dev.ui.winui/ViewModels/ProjectSettingsViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/ProjectSettingsViewModel.cs @@ -18,7 +18,6 @@ public partial class ProjectSettingsViewModel : ObservableObject // Project detail form [ObservableProperty] public partial string EditName { get; set; } = ""; [ObservableProperty] public partial string EditDescription { get; set; } = ""; - [ObservableProperty] public partial string EditCodebasePath { get; set; } = ""; [ObservableProperty] public partial string DetailsError { get; set; } = ""; [ObservableProperty] public partial bool DetailsSaved { get; set; } [ObservableProperty] public partial bool SavingDetails { get; set; } @@ -68,7 +67,6 @@ public void Load() { EditName = project.Name; EditDescription = project.Description; - EditCodebasePath = project.CodebasePath ?? ""; } RefreshAgents(); RefreshExecutors(); @@ -84,8 +82,7 @@ public void SaveDetails() DetailsSaved = false; if (string.IsNullOrWhiteSpace(EditName)) { DetailsError = "Name is required."; return; } SavingDetails = true; - var result = _workspaceService.UpdateProject(CurrentSlug, EditName, EditDescription, - string.IsNullOrWhiteSpace(EditCodebasePath) ? null : EditCodebasePath); + var result = _workspaceService.UpdateProject(CurrentSlug, EditName, EditDescription); SavingDetails = false; if (result is Err err) { DetailsError = err.Error.Message; return; } // Sync the shell title diff --git a/ai-dev.ui.winui/ViewModels/ProjectsViewModel.cs b/ai-dev.ui.winui/ViewModels/ProjectsViewModel.cs index abe49f9..fc8254e 100644 --- a/ai-dev.ui.winui/ViewModels/ProjectsViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/ProjectsViewModel.cs @@ -54,9 +54,9 @@ public Task LoadAsync() try { var result = _workspaceService.CreateProject( + codebasePath?.Trim() ?? "", slug, name, - description.Trim() is { Length: > 0 } d ? d : null, - string.IsNullOrWhiteSpace(codebasePath) ? null : codebasePath.Trim()); + description.Trim() is { Length: > 0 } d ? d : null); if (result is Err err) return $"[{err.Error.Code}] {err.Error.Message}"; diff --git a/ai-dev.ui.winui/ViewModels/TaskTranscriptViewModel.cs b/ai-dev.ui.winui/ViewModels/TaskTranscriptViewModel.cs index 1769159..fa96182 100644 --- a/ai-dev.ui.winui/ViewModels/TaskTranscriptViewModel.cs +++ b/ai-dev.ui.winui/ViewModels/TaskTranscriptViewModel.cs @@ -7,7 +7,7 @@ namespace AiDev.WinUI.ViewModels; public partial class TaskTranscriptViewModel : ObservableObject { - private readonly BoardService _boardService; + private readonly IBoardService _boardService; private readonly MessagesService _messagesService; private readonly MainViewModel _mainViewModel; @@ -37,7 +37,7 @@ public string ErrorText public event Action? NavigateBack; public TaskTranscriptViewModel( - BoardService boardService, + IBoardService boardService, MessagesService messagesService, MainViewModel mainViewModel) { diff --git a/ai-dev.ui.winui/Views/Dialogs/NewProjectDialog.xaml.cs b/ai-dev.ui.winui/Views/Dialogs/NewProjectDialog.xaml.cs index f48f06e..999960a 100644 --- a/ai-dev.ui.winui/Views/Dialogs/NewProjectDialog.xaml.cs +++ b/ai-dev.ui.winui/Views/Dialogs/NewProjectDialog.xaml.cs @@ -45,8 +45,9 @@ public NewProjectDialog(ProjectsViewModel viewModel) panel.Children.Add(BuildField("Slug", _slugBox, footer: "Used as the folder name. Lowercase letters, digits, and hyphens only.")); panel.Children.Add(BuildField("Description", _descriptionBox, optional: true)); - panel.Children.Add(BuildField("Codebase path", _codebasePathBox, optional: true, - footer: "Absolute path to the codebase agents will work on.")); + panel.Children.Add(BuildField("Codebase directory", + _codebasePathBox, + footer: "Absolute path to the codebase root. A .ai-dev/ folder will be created there.")); var templates = _viewModel.GetTemplates(); if (templates.Count > 0) @@ -142,8 +143,10 @@ private async void OnPrimaryButtonClick(ContentDialog sender, ContentDialogButto var name = _nameBox.Text.Trim(); var slug = _slugBox.Text.Trim(); + var codebasePath = _codebasePathBox.Text.Trim(); if (string.IsNullOrWhiteSpace(name)) { ShowError("Project name is required."); args.Cancel = true; return; } if (string.IsNullOrWhiteSpace(slug)) { ShowError("Slug is required."); args.Cancel = true; return; } + if (string.IsNullOrWhiteSpace(codebasePath)) { ShowError("Codebase directory is required."); args.Cancel = true; return; } var selectedTemplates = _templateItems .Where(t => t.IsSelected) @@ -152,7 +155,7 @@ private async void OnPrimaryButtonClick(ContentDialog sender, ContentDialogButto var error = await _viewModel.CreateProjectAsync( slug, name, _descriptionBox.Text.Trim(), - _codebasePathBox.Text.Trim() is { Length: > 0 } p ? p : null, + codebasePath, selectedTemplates); if (error != null) { ShowError(error); args.Cancel = true; } diff --git a/ai-dev.ui.winui/Views/Pages/CodebasePage.xaml b/ai-dev.ui.winui/Views/Pages/CodebasePage.xaml index cac873a..d6ab1bc 100644 --- a/ai-dev.ui.winui/Views/Pages/CodebasePage.xaml +++ b/ai-dev.ui.winui/Views/Pages/CodebasePage.xaml @@ -23,59 +23,13 @@ - - - - - - - - - - - - - - - - - - - - - -