diff --git a/AGENTS.md b/AGENTS.md index 2c3b8ba..e628bfc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,6 +35,8 @@ Structured state (trace index, sessions, channel/provider config, upstream targe - Production and the tracked default config use Postgres; the checked-in SQL migrations live in `ent/postgres-migrations/`. - SQLite is a local/dev/test fallback only, with default file `{{output_dir}}/llm_tracelab.sqlite3`; SQLite schema is applied at startup rather than by versioned migrations. - Raw `.http` cassettes remain the source of truth for replay and detail views; the database is a derived index for lists, filters, and aggregates. +- YAML channel configuration is a first-bootstrap input only. The first database write stores the application-database `app_settings` key `channels.initialized`; afterwards the database owns routing configuration even when every channel was disabled or deleted. `GET /api/settings/channels` reports the marker and `DELETE /api/settings/channels` clears it, which only re-opens the YAML bootstrap while the database still has no channels. A YAML config with an explicit `credentials` list stays YAML-managed and rejects Monitor channel/model/alias writes with 409. +- All management writes (channels, models, aliases, provider setup and probe apply) run in one `store.ConfigurationTransaction`, which holds the process-wide configuration lock, the upstream write lock, and one SQL transaction; runtime routing is published only after the commit succeeds. Background upstream refresh persists through the same upstream write lock on a best-effort basis. Current protocol families are documented in `docs/protocol-reference/implemented-protocols.md`. The proxy is protocol-aware pass-through plus recording/parsing; it does not currently translate requests between OpenAI, Anthropic, Gemini, and Vertex protocol families in the forwarding hot path. diff --git a/cmd/server/main_test.go b/cmd/server/main_test.go index f2d23c7..ebac9dc 100644 --- a/cmd/server/main_test.go +++ b/cmd/server/main_test.go @@ -5473,3 +5473,47 @@ func (t authTransport) RoundTrip(req *http.Request) (*http.Response, error) { clone.Header.Set("Authorization", "Bearer "+t.Token) return http.DefaultTransport.RoundTrip(clone) } + +func TestRouterConfigurationKeepsDisabledAndDeletedChannelsAcrossBootstrap(t *testing.T) { + for _, deleted := range []bool{false, true} { + t.Run(map[bool]string{false: "disabled", true: "deleted"}[deleted], func(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatal(err) + } + defer st.Close() + cfg := &config.Config{Upstream: config.UpstreamConfig{BaseURL: "https://yaml.example.invalid/v1", ProviderPreset: "openai"}} + svc := channel.NewService(st) + if _, err := svc.BootstrapFromConfig(cfg); err != nil { + t.Fatal(err) + } + channels, err := st.ListChannelConfigs() + if err != nil { + t.Fatal(err) + } + if len(channels) != 1 { + t.Fatalf("channels=%v", channels) + } + if deleted { + err = st.DeleteChannelConfig(channels[0].ID) + } else { + record := channels[0] + record.Enabled = false + _, err = st.UpsertChannelConfig(record) + } + if err != nil { + t.Fatal(err) + } + if imported, err := svc.BootstrapFromConfig(cfg); err != nil || imported != 0 { + t.Fatalf("bootstrap=%d %v", imported, err) + } + runtimeCfg, source, err := routerConfigFromChannels(cfg, svc) + if err != nil { + t.Fatal(err) + } + if source != "database" || len(runtimeCfg.EffectiveUpstreams()) != 0 { + t.Fatalf("source=%s targets=%v", source, runtimeCfg.EffectiveUpstreams()) + } + }) + } +} diff --git a/cmd/server/management.go b/cmd/server/management.go index d56121c..c9044fa 100644 --- a/cmd/server/management.go +++ b/cmd/server/management.go @@ -67,7 +67,7 @@ func newManagementMuxWithFunctionExecutorManager( } monitor.RegisterRoutes(mux, traceStore, monitor.RouteOptions{ Router: rtr, - ChannelService: channel.NewService(traceStore), + ChannelService: channel.NewService(traceStore).WithReadOnly(configHasExplicitCredentials(cfg)), AuthVerifier: verifier, MonitorAuthVerifier: monitorVerifier, MonitorJWT: monitorJWT, diff --git a/cmd/server/serve.go b/cmd/server/serve.go index 62962ff..3e859ed 100644 --- a/cmd/server/serve.go +++ b/cmd/server/serve.go @@ -347,7 +347,11 @@ func routerConfigFromChannels(cfg *config.Config, channelService *channel.Servic if err != nil { return nil, "", err } - if len(targets) == 0 { + initialized, err := channelService.HasConfiguration() + if err != nil { + return nil, "", err + } + if !initialized { return cfg, "yaml", nil } routerCfg := *cfg diff --git a/docs/MAINTAINER_BASELINE.md b/docs/MAINTAINER_BASELINE.md index d7e573c..fb3893c 100644 --- a/docs/MAINTAINER_BASELINE.md +++ b/docs/MAINTAINER_BASELINE.md @@ -98,9 +98,11 @@ YAML `upstream` / `upstreams` 是兼容 bootstrap 输入。 修改渠道管理时必须保持: - DB 优先。 -- legacy YAML 可首次导入。 +- legacy YAML 可首次导入。首次数据库写入会记录 `app_settings` 键 `channels.initialized`;此后 DB 是路由配置来源,全部渠道停用或删除也不会回退到 YAML。`GET /api/settings/channels` 报告该标记,`DELETE /api/settings/channels` 仅清除标记:只有在 DB 中确实没有渠道时,下次启动才会重新导入 YAML。 - API key 和敏感 header 本地加密。 - channel/model 启停能 reload router。 +- 所有管理写入(渠道、模型、别名、provider setup/probe apply)共用 `store.ConfigurationTransaction`:它按 `configMu` -> `upstreamMu` -> `reloadMu` -> `router.mu` 的顺序持锁并使用单个 SQL 事务,只有 commit 成功后才发布新路由快照。不要在事务内再开事务(会返回 `store.ErrNestedTransaction`),也不要新增 `reloadMu` -> `upstreamMu` 的反向获取。 +- 后台刷新和代理侧 `RefreshNow` 只以 best-effort 方式获取 `upstreamMu`:配置变更持锁时跳过落库但仍更新内存,并在获得锁后按当前 live target 集合过滤,避免为已删除的 target 复活 `upstream_targets`/`upstream_models` 行。 ## 协议边界 @@ -125,6 +127,8 @@ YAML `upstream` / `upstreams` 是兼容 bootstrap 输入。 - `/api/models` - `/api/channels` - `/api/routing/summary` +- `/api/settings/routing` +- `/api/settings/channels` - `/api/events` - `/api/findings` - `/api/analysis` diff --git a/docs/MONITOR_GUIDE.md b/docs/MONITOR_GUIDE.md index 6b74c7b..b78f898 100644 --- a/docs/MONITOR_GUIDE.md +++ b/docs/MONITOR_GUIDE.md @@ -96,15 +96,27 @@ Monitor 使用两类数据: - 设置 provider preset、base URL、API key、headers、routing 字段。 - 设置 provider API surface:`api_type`、`mode`,以及 Responses、Chat Completions、tool calling、models 等 capability 开关;这些字段会写入 channel store,并在运行时还原为 upstream routing target。 - 创建前可用 Detect provider 做临时探测,不落库返回 API surface 建议;需要采用建议时,使用 Apply suggestions 显式写入表单。 -- 创建前需用 Validate setup 调用 provider setup validate:它会组合 base URL、API key、provider preset、model discovery 和 capability 字段做一次探测并把归一化配置写回表单,但不会落库;dialog 会展示 normalized config、probe 和 redacted secret state,字段变更会清空旧验证结果;Create provider 才通过 setup apply 写入 channel store;若 probe 未检测成功,需显式提供 `api_type` 与 `protocol_family`。 +- 创建前可用 Validate setup 调用 provider setup validate:它会组合 base URL、API key、provider preset、model discovery 和 capability 字段做一次探测并把归一化配置写回表单,但不会落库;dialog 会展示 normalized config、probe 和 redacted secret state,字段变更会清空旧验证结果;Create provider 通过 setup apply 写入 channel store;显式提供协议信息时也允许直接创建,若 probe 未检测成功,需显式提供 `api_type` 与 `protocol_family`。 - setup validate/apply 响应不会回显 API key;只返回 `api_key_hint`、secret storage mode 和 redacted header 状态。 - 探测模型,并查看 provider detection 建议;需要写回建议时,使用 Apply suggestions 显式更新 channel 配置。 -- 在 Providers 列表页使用 Batch probe and apply 先运行只读 `POST /api/provider-probe/report` 预览,再对 detected 且有可补字段的 provider 执行批量 Apply detected suggestions;Monitor 不展示或传递 API key。批量应用只填缺失的 `api_type`、`protocol_family` 和未设置 capability,不覆盖显式配置,也不覆盖显式 `false` capability。 +- 在 Providers 列表页使用 Batch probe and apply:先运行只读 `POST /api/provider-probe/report` 预览,再通过 `POST /api/provider-probe/report/apply` 对 detected 且有可补字段的 provider 批量应用建议;单个 provider 的探测入口在卡片上。Monitor 不展示或传递 API key。批量应用只填缺失的 `api_type`、`protocol_family` 和未设置 capability,不覆盖显式配置,也不覆盖显式 `false` capability。 - 启停渠道。 - 启停单个模型。 - 查看渠道用量、token、失败和 probe 结果。 -长期渠道配置保存在 application store;Postgres 部署使用版本化迁移,SQLite 仍作为本地 fallback。YAML 只作为启动和首次 bootstrap 输入。 +长期渠道配置保存在 application store;Postgres 部署使用版本化迁移,SQLite 仍作为本地 fallback。通常 YAML 只作为启动和首次 bootstrap 输入;首次初始化会在应用库 `app_settings` 写入 `channels.initialized` 标记(`GET /api/settings/channels` 报告,`DELETE /api/settings/channels` 清除),即使后来停用或删除全部渠道,重启也不会重新导入 YAML。清除该标记只是重新放行 YAML bootstrap:只要数据库里仍有渠道配置,数据库依旧是路由配置来源;只有数据库确实为空时,下次启动才重新导入 YAML。使用显式 `credentials` 列表的 YAML 配置仍由 YAML 管理,此模式下 Monitor 的渠道、模型和别名写操作返回 409,避免数据库操作替换 YAML 中的凭据路由。 + +### 上游和模型的启停语义 + +- 创建上游只保存连接配置。创建成功后进入详情页,发现或手动添加模型,再选择启用。没有启用模型且未允许未知模型时,不接受命名模型请求。 +- 上游启用表示允许参与新请求路由;停用会移除该上游的路由资格,但保留各模型的选择。已在途请求不会因此被取消。 +- 模型启用只作用于当前上游,不会启动或停止远端模型进程,也不会改变同名模型在其他上游的配置。 +- 模型停用是明确拒绝:自动发现、未知模型放行和 fallback 策略均不能重新放行该上游上的已停用模型。删除模型则是移除配置,不等同于停用;允许未知模型时,删除后的模型可能再次作为未知模型被调用。 +- 模型发现默认不启用新模型,保留已有模型的启停选择和能力配置。API 调用方可显式传入 `enable_discovered: true` 启用本次新发现的模型。数据库管理的运行时只从已启用配置建立模型目录,不通过周期刷新扩大准入范围。 +- 配置开关与健康状态相互独立。上游停用时,模型行仍保留“已启用”的选择,同时提示路由被上游开关阻止;健康检查和熔断仍可能使已启用模型暂时不可用。 +- 仅来自历史请求的模型行不提供启停开关;需要管理时先手动添加模型。发现后停用的模型不再被标为“新模型”。 +- 渠道、模型、模型别名及批量修改通过同一数据库事务完成。运行时配置准备成功后才提交并切换路由;校验、批量更新或提交失败时保留原配置和原路由。返回失败的模型探测仍保留诊断记录。 + ### Connect diff --git a/internal/channel/service.go b/internal/channel/service.go index 72a9bc9..7c7b14b 100644 --- a/internal/channel/service.go +++ b/internal/channel/service.go @@ -20,6 +20,9 @@ import ( ) type Store interface { + LoadAppSettingJSON(context.Context, string, any) (bool, error) + SaveAppSettingJSON(context.Context, string, any) error + DeleteAppSetting(context.Context, string) (bool, error) ListChannelConfigs() ([]store.ChannelConfigRecord, error) GetChannelConfig(channelID string) (store.ChannelConfigRecord, error) UpsertChannelConfig(store.ChannelConfigRecord) (store.ChannelConfigRecord, error) @@ -36,15 +39,65 @@ type Store interface { type Service struct { store Store httpClient *http.Client + readOnly bool } func NewService(st Store) *Service { return &Service{store: st} } +// WithHTTPClient returns a copy of the service that probes with client. +// +// Every With* helper returns a derived service and leaves the receiver +// untouched, so a service shared by several callers (for example the one built +// for the Monitor) can be specialised without mutating it in place. func (s *Service) WithHTTPClient(client *http.Client) *Service { - s.httpClient = client - return s + next := *s + next.httpClient = client + return &next +} + +// WithStore preserves probe options when applying a configuration transaction. +func (s *Service) WithStore(st Store) *Service { + next := *s + next.store = st + return &next +} + +func (s *Service) WithReadOnly(readOnly bool) *Service { + next := *s + next.readOnly = readOnly + return &next +} + +func (s *Service) ReadOnly() bool { return s != nil && s.readOnly } + +const configurationInitializedKey = "channels.initialized" + +// HasConfiguration distinguishes an intentionally empty database from first startup. +func (s *Service) HasConfiguration() (bool, error) { + var initialized bool + if _, err := s.store.LoadAppSettingJSON(context.Background(), configurationInitializedKey, &initialized); err != nil { + return false, err + } + if initialized { + return true, nil + } + channels, err := s.store.ListChannelConfigs() + return len(channels) > 0, err +} + +func (s *Service) MarkConfigurationInitialized() error { + return s.store.SaveAppSettingJSON(context.Background(), configurationInitializedKey, true) +} + +// ResetConfigurationInitialized clears the explicit bootstrap marker so the next +// start may import YAML again. It deliberately does not delete channels: a +// database that still holds channel configuration keeps counting as +// initialized, because HasConfiguration also falls back to the stored channels. +func (s *Service) ResetConfigurationInitialized() error { + _, err := s.store.DeleteAppSetting(context.Background(), configurationInitializedKey) + return err } type ProbeResult struct { @@ -85,15 +138,19 @@ type ProviderProbeApplyItem struct { SkippedReason string `json:"skipped_reason,omitempty"` } +// BootstrapFromConfig imports YAML upstreams into the channel store on first +// startup only. It never writes once the database owns the configuration: the +// marker is stored by the first import or by the first management write, so a +// startup that is already initialized stays read-only. func (s *Service) BootstrapFromConfig(cfg *config.Config) (int, error) { if s == nil || s.store == nil { return 0, fmt.Errorf("channel service store is required") } - existing, err := s.store.ListChannelConfigs() + initialized, err := s.HasConfiguration() if err != nil { return 0, err } - if len(existing) > 0 { + if initialized { return 0, nil } @@ -114,6 +171,10 @@ func (s *Service) BootstrapFromConfig(cfg *config.Config) (int, error) { if target.Enabled != nil { enabled = *target.Enabled } + allowUnknown := false + if target.AllowUnknownModels != nil { + allowUnknown = *target.AllowUnknownModels + } headersJSON := "{}" if len(target.Upstream.Headers) > 0 { data, err := json.Marshal(target.Upstream.Headers) @@ -127,29 +188,30 @@ func (s *Service) BootstrapFromConfig(cfg *config.Config) (int, error) { return imported, err } _, err = s.store.UpsertChannelConfig(store.ChannelConfigRecord{ - ID: channelID, - Name: defaultChannelName(channelID, target.Upstream.ProviderPreset), - Source: "bootstrap", - BaseURL: target.Upstream.BaseURL, - ProviderPreset: target.Upstream.ProviderPreset, - APIType: target.Upstream.APIType, - Mode: target.Upstream.Mode, - CapabilitiesJSON: capabilitiesJSON, - ProtocolFamily: target.Upstream.ProtocolFamily, - RoutingProfile: target.Upstream.RoutingProfile, - APIVersion: target.Upstream.APIVersion, - Deployment: target.Upstream.Deployment, - Project: target.Upstream.Project, - Location: target.Upstream.Location, - ModelResource: target.Upstream.ModelResource, - APIKeyCiphertext: []byte(target.Upstream.ApiKey), - APIKeyHint: secretHint(target.Upstream.ApiKey), - HeadersJSON: headersJSON, - Enabled: enabled, - Priority: target.Priority, - Weight: target.Weight, - CapacityHint: target.CapacityHint, - ModelDiscovery: target.ModelDiscovery, + ID: channelID, + Name: defaultChannelName(channelID, target.Upstream.ProviderPreset), + Source: "bootstrap", + BaseURL: target.Upstream.BaseURL, + ProviderPreset: target.Upstream.ProviderPreset, + APIType: target.Upstream.APIType, + Mode: target.Upstream.Mode, + CapabilitiesJSON: capabilitiesJSON, + ProtocolFamily: target.Upstream.ProtocolFamily, + RoutingProfile: target.Upstream.RoutingProfile, + APIVersion: target.Upstream.APIVersion, + Deployment: target.Upstream.Deployment, + Project: target.Upstream.Project, + Location: target.Upstream.Location, + ModelResource: target.Upstream.ModelResource, + APIKeyCiphertext: []byte(target.Upstream.ApiKey), + APIKeyHint: secretHint(target.Upstream.ApiKey), + HeadersJSON: headersJSON, + Enabled: enabled, + Priority: target.Priority, + Weight: target.Weight, + CapacityHint: target.CapacityHint, + ModelDiscovery: target.ModelDiscovery, + AllowUnknownModels: allowUnknown, }) if err != nil { return imported, err @@ -176,7 +238,7 @@ func (s *Service) BootstrapFromConfig(cfg *config.Config) (int, error) { } imported++ } - return imported, nil + return imported, s.MarkConfigurationInitialized() } func configuredUpstreams(cfg *config.Config) []config.UpstreamTargetConfig { @@ -218,10 +280,20 @@ func (s *Service) RuntimeTargets() ([]config.UpstreamTargetConfig, error) { if !channel.Enabled { continue } - models, err := s.store.ListChannelModels(channel.ID, true) + models, err := s.store.ListChannelModels(channel.ID, false) if err != nil { return nil, err } + var enabledModels []store.ChannelModelRecord + var disabledModels []string + for _, model := range models { + if model.Enabled { + enabledModels = append(enabledModels, model) + } else { + disabledModels = append(disabledModels, model.Model) + } + } + models = enabledModels headers := map[string]string{} if strings.TrimSpace(channel.HeadersJSON) != "" { if err := json.Unmarshal([]byte(channel.HeadersJSON), &headers); err != nil { @@ -243,6 +315,7 @@ func (s *Service) RuntimeTargets() ([]config.UpstreamTargetConfig, error) { StaticModels: channelModelNamesWithAliases(models, aliases, channel.ID), ModelAliases: channelModelAliases(models, aliases, channel.ID), ConfiguredModelsOnly: true, + DisabledModels: disabledModels, AllowUnknownModels: &channel.AllowUnknownModels, Upstream: config.UpstreamConfig{ BaseURL: channel.BaseURL, @@ -539,16 +612,12 @@ func (s *Service) mergeDiscoveredChannelModels(channelID string, discovered []st } record.Enabled = enableNew if previous, ok := existingByModel[model]; ok { - record.Enabled = previous.Enabled - if strings.TrimSpace(previous.Source) != "" && previous.Source != "discovered" { - record.Source = previous.Source - } - if strings.TrimSpace(previous.DisplayName) != "" { - record.DisplayName = previous.DisplayName - } - if !previous.FirstSeenAt.IsZero() { - record.FirstSeenAt = previous.FirstSeenAt - } + // Re-discovery updates observation timestamps, not operator choices + // or an adopted model profile. + lastSeen, lastProbe := record.LastSeenAt, record.LastProbeAt + record = previous + record.LastSeenAt = lastSeen + record.LastProbeAt = lastProbe } saved, err := s.store.UpsertChannelModel(channelID, record) if err != nil { @@ -561,7 +630,7 @@ func (s *Service) mergeDiscoveredChannelModels(channelID string, discovered []st func enableDiscoveredByDefault(options ProbeOptions) bool { if options.EnableDiscovered == nil { - return true + return false } return *options.EnableDiscovered } diff --git a/internal/channel/service_test.go b/internal/channel/service_test.go index cea6c53..105e53c 100644 --- a/internal/channel/service_test.go +++ b/internal/channel/service_test.go @@ -186,7 +186,8 @@ func TestProbeDiscoversModelsAndUpdatesCatalogs(t *testing.T) { t.Fatalf("UpsertChannelConfig() error = %v", err) } - result, err := NewService(st).Probe("probe-channel") + enable := true + result, err := NewService(st).ProbeWithOptions("probe-channel", ProbeOptions{EnableDiscovered: &enable}) if err != nil { t.Fatalf("Probe() error = %v", err) } @@ -852,3 +853,187 @@ func TestBootstrapFromConfigImportsPerModelCapabilities(t *testing.T) { t.Fatalf("gpt-native must not carry an override, got %+v", caps["gpt-native"]) } } + +func TestProbeDefaultsToDisabledAndPreservesManualChoices(t *testing.T) { + upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte(`{"data":[{"id":"new"},{"id":"enabled"},{"id":"disabled"}]}`)) + })) + defer upstreamServer.Close() + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatal(err) + } + defer st.Close() + if _, err := st.UpsertChannelConfig(store.ChannelConfigRecord{ID: "p", Name: "P", Enabled: true, BaseURL: upstreamServer.URL + "/v1", ProviderPreset: "openai"}); err != nil { + t.Fatal(err) + } + contextWindow := 128000 + for _, model := range []store.ChannelModelRecord{{Model: "enabled", Enabled: true, Source: "manual", ContextWindow: &contextWindow, ProfileAdoptionStatus: "adopted"}, {Model: "disabled", Enabled: false, Source: "discovered"}} { + if _, err := st.UpsertChannelModel("p", model); err != nil { + t.Fatal(err) + } + } + if _, err := NewService(st).Probe("p"); err != nil { + t.Fatal(err) + } + models, err := st.ListChannelModels("p", false) + if err != nil { + t.Fatal(err) + } + if len(models) != 3 { + t.Fatalf("models=%v", models) + } + for _, model := range models { + if model.Model == "enabled" && (model.ContextWindow == nil || *model.ContextWindow != contextWindow || model.ProfileAdoptionStatus != "adopted") { + t.Fatalf("discovery erased model profile: %+v", model) + } + if model.Enabled != (model.Model == "enabled") { + t.Fatalf("discovery changed authorization: %+v", model) + } + } +} + +func TestServiceBuildersLeaveTheirReceiverUntouched(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatalf("store.New() error = %v", err) + } + defer st.Close() + + base := NewService(st) + scoped := base.WithStore(st) + readOnly := base.WithReadOnly(true) + withClient := base.WithHTTPClient(&http.Client{}) + + if base.ReadOnly() { + t.Fatal("WithReadOnly mutated the receiver") + } + if !readOnly.ReadOnly() { + t.Fatal("WithReadOnly did not apply to the derived service") + } + if base.httpClient != nil { + t.Fatal("WithHTTPClient mutated the receiver") + } + if withClient.httpClient == nil { + t.Fatal("WithHTTPClient did not apply to the derived service") + } + if scoped == base || readOnly == base || withClient == base { + t.Fatal("With* helpers returned the receiver instead of a derived service") + } + // A derived service must keep the specialization of the service it came from. + if !readOnly.WithStore(st).ReadOnly() { + t.Fatal("WithStore dropped the read-only flag") + } +} + +func TestResetConfigurationInitializedReopensYAMLImport(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatalf("store.New() error = %v", err) + } + defer st.Close() + svc := NewService(st) + + if initialized, err := svc.HasConfiguration(); err != nil || initialized { + t.Fatalf("HasConfiguration() on a fresh store = %v, %v; want false", initialized, err) + } + if err := svc.MarkConfigurationInitialized(); err != nil { + t.Fatalf("MarkConfigurationInitialized() error = %v", err) + } + if initialized, err := svc.HasConfiguration(); err != nil || !initialized { + t.Fatalf("HasConfiguration() after marking = %v, %v; want true", initialized, err) + } + if err := svc.ResetConfigurationInitialized(); err != nil { + t.Fatalf("ResetConfigurationInitialized() error = %v", err) + } + if initialized, err := svc.HasConfiguration(); err != nil || initialized { + t.Fatalf("HasConfiguration() after reset = %v, %v; want false", initialized, err) + } + // Resetting never deletes channels: stored configuration still wins over YAML. + if _, err := st.UpsertChannelConfig(store.ChannelConfigRecord{ID: "primary", Name: "Primary", Enabled: true, BaseURL: "https://example.invalid/v1"}); err != nil { + t.Fatal(err) + } + if initialized, err := svc.HasConfiguration(); err != nil || !initialized { + t.Fatalf("HasConfiguration() with a stored channel = %v, %v; want true", initialized, err) + } + if err := svc.ResetConfigurationInitialized(); err != nil { + t.Fatalf("ResetConfigurationInitialized() error = %v", err) + } + if initialized, err := svc.HasConfiguration(); err != nil || !initialized { + t.Fatalf("reset dropped stored channels: initialized=%v err=%v", initialized, err) + } +} + +func TestBootstrapFromConfigStopsWritingOnceInitialized(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatalf("store.New() error = %v", err) + } + defer st.Close() + svc := NewService(st) + + if _, err := st.UpsertChannelConfig(store.ChannelConfigRecord{ID: "primary", Name: "Primary", Enabled: true, BaseURL: "https://example.invalid/v1"}); err != nil { + t.Fatal(err) + } + if err := svc.ResetConfigurationInitialized(); err != nil { + t.Fatal(err) + } + imported, err := svc.BootstrapFromConfig(&config.Config{}) + if err != nil || imported != 0 { + t.Fatalf("BootstrapFromConfig() = %d, %v; want 0, nil", imported, err) + } + var marker bool + if found, err := st.LoadAppSettingJSON(context.Background(), "channels.initialized", &marker); err != nil { + t.Fatal(err) + } else if found { + t.Fatal("an already-initialized startup rewrote the bootstrap marker") + } + if initialized, err := svc.HasConfiguration(); err != nil || !initialized { + t.Fatalf("stored channels no longer count as initialized: initialized=%v err=%v", initialized, err) + } +} + +func TestBootstrapFromConfigReimportsYAMLAfterReset(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatalf("store.New() error = %v", err) + } + defer st.Close() + svc := NewService(st) + + enabled := true + cfg := &config.Config{ + Upstreams: []config.UpstreamTargetConfig{{ + ID: "openai-primary", + Enabled: &enabled, + Upstream: config.UpstreamConfig{ + BaseURL: "https://example.invalid/v1", + ProviderPreset: "openai", + }, + }}, + } + if imported, err := svc.BootstrapFromConfig(cfg); err != nil || imported != 1 { + t.Fatalf("first BootstrapFromConfig() = %d, %v; want 1, nil", imported, err) + } + channels, err := st.ListChannelConfigs() + if err != nil { + t.Fatal(err) + } + for _, record := range channels { + if err := st.DeleteChannelConfig(record.ID); err != nil { + t.Fatal(err) + } + } + if initialized, err := svc.HasConfiguration(); err != nil || !initialized { + t.Fatalf("marker was not persisted by the first import: initialized=%v err=%v", initialized, err) + } + if imported, err := svc.BootstrapFromConfig(cfg); err != nil || imported != 0 { + t.Fatalf("BootstrapFromConfig() before reset = %d, %v; want 0, nil", imported, err) + } + if err := svc.ResetConfigurationInitialized(); err != nil { + t.Fatal(err) + } + if imported, err := svc.BootstrapFromConfig(cfg); err != nil || imported != 1 { + t.Fatalf("BootstrapFromConfig() after reset = %d, %v; want 1, nil", imported, err) + } +} diff --git a/internal/config/config.go b/internal/config/config.go index e6b5fc4..3651f8a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -115,6 +115,7 @@ type UpstreamTargetConfig struct { StaticModels []string `yaml:"static_models"` ModelAliases map[string]string `yaml:"-"` ConfiguredModelsOnly bool `yaml:"-"` + DisabledModels []string `yaml:"-"` AllowUnknownModels *bool `yaml:"allow_unknown_models"` Upstream UpstreamConfig `yaml:"upstream"` Credentials []CredentialConfig `yaml:"credentials"` diff --git a/internal/monitor/configuration.go b/internal/monitor/configuration.go new file mode 100644 index 0000000..77214fe --- /dev/null +++ b/internal/monitor/configuration.go @@ -0,0 +1,108 @@ +package monitor + +import ( + "bytes" + "encoding/json" + "errors" + "net/http" + "strings" + + "github.com/kingfs/llm-tracelab/internal/channel" + "github.com/kingfs/llm-tracelab/internal/config" + "github.com/kingfs/llm-tracelab/internal/router" + "github.com/kingfs/llm-tracelab/internal/store" +) + +type configurationHandlerFactory func(*store.Store, *router.Router, *channel.Service) http.HandlerFunc + +// Buffer the small JSON response until both persistence and runtime publication +// succeed. Existing handlers operate on the transaction, with reload deferred. +func configurationAPIHandler(st *store.Store, rtr *router.Router, svc *channel.Service, factory configurationHandlerFactory) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if st == nil || r.Method == http.MethodGet || r.Method == http.MethodHead || strings.HasSuffix(r.URL.Path, "/validate") { + factory(st, rtr, svc)(w, r) + return + } + svc := effectiveChannelService(st, svc) + if svc.ReadOnly() { + writeJSON(w, http.StatusConflict, map[string]string{"error": "upstreams are managed by YAML credentials; edit YAML and restart instead"}) + return + } + response := &configurationResponse{header: make(http.Header)} + rejected := errors.New("configuration request rejected") + err := st.ConfigurationTransaction(r.Context(), func(tx *store.Store, commit func() error) error { + txService := svc.WithStore(tx) + factory(tx, nil, txService)(response, r) + if response.status >= http.StatusBadRequest { + // Failed discovery keeps its diagnostic run, but never changes routing. + if response.status == http.StatusBadGateway && strings.HasSuffix(r.URL.Path, "/probe") { + var result channelProbeResponse + if json.Unmarshal(response.body.Bytes(), &result) == nil && result.Status == "failed" { + return commit() + } + } + return rejected + } + if err := txService.MarkConfigurationInitialized(); err != nil { + return err + } + targets, err := txService.RuntimeTargets() + if err != nil { + return err + } + if rtr == nil { + prepared, err := router.New(&config.Config{}, nil) + if err != nil { + return err + } + return prepared.ReloadWithCommit(targets, tx, commit) + } + return rtr.ReloadWithCommit(targets, tx, commit) + }) + if err != nil && !errors.Is(err, rejected) { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "configuration not applied: " + err.Error()}) + return + } + for key, values := range response.header { + w.Header()[key] = values + } + if response.status != 0 { + w.WriteHeader(response.status) + } + _, _ = w.Write(response.body.Bytes()) + } +} + +type configurationResponse struct { + header http.Header + body bytes.Buffer + status int +} + +func (w *configurationResponse) Header() http.Header { return w.header } +func (w *configurationResponse) WriteHeader(status int) { + if w.status == 0 { + w.status = status + } +} +func (w *configurationResponse) Write(p []byte) (int, error) { + if w.status == 0 { + w.status = http.StatusOK + } + return w.body.Write(p) +} +func channelListCreateAPIHandler(st *store.Store, rtr *router.Router, svc *channel.Service) http.HandlerFunc { + return configurationAPIHandler(st, rtr, svc, channelListCreateAPIHandlerUncommitted) +} + +func channelDetailAPIHandler(st *store.Store, rtr *router.Router, svc *channel.Service) http.HandlerFunc { + return configurationAPIHandler(st, rtr, svc, channelDetailAPIHandlerUncommitted) +} + +func providerSetupAPIHandler(st *store.Store, rtr *router.Router, svc *channel.Service) http.HandlerFunc { + return configurationAPIHandler(st, rtr, svc, providerSetupAPIHandlerUncommitted) +} + +func providerProbeReportApplyAPIHandler(st *store.Store, rtr *router.Router, svc *channel.Service) http.HandlerFunc { + return configurationAPIHandler(st, rtr, svc, providerProbeReportApplyAPIHandlerUncommitted) +} diff --git a/internal/monitor/configuration_test.go b/internal/monitor/configuration_test.go new file mode 100644 index 0000000..b4ff5b9 --- /dev/null +++ b/internal/monitor/configuration_test.go @@ -0,0 +1,237 @@ +package monitor + +import ( + "net/http" + "net/http/httptest" + "strings" + "sync" + "testing" + + "github.com/kingfs/llm-tracelab/internal/channel" + "github.com/kingfs/llm-tracelab/internal/config" + "github.com/kingfs/llm-tracelab/internal/router" + "github.com/kingfs/llm-tracelab/internal/store" +) + +func configurationFixture(t *testing.T) (*store.Store, *router.Router, *channel.Service) { + t.Helper() + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = st.Close() }) + _, err = st.UpsertChannelConfig(store.ChannelConfigRecord{ID: "primary", Name: "Primary", Enabled: true, BaseURL: "https://example.invalid/v1", ProviderPreset: "openai", ModelDiscovery: "list_models", AllowUnknownModels: true}) + if err != nil { + t.Fatal(err) + } + for _, model := range []string{"one", "two"} { + if _, err := st.UpsertChannelModel("primary", store.ChannelModelRecord{Model: model, Enabled: true, Source: "manual"}); err != nil { + t.Fatal(err) + } + } + svc := channel.NewService(st) + rtr, err := router.New(&config.Config{}, st) + if err != nil { + t.Fatal(err) + } + targets, err := svc.RuntimeTargets() + if err != nil { + t.Fatal(err) + } + if err := rtr.Reload(targets); err != nil { + t.Fatal(err) + } + return st, rtr, svc +} + +func configurationRequest(h http.Handler, method, path, body string) *httptest.ResponseRecorder { + response := httptest.NewRecorder() + h.ServeHTTP(response, httptest.NewRequest(method, path, strings.NewReader(body))) + return response +} + +func TestConfigurationMutationRollsBackOnInvalidRouter(t *testing.T) { + st, rtr, svc := configurationFixture(t) + response := configurationRequest(channelDetailAPIHandler(st, rtr, svc), http.MethodPatch, "/api/channels/primary", `{"base_url":"://invalid"}`) + if response.Code != http.StatusInternalServerError { + t.Fatalf("status=%d body=%s", response.Code, response.Body) + } + saved, err := st.GetChannelConfig("primary") + if err != nil { + t.Fatal(err) + } + if saved.BaseURL != "https://example.invalid/v1" { + t.Fatalf("failed update persisted: %s", saved.BaseURL) + } + if got := rtr.AggregatedModels(); len(got) != 2 { + t.Fatalf("runtime changed: %v", got) + } +} + +func TestConfigurationBatchFailureIsAtomic(t *testing.T) { + st, rtr, svc := configurationFixture(t) + response := configurationRequest(channelDetailAPIHandler(st, rtr, svc), http.MethodPatch, "/api/channels/primary/models/batch", `{"models":["one","missing"],"enabled":false}`) + if response.Code != http.StatusBadRequest { + t.Fatalf("status=%d body=%s", response.Code, response.Body) + } + models, err := st.ListChannelModels("primary", true) + if err != nil { + t.Fatal(err) + } + if len(models) != 2 { + t.Fatalf("partial batch persisted: %v", models) + } + if got := rtr.AggregatedModels(); len(got) != 2 { + t.Fatalf("runtime changed: %v", got) + } +} + +func TestConfigurationDisableAndReenablePreservesModelChoices(t *testing.T) { + st, rtr, svc := configurationFixture(t) + h := channelDetailAPIHandler(st, rtr, svc) + for _, op := range []struct{ path, body string }{{"/api/channels/primary/models/one", `{"enabled":false}`}, {"/api/channels/primary", `{"enabled":false}`}} { + rr := configurationRequest(h, http.MethodPatch, op.path, op.body) + if rr.Code != http.StatusOK { + t.Fatalf("status=%d body=%s", rr.Code, rr.Body) + } + } + if len(rtr.Targets()) != 0 { + t.Fatal("disabled provider remains in runtime") + } + rr := configurationRequest(h, http.MethodPatch, "/api/channels/primary", `{"enabled":true}`) + if rr.Code != http.StatusOK { + t.Fatal(rr.Body.String()) + } + if got := rtr.AggregatedModels(); len(got) != 1 || got[0] != "two" { + t.Fatalf("model choices changed: %v", got) + } + if _, err := rtr.Select(httptest.NewRequest(http.MethodPost, "/v1/chat/completions", strings.NewReader(`{"model":"one"}`))); err == nil { + t.Fatal("disabled model admitted through unknown-model fallback") + } +} + +func TestConfigurationConcurrentMutationsKeepLatestSnapshot(t *testing.T) { + st, rtr, svc := configurationFixture(t) + h := channelDetailAPIHandler(st, rtr, svc) + var wg sync.WaitGroup + for _, model := range []string{"one", "two"} { + wg.Add(1) + go func(model string) { + defer wg.Done() + rr := configurationRequest(h, http.MethodPatch, "/api/channels/primary/models/"+model, `{"enabled":false}`) + if rr.Code != http.StatusOK { + t.Errorf("status=%d body=%s", rr.Code, rr.Body) + } + }(model) + } + wg.Wait() + if got := rtr.AggregatedModels(); len(got) != 0 { + t.Fatalf("stale snapshot: %v", got) + } +} + +func TestYAMLCredentialsRejectDatabaseMutation(t *testing.T) { + st, rtr, svc := configurationFixture(t) + rr := configurationRequest(channelDetailAPIHandler(st, rtr, svc.WithReadOnly(true)), http.MethodPatch, "/api/channels/primary", `{"enabled":false}`) + if rr.Code != http.StatusConflict { + t.Fatalf("status=%d body=%s", rr.Code, rr.Body) + } + record, err := st.GetChannelConfig("primary") + if err != nil { + t.Fatal(err) + } + if !record.Enabled || len(rtr.Targets()) != 1 { + t.Fatal("YAML runtime changed through database management") + } +} + +func TestModelAliasMutationPublishesRuntimeAndRollsBack(t *testing.T) { + st, rtr, svc := configurationFixture(t) + mux := http.NewServeMux() + RegisterRoutes(mux, st, RouteOptions{Router: rtr, ChannelService: svc}) + rr := configurationRequest(mux, http.MethodPost, "/api/model-aliases", `{"id":"alias-one","alias":"friendly","target_model":"one","channel_id":"primary","enabled":true}`) + if rr.Code != http.StatusOK { + t.Fatalf("status=%d body=%s", rr.Code, rr.Body) + } + if rtr.Targets()[0].ResolveModelAlias("friendly") != "one" { + t.Fatal("alias was saved without publishing runtime") + } + // A bad active configuration forces preparation failure after the raw SQL write. + record, err := st.GetChannelConfig("primary") + if err != nil { + t.Fatal(err) + } + record.BaseURL = "://invalid" + if _, err := st.UpsertChannelConfig(record); err != nil { + t.Fatal(err) + } + rr = configurationRequest(mux, http.MethodPatch, "/api/model-aliases/alias-one", `{"enabled":false}`) + if rr.Code != http.StatusInternalServerError { + t.Fatalf("status=%d body=%s", rr.Code, rr.Body) + } + alias, err := st.GetModelAlias("alias-one") + if err != nil { + t.Fatal(err) + } + if !alias.Enabled || rtr.Targets()[0].ResolveModelAlias("friendly") != "one" { + t.Fatal("failed alias update changed database or runtime") + } +} + +func TestDeleteChannelRollbackRestoresItsModels(t *testing.T) { + st, rtr, svc := configurationFixture(t) + if _, err := st.UpsertChannelConfig(store.ChannelConfigRecord{ID: "broken", Name: "Broken", Enabled: true, BaseURL: "://invalid"}); err != nil { + t.Fatal(err) + } + rr := configurationRequest(channelDetailAPIHandler(st, rtr, svc), http.MethodDelete, "/api/channels/primary", "") + if rr.Code != http.StatusInternalServerError { + t.Fatalf("status=%d body=%s", rr.Code, rr.Body) + } + if _, err := st.GetChannelConfig("primary"); err != nil { + t.Fatal("nested delete transaction escaped rollback:", err) + } + models, err := st.ListChannelModels("primary", true) + if err != nil { + t.Fatal(err) + } + if len(models) != 2 { + t.Fatalf("models not restored: %v", models) + } +} + +func TestChannelBootstrapSettingsReportAndResetTheMarker(t *testing.T) { + st, err := store.New(t.TempDir()) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = st.Close() }) + svc := channel.NewService(st) + mux := http.NewServeMux() + RegisterRoutes(mux, st, RouteOptions{ChannelService: svc}) + + rr := configurationRequest(mux, http.MethodGet, "/api/settings/channels", "") + if rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), `"initialized":false`) { + t.Fatalf("GET on a fresh database status=%d body=%s", rr.Code, rr.Body) + } + + if err := svc.MarkConfigurationInitialized(); err != nil { + t.Fatal(err) + } + rr = configurationRequest(mux, http.MethodGet, "/api/settings/channels", "") + if rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), `"initialized":true`) { + t.Fatalf("GET after marking status=%d body=%s", rr.Code, rr.Body) + } + + rr = configurationRequest(mux, http.MethodDelete, "/api/settings/channels", "") + if rr.Code != http.StatusOK || !strings.Contains(rr.Body.String(), `"initialized":false`) { + t.Fatalf("DELETE status=%d body=%s", rr.Code, rr.Body) + } + if initialized, err := svc.HasConfiguration(); err != nil || initialized { + t.Fatalf("marker survived the reset: initialized=%v err=%v", initialized, err) + } + + rr = configurationRequest(mux, http.MethodPost, "/api/settings/channels", "") + if rr.Code != http.StatusNotFound { + t.Fatalf("POST status=%d body=%s, want 404", rr.Code, rr.Body) + } +} diff --git a/internal/monitor/server.go b/internal/monitor/server.go index 2272eb2..7dfb6ed 100644 --- a/internal/monitor/server.go +++ b/internal/monitor/server.go @@ -1509,9 +1509,14 @@ func RegisterRoutes(mux *http.ServeMux, st *store.Store, opts ...RouteOptions) { mux.HandleFunc("/api/routing/inspect", monitorAuthRequired(routingInspectAPIHandler(st), monitorVerifier)) mux.HandleFunc("/api/routing/summary", monitorAuthRequired(routingSummaryAPIHandler(st), monitorVerifier)) mux.HandleFunc("/api/settings/routing", monitorAuthRequired(routingSettingsAPIHandler(st), monitorVerifier)) + mux.HandleFunc("/api/settings/channels", monitorAuthRequired(channelBootstrapSettingsAPIHandler(st, opt.ChannelService), monitorVerifier)) mux.HandleFunc("/api/model-aliases/validate", monitorAuthRequired(modelAliasValidateAPIHandler(st), monitorVerifier)) - mux.HandleFunc("/api/model-aliases", monitorAuthRequired(modelAliasListCreateAPIHandler(st), monitorVerifier)) - mux.HandleFunc("/api/model-aliases/", monitorAuthRequired(modelAliasDetailAPIHandler(st), monitorVerifier)) + mux.HandleFunc("/api/model-aliases", monitorAuthRequired(configurationAPIHandler(st, opt.Router, opt.ChannelService, func(st *store.Store, _ *router.Router, _ *channel.Service) http.HandlerFunc { + return modelAliasListCreateAPIHandler(st) + }), monitorVerifier)) + mux.HandleFunc("/api/model-aliases/", monitorAuthRequired(configurationAPIHandler(st, opt.Router, opt.ChannelService, func(st *store.Store, _ *router.Router, _ *channel.Service) http.HandlerFunc { + return modelAliasDetailAPIHandler(st) + }), monitorVerifier)) mux.HandleFunc("/api/traces", monitorAuthRequired(listAPIHandler(st), monitorVerifier)) mux.HandleFunc("/api/traces/", monitorAuthRequired(traceAPIHandler(st, opt.Router), monitorVerifier)) mux.HandleFunc("/api/sessions", monitorAuthRequired(sessionListAPIHandler(st), monitorVerifier)) @@ -2530,7 +2535,7 @@ func providerProbeAPIHandler() http.HandlerFunc { } } -func providerSetupAPIHandler(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { +func providerSetupAPIHandlerUncommitted(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.NotFound(w, r) @@ -2758,7 +2763,7 @@ func providerProbeReportAPIHandler(st *store.Store, channelService *channel.Serv } } -func providerProbeReportApplyAPIHandler(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { +func providerProbeReportApplyAPIHandlerUncommitted(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.NotFound(w, r) @@ -2895,7 +2900,7 @@ func appHandler() http.Handler { }) } -func channelListCreateAPIHandler(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { +func channelListCreateAPIHandlerUncommitted(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if st == nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "store not configured"}) @@ -2945,7 +2950,7 @@ func channelListCreateAPIHandler(st *store.Store, rtr *router.Router, channelSer } } -func channelDetailAPIHandler(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { +func channelDetailAPIHandlerUncommitted(st *store.Store, rtr *router.Router, channelService *channel.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if st == nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "store not configured"}) @@ -3090,6 +3095,55 @@ func routingSettingsAPIHandler(st *store.Store) http.HandlerFunc { } } +// channelBootstrapSettingsAPIHandler reports and clears the YAML bootstrap +// marker for channel configuration. GET answers whether the database owns the +// routing configuration; DELETE clears only the explicit marker, so a database +// that still stores channels keeps winning over YAML. +func channelBootstrapSettingsAPIHandler(st *store.Store, channelService *channel.Service) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if st == nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "store not configured"}) + return + } + svc := effectiveChannelService(st, channelService) + if svc == nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "store not configured"}) + return + } + switch r.Method { + case http.MethodGet: + initialized, err := svc.HasConfiguration() + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + writeJSON(w, http.StatusOK, map[string]bool{"initialized": initialized}) + case http.MethodDelete: + // Clearing the marker is a settings write, but it still goes through + // the configuration transaction so it cannot interleave with a + // management write that re-marks it. + err := st.ConfigurationTransaction(r.Context(), func(tx *store.Store, commit func() error) error { + if err := svc.WithStore(tx).ResetConfigurationInitialized(); err != nil { + return err + } + return commit() + }) + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + initialized, err := svc.HasConfiguration() + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + writeJSON(w, http.StatusOK, map[string]bool{"initialized": initialized}) + default: + http.NotFound(w, r) + } + } +} + func modelAliasListCreateAPIHandler(st *store.Store) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if st == nil { @@ -3975,7 +4029,7 @@ func channelRecordFromRequest(req channelUpsertRequest, existing store.ChannelCo } if req.Enabled != nil { record.Enabled = *req.Enabled - } else if record.ID == "" { + } else if existing.ID == "" { record.Enabled = true } if req.Priority != nil { diff --git a/internal/monitor/server_test.go b/internal/monitor/server_test.go index 3aaccf3..8ca5e8e 100644 --- a/internal/monitor/server_test.go +++ b/internal/monitor/server_test.go @@ -2017,7 +2017,7 @@ func TestChannelManagementAPI(t *testing.T) { t.Fatalf("created.Capabilities.Responses = %#v", created.Capabilities.Responses) } - req = httptest.NewRequest(http.MethodPost, "/api/channels/openai-primary/probe", nil) + req = httptest.NewRequest(http.MethodPost, "/api/channels/openai-primary/probe", strings.NewReader(`{"enable_discovered":true}`)) rr = httptest.NewRecorder() channelDetailAPIHandler(st, nil, nil).ServeHTTP(rr, req) if rr.Code != http.StatusOK { @@ -2602,7 +2602,7 @@ func TestProviderSetupSuggestionsDoNotOverrideExplicitFields(t *testing.T) { "id":"explicit-provider", "name":"Explicit Provider", "base_url":"` + upstreamServer.URL + `/v1", - "provider_preset":"custom", + "provider_preset":"anthropic", "api_type":"messages", "protocol_family":"anthropic_messages", "capabilities":{"chat_completions":false}, diff --git a/internal/monitor/ui/dist/assets/index-D_MD5F8Z.js b/internal/monitor/ui/dist/assets/index-FGs8n2-K.js similarity index 61% rename from internal/monitor/ui/dist/assets/index-D_MD5F8Z.js rename to internal/monitor/ui/dist/assets/index-FGs8n2-K.js index 6196d7e..a0f4507 100644 --- a/internal/monitor/ui/dist/assets/index-D_MD5F8Z.js +++ b/internal/monitor/ui/dist/assets/index-FGs8n2-K.js @@ -1,4 +1,4 @@ -var oL=Object.defineProperty;var uL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var pv=(e,t,n)=>uL(e,typeof t!="symbol"?t+"":t,n);function cL(e,t){for(var n=0;nr[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const c of o.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&r(c)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerPolicy&&(o.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?o.credentials="include":l.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}})();var h1=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Ma(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var mv={exports:{}},Wo={};/** +var oL=Object.defineProperty;var cL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var pv=(e,t,n)=>cL(e,typeof t!="symbol"?t+"":t,n);function uL(e,t){for(var n=0;nr[l]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);new MutationObserver(l=>{for(const o of l)if(o.type==="childList")for(const u of o.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&r(u)}).observe(document,{childList:!0,subtree:!0});function n(l){const o={};return l.integrity&&(o.integrity=l.integrity),l.referrerPolicy&&(o.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?o.credentials="include":l.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(l){if(l.ep)return;l.ep=!0;const o=n(l);fetch(l.href,o)}})();var h1=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Ma(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var mv={exports:{}},Wo={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ var oL=Object.defineProperty;var uL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var p1;function dL(){if(p1)return Wo;p1=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,l,o){var c=null;if(o!==void 0&&(c=""+o),l.key!==void 0&&(c=""+l.key),"key"in l){o={};for(var d in l)d!=="key"&&(o[d]=l[d])}else o=l;return l=o.ref,{$$typeof:e,type:r,key:c,ref:l!==void 0?l:null,props:o}}return Wo.Fragment=t,Wo.jsx=n,Wo.jsxs=n,Wo}var m1;function fL(){return m1||(m1=1,mv.exports=dL()),mv.exports}var s=fL(),vv={exports:{}},Te={};/** + */var p1;function dL(){if(p1)return Wo;p1=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,l,o){var u=null;if(o!==void 0&&(u=""+o),l.key!==void 0&&(u=""+l.key),"key"in l){o={};for(var d in l)d!=="key"&&(o[d]=l[d])}else o=l;return l=o.ref,{$$typeof:e,type:r,key:u,ref:l!==void 0?l:null,props:o}}return Wo.Fragment=t,Wo.jsx=n,Wo.jsxs=n,Wo}var m1;function fL(){return m1||(m1=1,mv.exports=dL()),mv.exports}var s=fL(),vv={exports:{}},Te={};/** * @license React * react.production.js * @@ -14,7 +14,7 @@ var oL=Object.defineProperty;var uL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var v1;function hL(){if(v1)return Te;v1=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),l=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),c=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),v=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),y=Symbol.iterator;function x(z){return z===null||typeof z!="object"?null:(z=y&&z[y]||z["@@iterator"],typeof z=="function"?z:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,S={};function N(z,Q,ue){this.props=z,this.context=Q,this.refs=S,this.updater=ue||_}N.prototype.isReactComponent={},N.prototype.setState=function(z,Q){if(typeof z!="object"&&typeof z!="function"&&z!=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,z,Q,"setState")},N.prototype.forceUpdate=function(z){this.updater.enqueueForceUpdate(this,z,"forceUpdate")};function E(){}E.prototype=N.prototype;function T(z,Q,ue){this.props=z,this.context=Q,this.refs=S,this.updater=ue||_}var M=T.prototype=new E;M.constructor=T,w(M,N.prototype),M.isPureReactComponent=!0;var k=Array.isArray;function A(){}var P={H:null,A:null,T:null,S:null},L=Object.prototype.hasOwnProperty;function D(z,Q,ue){var oe=ue.ref;return{$$typeof:e,type:z,key:Q,ref:oe!==void 0?oe:null,props:ue}}function W(z,Q){return D(z.type,Q,z.props)}function K(z){return typeof z=="object"&&z!==null&&z.$$typeof===e}function I(z){var Q={"=":"=0",":":"=2"};return"$"+z.replace(/[=:]/g,function(ue){return Q[ue]})}var ce=/\/+/g;function pe(z,Q){return typeof z=="object"&&z!==null&&z.key!=null?I(""+z.key):Q.toString(36)}function ge(z){switch(z.status){case"fulfilled":return z.value;case"rejected":throw z.reason;default:switch(typeof z.status=="string"?z.then(A,A):(z.status="pending",z.then(function(Q){z.status==="pending"&&(z.status="fulfilled",z.value=Q)},function(Q){z.status==="pending"&&(z.status="rejected",z.reason=Q)})),z.status){case"fulfilled":return z.value;case"rejected":throw z.reason}}throw z}function $(z,Q,ue,oe,de){var Ee=typeof z;(Ee==="undefined"||Ee==="boolean")&&(z=null);var re=!1;if(z===null)re=!0;else switch(Ee){case"bigint":case"string":case"number":re=!0;break;case"object":switch(z.$$typeof){case e:case t:re=!0;break;case v:return re=z._init,$(re(z._payload),Q,ue,oe,de)}}if(re)return de=de(z),re=oe===""?"."+pe(z,0):oe,k(de)?(ue="",re!=null&&(ue=re.replace(ce,"$&/")+"/"),$(de,Q,ue,"",function(fe){return fe})):de!=null&&(K(de)&&(de=W(de,ue+(de.key==null||z&&z.key===de.key?"":(""+de.key).replace(ce,"$&/")+"/")+re)),Q.push(de)),1;re=0;var _e=oe===""?".":oe+":";if(k(z))for(var se=0;set in e?oL(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var y1;function mL(){return y1||(y1=1,(function(e){function t($,X){var G=$.length;$.push(X);e:for(;0>>1,xe=$[le];if(0>>1;lel(ue,G))oel(de,ue)?($[le]=de,$[oe]=G,le=oe):($[le]=ue,$[Q]=G,le=Q);else if(oel(de,G))$[le]=de,$[oe]=G,le=oe;else break e}}return X}function l($,X){var G=$.sortIndex-X.sortIndex;return G!==0?G:$.id-X.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var c=Date,d=c.now();e.unstable_now=function(){return c.now()-d}}var h=[],p=[],v=1,m=null,y=3,x=!1,_=!1,w=!1,S=!1,N=typeof setTimeout=="function"?setTimeout:null,E=typeof clearTimeout=="function"?clearTimeout:null,T=typeof setImmediate<"u"?setImmediate:null;function M($){for(var X=n(p);X!==null;){if(X.callback===null)r(p);else if(X.startTime<=$)r(p),X.sortIndex=X.expirationTime,t(h,X);else break;X=n(p)}}function k($){if(w=!1,M($),!_)if(n(h)!==null)_=!0,A||(A=!0,I());else{var X=n(p);X!==null&&ge(k,X.startTime-$)}}var A=!1,P=-1,L=5,D=-1;function W(){return S?!0:!(e.unstable_now()-D$&&W());){var le=m.callback;if(typeof le=="function"){m.callback=null,y=m.priorityLevel;var xe=le(m.expirationTime<=$);if($=e.unstable_now(),typeof xe=="function"){m.callback=xe,M($),X=!0;break t}m===n(h)&&r(h),M($)}else r(h);m=n(h)}if(m!==null)X=!0;else{var z=n(p);z!==null&&ge(k,z.startTime-$),X=!1}}break e}finally{m=null,y=G,x=!1}X=void 0}}finally{X?I():A=!1}}}var I;if(typeof T=="function")I=function(){T(K)};else if(typeof MessageChannel<"u"){var ce=new MessageChannel,pe=ce.port2;ce.port1.onmessage=K,I=function(){pe.postMessage(null)}}else I=function(){N(K,0)};function ge($,X){P=N(function(){$(e.unstable_now())},X)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function($){$.callback=null},e.unstable_forceFrameRate=function($){0>$||125<$?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):L=0<$?Math.floor(1e3/$):5},e.unstable_getCurrentPriorityLevel=function(){return y},e.unstable_next=function($){switch(y){case 1:case 2:case 3:var X=3;break;default:X=y}var G=y;y=X;try{return $()}finally{y=G}},e.unstable_requestPaint=function(){S=!0},e.unstable_runWithPriority=function($,X){switch($){case 1:case 2:case 3:case 4:case 5:break;default:$=3}var G=y;y=$;try{return X()}finally{y=G}},e.unstable_scheduleCallback=function($,X,G){var le=e.unstable_now();switch(typeof G=="object"&&G!==null?(G=G.delay,G=typeof G=="number"&&0le?($.sortIndex=G,t(p,$),n(h)===null&&$===n(p)&&(w?(E(P),P=-1):w=!0,ge(k,G-le))):($.sortIndex=xe,t(h,$),_||x||(_=!0,A||(A=!0,I()))),$},e.unstable_shouldYield=W,e.unstable_wrapCallback=function($){var X=y;return function(){var G=y;y=X;try{return $.apply(this,arguments)}finally{y=G}}}})(bv)),bv}var b1;function vL(){return b1||(b1=1,yv.exports=mL()),yv.exports}var xv={exports:{}},cn={};/** + */var y1;function mL(){return y1||(y1=1,(function(e){function t($,X){var Y=$.length;$.push(X);e:for(;0>>1,xe=$[le];if(0>>1;lel(ce,Y))oel(de,ce)?($[le]=de,$[oe]=Y,le=oe):($[le]=ce,$[Q]=Y,le=Q);else if(oel(de,Y))$[le]=de,$[oe]=Y,le=oe;else break e}}return X}function l($,X){var Y=$.sortIndex-X.sortIndex;return Y!==0?Y:$.id-X.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var u=Date,d=u.now();e.unstable_now=function(){return u.now()-d}}var h=[],p=[],v=1,m=null,y=3,x=!1,_=!1,w=!1,S=!1,N=typeof setTimeout=="function"?setTimeout:null,E=typeof clearTimeout=="function"?clearTimeout:null,A=typeof setImmediate<"u"?setImmediate:null;function P($){for(var X=n(p);X!==null;){if(X.callback===null)r(p);else if(X.startTime<=$)r(p),X.sortIndex=X.expirationTime,t(h,X);else break;X=n(p)}}function k($){if(w=!1,P($),!_)if(n(h)!==null)_=!0,T||(T=!0,I());else{var X=n(p);X!==null&&ge(k,X.startTime-$)}}var T=!1,M=-1,L=5,D=-1;function W(){return S?!0:!(e.unstable_now()-D$&&W());){var le=m.callback;if(typeof le=="function"){m.callback=null,y=m.priorityLevel;var xe=le(m.expirationTime<=$);if($=e.unstable_now(),typeof xe=="function"){m.callback=xe,P($),X=!0;break t}m===n(h)&&r(h),P($)}else r(h);m=n(h)}if(m!==null)X=!0;else{var z=n(p);z!==null&&ge(k,z.startTime-$),X=!1}}break e}finally{m=null,y=Y,x=!1}X=void 0}}finally{X?I():T=!1}}}var I;if(typeof A=="function")I=function(){A(K)};else if(typeof MessageChannel<"u"){var ue=new MessageChannel,pe=ue.port2;ue.port1.onmessage=K,I=function(){pe.postMessage(null)}}else I=function(){N(K,0)};function ge($,X){M=N(function(){$(e.unstable_now())},X)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function($){$.callback=null},e.unstable_forceFrameRate=function($){0>$||125<$?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):L=0<$?Math.floor(1e3/$):5},e.unstable_getCurrentPriorityLevel=function(){return y},e.unstable_next=function($){switch(y){case 1:case 2:case 3:var X=3;break;default:X=y}var Y=y;y=X;try{return $()}finally{y=Y}},e.unstable_requestPaint=function(){S=!0},e.unstable_runWithPriority=function($,X){switch($){case 1:case 2:case 3:case 4:case 5:break;default:$=3}var Y=y;y=$;try{return X()}finally{y=Y}},e.unstable_scheduleCallback=function($,X,Y){var le=e.unstable_now();switch(typeof Y=="object"&&Y!==null?(Y=Y.delay,Y=typeof Y=="number"&&0le?($.sortIndex=Y,t(p,$),n(h)===null&&$===n(p)&&(w?(E(M),M=-1):w=!0,ge(k,Y-le))):($.sortIndex=xe,t(h,$),_||x||(_=!0,T||(T=!0,I()))),$},e.unstable_shouldYield=W,e.unstable_wrapCallback=function($){var X=y;return function(){var Y=y;y=X;try{return $.apply(this,arguments)}finally{y=Y}}}})(bv)),bv}var b1;function vL(){return b1||(b1=1,yv.exports=mL()),yv.exports}var xv={exports:{}},un={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ var oL=Object.defineProperty;var uL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var x1;function gL(){if(x1)return cn;x1=1;var e=Bs();function t(h){var p="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),xv.exports=gL(),xv.exports}/** + */var x1;function gL(){if(x1)return un;x1=1;var e=Bs();function t(h){var p="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),xv.exports=gL(),xv.exports}/** * @license React * react-dom-client.production.js * @@ -38,15 +38,15 @@ var oL=Object.defineProperty;var uL=(e,t,n)=>t in e?oL(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var _1;function yL(){if(_1)return Zo;_1=1;var e=vL(),t=Bs(),n=Hk();function r(a){var i="https://react.dev/errors/"+a;if(1xe||(a.current=le[xe],le[xe]=null,xe--)}function ue(a,i){xe++,le[xe]=a.current,a.current=i}var oe=z(null),de=z(null),Ee=z(null),re=z(null);function _e(a,i){switch(ue(Ee,i),ue(de,a),ue(oe,null),i.nodeType){case 9:case 11:a=(a=i.documentElement)&&(a=a.namespaceURI)?Lw(a):0;break;default:if(a=i.tagName,i=i.namespaceURI)i=Lw(i),a=zw(i,a);else switch(a){case"svg":a=1;break;case"math":a=2;break;default:a=0}}Q(oe),ue(oe,a)}function se(){Q(oe),Q(de),Q(Ee)}function fe(a){a.memoizedState!==null&&ue(re,a);var i=oe.current,u=zw(i,a.type);i!==u&&(ue(de,a),ue(oe,u))}function Me(a){de.current===a&&(Q(oe),Q(de)),re.current===a&&(Q(re),Yo._currentValue=G)}var ie,Pt;function Re(a){if(ie===void 0)try{throw Error()}catch(u){var i=u.stack.trim().match(/\n( *(at )?)/);ie=i&&i[1]||"",Pt=-1)":-1xe||(a.current=le[xe],le[xe]=null,xe--)}function ce(a,i){xe++,le[xe]=a.current,a.current=i}var oe=z(null),de=z(null),Ee=z(null),re=z(null);function _e(a,i){switch(ce(Ee,i),ce(de,a),ce(oe,null),i.nodeType){case 9:case 11:a=(a=i.documentElement)&&(a=a.namespaceURI)?Lw(a):0;break;default:if(a=i.tagName,i=i.namespaceURI)i=Lw(i),a=zw(i,a);else switch(a){case"svg":a=1;break;case"math":a=2;break;default:a=0}}Q(oe),ce(oe,a)}function se(){Q(oe),Q(de),Q(Ee)}function fe(a){a.memoizedState!==null&&ce(re,a);var i=oe.current,c=zw(i,a.type);i!==c&&(ce(de,a),ce(oe,c))}function Me(a){de.current===a&&(Q(oe),Q(de)),re.current===a&&(Q(re),Yo._currentValue=Y)}var ie,Pt;function Re(a){if(ie===void 0)try{throw Error()}catch(c){var i=c.stack.trim().match(/\n( *(at )?)/);ie=i&&i[1]||"",Pt=-1)":-1g||R[f]!==H[g]){var J=` -`+R[f].replace(" at new "," at ");return a.displayName&&J.includes("")&&(J=J.replace("",a.displayName)),J}while(1<=f&&0<=g);break}}}finally{St=!1,Error.prepareStackTrace=u}return(u=a?a.displayName||a.name:"")?Re(u):""}function Qn(a,i){switch(a.tag){case 26:case 27:case 5:return Re(a.type);case 16:return Re("Lazy");case 13:return a.child!==i&&i!==null?Re("Suspense Fallback"):Re("Suspense");case 19:return Re("SuspenseList");case 0:case 15:return Nt(a.type,!1);case 11:return Nt(a.type.render,!1);case 1:return Nt(a.type,!0);case 31:return Re("Activity");default:return""}}function Ba(a){try{var i="",u=null;do i+=Qn(a,u),u=a,a=a.return;while(a);return i}catch(f){return` +`+R[f].replace(" at new "," at ");return a.displayName&&J.includes("")&&(J=J.replace("",a.displayName)),J}while(1<=f&&0<=g);break}}}finally{St=!1,Error.prepareStackTrace=c}return(c=a?a.displayName||a.name:"")?Re(c):""}function Qn(a,i){switch(a.tag){case 26:case 27:case 5:return Re(a.type);case 16:return Re("Lazy");case 13:return a.child!==i&&i!==null?Re("Suspense Fallback"):Re("Suspense");case 19:return Re("SuspenseList");case 0:case 15:return Nt(a.type,!1);case 11:return Nt(a.type.render,!1);case 1:return Nt(a.type,!0);case 31:return Re("Activity");default:return""}}function Ba(a){try{var i="",c=null;do i+=Qn(a,c),c=a,a=a.return;while(a);return i}catch(f){return` Error generating stack: `+f.message+` -`+f.stack}}var Nl=Object.prototype.hasOwnProperty,Ol=e.unstable_scheduleCallback,El=e.unstable_cancelCallback,uc=e.unstable_shouldYield,cc=e.unstable_requestPaint,sn=e.unstable_now,dc=e.unstable_getCurrentPriorityLevel,no=e.unstable_ImmediatePriority,ro=e.unstable_UserBlockingPriority,ki=e.unstable_NormalPriority,fc=e.unstable_LowPriority,ao=e.unstable_IdlePriority,hc=e.log,pc=e.unstable_setDisableYieldValue,Ha=null,on=null;function xr(a){if(typeof hc=="function"&&pc(a),on&&typeof on.setStrictMode=="function")try{on.setStrictMode(Ha,a)}catch{}}var un=Math.clz32?Math.clz32:gc,mc=Math.log,vc=Math.LN2;function gc(a){return a>>>=0,a===0?32:31-(mc(a)/vc|0)|0}var Ai=256,Ti=262144,Ci=4194304;function Ae(a){var i=a&42;if(i!==0)return i;switch(a&-a){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 a&261888;case 262144:case 524288:case 1048576:case 2097152:return a&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return a&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return a}}function pt(a,i,u){var f=a.pendingLanes;if(f===0)return 0;var g=0,b=a.suspendedLanes,O=a.pingedLanes;a=a.warmLanes;var C=f&134217727;return C!==0?(f=C&~b,f!==0?g=Ae(f):(O&=C,O!==0?g=Ae(O):u||(u=C&~a,u!==0&&(g=Ae(u))))):(C=f&~b,C!==0?g=Ae(C):O!==0?g=Ae(O):u||(u=f&~a,u!==0&&(g=Ae(u)))),g===0?0:i!==0&&i!==g&&(i&b)===0&&(b=g&-g,u=i&-i,b>=u||b===32&&(u&4194048)!==0)?i:g}function Vt(a,i){return(a.pendingLanes&~(a.suspendedLanes&~a.pingedLanes)&i)===0}function yc(a,i){switch(a){case 1:case 2:case 4:case 8:case 64:return i+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 i+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 io(){var a=Ci;return Ci<<=1,(Ci&62914560)===0&&(Ci=4194304),a}function kl(a){for(var i=[],u=0;31>u;u++)i.push(a);return i}function jr(a,i){a.pendingLanes|=i,i!==268435456&&(a.suspendedLanes=0,a.pingedLanes=0,a.warmLanes=0)}function np(a,i,u,f,g,b){var O=a.pendingLanes;a.pendingLanes=u,a.suspendedLanes=0,a.pingedLanes=0,a.warmLanes=0,a.expiredLanes&=u,a.entangledLanes&=u,a.errorRecoveryDisabledLanes&=u,a.shellSuspendCounter=0;var C=a.entanglements,R=a.expirationTimes,H=a.hiddenUpdates;for(u=O&~u;0"u")return null;try{return a.activeElement||a.body}catch{return a.body}}var nD=/[\n"\\]/g;function er(a){return a.replace(nD,function(i){return"\\"+i.charCodeAt(0).toString(16)+" "})}function op(a,i,u,f,g,b,O,C){a.name="",O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"?a.type=O:a.removeAttribute("type"),i!=null?O==="number"?(i===0&&a.value===""||a.value!=i)&&(a.value=""+Jn(i)):a.value!==""+Jn(i)&&(a.value=""+Jn(i)):O!=="submit"&&O!=="reset"||a.removeAttribute("value"),i!=null?up(a,O,Jn(i)):u!=null?up(a,O,Jn(u)):f!=null&&a.removeAttribute("value"),g==null&&b!=null&&(a.defaultChecked=!!b),g!=null&&(a.checked=g&&typeof g!="function"&&typeof g!="symbol"),C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?a.name=""+Jn(C):a.removeAttribute("name")}function T0(a,i,u,f,g,b,O,C){if(b!=null&&typeof b!="function"&&typeof b!="symbol"&&typeof b!="boolean"&&(a.type=b),i!=null||u!=null){if(!(b!=="submit"&&b!=="reset"||i!=null)){sp(a);return}u=u!=null?""+Jn(u):"",i=i!=null?""+Jn(i):u,C||i===a.value||(a.value=i),a.defaultValue=i}f=f??g,f=typeof f!="function"&&typeof f!="symbol"&&!!f,a.checked=C?a.checked:!!f,a.defaultChecked=!!f,O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"&&(a.name=O),sp(a)}function up(a,i,u){i==="number"&&jc(a.ownerDocument)===a||a.defaultValue===""+u||(a.defaultValue=""+u)}function Dl(a,i,u,f){if(a=a.options,i){i={};for(var g=0;g"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),pp=!1;if(ra)try{var uo={};Object.defineProperty(uo,"passive",{get:function(){pp=!0}}),window.addEventListener("test",uo,uo),window.removeEventListener("test",uo,uo)}catch{pp=!1}var Ka=null,mp=null,wc=null;function z0(){if(wc)return wc;var a,i=mp,u=i.length,f,g="value"in Ka?Ka.value:Ka.textContent,b=g.length;for(a=0;a=ho),H0=" ",F0=!1;function K0(a,i){switch(a){case"keyup":return TD.indexOf(i.keyCode)!==-1;case"keydown":return i.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Y0(a){return a=a.detail,typeof a=="object"&&"data"in a?a.data:null}var ql=!1;function PD(a,i){switch(a){case"compositionend":return Y0(i);case"keypress":return i.which!==32?null:(F0=!0,H0);case"textInput":return a=i.data,a===H0&&F0?null:a;default:return null}}function MD(a,i){if(ql)return a==="compositionend"||!xp&&K0(a,i)?(a=z0(),wc=mp=Ka=null,ql=!1,a):null;switch(a){case"paste":return null;case"keypress":if(!(i.ctrlKey||i.altKey||i.metaKey)||i.ctrlKey&&i.altKey){if(i.char&&1=i)return{node:u,offset:i-a};a=f}e:{for(;u;){if(u.nextSibling){u=u.nextSibling;break e}u=u.parentNode}u=void 0}u=ej(u)}}function nj(a,i){return a&&i?a===i?!0:a&&a.nodeType===3?!1:i&&i.nodeType===3?nj(a,i.parentNode):"contains"in a?a.contains(i):a.compareDocumentPosition?!!(a.compareDocumentPosition(i)&16):!1:!1}function rj(a){a=a!=null&&a.ownerDocument!=null&&a.ownerDocument.defaultView!=null?a.ownerDocument.defaultView:window;for(var i=jc(a.document);i instanceof a.HTMLIFrameElement;){try{var u=typeof i.contentWindow.location.href=="string"}catch{u=!1}if(u)a=i.contentWindow;else break;i=jc(a.document)}return i}function wp(a){var i=a&&a.nodeName&&a.nodeName.toLowerCase();return i&&(i==="input"&&(a.type==="text"||a.type==="search"||a.type==="tel"||a.type==="url"||a.type==="password")||i==="textarea"||a.contentEditable==="true")}var ID=ra&&"documentMode"in document&&11>=document.documentMode,Ul=null,Sp=null,go=null,Np=!1;function aj(a,i,u){var f=u.window===u?u.document:u.nodeType===9?u:u.ownerDocument;Np||Ul==null||Ul!==jc(f)||(f=Ul,"selectionStart"in f&&wp(f)?f={start:f.selectionStart,end:f.selectionEnd}:(f=(f.ownerDocument&&f.ownerDocument.defaultView||window).getSelection(),f={anchorNode:f.anchorNode,anchorOffset:f.anchorOffset,focusNode:f.focusNode,focusOffset:f.focusOffset}),go&&vo(go,f)||(go=f,f=vd(Sp,"onSelect"),0>=O,g-=O,Pr=1<<32-un(i)+g|u<De?(Ue=je,je=null):Ue=je.sibling;var Ke=F(U,je,B[De],te);if(Ke===null){je===null&&(je=Ue);break}a&&je&&Ke.alternate===null&&i(U,je),q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke,je=Ue}if(De===B.length)return u(U,je),Ie&&ia(U,De),Se;if(je===null){for(;DeDe?(Ue=je,je=null):Ue=je.sibling;var hi=F(U,je,Ke.value,te);if(hi===null){je===null&&(je=Ue);break}a&&je&&hi.alternate===null&&i(U,je),q=b(hi,q,De),Fe===null?Se=hi:Fe.sibling=hi,Fe=hi,je=Ue}if(Ke.done)return u(U,je),Ie&&ia(U,De),Se;if(je===null){for(;!Ke.done;De++,Ke=B.next())Ke=ne(U,Ke.value,te),Ke!==null&&(q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke);return Ie&&ia(U,De),Se}for(je=f(je);!Ke.done;De++,Ke=B.next())Ke=Z(je,U,De,Ke.value,te),Ke!==null&&(a&&Ke.alternate!==null&&je.delete(Ke.key===null?De:Ke.key),q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke);return a&&je.forEach(function(sL){return i(U,sL)}),Ie&&ia(U,De),Se}function et(U,q,B,te){if(typeof B=="object"&&B!==null&&B.type===w&&B.key===null&&(B=B.props.children),typeof B=="object"&&B!==null){switch(B.$$typeof){case x:e:{for(var Se=B.key;q!==null;){if(q.key===Se){if(Se=B.type,Se===w){if(q.tag===7){u(U,q.sibling),te=g(q,B.props.children),te.return=U,U=te;break e}}else if(q.elementType===Se||typeof Se=="object"&&Se!==null&&Se.$$typeof===L&&Bi(Se)===q.type){u(U,q.sibling),te=g(q,B.props),wo(te,B),te.return=U,U=te;break e}u(U,q);break}else i(U,q);q=q.sibling}B.type===w?(te=zi(B.props.children,U.mode,te,B.key),te.return=U,U=te):(te=Mc(B.type,B.key,B.props,null,U.mode,te),wo(te,B),te.return=U,U=te)}return O(U);case _:e:{for(Se=B.key;q!==null;){if(q.key===Se)if(q.tag===4&&q.stateNode.containerInfo===B.containerInfo&&q.stateNode.implementation===B.implementation){u(U,q.sibling),te=g(q,B.children||[]),te.return=U,U=te;break e}else{u(U,q);break}else i(U,q);q=q.sibling}te=Pp(B,U.mode,te),te.return=U,U=te}return O(U);case L:return B=Bi(B),et(U,q,B,te)}if(ge(B))return be(U,q,B,te);if(I(B)){if(Se=I(B),typeof Se!="function")throw Error(r(150));return B=Se.call(B),Oe(U,q,B,te)}if(typeof B.then=="function")return et(U,q,$c(B),te);if(B.$$typeof===T)return et(U,q,Lc(U,B),te);Ic(U,B)}return typeof B=="string"&&B!==""||typeof B=="number"||typeof B=="bigint"?(B=""+B,q!==null&&q.tag===6?(u(U,q.sibling),te=g(q,B),te.return=U,U=te):(u(U,q),te=Cp(B,U.mode,te),te.return=U,U=te),O(U)):u(U,q)}return function(U,q,B,te){try{_o=0;var Se=et(U,q,B,te);return Wl=null,Se}catch(je){if(je===Xl||je===qc)throw je;var Fe=zn(29,je,null,U.mode);return Fe.lanes=te,Fe.return=U,Fe}finally{}}}var Fi=Ej(!0),kj=Ej(!1),Wa=!1;function Fp(a){a.updateQueue={baseState:a.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Kp(a,i){a=a.updateQueue,i.updateQueue===a&&(i.updateQueue={baseState:a.baseState,firstBaseUpdate:a.firstBaseUpdate,lastBaseUpdate:a.lastBaseUpdate,shared:a.shared,callbacks:null})}function Za(a){return{lane:a,tag:0,payload:null,callback:null,next:null}}function Qa(a,i,u){var f=a.updateQueue;if(f===null)return null;if(f=f.shared,(Ve&2)!==0){var g=f.pending;return g===null?i.next=i:(i.next=g.next,g.next=i),f.pending=i,i=Pc(a),dj(a,null,u),i}return Cc(a,f,i,u),Pc(a)}function So(a,i,u){if(i=i.updateQueue,i!==null&&(i=i.shared,(u&4194048)!==0)){var f=i.lanes;f&=a.pendingLanes,u|=f,i.lanes=u,b0(a,u)}}function Yp(a,i){var u=a.updateQueue,f=a.alternate;if(f!==null&&(f=f.updateQueue,u===f)){var g=null,b=null;if(u=u.firstBaseUpdate,u!==null){do{var O={lane:u.lane,tag:u.tag,payload:u.payload,callback:null,next:null};b===null?g=b=O:b=b.next=O,u=u.next}while(u!==null);b===null?g=b=i:b=b.next=i}else g=b=i;u={baseState:f.baseState,firstBaseUpdate:g,lastBaseUpdate:b,shared:f.shared,callbacks:f.callbacks},a.updateQueue=u;return}a=u.lastBaseUpdate,a===null?u.firstBaseUpdate=i:a.next=i,u.lastBaseUpdate=i}var Gp=!1;function No(){if(Gp){var a=Vl;if(a!==null)throw a}}function Oo(a,i,u,f){Gp=!1;var g=a.updateQueue;Wa=!1;var b=g.firstBaseUpdate,O=g.lastBaseUpdate,C=g.shared.pending;if(C!==null){g.shared.pending=null;var R=C,H=R.next;R.next=null,O===null?b=H:O.next=H,O=R;var J=a.alternate;J!==null&&(J=J.updateQueue,C=J.lastBaseUpdate,C!==O&&(C===null?J.firstBaseUpdate=H:C.next=H,J.lastBaseUpdate=R))}if(b!==null){var ne=g.baseState;O=0,J=H=R=null,C=b;do{var F=C.lane&-536870913,Z=F!==C.lane;if(Z?(qe&F)===F:(f&F)===F){F!==0&&F===Gl&&(Gp=!0),J!==null&&(J=J.next={lane:0,tag:C.tag,payload:C.payload,callback:null,next:null});e:{var be=a,Oe=C;F=i;var et=u;switch(Oe.tag){case 1:if(be=Oe.payload,typeof be=="function"){ne=be.call(et,ne,F);break e}ne=be;break e;case 3:be.flags=be.flags&-65537|128;case 0:if(be=Oe.payload,F=typeof be=="function"?be.call(et,ne,F):be,F==null)break e;ne=m({},ne,F);break e;case 2:Wa=!0}}F=C.callback,F!==null&&(a.flags|=64,Z&&(a.flags|=8192),Z=g.callbacks,Z===null?g.callbacks=[F]:Z.push(F))}else Z={lane:F,tag:C.tag,payload:C.payload,callback:C.callback,next:null},J===null?(H=J=Z,R=ne):J=J.next=Z,O|=F;if(C=C.next,C===null){if(C=g.shared.pending,C===null)break;Z=C,C=Z.next,Z.next=null,g.lastBaseUpdate=Z,g.shared.pending=null}}while(!0);J===null&&(R=ne),g.baseState=R,g.firstBaseUpdate=H,g.lastBaseUpdate=J,b===null&&(g.shared.lanes=0),ri|=O,a.lanes=O,a.memoizedState=ne}}function Aj(a,i){if(typeof a!="function")throw Error(r(191,a));a.call(i)}function Tj(a,i){var u=a.callbacks;if(u!==null)for(a.callbacks=null,a=0;ab?b:8;var O=$.T,C={};$.T=C,fm(a,!1,i,u);try{var R=g(),H=$.S;if(H!==null&&H(C,R),R!==null&&typeof R=="object"&&typeof R.then=="function"){var J=WD(R,f);Ao(a,i,J,Bn(a))}else Ao(a,i,f,Bn(a))}catch(ne){Ao(a,i,{then:function(){},status:"rejected",reason:ne},Bn())}finally{X.p=b,O!==null&&C.types!==null&&(O.types=C.types),$.T=O}}function nR(){}function cm(a,i,u,f){if(a.tag!==5)throw Error(r(476));var g=o_(a).queue;s_(a,g,i,G,u===null?nR:function(){return u_(a),u(f)})}function o_(a){var i=a.memoizedState;if(i!==null)return i;i={memoizedState:G,baseState:G,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ua,lastRenderedState:G},next:null};var u={};return i.next={memoizedState:u,baseState:u,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ua,lastRenderedState:u},next:null},a.memoizedState=i,a=a.alternate,a!==null&&(a.memoizedState=i),i}function u_(a){var i=o_(a);i.next===null&&(i=a.alternate.memoizedState),Ao(a,i.next.queue,{},Bn())}function dm(){return Zt(Yo)}function c_(){return jt().memoizedState}function d_(){return jt().memoizedState}function rR(a){for(var i=a.return;i!==null;){switch(i.tag){case 24:case 3:var u=Bn();a=Za(u);var f=Qa(i,a,u);f!==null&&(Tn(f,i,u),So(f,i,u)),i={cache:$p()},a.payload=i;return}i=i.return}}function aR(a,i,u){var f=Bn();u={lane:f,revertLane:0,gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},Zc(a)?h_(i,u):(u=Ap(a,i,u,f),u!==null&&(Tn(u,a,f),p_(u,i,f)))}function f_(a,i,u){var f=Bn();Ao(a,i,u,f)}function Ao(a,i,u,f){var g={lane:f,revertLane:0,gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null};if(Zc(a))h_(i,g);else{var b=a.alternate;if(a.lanes===0&&(b===null||b.lanes===0)&&(b=i.lastRenderedReducer,b!==null))try{var O=i.lastRenderedState,C=b(O,u);if(g.hasEagerState=!0,g.eagerState=C,Ln(C,O))return Cc(a,i,g,0),nt===null&&Tc(),!1}catch{}finally{}if(u=Ap(a,i,g,f),u!==null)return Tn(u,a,f),p_(u,i,f),!0}return!1}function fm(a,i,u,f){if(f={lane:2,revertLane:Fm(),gesture:null,action:f,hasEagerState:!1,eagerState:null,next:null},Zc(a)){if(i)throw Error(r(479))}else i=Ap(a,u,f,2),i!==null&&Tn(i,a,2)}function Zc(a){var i=a.alternate;return a===Ce||i!==null&&i===Ce}function h_(a,i){Ql=Fc=!0;var u=a.pending;u===null?i.next=i:(i.next=u.next,u.next=i),a.pending=i}function p_(a,i,u){if((u&4194048)!==0){var f=i.lanes;f&=a.pendingLanes,u|=f,i.lanes=u,b0(a,u)}}var To={readContext:Zt,use:Gc,useCallback:mt,useContext:mt,useEffect:mt,useImperativeHandle:mt,useLayoutEffect:mt,useInsertionEffect:mt,useMemo:mt,useReducer:mt,useRef:mt,useState:mt,useDebugValue:mt,useDeferredValue:mt,useTransition:mt,useSyncExternalStore:mt,useId:mt,useHostTransitionStatus:mt,useFormState:mt,useActionState:mt,useOptimistic:mt,useMemoCache:mt,useCacheRefresh:mt};To.useEffectEvent=mt;var m_={readContext:Zt,use:Gc,useCallback:function(a,i){return vn().memoizedState=[a,i===void 0?null:i],a},useContext:Zt,useEffect:Qj,useImperativeHandle:function(a,i,u){u=u!=null?u.concat([a]):null,Xc(4194308,4,n_.bind(null,i,a),u)},useLayoutEffect:function(a,i){return Xc(4194308,4,a,i)},useInsertionEffect:function(a,i){Xc(4,2,a,i)},useMemo:function(a,i){var u=vn();i=i===void 0?null:i;var f=a();if(Ki){xr(!0);try{a()}finally{xr(!1)}}return u.memoizedState=[f,i],f},useReducer:function(a,i,u){var f=vn();if(u!==void 0){var g=u(i);if(Ki){xr(!0);try{u(i)}finally{xr(!1)}}}else g=i;return f.memoizedState=f.baseState=g,a={pending:null,lanes:0,dispatch:null,lastRenderedReducer:a,lastRenderedState:g},f.queue=a,a=a.dispatch=aR.bind(null,Ce,a),[f.memoizedState,a]},useRef:function(a){var i=vn();return a={current:a},i.memoizedState=a},useState:function(a){a=im(a);var i=a.queue,u=f_.bind(null,Ce,i);return i.dispatch=u,[a.memoizedState,u]},useDebugValue:om,useDeferredValue:function(a,i){var u=vn();return um(u,a,i)},useTransition:function(){var a=im(!1);return a=s_.bind(null,Ce,a.queue,!0,!1),vn().memoizedState=a,[!1,a]},useSyncExternalStore:function(a,i,u){var f=Ce,g=vn();if(Ie){if(u===void 0)throw Error(r(407));u=u()}else{if(u=i(),nt===null)throw Error(r(349));(qe&127)!==0||Lj(f,i,u)}g.memoizedState=u;var b={value:u,getSnapshot:i};return g.queue=b,Qj(qj.bind(null,f,b,a),[a]),f.flags|=2048,es(9,{destroy:void 0},zj.bind(null,f,b,u,i),null),u},useId:function(){var a=vn(),i=nt.identifierPrefix;if(Ie){var u=Mr,f=Pr;u=(f&~(1<<32-un(f)-1)).toString(32)+u,i="_"+i+"R_"+u,u=Kc++,0<\/script>",b=b.removeChild(b.firstChild);break;case"select":b=typeof f.is=="string"?O.createElement("select",{is:f.is}):O.createElement("select"),f.multiple?b.multiple=!0:f.size&&(b.size=f.size);break;default:b=typeof f.is=="string"?O.createElement(g,{is:f.is}):O.createElement(g)}}b[Xt]=i,b[Sn]=f;e:for(O=i.child;O!==null;){if(O.tag===5||O.tag===6)b.appendChild(O.stateNode);else if(O.tag!==4&&O.tag!==27&&O.child!==null){O.child.return=O,O=O.child;continue}if(O===i)break e;for(;O.sibling===null;){if(O.return===null||O.return===i)break e;O=O.return}O.sibling.return=O.return,O=O.sibling}i.stateNode=b;e:switch(Jt(b,g,f),g){case"button":case"input":case"select":case"textarea":f=!!f.autoFocus;break e;case"img":f=!0;break e;default:f=!1}f&&da(i)}}return lt(i),Om(i,i.type,a===null?null:a.memoizedProps,i.pendingProps,u),null;case 6:if(a&&i.stateNode!=null)a.memoizedProps!==f&&da(i);else{if(typeof f!="string"&&i.stateNode===null)throw Error(r(166));if(a=Ee.current,Kl(i)){if(a=i.stateNode,u=i.memoizedProps,f=null,g=Wt,g!==null)switch(g.tag){case 27:case 5:f=g.memoizedProps}a[Xt]=i,a=!!(a.nodeValue===u||f!==null&&f.suppressHydrationWarning===!0||Dw(a.nodeValue,u)),a||Va(i,!0)}else a=gd(a).createTextNode(f),a[Xt]=i,i.stateNode=a}return lt(i),null;case 31:if(u=i.memoizedState,a===null||a.memoizedState!==null){if(f=Kl(i),u!==null){if(a===null){if(!f)throw Error(r(318));if(a=i.memoizedState,a=a!==null?a.dehydrated:null,!a)throw Error(r(557));a[Xt]=i}else qi(),(i.flags&128)===0&&(i.memoizedState=null),i.flags|=4;lt(i),a=!1}else u=Lp(),a!==null&&a.memoizedState!==null&&(a.memoizedState.hydrationErrors=u),a=!0;if(!a)return i.flags&256?(Un(i),i):(Un(i),null);if((i.flags&128)!==0)throw Error(r(558))}return lt(i),null;case 13:if(f=i.memoizedState,a===null||a.memoizedState!==null&&a.memoizedState.dehydrated!==null){if(g=Kl(i),f!==null&&f.dehydrated!==null){if(a===null){if(!g)throw Error(r(318));if(g=i.memoizedState,g=g!==null?g.dehydrated:null,!g)throw Error(r(317));g[Xt]=i}else qi(),(i.flags&128)===0&&(i.memoizedState=null),i.flags|=4;lt(i),g=!1}else g=Lp(),a!==null&&a.memoizedState!==null&&(a.memoizedState.hydrationErrors=g),g=!0;if(!g)return i.flags&256?(Un(i),i):(Un(i),null)}return Un(i),(i.flags&128)!==0?(i.lanes=u,i):(u=f!==null,a=a!==null&&a.memoizedState!==null,u&&(f=i.child,g=null,f.alternate!==null&&f.alternate.memoizedState!==null&&f.alternate.memoizedState.cachePool!==null&&(g=f.alternate.memoizedState.cachePool.pool),b=null,f.memoizedState!==null&&f.memoizedState.cachePool!==null&&(b=f.memoizedState.cachePool.pool),b!==g&&(f.flags|=2048)),u!==a&&u&&(i.child.flags|=8192),nd(i,i.updateQueue),lt(i),null);case 4:return se(),a===null&&Vm(i.stateNode.containerInfo),lt(i),null;case 10:return sa(i.type),lt(i),null;case 19:if(Q(xt),f=i.memoizedState,f===null)return lt(i),null;if(g=(i.flags&128)!==0,b=f.rendering,b===null)if(g)Po(f,!1);else{if(vt!==0||a!==null&&(a.flags&128)!==0)for(a=i.child;a!==null;){if(b=Hc(a),b!==null){for(i.flags|=128,Po(f,!1),a=b.updateQueue,i.updateQueue=a,nd(i,a),i.subtreeFlags=0,a=u,u=i.child;u!==null;)fj(u,a),u=u.sibling;return ue(xt,xt.current&1|2),Ie&&ia(i,f.treeForkCount),i.child}a=a.sibling}f.tail!==null&&sn()>sd&&(i.flags|=128,g=!0,Po(f,!1),i.lanes=4194304)}else{if(!g)if(a=Hc(b),a!==null){if(i.flags|=128,g=!0,a=a.updateQueue,i.updateQueue=a,nd(i,a),Po(f,!0),f.tail===null&&f.tailMode==="hidden"&&!b.alternate&&!Ie)return lt(i),null}else 2*sn()-f.renderingStartTime>sd&&u!==536870912&&(i.flags|=128,g=!0,Po(f,!1),i.lanes=4194304);f.isBackwards?(b.sibling=i.child,i.child=b):(a=f.last,a!==null?a.sibling=b:i.child=b,f.last=b)}return f.tail!==null?(a=f.tail,f.rendering=a,f.tail=a.sibling,f.renderingStartTime=sn(),a.sibling=null,u=xt.current,ue(xt,g?u&1|2:u&1),Ie&&ia(i,f.treeForkCount),a):(lt(i),null);case 22:case 23:return Un(i),Xp(),f=i.memoizedState!==null,a!==null?a.memoizedState!==null!==f&&(i.flags|=8192):f&&(i.flags|=8192),f?(u&536870912)!==0&&(i.flags&128)===0&&(lt(i),i.subtreeFlags&6&&(i.flags|=8192)):lt(i),u=i.updateQueue,u!==null&&nd(i,u.retryQueue),u=null,a!==null&&a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),f=null,i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),f!==u&&(i.flags|=2048),a!==null&&Q(Ii),null;case 24:return u=null,a!==null&&(u=a.memoizedState.cache),i.memoizedState.cache!==u&&(i.flags|=2048),sa(Ot),lt(i),null;case 25:return null;case 30:return null}throw Error(r(156,i.tag))}function uR(a,i){switch(Dp(i),i.tag){case 1:return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 3:return sa(Ot),se(),a=i.flags,(a&65536)!==0&&(a&128)===0?(i.flags=a&-65537|128,i):null;case 26:case 27:case 5:return Me(i),null;case 31:if(i.memoizedState!==null){if(Un(i),i.alternate===null)throw Error(r(340));qi()}return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 13:if(Un(i),a=i.memoizedState,a!==null&&a.dehydrated!==null){if(i.alternate===null)throw Error(r(340));qi()}return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 19:return Q(xt),null;case 4:return se(),null;case 10:return sa(i.type),null;case 22:case 23:return Un(i),Xp(),a!==null&&Q(Ii),a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 24:return sa(Ot),null;case 25:return null;default:return null}}function U_(a,i){switch(Dp(i),i.tag){case 3:sa(Ot),se();break;case 26:case 27:case 5:Me(i);break;case 4:se();break;case 31:i.memoizedState!==null&&Un(i);break;case 13:Un(i);break;case 19:Q(xt);break;case 10:sa(i.type);break;case 22:case 23:Un(i),Xp(),a!==null&&Q(Ii);break;case 24:sa(Ot)}}function Mo(a,i){try{var u=i.updateQueue,f=u!==null?u.lastEffect:null;if(f!==null){var g=f.next;u=g;do{if((u.tag&a)===a){f=void 0;var b=u.create,O=u.inst;f=b(),O.destroy=f}u=u.next}while(u!==g)}}catch(C){We(i,i.return,C)}}function ti(a,i,u){try{var f=i.updateQueue,g=f!==null?f.lastEffect:null;if(g!==null){var b=g.next;f=b;do{if((f.tag&a)===a){var O=f.inst,C=O.destroy;if(C!==void 0){O.destroy=void 0,g=i;var R=u,H=C;try{H()}catch(J){We(g,R,J)}}}f=f.next}while(f!==b)}}catch(J){We(i,i.return,J)}}function $_(a){var i=a.updateQueue;if(i!==null){var u=a.stateNode;try{Tj(i,u)}catch(f){We(a,a.return,f)}}}function I_(a,i,u){u.props=Yi(a.type,a.memoizedProps),u.state=a.memoizedState;try{u.componentWillUnmount()}catch(f){We(a,i,f)}}function Do(a,i){try{var u=a.ref;if(u!==null){switch(a.tag){case 26:case 27:case 5:var f=a.stateNode;break;case 30:f=a.stateNode;break;default:f=a.stateNode}typeof u=="function"?a.refCleanup=u(f):u.current=f}}catch(g){We(a,i,g)}}function Dr(a,i){var u=a.ref,f=a.refCleanup;if(u!==null)if(typeof f=="function")try{f()}catch(g){We(a,i,g)}finally{a.refCleanup=null,a=a.alternate,a!=null&&(a.refCleanup=null)}else if(typeof u=="function")try{u(null)}catch(g){We(a,i,g)}else u.current=null}function B_(a){var i=a.type,u=a.memoizedProps,f=a.stateNode;try{e:switch(i){case"button":case"input":case"select":case"textarea":u.autoFocus&&f.focus();break e;case"img":u.src?f.src=u.src:u.srcSet&&(f.srcset=u.srcSet)}}catch(g){We(a,a.return,g)}}function Em(a,i,u){try{var f=a.stateNode;CR(f,a.type,u,i),f[Sn]=i}catch(g){We(a,a.return,g)}}function H_(a){return a.tag===5||a.tag===3||a.tag===26||a.tag===27&&oi(a.type)||a.tag===4}function km(a){e:for(;;){for(;a.sibling===null;){if(a.return===null||H_(a.return))return null;a=a.return}for(a.sibling.return=a.return,a=a.sibling;a.tag!==5&&a.tag!==6&&a.tag!==18;){if(a.tag===27&&oi(a.type)||a.flags&2||a.child===null||a.tag===4)continue e;a.child.return=a,a=a.child}if(!(a.flags&2))return a.stateNode}}function Am(a,i,u){var f=a.tag;if(f===5||f===6)a=a.stateNode,i?(u.nodeType===9?u.body:u.nodeName==="HTML"?u.ownerDocument.body:u).insertBefore(a,i):(i=u.nodeType===9?u.body:u.nodeName==="HTML"?u.ownerDocument.body:u,i.appendChild(a),u=u._reactRootContainer,u!=null||i.onclick!==null||(i.onclick=na));else if(f!==4&&(f===27&&oi(a.type)&&(u=a.stateNode,i=null),a=a.child,a!==null))for(Am(a,i,u),a=a.sibling;a!==null;)Am(a,i,u),a=a.sibling}function rd(a,i,u){var f=a.tag;if(f===5||f===6)a=a.stateNode,i?u.insertBefore(a,i):u.appendChild(a);else if(f!==4&&(f===27&&oi(a.type)&&(u=a.stateNode),a=a.child,a!==null))for(rd(a,i,u),a=a.sibling;a!==null;)rd(a,i,u),a=a.sibling}function F_(a){var i=a.stateNode,u=a.memoizedProps;try{for(var f=a.type,g=i.attributes;g.length;)i.removeAttributeNode(g[0]);Jt(i,f,u),i[Xt]=a,i[Sn]=u}catch(b){We(a,a.return,b)}}var fa=!1,At=!1,Tm=!1,K_=typeof WeakSet=="function"?WeakSet:Set,$t=null;function cR(a,i){if(a=a.containerInfo,Zm=Sd,a=rj(a),wp(a)){if("selectionStart"in a)var u={start:a.selectionStart,end:a.selectionEnd};else e:{u=(u=a.ownerDocument)&&u.defaultView||window;var f=u.getSelection&&u.getSelection();if(f&&f.rangeCount!==0){u=f.anchorNode;var g=f.anchorOffset,b=f.focusNode;f=f.focusOffset;try{u.nodeType,b.nodeType}catch{u=null;break e}var O=0,C=-1,R=-1,H=0,J=0,ne=a,F=null;t:for(;;){for(var Z;ne!==u||g!==0&&ne.nodeType!==3||(C=O+g),ne!==b||f!==0&&ne.nodeType!==3||(R=O+f),ne.nodeType===3&&(O+=ne.nodeValue.length),(Z=ne.firstChild)!==null;)F=ne,ne=Z;for(;;){if(ne===a)break t;if(F===u&&++H===g&&(C=O),F===b&&++J===f&&(R=O),(Z=ne.nextSibling)!==null)break;ne=F,F=ne.parentNode}ne=Z}u=C===-1||R===-1?null:{start:C,end:R}}else u=null}u=u||{start:0,end:0}}else u=null;for(Qm={focusedElem:a,selectionRange:u},Sd=!1,$t=i;$t!==null;)if(i=$t,a=i.child,(i.subtreeFlags&1028)!==0&&a!==null)a.return=i,$t=a;else for(;$t!==null;){switch(i=$t,b=i.alternate,a=i.flags,i.tag){case 0:if((a&4)!==0&&(a=i.updateQueue,a=a!==null?a.events:null,a!==null))for(u=0;u title"))),Jt(b,f,u),b[Xt]=a,Ut(b),f=b;break e;case"link":var O=Zw("link","href",g).get(f+(u.href||""));if(O){for(var C=0;Cet&&(O=et,et=Oe,Oe=O);var U=tj(C,Oe),q=tj(C,et);if(U&&q&&(Z.rangeCount!==1||Z.anchorNode!==U.node||Z.anchorOffset!==U.offset||Z.focusNode!==q.node||Z.focusOffset!==q.offset)){var B=ne.createRange();B.setStart(U.node,U.offset),Z.removeAllRanges(),Oe>et?(Z.addRange(B),Z.extend(q.node,q.offset)):(B.setEnd(q.node,q.offset),Z.addRange(B))}}}}for(ne=[],Z=C;Z=Z.parentNode;)Z.nodeType===1&&ne.push({element:Z,left:Z.scrollLeft,top:Z.scrollTop});for(typeof C.focus=="function"&&C.focus(),C=0;Cu?32:u,$.T=null,u=zm,zm=null;var b=ii,O=ga;if(Mt=0,is=ii=null,ga=0,(Ve&6)!==0)throw Error(r(331));var C=Ve;if(Ve|=4,nw(b.current),J_(b,b.current,O,u),Ve=C,$o(0,!1),on&&typeof on.onPostCommitFiberRoot=="function")try{on.onPostCommitFiberRoot(Ha,b)}catch{}return!0}finally{X.p=g,$.T=f,xw(a,i)}}function _w(a,i,u){i=nr(u,i),i=vm(a.stateNode,i,2),a=Qa(a,i,2),a!==null&&(jr(a,2),Rr(a))}function We(a,i,u){if(a.tag===3)_w(a,a,u);else for(;i!==null;){if(i.tag===3){_w(i,a,u);break}else if(i.tag===1){var f=i.stateNode;if(typeof i.type.getDerivedStateFromError=="function"||typeof f.componentDidCatch=="function"&&(ai===null||!ai.has(f))){a=nr(u,a),u=w_(2),f=Qa(i,u,2),f!==null&&(S_(u,f,i,a),jr(f,2),Rr(f));break}}i=i.return}}function Im(a,i,u){var f=a.pingCache;if(f===null){f=a.pingCache=new hR;var g=new Set;f.set(i,g)}else g=f.get(i),g===void 0&&(g=new Set,f.set(i,g));g.has(u)||(Mm=!0,g.add(u),a=yR.bind(null,a,i,u),i.then(a,a))}function yR(a,i,u){var f=a.pingCache;f!==null&&f.delete(i),a.pingedLanes|=a.suspendedLanes&u,a.warmLanes&=~u,nt===a&&(qe&u)===u&&(vt===4||vt===3&&(qe&62914560)===qe&&300>sn()-ld?(Ve&2)===0&&ls(a,0):Dm|=u,as===qe&&(as=0)),Rr(a)}function ww(a,i){i===0&&(i=io()),a=Li(a,i),a!==null&&(jr(a,i),Rr(a))}function bR(a){var i=a.memoizedState,u=0;i!==null&&(u=i.retryLane),ww(a,u)}function xR(a,i){var u=0;switch(a.tag){case 31:case 13:var f=a.stateNode,g=a.memoizedState;g!==null&&(u=g.retryLane);break;case 19:f=a.stateNode;break;case 22:f=a.stateNode._retryCache;break;default:throw Error(r(314))}f!==null&&f.delete(i),ww(a,u)}function jR(a,i){return Ol(a,i)}var hd=null,os=null,Bm=!1,pd=!1,Hm=!1,si=0;function Rr(a){a!==os&&a.next===null&&(os===null?hd=os=a:os=os.next=a),pd=!0,Bm||(Bm=!0,wR())}function $o(a,i){if(!Hm&&pd){Hm=!0;do for(var u=!1,f=hd;f!==null;){if(a!==0){var g=f.pendingLanes;if(g===0)var b=0;else{var O=f.suspendedLanes,C=f.pingedLanes;b=(1<<31-un(42|a)+1)-1,b&=g&~(O&~C),b=b&201326741?b&201326741|1:b?b|2:0}b!==0&&(u=!0,Ew(f,b))}else b=qe,b=pt(f,f===nt?b:0,f.cancelPendingCommit!==null||f.timeoutHandle!==-1),(b&3)===0||Vt(f,b)||(u=!0,Ew(f,b));f=f.next}while(u);Hm=!1}}function _R(){Sw()}function Sw(){pd=Bm=!1;var a=0;si!==0&&MR()&&(a=si);for(var i=sn(),u=null,f=hd;f!==null;){var g=f.next,b=Nw(f,i);b===0?(f.next=null,u===null?hd=g:u.next=g,g===null&&(os=u)):(u=f,(a!==0||(b&3)!==0)&&(pd=!0)),f=g}Mt!==0&&Mt!==5||$o(a),si!==0&&(si=0)}function Nw(a,i){for(var u=a.suspendedLanes,f=a.pingedLanes,g=a.expirationTimes,b=a.pendingLanes&-62914561;0C)break;var J=R.transferSize,ne=R.initiatorType;J&&Rw(ne)&&(R=R.responseEnd,O+=J*(R"u"?null:document;function Gw(a,i,u){var f=us;if(f&&typeof i=="string"&&i){var g=er(i);g='link[rel="'+a+'"][href="'+g+'"]',typeof u=="string"&&(g+='[crossorigin="'+u+'"]'),Yw.has(g)||(Yw.add(g),a={rel:a,crossOrigin:u,href:i},f.querySelector(g)===null&&(i=f.createElement("link"),Jt(i,"link",a),Ut(i),f.head.appendChild(i)))}}function BR(a){ya.D(a),Gw("dns-prefetch",a,null)}function HR(a,i){ya.C(a,i),Gw("preconnect",a,i)}function FR(a,i,u){ya.L(a,i,u);var f=us;if(f&&a&&i){var g='link[rel="preload"][as="'+er(i)+'"]';i==="image"&&u&&u.imageSrcSet?(g+='[imagesrcset="'+er(u.imageSrcSet)+'"]',typeof u.imageSizes=="string"&&(g+='[imagesizes="'+er(u.imageSizes)+'"]')):g+='[href="'+er(a)+'"]';var b=g;switch(i){case"style":b=cs(a);break;case"script":b=ds(a)}or.has(b)||(a=m({rel:"preload",href:i==="image"&&u&&u.imageSrcSet?void 0:a,as:i},u),or.set(b,a),f.querySelector(g)!==null||i==="style"&&f.querySelector(Fo(b))||i==="script"&&f.querySelector(Ko(b))||(i=f.createElement("link"),Jt(i,"link",a),Ut(i),f.head.appendChild(i)))}}function KR(a,i){ya.m(a,i);var u=us;if(u&&a){var f=i&&typeof i.as=="string"?i.as:"script",g='link[rel="modulepreload"][as="'+er(f)+'"][href="'+er(a)+'"]',b=g;switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":b=ds(a)}if(!or.has(b)&&(a=m({rel:"modulepreload",href:a},i),or.set(b,a),u.querySelector(g)===null)){switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(u.querySelector(Ko(b)))return}f=u.createElement("link"),Jt(f,"link",a),Ut(f),u.head.appendChild(f)}}}function YR(a,i,u){ya.S(a,i,u);var f=us;if(f&&a){var g=Pl(f).hoistableStyles,b=cs(a);i=i||"default";var O=g.get(b);if(!O){var C={loading:0,preload:null};if(O=f.querySelector(Fo(b)))C.loading=5;else{a=m({rel:"stylesheet",href:a,"data-precedence":i},u),(u=or.get(b))&&iv(a,u);var R=O=f.createElement("link");Ut(R),Jt(R,"link",a),R._p=new Promise(function(H,J){R.onload=H,R.onerror=J}),R.addEventListener("load",function(){C.loading|=1}),R.addEventListener("error",function(){C.loading|=2}),C.loading|=4,bd(O,i,f)}O={type:"stylesheet",instance:O,count:1,state:C},g.set(b,O)}}}function GR(a,i){ya.X(a,i);var u=us;if(u&&a){var f=Pl(u).hoistableScripts,g=ds(a),b=f.get(g);b||(b=u.querySelector(Ko(g)),b||(a=m({src:a,async:!0},i),(i=or.get(g))&&lv(a,i),b=u.createElement("script"),Ut(b),Jt(b,"link",a),u.head.appendChild(b)),b={type:"script",instance:b,count:1,state:null},f.set(g,b))}}function VR(a,i){ya.M(a,i);var u=us;if(u&&a){var f=Pl(u).hoistableScripts,g=ds(a),b=f.get(g);b||(b=u.querySelector(Ko(g)),b||(a=m({src:a,async:!0,type:"module"},i),(i=or.get(g))&&lv(a,i),b=u.createElement("script"),Ut(b),Jt(b,"link",a),u.head.appendChild(b)),b={type:"script",instance:b,count:1,state:null},f.set(g,b))}}function Vw(a,i,u,f){var g=(g=Ee.current)?yd(g):null;if(!g)throw Error(r(446));switch(a){case"meta":case"title":return null;case"style":return typeof u.precedence=="string"&&typeof u.href=="string"?(i=cs(u.href),u=Pl(g).hoistableStyles,f=u.get(i),f||(f={type:"style",instance:null,count:0,state:null},u.set(i,f)),f):{type:"void",instance:null,count:0,state:null};case"link":if(u.rel==="stylesheet"&&typeof u.href=="string"&&typeof u.precedence=="string"){a=cs(u.href);var b=Pl(g).hoistableStyles,O=b.get(a);if(O||(g=g.ownerDocument||g,O={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},b.set(a,O),(b=g.querySelector(Fo(a)))&&!b._p&&(O.instance=b,O.state.loading=5),or.has(a)||(u={rel:"preload",as:"style",href:u.href,crossOrigin:u.crossOrigin,integrity:u.integrity,media:u.media,hrefLang:u.hrefLang,referrerPolicy:u.referrerPolicy},or.set(a,u),b||XR(g,a,u,O.state))),i&&f===null)throw Error(r(528,""));return O}if(i&&f!==null)throw Error(r(529,""));return null;case"script":return i=u.async,u=u.src,typeof u=="string"&&i&&typeof i!="function"&&typeof i!="symbol"?(i=ds(u),u=Pl(g).hoistableScripts,f=u.get(i),f||(f={type:"script",instance:null,count:0,state:null},u.set(i,f)),f):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,a))}}function cs(a){return'href="'+er(a)+'"'}function Fo(a){return'link[rel="stylesheet"]['+a+"]"}function Xw(a){return m({},a,{"data-precedence":a.precedence,precedence:null})}function XR(a,i,u,f){a.querySelector('link[rel="preload"][as="style"]['+i+"]")?f.loading=1:(i=a.createElement("link"),f.preload=i,i.addEventListener("load",function(){return f.loading|=1}),i.addEventListener("error",function(){return f.loading|=2}),Jt(i,"link",u),Ut(i),a.head.appendChild(i))}function ds(a){return'[src="'+er(a)+'"]'}function Ko(a){return"script[async]"+a}function Ww(a,i,u){if(i.count++,i.instance===null)switch(i.type){case"style":var f=a.querySelector('style[data-href~="'+er(u.href)+'"]');if(f)return i.instance=f,Ut(f),f;var g=m({},u,{"data-href":u.href,"data-precedence":u.precedence,href:null,precedence:null});return f=(a.ownerDocument||a).createElement("style"),Ut(f),Jt(f,"style",g),bd(f,u.precedence,a),i.instance=f;case"stylesheet":g=cs(u.href);var b=a.querySelector(Fo(g));if(b)return i.state.loading|=4,i.instance=b,Ut(b),b;f=Xw(u),(g=or.get(g))&&iv(f,g),b=(a.ownerDocument||a).createElement("link"),Ut(b);var O=b;return O._p=new Promise(function(C,R){O.onload=C,O.onerror=R}),Jt(b,"link",f),i.state.loading|=4,bd(b,u.precedence,a),i.instance=b;case"script":return b=ds(u.src),(g=a.querySelector(Ko(b)))?(i.instance=g,Ut(g),g):(f=u,(g=or.get(b))&&(f=m({},u),lv(f,g)),a=a.ownerDocument||a,g=a.createElement("script"),Ut(g),Jt(g,"link",f),a.head.appendChild(g),i.instance=g);case"void":return null;default:throw Error(r(443,i.type))}else i.type==="stylesheet"&&(i.state.loading&4)===0&&(f=i.instance,i.state.loading|=4,bd(f,u.precedence,a));return i.instance}function bd(a,i,u){for(var f=u.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),g=f.length?f[f.length-1]:null,b=g,O=0;O title"):null)}function WR(a,i,u){if(u===1||i.itemProp!=null)return!1;switch(a){case"meta":case"title":return!0;case"style":if(typeof i.precedence!="string"||typeof i.href!="string"||i.href==="")break;return!0;case"link":if(typeof i.rel!="string"||typeof i.href!="string"||i.href===""||i.onLoad||i.onError)break;switch(i.rel){case"stylesheet":return a=i.disabled,typeof i.precedence=="string"&&a==null;default:return!0}case"script":if(i.async&&typeof i.async!="function"&&typeof i.async!="symbol"&&!i.onLoad&&!i.onError&&i.src&&typeof i.src=="string")return!0}return!1}function Jw(a){return!(a.type==="stylesheet"&&(a.state.loading&3)===0)}function ZR(a,i,u,f){if(u.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&(u.state.loading&4)===0){if(u.instance===null){var g=cs(f.href),b=i.querySelector(Fo(g));if(b){i=b._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(a.count++,a=jd.bind(a),i.then(a,a)),u.state.loading|=4,u.instance=b,Ut(b);return}b=i.ownerDocument||i,f=Xw(f),(g=or.get(g))&&iv(f,g),b=b.createElement("link"),Ut(b);var O=b;O._p=new Promise(function(C,R){O.onload=C,O.onerror=R}),Jt(b,"link",f),u.instance=b}a.stylesheets===null&&(a.stylesheets=new Map),a.stylesheets.set(u,i),(i=u.state.preload)&&(u.state.loading&3)===0&&(a.count++,u=jd.bind(a),i.addEventListener("load",u),i.addEventListener("error",u))}}var sv=0;function QR(a,i){return a.stylesheets&&a.count===0&&wd(a,a.stylesheets),0sv?50:800)+i);return a.unsuspend=u,function(){a.unsuspend=null,clearTimeout(f),clearTimeout(g)}}:null}function jd(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)wd(this,this.stylesheets);else if(this.unsuspend){var a=this.unsuspend;this.unsuspend=null,a()}}}var _d=null;function wd(a,i){a.stylesheets=null,a.unsuspend!==null&&(a.count++,_d=new Map,i.forEach(JR,a),_d=null,jd.call(a))}function JR(a,i){if(!(i.state.loading&4)){var u=_d.get(a);if(u)var f=u.get(null);else{u=new Map,_d.set(a,u);for(var g=a.querySelectorAll("link[data-precedence],style[data-precedence]"),b=0;b"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),gv.exports=yL(),gv.exports}var xL=bL();const jL=Ma(xL);/** +`+f.stack}}var Nl=Object.prototype.hasOwnProperty,Ol=e.unstable_scheduleCallback,El=e.unstable_cancelCallback,du=e.unstable_shouldYield,fu=e.unstable_requestPaint,sn=e.unstable_now,hu=e.unstable_getCurrentPriorityLevel,no=e.unstable_ImmediatePriority,ro=e.unstable_UserBlockingPriority,ki=e.unstable_NormalPriority,pu=e.unstable_LowPriority,ao=e.unstable_IdlePriority,mu=e.log,vu=e.unstable_setDisableYieldValue,Ha=null,on=null;function xr(a){if(typeof mu=="function"&&vu(a),on&&typeof on.setStrictMode=="function")try{on.setStrictMode(Ha,a)}catch{}}var cn=Math.clz32?Math.clz32:bu,gu=Math.log,yu=Math.LN2;function bu(a){return a>>>=0,a===0?32:31-(gu(a)/yu|0)|0}var Ai=256,Ti=262144,Ci=4194304;function Ae(a){var i=a&42;if(i!==0)return i;switch(a&-a){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 a&261888;case 262144:case 524288:case 1048576:case 2097152:return a&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return a&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return a}}function pt(a,i,c){var f=a.pendingLanes;if(f===0)return 0;var g=0,b=a.suspendedLanes,O=a.pingedLanes;a=a.warmLanes;var C=f&134217727;return C!==0?(f=C&~b,f!==0?g=Ae(f):(O&=C,O!==0?g=Ae(O):c||(c=C&~a,c!==0&&(g=Ae(c))))):(C=f&~b,C!==0?g=Ae(C):O!==0?g=Ae(O):c||(c=f&~a,c!==0&&(g=Ae(c)))),g===0?0:i!==0&&i!==g&&(i&b)===0&&(b=g&-g,c=i&-i,b>=c||b===32&&(c&4194048)!==0)?i:g}function Vt(a,i){return(a.pendingLanes&~(a.suspendedLanes&~a.pingedLanes)&i)===0}function xu(a,i){switch(a){case 1:case 2:case 4:case 8:case 64:return i+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 i+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 io(){var a=Ci;return Ci<<=1,(Ci&62914560)===0&&(Ci=4194304),a}function kl(a){for(var i=[],c=0;31>c;c++)i.push(a);return i}function jr(a,i){a.pendingLanes|=i,i!==268435456&&(a.suspendedLanes=0,a.pingedLanes=0,a.warmLanes=0)}function np(a,i,c,f,g,b){var O=a.pendingLanes;a.pendingLanes=c,a.suspendedLanes=0,a.pingedLanes=0,a.warmLanes=0,a.expiredLanes&=c,a.entangledLanes&=c,a.errorRecoveryDisabledLanes&=c,a.shellSuspendCounter=0;var C=a.entanglements,R=a.expirationTimes,H=a.hiddenUpdates;for(c=O&~c;0"u")return null;try{return a.activeElement||a.body}catch{return a.body}}var nD=/[\n"\\]/g;function er(a){return a.replace(nD,function(i){return"\\"+i.charCodeAt(0).toString(16)+" "})}function op(a,i,c,f,g,b,O,C){a.name="",O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"?a.type=O:a.removeAttribute("type"),i!=null?O==="number"?(i===0&&a.value===""||a.value!=i)&&(a.value=""+Jn(i)):a.value!==""+Jn(i)&&(a.value=""+Jn(i)):O!=="submit"&&O!=="reset"||a.removeAttribute("value"),i!=null?cp(a,O,Jn(i)):c!=null?cp(a,O,Jn(c)):f!=null&&a.removeAttribute("value"),g==null&&b!=null&&(a.defaultChecked=!!b),g!=null&&(a.checked=g&&typeof g!="function"&&typeof g!="symbol"),C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?a.name=""+Jn(C):a.removeAttribute("name")}function T0(a,i,c,f,g,b,O,C){if(b!=null&&typeof b!="function"&&typeof b!="symbol"&&typeof b!="boolean"&&(a.type=b),i!=null||c!=null){if(!(b!=="submit"&&b!=="reset"||i!=null)){sp(a);return}c=c!=null?""+Jn(c):"",i=i!=null?""+Jn(i):c,C||i===a.value||(a.value=i),a.defaultValue=i}f=f??g,f=typeof f!="function"&&typeof f!="symbol"&&!!f,a.checked=C?a.checked:!!f,a.defaultChecked=!!f,O!=null&&typeof O!="function"&&typeof O!="symbol"&&typeof O!="boolean"&&(a.name=O),sp(a)}function cp(a,i,c){i==="number"&&wu(a.ownerDocument)===a||a.defaultValue===""+c||(a.defaultValue=""+c)}function Dl(a,i,c,f){if(a=a.options,i){i={};for(var g=0;g"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),pp=!1;if(ra)try{var co={};Object.defineProperty(co,"passive",{get:function(){pp=!0}}),window.addEventListener("test",co,co),window.removeEventListener("test",co,co)}catch{pp=!1}var Ka=null,mp=null,Nu=null;function z0(){if(Nu)return Nu;var a,i=mp,c=i.length,f,g="value"in Ka?Ka.value:Ka.textContent,b=g.length;for(a=0;a=ho),H0=" ",F0=!1;function K0(a,i){switch(a){case"keyup":return TD.indexOf(i.keyCode)!==-1;case"keydown":return i.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Y0(a){return a=a.detail,typeof a=="object"&&"data"in a?a.data:null}var ql=!1;function PD(a,i){switch(a){case"compositionend":return Y0(i);case"keypress":return i.which!==32?null:(F0=!0,H0);case"textInput":return a=i.data,a===H0&&F0?null:a;default:return null}}function MD(a,i){if(ql)return a==="compositionend"||!xp&&K0(a,i)?(a=z0(),Nu=mp=Ka=null,ql=!1,a):null;switch(a){case"paste":return null;case"keypress":if(!(i.ctrlKey||i.altKey||i.metaKey)||i.ctrlKey&&i.altKey){if(i.char&&1=i)return{node:c,offset:i-a};a=f}e:{for(;c;){if(c.nextSibling){c=c.nextSibling;break e}c=c.parentNode}c=void 0}c=ej(c)}}function nj(a,i){return a&&i?a===i?!0:a&&a.nodeType===3?!1:i&&i.nodeType===3?nj(a,i.parentNode):"contains"in a?a.contains(i):a.compareDocumentPosition?!!(a.compareDocumentPosition(i)&16):!1:!1}function rj(a){a=a!=null&&a.ownerDocument!=null&&a.ownerDocument.defaultView!=null?a.ownerDocument.defaultView:window;for(var i=wu(a.document);i instanceof a.HTMLIFrameElement;){try{var c=typeof i.contentWindow.location.href=="string"}catch{c=!1}if(c)a=i.contentWindow;else break;i=wu(a.document)}return i}function wp(a){var i=a&&a.nodeName&&a.nodeName.toLowerCase();return i&&(i==="input"&&(a.type==="text"||a.type==="search"||a.type==="tel"||a.type==="url"||a.type==="password")||i==="textarea"||a.contentEditable==="true")}var ID=ra&&"documentMode"in document&&11>=document.documentMode,Ul=null,Sp=null,go=null,Np=!1;function aj(a,i,c){var f=c.window===c?c.document:c.nodeType===9?c:c.ownerDocument;Np||Ul==null||Ul!==wu(f)||(f=Ul,"selectionStart"in f&&wp(f)?f={start:f.selectionStart,end:f.selectionEnd}:(f=(f.ownerDocument&&f.ownerDocument.defaultView||window).getSelection(),f={anchorNode:f.anchorNode,anchorOffset:f.anchorOffset,focusNode:f.focusNode,focusOffset:f.focusOffset}),go&&vo(go,f)||(go=f,f=yd(Sp,"onSelect"),0>=O,g-=O,Pr=1<<32-cn(i)+g|c<De?(Ue=je,je=null):Ue=je.sibling;var Ke=F(U,je,B[De],te);if(Ke===null){je===null&&(je=Ue);break}a&&je&&Ke.alternate===null&&i(U,je),q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke,je=Ue}if(De===B.length)return c(U,je),Ie&&ia(U,De),Se;if(je===null){for(;DeDe?(Ue=je,je=null):Ue=je.sibling;var hi=F(U,je,Ke.value,te);if(hi===null){je===null&&(je=Ue);break}a&&je&&hi.alternate===null&&i(U,je),q=b(hi,q,De),Fe===null?Se=hi:Fe.sibling=hi,Fe=hi,je=Ue}if(Ke.done)return c(U,je),Ie&&ia(U,De),Se;if(je===null){for(;!Ke.done;De++,Ke=B.next())Ke=ne(U,Ke.value,te),Ke!==null&&(q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke);return Ie&&ia(U,De),Se}for(je=f(je);!Ke.done;De++,Ke=B.next())Ke=Z(je,U,De,Ke.value,te),Ke!==null&&(a&&Ke.alternate!==null&&je.delete(Ke.key===null?De:Ke.key),q=b(Ke,q,De),Fe===null?Se=Ke:Fe.sibling=Ke,Fe=Ke);return a&&je.forEach(function(sL){return i(U,sL)}),Ie&&ia(U,De),Se}function et(U,q,B,te){if(typeof B=="object"&&B!==null&&B.type===w&&B.key===null&&(B=B.props.children),typeof B=="object"&&B!==null){switch(B.$$typeof){case x:e:{for(var Se=B.key;q!==null;){if(q.key===Se){if(Se=B.type,Se===w){if(q.tag===7){c(U,q.sibling),te=g(q,B.props.children),te.return=U,U=te;break e}}else if(q.elementType===Se||typeof Se=="object"&&Se!==null&&Se.$$typeof===L&&Bi(Se)===q.type){c(U,q.sibling),te=g(q,B.props),wo(te,B),te.return=U,U=te;break e}c(U,q);break}else i(U,q);q=q.sibling}B.type===w?(te=zi(B.props.children,U.mode,te,B.key),te.return=U,U=te):(te=Ru(B.type,B.key,B.props,null,U.mode,te),wo(te,B),te.return=U,U=te)}return O(U);case _:e:{for(Se=B.key;q!==null;){if(q.key===Se)if(q.tag===4&&q.stateNode.containerInfo===B.containerInfo&&q.stateNode.implementation===B.implementation){c(U,q.sibling),te=g(q,B.children||[]),te.return=U,U=te;break e}else{c(U,q);break}else i(U,q);q=q.sibling}te=Pp(B,U.mode,te),te.return=U,U=te}return O(U);case L:return B=Bi(B),et(U,q,B,te)}if(ge(B))return be(U,q,B,te);if(I(B)){if(Se=I(B),typeof Se!="function")throw Error(r(150));return B=Se.call(B),Oe(U,q,B,te)}if(typeof B.then=="function")return et(U,q,Bu(B),te);if(B.$$typeof===A)return et(U,q,qu(U,B),te);Hu(U,B)}return typeof B=="string"&&B!==""||typeof B=="number"||typeof B=="bigint"?(B=""+B,q!==null&&q.tag===6?(c(U,q.sibling),te=g(q,B),te.return=U,U=te):(c(U,q),te=Cp(B,U.mode,te),te.return=U,U=te),O(U)):c(U,q)}return function(U,q,B,te){try{_o=0;var Se=et(U,q,B,te);return Wl=null,Se}catch(je){if(je===Xl||je===$u)throw je;var Fe=zn(29,je,null,U.mode);return Fe.lanes=te,Fe.return=U,Fe}finally{}}}var Fi=Ej(!0),kj=Ej(!1),Wa=!1;function Fp(a){a.updateQueue={baseState:a.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Kp(a,i){a=a.updateQueue,i.updateQueue===a&&(i.updateQueue={baseState:a.baseState,firstBaseUpdate:a.firstBaseUpdate,lastBaseUpdate:a.lastBaseUpdate,shared:a.shared,callbacks:null})}function Za(a){return{lane:a,tag:0,payload:null,callback:null,next:null}}function Qa(a,i,c){var f=a.updateQueue;if(f===null)return null;if(f=f.shared,(Ve&2)!==0){var g=f.pending;return g===null?i.next=i:(i.next=g.next,g.next=i),f.pending=i,i=Du(a),dj(a,null,c),i}return Mu(a,f,i,c),Du(a)}function So(a,i,c){if(i=i.updateQueue,i!==null&&(i=i.shared,(c&4194048)!==0)){var f=i.lanes;f&=a.pendingLanes,c|=f,i.lanes=c,b0(a,c)}}function Yp(a,i){var c=a.updateQueue,f=a.alternate;if(f!==null&&(f=f.updateQueue,c===f)){var g=null,b=null;if(c=c.firstBaseUpdate,c!==null){do{var O={lane:c.lane,tag:c.tag,payload:c.payload,callback:null,next:null};b===null?g=b=O:b=b.next=O,c=c.next}while(c!==null);b===null?g=b=i:b=b.next=i}else g=b=i;c={baseState:f.baseState,firstBaseUpdate:g,lastBaseUpdate:b,shared:f.shared,callbacks:f.callbacks},a.updateQueue=c;return}a=c.lastBaseUpdate,a===null?c.firstBaseUpdate=i:a.next=i,c.lastBaseUpdate=i}var Gp=!1;function No(){if(Gp){var a=Vl;if(a!==null)throw a}}function Oo(a,i,c,f){Gp=!1;var g=a.updateQueue;Wa=!1;var b=g.firstBaseUpdate,O=g.lastBaseUpdate,C=g.shared.pending;if(C!==null){g.shared.pending=null;var R=C,H=R.next;R.next=null,O===null?b=H:O.next=H,O=R;var J=a.alternate;J!==null&&(J=J.updateQueue,C=J.lastBaseUpdate,C!==O&&(C===null?J.firstBaseUpdate=H:C.next=H,J.lastBaseUpdate=R))}if(b!==null){var ne=g.baseState;O=0,J=H=R=null,C=b;do{var F=C.lane&-536870913,Z=F!==C.lane;if(Z?(qe&F)===F:(f&F)===F){F!==0&&F===Gl&&(Gp=!0),J!==null&&(J=J.next={lane:0,tag:C.tag,payload:C.payload,callback:null,next:null});e:{var be=a,Oe=C;F=i;var et=c;switch(Oe.tag){case 1:if(be=Oe.payload,typeof be=="function"){ne=be.call(et,ne,F);break e}ne=be;break e;case 3:be.flags=be.flags&-65537|128;case 0:if(be=Oe.payload,F=typeof be=="function"?be.call(et,ne,F):be,F==null)break e;ne=m({},ne,F);break e;case 2:Wa=!0}}F=C.callback,F!==null&&(a.flags|=64,Z&&(a.flags|=8192),Z=g.callbacks,Z===null?g.callbacks=[F]:Z.push(F))}else Z={lane:F,tag:C.tag,payload:C.payload,callback:C.callback,next:null},J===null?(H=J=Z,R=ne):J=J.next=Z,O|=F;if(C=C.next,C===null){if(C=g.shared.pending,C===null)break;Z=C,C=Z.next,Z.next=null,g.lastBaseUpdate=Z,g.shared.pending=null}}while(!0);J===null&&(R=ne),g.baseState=R,g.firstBaseUpdate=H,g.lastBaseUpdate=J,b===null&&(g.shared.lanes=0),ri|=O,a.lanes=O,a.memoizedState=ne}}function Aj(a,i){if(typeof a!="function")throw Error(r(191,a));a.call(i)}function Tj(a,i){var c=a.callbacks;if(c!==null)for(a.callbacks=null,a=0;ab?b:8;var O=$.T,C={};$.T=C,fm(a,!1,i,c);try{var R=g(),H=$.S;if(H!==null&&H(C,R),R!==null&&typeof R=="object"&&typeof R.then=="function"){var J=WD(R,f);Ao(a,i,J,Bn(a))}else Ao(a,i,f,Bn(a))}catch(ne){Ao(a,i,{then:function(){},status:"rejected",reason:ne},Bn())}finally{X.p=b,O!==null&&C.types!==null&&(O.types=C.types),$.T=O}}function nR(){}function um(a,i,c,f){if(a.tag!==5)throw Error(r(476));var g=o_(a).queue;s_(a,g,i,Y,c===null?nR:function(){return c_(a),c(f)})}function o_(a){var i=a.memoizedState;if(i!==null)return i;i={memoizedState:Y,baseState:Y,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ca,lastRenderedState:Y},next:null};var c={};return i.next={memoizedState:c,baseState:c,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ca,lastRenderedState:c},next:null},a.memoizedState=i,a=a.alternate,a!==null&&(a.memoizedState=i),i}function c_(a){var i=o_(a);i.next===null&&(i=a.alternate.memoizedState),Ao(a,i.next.queue,{},Bn())}function dm(){return Zt(Yo)}function u_(){return jt().memoizedState}function d_(){return jt().memoizedState}function rR(a){for(var i=a.return;i!==null;){switch(i.tag){case 24:case 3:var c=Bn();a=Za(c);var f=Qa(i,a,c);f!==null&&(Tn(f,i,c),So(f,i,c)),i={cache:$p()},a.payload=i;return}i=i.return}}function aR(a,i,c){var f=Bn();c={lane:f,revertLane:0,gesture:null,action:c,hasEagerState:!1,eagerState:null,next:null},Ju(a)?h_(i,c):(c=Ap(a,i,c,f),c!==null&&(Tn(c,a,f),p_(c,i,f)))}function f_(a,i,c){var f=Bn();Ao(a,i,c,f)}function Ao(a,i,c,f){var g={lane:f,revertLane:0,gesture:null,action:c,hasEagerState:!1,eagerState:null,next:null};if(Ju(a))h_(i,g);else{var b=a.alternate;if(a.lanes===0&&(b===null||b.lanes===0)&&(b=i.lastRenderedReducer,b!==null))try{var O=i.lastRenderedState,C=b(O,c);if(g.hasEagerState=!0,g.eagerState=C,Ln(C,O))return Mu(a,i,g,0),nt===null&&Pu(),!1}catch{}finally{}if(c=Ap(a,i,g,f),c!==null)return Tn(c,a,f),p_(c,i,f),!0}return!1}function fm(a,i,c,f){if(f={lane:2,revertLane:Fm(),gesture:null,action:f,hasEagerState:!1,eagerState:null,next:null},Ju(a)){if(i)throw Error(r(479))}else i=Ap(a,c,f,2),i!==null&&Tn(i,a,2)}function Ju(a){var i=a.alternate;return a===Ce||i!==null&&i===Ce}function h_(a,i){Ql=Yu=!0;var c=a.pending;c===null?i.next=i:(i.next=c.next,c.next=i),a.pending=i}function p_(a,i,c){if((c&4194048)!==0){var f=i.lanes;f&=a.pendingLanes,c|=f,i.lanes=c,b0(a,c)}}var To={readContext:Zt,use:Xu,useCallback:mt,useContext:mt,useEffect:mt,useImperativeHandle:mt,useLayoutEffect:mt,useInsertionEffect:mt,useMemo:mt,useReducer:mt,useRef:mt,useState:mt,useDebugValue:mt,useDeferredValue:mt,useTransition:mt,useSyncExternalStore:mt,useId:mt,useHostTransitionStatus:mt,useFormState:mt,useActionState:mt,useOptimistic:mt,useMemoCache:mt,useCacheRefresh:mt};To.useEffectEvent=mt;var m_={readContext:Zt,use:Xu,useCallback:function(a,i){return vn().memoizedState=[a,i===void 0?null:i],a},useContext:Zt,useEffect:Qj,useImperativeHandle:function(a,i,c){c=c!=null?c.concat([a]):null,Zu(4194308,4,n_.bind(null,i,a),c)},useLayoutEffect:function(a,i){return Zu(4194308,4,a,i)},useInsertionEffect:function(a,i){Zu(4,2,a,i)},useMemo:function(a,i){var c=vn();i=i===void 0?null:i;var f=a();if(Ki){xr(!0);try{a()}finally{xr(!1)}}return c.memoizedState=[f,i],f},useReducer:function(a,i,c){var f=vn();if(c!==void 0){var g=c(i);if(Ki){xr(!0);try{c(i)}finally{xr(!1)}}}else g=i;return f.memoizedState=f.baseState=g,a={pending:null,lanes:0,dispatch:null,lastRenderedReducer:a,lastRenderedState:g},f.queue=a,a=a.dispatch=aR.bind(null,Ce,a),[f.memoizedState,a]},useRef:function(a){var i=vn();return a={current:a},i.memoizedState=a},useState:function(a){a=im(a);var i=a.queue,c=f_.bind(null,Ce,i);return i.dispatch=c,[a.memoizedState,c]},useDebugValue:om,useDeferredValue:function(a,i){var c=vn();return cm(c,a,i)},useTransition:function(){var a=im(!1);return a=s_.bind(null,Ce,a.queue,!0,!1),vn().memoizedState=a,[!1,a]},useSyncExternalStore:function(a,i,c){var f=Ce,g=vn();if(Ie){if(c===void 0)throw Error(r(407));c=c()}else{if(c=i(),nt===null)throw Error(r(349));(qe&127)!==0||Lj(f,i,c)}g.memoizedState=c;var b={value:c,getSnapshot:i};return g.queue=b,Qj(qj.bind(null,f,b,a),[a]),f.flags|=2048,es(9,{destroy:void 0},zj.bind(null,f,b,c,i),null),c},useId:function(){var a=vn(),i=nt.identifierPrefix;if(Ie){var c=Mr,f=Pr;c=(f&~(1<<32-cn(f)-1)).toString(32)+c,i="_"+i+"R_"+c,c=Gu++,0<\/script>",b=b.removeChild(b.firstChild);break;case"select":b=typeof f.is=="string"?O.createElement("select",{is:f.is}):O.createElement("select"),f.multiple?b.multiple=!0:f.size&&(b.size=f.size);break;default:b=typeof f.is=="string"?O.createElement(g,{is:f.is}):O.createElement(g)}}b[Xt]=i,b[Sn]=f;e:for(O=i.child;O!==null;){if(O.tag===5||O.tag===6)b.appendChild(O.stateNode);else if(O.tag!==4&&O.tag!==27&&O.child!==null){O.child.return=O,O=O.child;continue}if(O===i)break e;for(;O.sibling===null;){if(O.return===null||O.return===i)break e;O=O.return}O.sibling.return=O.return,O=O.sibling}i.stateNode=b;e:switch(Jt(b,g,f),g){case"button":case"input":case"select":case"textarea":f=!!f.autoFocus;break e;case"img":f=!0;break e;default:f=!1}f&&da(i)}}return lt(i),Om(i,i.type,a===null?null:a.memoizedProps,i.pendingProps,c),null;case 6:if(a&&i.stateNode!=null)a.memoizedProps!==f&&da(i);else{if(typeof f!="string"&&i.stateNode===null)throw Error(r(166));if(a=Ee.current,Kl(i)){if(a=i.stateNode,c=i.memoizedProps,f=null,g=Wt,g!==null)switch(g.tag){case 27:case 5:f=g.memoizedProps}a[Xt]=i,a=!!(a.nodeValue===c||f!==null&&f.suppressHydrationWarning===!0||Dw(a.nodeValue,c)),a||Va(i,!0)}else a=bd(a).createTextNode(f),a[Xt]=i,i.stateNode=a}return lt(i),null;case 31:if(c=i.memoizedState,a===null||a.memoizedState!==null){if(f=Kl(i),c!==null){if(a===null){if(!f)throw Error(r(318));if(a=i.memoizedState,a=a!==null?a.dehydrated:null,!a)throw Error(r(557));a[Xt]=i}else qi(),(i.flags&128)===0&&(i.memoizedState=null),i.flags|=4;lt(i),a=!1}else c=Lp(),a!==null&&a.memoizedState!==null&&(a.memoizedState.hydrationErrors=c),a=!0;if(!a)return i.flags&256?(Un(i),i):(Un(i),null);if((i.flags&128)!==0)throw Error(r(558))}return lt(i),null;case 13:if(f=i.memoizedState,a===null||a.memoizedState!==null&&a.memoizedState.dehydrated!==null){if(g=Kl(i),f!==null&&f.dehydrated!==null){if(a===null){if(!g)throw Error(r(318));if(g=i.memoizedState,g=g!==null?g.dehydrated:null,!g)throw Error(r(317));g[Xt]=i}else qi(),(i.flags&128)===0&&(i.memoizedState=null),i.flags|=4;lt(i),g=!1}else g=Lp(),a!==null&&a.memoizedState!==null&&(a.memoizedState.hydrationErrors=g),g=!0;if(!g)return i.flags&256?(Un(i),i):(Un(i),null)}return Un(i),(i.flags&128)!==0?(i.lanes=c,i):(c=f!==null,a=a!==null&&a.memoizedState!==null,c&&(f=i.child,g=null,f.alternate!==null&&f.alternate.memoizedState!==null&&f.alternate.memoizedState.cachePool!==null&&(g=f.alternate.memoizedState.cachePool.pool),b=null,f.memoizedState!==null&&f.memoizedState.cachePool!==null&&(b=f.memoizedState.cachePool.pool),b!==g&&(f.flags|=2048)),c!==a&&c&&(i.child.flags|=8192),ad(i,i.updateQueue),lt(i),null);case 4:return se(),a===null&&Vm(i.stateNode.containerInfo),lt(i),null;case 10:return sa(i.type),lt(i),null;case 19:if(Q(xt),f=i.memoizedState,f===null)return lt(i),null;if(g=(i.flags&128)!==0,b=f.rendering,b===null)if(g)Po(f,!1);else{if(vt!==0||a!==null&&(a.flags&128)!==0)for(a=i.child;a!==null;){if(b=Ku(a),b!==null){for(i.flags|=128,Po(f,!1),a=b.updateQueue,i.updateQueue=a,ad(i,a),i.subtreeFlags=0,a=c,c=i.child;c!==null;)fj(c,a),c=c.sibling;return ce(xt,xt.current&1|2),Ie&&ia(i,f.treeForkCount),i.child}a=a.sibling}f.tail!==null&&sn()>cd&&(i.flags|=128,g=!0,Po(f,!1),i.lanes=4194304)}else{if(!g)if(a=Ku(b),a!==null){if(i.flags|=128,g=!0,a=a.updateQueue,i.updateQueue=a,ad(i,a),Po(f,!0),f.tail===null&&f.tailMode==="hidden"&&!b.alternate&&!Ie)return lt(i),null}else 2*sn()-f.renderingStartTime>cd&&c!==536870912&&(i.flags|=128,g=!0,Po(f,!1),i.lanes=4194304);f.isBackwards?(b.sibling=i.child,i.child=b):(a=f.last,a!==null?a.sibling=b:i.child=b,f.last=b)}return f.tail!==null?(a=f.tail,f.rendering=a,f.tail=a.sibling,f.renderingStartTime=sn(),a.sibling=null,c=xt.current,ce(xt,g?c&1|2:c&1),Ie&&ia(i,f.treeForkCount),a):(lt(i),null);case 22:case 23:return Un(i),Xp(),f=i.memoizedState!==null,a!==null?a.memoizedState!==null!==f&&(i.flags|=8192):f&&(i.flags|=8192),f?(c&536870912)!==0&&(i.flags&128)===0&&(lt(i),i.subtreeFlags&6&&(i.flags|=8192)):lt(i),c=i.updateQueue,c!==null&&ad(i,c.retryQueue),c=null,a!==null&&a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(c=a.memoizedState.cachePool.pool),f=null,i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),f!==c&&(i.flags|=2048),a!==null&&Q(Ii),null;case 24:return c=null,a!==null&&(c=a.memoizedState.cache),i.memoizedState.cache!==c&&(i.flags|=2048),sa(Ot),lt(i),null;case 25:return null;case 30:return null}throw Error(r(156,i.tag))}function cR(a,i){switch(Dp(i),i.tag){case 1:return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 3:return sa(Ot),se(),a=i.flags,(a&65536)!==0&&(a&128)===0?(i.flags=a&-65537|128,i):null;case 26:case 27:case 5:return Me(i),null;case 31:if(i.memoizedState!==null){if(Un(i),i.alternate===null)throw Error(r(340));qi()}return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 13:if(Un(i),a=i.memoizedState,a!==null&&a.dehydrated!==null){if(i.alternate===null)throw Error(r(340));qi()}return a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 19:return Q(xt),null;case 4:return se(),null;case 10:return sa(i.type),null;case 22:case 23:return Un(i),Xp(),a!==null&&Q(Ii),a=i.flags,a&65536?(i.flags=a&-65537|128,i):null;case 24:return sa(Ot),null;case 25:return null;default:return null}}function U_(a,i){switch(Dp(i),i.tag){case 3:sa(Ot),se();break;case 26:case 27:case 5:Me(i);break;case 4:se();break;case 31:i.memoizedState!==null&&Un(i);break;case 13:Un(i);break;case 19:Q(xt);break;case 10:sa(i.type);break;case 22:case 23:Un(i),Xp(),a!==null&&Q(Ii);break;case 24:sa(Ot)}}function Mo(a,i){try{var c=i.updateQueue,f=c!==null?c.lastEffect:null;if(f!==null){var g=f.next;c=g;do{if((c.tag&a)===a){f=void 0;var b=c.create,O=c.inst;f=b(),O.destroy=f}c=c.next}while(c!==g)}}catch(C){We(i,i.return,C)}}function ti(a,i,c){try{var f=i.updateQueue,g=f!==null?f.lastEffect:null;if(g!==null){var b=g.next;f=b;do{if((f.tag&a)===a){var O=f.inst,C=O.destroy;if(C!==void 0){O.destroy=void 0,g=i;var R=c,H=C;try{H()}catch(J){We(g,R,J)}}}f=f.next}while(f!==b)}}catch(J){We(i,i.return,J)}}function $_(a){var i=a.updateQueue;if(i!==null){var c=a.stateNode;try{Tj(i,c)}catch(f){We(a,a.return,f)}}}function I_(a,i,c){c.props=Yi(a.type,a.memoizedProps),c.state=a.memoizedState;try{c.componentWillUnmount()}catch(f){We(a,i,f)}}function Do(a,i){try{var c=a.ref;if(c!==null){switch(a.tag){case 26:case 27:case 5:var f=a.stateNode;break;case 30:f=a.stateNode;break;default:f=a.stateNode}typeof c=="function"?a.refCleanup=c(f):c.current=f}}catch(g){We(a,i,g)}}function Dr(a,i){var c=a.ref,f=a.refCleanup;if(c!==null)if(typeof f=="function")try{f()}catch(g){We(a,i,g)}finally{a.refCleanup=null,a=a.alternate,a!=null&&(a.refCleanup=null)}else if(typeof c=="function")try{c(null)}catch(g){We(a,i,g)}else c.current=null}function B_(a){var i=a.type,c=a.memoizedProps,f=a.stateNode;try{e:switch(i){case"button":case"input":case"select":case"textarea":c.autoFocus&&f.focus();break e;case"img":c.src?f.src=c.src:c.srcSet&&(f.srcset=c.srcSet)}}catch(g){We(a,a.return,g)}}function Em(a,i,c){try{var f=a.stateNode;CR(f,a.type,c,i),f[Sn]=i}catch(g){We(a,a.return,g)}}function H_(a){return a.tag===5||a.tag===3||a.tag===26||a.tag===27&&oi(a.type)||a.tag===4}function km(a){e:for(;;){for(;a.sibling===null;){if(a.return===null||H_(a.return))return null;a=a.return}for(a.sibling.return=a.return,a=a.sibling;a.tag!==5&&a.tag!==6&&a.tag!==18;){if(a.tag===27&&oi(a.type)||a.flags&2||a.child===null||a.tag===4)continue e;a.child.return=a,a=a.child}if(!(a.flags&2))return a.stateNode}}function Am(a,i,c){var f=a.tag;if(f===5||f===6)a=a.stateNode,i?(c.nodeType===9?c.body:c.nodeName==="HTML"?c.ownerDocument.body:c).insertBefore(a,i):(i=c.nodeType===9?c.body:c.nodeName==="HTML"?c.ownerDocument.body:c,i.appendChild(a),c=c._reactRootContainer,c!=null||i.onclick!==null||(i.onclick=na));else if(f!==4&&(f===27&&oi(a.type)&&(c=a.stateNode,i=null),a=a.child,a!==null))for(Am(a,i,c),a=a.sibling;a!==null;)Am(a,i,c),a=a.sibling}function id(a,i,c){var f=a.tag;if(f===5||f===6)a=a.stateNode,i?c.insertBefore(a,i):c.appendChild(a);else if(f!==4&&(f===27&&oi(a.type)&&(c=a.stateNode),a=a.child,a!==null))for(id(a,i,c),a=a.sibling;a!==null;)id(a,i,c),a=a.sibling}function F_(a){var i=a.stateNode,c=a.memoizedProps;try{for(var f=a.type,g=i.attributes;g.length;)i.removeAttributeNode(g[0]);Jt(i,f,c),i[Xt]=a,i[Sn]=c}catch(b){We(a,a.return,b)}}var fa=!1,At=!1,Tm=!1,K_=typeof WeakSet=="function"?WeakSet:Set,$t=null;function uR(a,i){if(a=a.containerInfo,Zm=Od,a=rj(a),wp(a)){if("selectionStart"in a)var c={start:a.selectionStart,end:a.selectionEnd};else e:{c=(c=a.ownerDocument)&&c.defaultView||window;var f=c.getSelection&&c.getSelection();if(f&&f.rangeCount!==0){c=f.anchorNode;var g=f.anchorOffset,b=f.focusNode;f=f.focusOffset;try{c.nodeType,b.nodeType}catch{c=null;break e}var O=0,C=-1,R=-1,H=0,J=0,ne=a,F=null;t:for(;;){for(var Z;ne!==c||g!==0&&ne.nodeType!==3||(C=O+g),ne!==b||f!==0&&ne.nodeType!==3||(R=O+f),ne.nodeType===3&&(O+=ne.nodeValue.length),(Z=ne.firstChild)!==null;)F=ne,ne=Z;for(;;){if(ne===a)break t;if(F===c&&++H===g&&(C=O),F===b&&++J===f&&(R=O),(Z=ne.nextSibling)!==null)break;ne=F,F=ne.parentNode}ne=Z}c=C===-1||R===-1?null:{start:C,end:R}}else c=null}c=c||{start:0,end:0}}else c=null;for(Qm={focusedElem:a,selectionRange:c},Od=!1,$t=i;$t!==null;)if(i=$t,a=i.child,(i.subtreeFlags&1028)!==0&&a!==null)a.return=i,$t=a;else for(;$t!==null;){switch(i=$t,b=i.alternate,a=i.flags,i.tag){case 0:if((a&4)!==0&&(a=i.updateQueue,a=a!==null?a.events:null,a!==null))for(c=0;c title"))),Jt(b,f,c),b[Xt]=a,Ut(b),f=b;break e;case"link":var O=Zw("link","href",g).get(f+(c.href||""));if(O){for(var C=0;Cet&&(O=et,et=Oe,Oe=O);var U=tj(C,Oe),q=tj(C,et);if(U&&q&&(Z.rangeCount!==1||Z.anchorNode!==U.node||Z.anchorOffset!==U.offset||Z.focusNode!==q.node||Z.focusOffset!==q.offset)){var B=ne.createRange();B.setStart(U.node,U.offset),Z.removeAllRanges(),Oe>et?(Z.addRange(B),Z.extend(q.node,q.offset)):(B.setEnd(q.node,q.offset),Z.addRange(B))}}}}for(ne=[],Z=C;Z=Z.parentNode;)Z.nodeType===1&&ne.push({element:Z,left:Z.scrollLeft,top:Z.scrollTop});for(typeof C.focus=="function"&&C.focus(),C=0;Cc?32:c,$.T=null,c=zm,zm=null;var b=ii,O=ga;if(Mt=0,is=ii=null,ga=0,(Ve&6)!==0)throw Error(r(331));var C=Ve;if(Ve|=4,nw(b.current),J_(b,b.current,O,c),Ve=C,$o(0,!1),on&&typeof on.onPostCommitFiberRoot=="function")try{on.onPostCommitFiberRoot(Ha,b)}catch{}return!0}finally{X.p=g,$.T=f,xw(a,i)}}function _w(a,i,c){i=nr(c,i),i=vm(a.stateNode,i,2),a=Qa(a,i,2),a!==null&&(jr(a,2),Rr(a))}function We(a,i,c){if(a.tag===3)_w(a,a,c);else for(;i!==null;){if(i.tag===3){_w(i,a,c);break}else if(i.tag===1){var f=i.stateNode;if(typeof i.type.getDerivedStateFromError=="function"||typeof f.componentDidCatch=="function"&&(ai===null||!ai.has(f))){a=nr(c,a),c=w_(2),f=Qa(i,c,2),f!==null&&(S_(c,f,i,a),jr(f,2),Rr(f));break}}i=i.return}}function Im(a,i,c){var f=a.pingCache;if(f===null){f=a.pingCache=new hR;var g=new Set;f.set(i,g)}else g=f.get(i),g===void 0&&(g=new Set,f.set(i,g));g.has(c)||(Mm=!0,g.add(c),a=yR.bind(null,a,i,c),i.then(a,a))}function yR(a,i,c){var f=a.pingCache;f!==null&&f.delete(i),a.pingedLanes|=a.suspendedLanes&c,a.warmLanes&=~c,nt===a&&(qe&c)===c&&(vt===4||vt===3&&(qe&62914560)===qe&&300>sn()-od?(Ve&2)===0&&ls(a,0):Dm|=c,as===qe&&(as=0)),Rr(a)}function ww(a,i){i===0&&(i=io()),a=Li(a,i),a!==null&&(jr(a,i),Rr(a))}function bR(a){var i=a.memoizedState,c=0;i!==null&&(c=i.retryLane),ww(a,c)}function xR(a,i){var c=0;switch(a.tag){case 31:case 13:var f=a.stateNode,g=a.memoizedState;g!==null&&(c=g.retryLane);break;case 19:f=a.stateNode;break;case 22:f=a.stateNode._retryCache;break;default:throw Error(r(314))}f!==null&&f.delete(i),ww(a,c)}function jR(a,i){return Ol(a,i)}var md=null,os=null,Bm=!1,vd=!1,Hm=!1,si=0;function Rr(a){a!==os&&a.next===null&&(os===null?md=os=a:os=os.next=a),vd=!0,Bm||(Bm=!0,wR())}function $o(a,i){if(!Hm&&vd){Hm=!0;do for(var c=!1,f=md;f!==null;){if(a!==0){var g=f.pendingLanes;if(g===0)var b=0;else{var O=f.suspendedLanes,C=f.pingedLanes;b=(1<<31-cn(42|a)+1)-1,b&=g&~(O&~C),b=b&201326741?b&201326741|1:b?b|2:0}b!==0&&(c=!0,Ew(f,b))}else b=qe,b=pt(f,f===nt?b:0,f.cancelPendingCommit!==null||f.timeoutHandle!==-1),(b&3)===0||Vt(f,b)||(c=!0,Ew(f,b));f=f.next}while(c);Hm=!1}}function _R(){Sw()}function Sw(){vd=Bm=!1;var a=0;si!==0&&MR()&&(a=si);for(var i=sn(),c=null,f=md;f!==null;){var g=f.next,b=Nw(f,i);b===0?(f.next=null,c===null?md=g:c.next=g,g===null&&(os=c)):(c=f,(a!==0||(b&3)!==0)&&(vd=!0)),f=g}Mt!==0&&Mt!==5||$o(a),si!==0&&(si=0)}function Nw(a,i){for(var c=a.suspendedLanes,f=a.pingedLanes,g=a.expirationTimes,b=a.pendingLanes&-62914561;0C)break;var J=R.transferSize,ne=R.initiatorType;J&&Rw(ne)&&(R=R.responseEnd,O+=J*(R"u"?null:document;function Gw(a,i,c){var f=cs;if(f&&typeof i=="string"&&i){var g=er(i);g='link[rel="'+a+'"][href="'+g+'"]',typeof c=="string"&&(g+='[crossorigin="'+c+'"]'),Yw.has(g)||(Yw.add(g),a={rel:a,crossOrigin:c,href:i},f.querySelector(g)===null&&(i=f.createElement("link"),Jt(i,"link",a),Ut(i),f.head.appendChild(i)))}}function BR(a){ya.D(a),Gw("dns-prefetch",a,null)}function HR(a,i){ya.C(a,i),Gw("preconnect",a,i)}function FR(a,i,c){ya.L(a,i,c);var f=cs;if(f&&a&&i){var g='link[rel="preload"][as="'+er(i)+'"]';i==="image"&&c&&c.imageSrcSet?(g+='[imagesrcset="'+er(c.imageSrcSet)+'"]',typeof c.imageSizes=="string"&&(g+='[imagesizes="'+er(c.imageSizes)+'"]')):g+='[href="'+er(a)+'"]';var b=g;switch(i){case"style":b=us(a);break;case"script":b=ds(a)}or.has(b)||(a=m({rel:"preload",href:i==="image"&&c&&c.imageSrcSet?void 0:a,as:i},c),or.set(b,a),f.querySelector(g)!==null||i==="style"&&f.querySelector(Fo(b))||i==="script"&&f.querySelector(Ko(b))||(i=f.createElement("link"),Jt(i,"link",a),Ut(i),f.head.appendChild(i)))}}function KR(a,i){ya.m(a,i);var c=cs;if(c&&a){var f=i&&typeof i.as=="string"?i.as:"script",g='link[rel="modulepreload"][as="'+er(f)+'"][href="'+er(a)+'"]',b=g;switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":b=ds(a)}if(!or.has(b)&&(a=m({rel:"modulepreload",href:a},i),or.set(b,a),c.querySelector(g)===null)){switch(f){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(c.querySelector(Ko(b)))return}f=c.createElement("link"),Jt(f,"link",a),Ut(f),c.head.appendChild(f)}}}function YR(a,i,c){ya.S(a,i,c);var f=cs;if(f&&a){var g=Pl(f).hoistableStyles,b=us(a);i=i||"default";var O=g.get(b);if(!O){var C={loading:0,preload:null};if(O=f.querySelector(Fo(b)))C.loading=5;else{a=m({rel:"stylesheet",href:a,"data-precedence":i},c),(c=or.get(b))&&iv(a,c);var R=O=f.createElement("link");Ut(R),Jt(R,"link",a),R._p=new Promise(function(H,J){R.onload=H,R.onerror=J}),R.addEventListener("load",function(){C.loading|=1}),R.addEventListener("error",function(){C.loading|=2}),C.loading|=4,jd(O,i,f)}O={type:"stylesheet",instance:O,count:1,state:C},g.set(b,O)}}}function GR(a,i){ya.X(a,i);var c=cs;if(c&&a){var f=Pl(c).hoistableScripts,g=ds(a),b=f.get(g);b||(b=c.querySelector(Ko(g)),b||(a=m({src:a,async:!0},i),(i=or.get(g))&&lv(a,i),b=c.createElement("script"),Ut(b),Jt(b,"link",a),c.head.appendChild(b)),b={type:"script",instance:b,count:1,state:null},f.set(g,b))}}function VR(a,i){ya.M(a,i);var c=cs;if(c&&a){var f=Pl(c).hoistableScripts,g=ds(a),b=f.get(g);b||(b=c.querySelector(Ko(g)),b||(a=m({src:a,async:!0,type:"module"},i),(i=or.get(g))&&lv(a,i),b=c.createElement("script"),Ut(b),Jt(b,"link",a),c.head.appendChild(b)),b={type:"script",instance:b,count:1,state:null},f.set(g,b))}}function Vw(a,i,c,f){var g=(g=Ee.current)?xd(g):null;if(!g)throw Error(r(446));switch(a){case"meta":case"title":return null;case"style":return typeof c.precedence=="string"&&typeof c.href=="string"?(i=us(c.href),c=Pl(g).hoistableStyles,f=c.get(i),f||(f={type:"style",instance:null,count:0,state:null},c.set(i,f)),f):{type:"void",instance:null,count:0,state:null};case"link":if(c.rel==="stylesheet"&&typeof c.href=="string"&&typeof c.precedence=="string"){a=us(c.href);var b=Pl(g).hoistableStyles,O=b.get(a);if(O||(g=g.ownerDocument||g,O={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},b.set(a,O),(b=g.querySelector(Fo(a)))&&!b._p&&(O.instance=b,O.state.loading=5),or.has(a)||(c={rel:"preload",as:"style",href:c.href,crossOrigin:c.crossOrigin,integrity:c.integrity,media:c.media,hrefLang:c.hrefLang,referrerPolicy:c.referrerPolicy},or.set(a,c),b||XR(g,a,c,O.state))),i&&f===null)throw Error(r(528,""));return O}if(i&&f!==null)throw Error(r(529,""));return null;case"script":return i=c.async,c=c.src,typeof c=="string"&&i&&typeof i!="function"&&typeof i!="symbol"?(i=ds(c),c=Pl(g).hoistableScripts,f=c.get(i),f||(f={type:"script",instance:null,count:0,state:null},c.set(i,f)),f):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,a))}}function us(a){return'href="'+er(a)+'"'}function Fo(a){return'link[rel="stylesheet"]['+a+"]"}function Xw(a){return m({},a,{"data-precedence":a.precedence,precedence:null})}function XR(a,i,c,f){a.querySelector('link[rel="preload"][as="style"]['+i+"]")?f.loading=1:(i=a.createElement("link"),f.preload=i,i.addEventListener("load",function(){return f.loading|=1}),i.addEventListener("error",function(){return f.loading|=2}),Jt(i,"link",c),Ut(i),a.head.appendChild(i))}function ds(a){return'[src="'+er(a)+'"]'}function Ko(a){return"script[async]"+a}function Ww(a,i,c){if(i.count++,i.instance===null)switch(i.type){case"style":var f=a.querySelector('style[data-href~="'+er(c.href)+'"]');if(f)return i.instance=f,Ut(f),f;var g=m({},c,{"data-href":c.href,"data-precedence":c.precedence,href:null,precedence:null});return f=(a.ownerDocument||a).createElement("style"),Ut(f),Jt(f,"style",g),jd(f,c.precedence,a),i.instance=f;case"stylesheet":g=us(c.href);var b=a.querySelector(Fo(g));if(b)return i.state.loading|=4,i.instance=b,Ut(b),b;f=Xw(c),(g=or.get(g))&&iv(f,g),b=(a.ownerDocument||a).createElement("link"),Ut(b);var O=b;return O._p=new Promise(function(C,R){O.onload=C,O.onerror=R}),Jt(b,"link",f),i.state.loading|=4,jd(b,c.precedence,a),i.instance=b;case"script":return b=ds(c.src),(g=a.querySelector(Ko(b)))?(i.instance=g,Ut(g),g):(f=c,(g=or.get(b))&&(f=m({},c),lv(f,g)),a=a.ownerDocument||a,g=a.createElement("script"),Ut(g),Jt(g,"link",f),a.head.appendChild(g),i.instance=g);case"void":return null;default:throw Error(r(443,i.type))}else i.type==="stylesheet"&&(i.state.loading&4)===0&&(f=i.instance,i.state.loading|=4,jd(f,c.precedence,a));return i.instance}function jd(a,i,c){for(var f=c.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),g=f.length?f[f.length-1]:null,b=g,O=0;O title"):null)}function WR(a,i,c){if(c===1||i.itemProp!=null)return!1;switch(a){case"meta":case"title":return!0;case"style":if(typeof i.precedence!="string"||typeof i.href!="string"||i.href==="")break;return!0;case"link":if(typeof i.rel!="string"||typeof i.href!="string"||i.href===""||i.onLoad||i.onError)break;switch(i.rel){case"stylesheet":return a=i.disabled,typeof i.precedence=="string"&&a==null;default:return!0}case"script":if(i.async&&typeof i.async!="function"&&typeof i.async!="symbol"&&!i.onLoad&&!i.onError&&i.src&&typeof i.src=="string")return!0}return!1}function Jw(a){return!(a.type==="stylesheet"&&(a.state.loading&3)===0)}function ZR(a,i,c,f){if(c.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&(c.state.loading&4)===0){if(c.instance===null){var g=us(f.href),b=i.querySelector(Fo(g));if(b){i=b._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(a.count++,a=wd.bind(a),i.then(a,a)),c.state.loading|=4,c.instance=b,Ut(b);return}b=i.ownerDocument||i,f=Xw(f),(g=or.get(g))&&iv(f,g),b=b.createElement("link"),Ut(b);var O=b;O._p=new Promise(function(C,R){O.onload=C,O.onerror=R}),Jt(b,"link",f),c.instance=b}a.stylesheets===null&&(a.stylesheets=new Map),a.stylesheets.set(c,i),(i=c.state.preload)&&(c.state.loading&3)===0&&(a.count++,c=wd.bind(a),i.addEventListener("load",c),i.addEventListener("error",c))}}var sv=0;function QR(a,i){return a.stylesheets&&a.count===0&&Nd(a,a.stylesheets),0sv?50:800)+i);return a.unsuspend=c,function(){a.unsuspend=null,clearTimeout(f),clearTimeout(g)}}:null}function wd(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Nd(this,this.stylesheets);else if(this.unsuspend){var a=this.unsuspend;this.unsuspend=null,a()}}}var Sd=null;function Nd(a,i){a.stylesheets=null,a.unsuspend!==null&&(a.count++,Sd=new Map,i.forEach(JR,a),Sd=null,wd.call(a))}function JR(a,i){if(!(i.state.loading&4)){var c=Sd.get(a);if(c)var f=c.get(null);else{c=new Map,Sd.set(a,c);for(var g=a.querySelectorAll("link[data-precedence],style[data-precedence]"),b=0;b"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),gv.exports=yL(),gv.exports}var xL=bL();const jL=Ma(xL);/** * react-router v7.13.2 * * Copyright (c) Remix Software Inc. @@ -55,14 +55,14 @@ Error generating stack: `+f.message+` * LICENSE.md file in the root directory of this source tree. * * @license MIT - */var S1="popstate";function N1(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function _L(e={}){function t(r,l){var p;let o=(p=l.state)==null?void 0:p.masked,{pathname:c,search:d,hash:h}=o||r.location;return vy("",{pathname:c,search:d,hash:h},l.state&&l.state.usr||null,l.state&&l.state.key||"default",o?{pathname:r.location.pathname,search:r.location.search,hash:r.location.hash}:void 0)}function n(r,l){return typeof l=="string"?l:ju(l)}return SL(t,n,null,e)}function ft(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function vr(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function wL(){return Math.random().toString(36).substring(2,10)}function O1(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.unstable_mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function vy(e,t,n=null,r,l){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?Hs(t):t,state:n,key:t&&t.key||r||wL(),unstable_mask:l}}function ju({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function Hs(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function SL(e,t,n,r={}){let{window:l=document.defaultView,v5Compat:o=!1}=r,c=l.history,d="POP",h=null,p=v();p==null&&(p=0,c.replaceState({...c.state,idx:p},""));function v(){return(c.state||{idx:null}).idx}function m(){d="POP";let S=v(),N=S==null?null:S-p;p=S,h&&h({action:d,location:w.location,delta:N})}function y(S,N){d="PUSH";let E=N1(S)?S:vy(w.location,S,N);p=v()+1;let T=O1(E,p),M=w.createHref(E.unstable_mask||E);try{c.pushState(T,"",M)}catch(k){if(k instanceof DOMException&&k.name==="DataCloneError")throw k;l.location.assign(M)}o&&h&&h({action:d,location:w.location,delta:1})}function x(S,N){d="REPLACE";let E=N1(S)?S:vy(w.location,S,N);p=v();let T=O1(E,p),M=w.createHref(E.unstable_mask||E);c.replaceState(T,"",M),o&&h&&h({action:d,location:w.location,delta:0})}function _(S){return NL(S)}let w={get action(){return d},get location(){return e(l,c)},listen(S){if(h)throw new Error("A history only accepts one active listener");return l.addEventListener(S1,m),h=S,()=>{l.removeEventListener(S1,m),h=null}},createHref(S){return t(l,S)},createURL:_,encodeLocation(S){let N=_(S);return{pathname:N.pathname,search:N.search,hash:N.hash}},push:y,replace:x,go(S){return c.go(S)}};return w}function NL(e,t=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),ft(n,"No window.location.(origin|href) available to create URL");let r=typeof e=="string"?e:ju(e);return r=r.replace(/ $/,"%20"),!t&&r.startsWith("//")&&(r=n+r),new URL(r,n)}function Fk(e,t,n="/"){return OL(e,t,n,!1)}function OL(e,t,n,r){let l=typeof t=="string"?Hs(t):t,o=Oa(l.pathname||"/",n);if(o==null)return null;let c=Kk(e);EL(c);let d=null;for(let h=0;d==null&&h{let v={relativePath:p===void 0?c.path||"":p,caseSensitive:c.caseSensitive===!0,childrenIndex:d,route:c};if(v.relativePath.startsWith("/")){if(!v.relativePath.startsWith(r)&&h)return;ft(v.relativePath.startsWith(r),`Absolute route path "${v.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),v.relativePath=v.relativePath.slice(r.length)}let m=Kr([r,v.relativePath]),y=n.concat(v);c.children&&c.children.length>0&&(ft(c.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${m}".`),Kk(c.children,t,y,m,h)),!(c.path==null&&!c.index)&&t.push({path:m,score:DL(m,c.index),routesMeta:y})};return e.forEach((c,d)=>{var h;if(c.path===""||!((h=c.path)!=null&&h.includes("?")))o(c,d);else for(let p of Yk(c.path))o(c,d,!0,p)}),t}function Yk(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,l=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return l?[o,""]:[o];let c=Yk(r.join("/")),d=[];return d.push(...c.map(h=>h===""?o:[o,h].join("/"))),l&&d.push(...c),d.map(h=>e.startsWith("/")&&h===""?"/":h)}function EL(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:RL(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var kL=/^:[\w-]+$/,AL=3,TL=2,CL=1,PL=10,ML=-2,E1=e=>e==="*";function DL(e,t){let n=e.split("/"),r=n.length;return n.some(E1)&&(r+=ML),t&&(r+=TL),n.filter(l=>!E1(l)).reduce((l,o)=>l+(kL.test(o)?AL:o===""?CL:PL),r)}function RL(e,t){return e.length===t.length&&e.slice(0,-1).every((r,l)=>r===t[l])?e[e.length-1]-t[t.length-1]:0}function LL(e,t,n=!1){let{routesMeta:r}=e,l={},o="/",c=[];for(let d=0;d{if(v==="*"){let _=d[y]||"";c=o.slice(0,o.length-_.length).replace(/(.)\/+$/,"$1")}const x=d[y];return m&&!x?p[v]=void 0:p[v]=(x||"").replace(/%2F/g,"/"),p},{}),pathname:o,pathnameBase:c,pattern:e}}function zL(e,t=!1,n=!0){vr(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],l="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(c,d,h,p,v)=>{if(r.push({paramName:d,isOptional:h!=null}),h){let m=v.charAt(p+c.length);return m&&m!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(r.push({paramName:"*"}),l+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?l+="\\/*$":e!==""&&e!=="/"&&(l+="(?:(?=\\/|$))"),[new RegExp(l,t?void 0:"i"),r]}function qL(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return vr(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Oa(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}var UL=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function $L(e,t="/"){let{pathname:n,search:r="",hash:l=""}=typeof e=="string"?Hs(e):e,o;return n?(n=n.replace(/\/\/+/g,"/"),n.startsWith("/")?o=k1(n.substring(1),"/"):o=k1(n,t)):o=t,{pathname:o,search:HL(r),hash:FL(l)}}function k1(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(l=>{l===".."?n.length>1&&n.pop():l!=="."&&n.push(l)}),n.length>1?n.join("/"):"/"}function jv(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function IL(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function bb(e){let t=IL(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function dh(e,t,n,r=!1){let l;typeof e=="string"?l=Hs(e):(l={...e},ft(!l.pathname||!l.pathname.includes("?"),jv("?","pathname","search",l)),ft(!l.pathname||!l.pathname.includes("#"),jv("#","pathname","hash",l)),ft(!l.search||!l.search.includes("#"),jv("#","search","hash",l)));let o=e===""||l.pathname==="",c=o?"/":l.pathname,d;if(c==null)d=n;else{let m=t.length-1;if(!r&&c.startsWith("..")){let y=c.split("/");for(;y[0]==="..";)y.shift(),m-=1;l.pathname=y.join("/")}d=m>=0?t[m]:"/"}let h=$L(l,d),p=c&&c!=="/"&&c.endsWith("/"),v=(o||c===".")&&n.endsWith("/");return!h.pathname.endsWith("/")&&(p||v)&&(h.pathname+="/"),h}var Kr=e=>e.join("/").replace(/\/\/+/g,"/"),BL=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),HL=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,FL=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,KL=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||"",this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function YL(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function GL(e){return e.map(t=>t.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var Gk=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Vk(e,t){let n=e;if(typeof n!="string"||!UL.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,l=!1;if(Gk)try{let o=new URL(window.location.href),c=n.startsWith("//")?new URL(o.protocol+n):new URL(n),d=Oa(c.pathname,t);c.origin===o.origin&&d!=null?n=d+c.search+c.hash:l=!0}catch{vr(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:l,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Xk=["POST","PUT","PATCH","DELETE"];new Set(Xk);var VL=["GET",...Xk];new Set(VL);var Fs=j.createContext(null);Fs.displayName="DataRouter";var fh=j.createContext(null);fh.displayName="DataRouterState";var XL=j.createContext(!1),Wk=j.createContext({isTransitioning:!1});Wk.displayName="ViewTransition";var WL=j.createContext(new Map);WL.displayName="Fetchers";var ZL=j.createContext(null);ZL.displayName="Await";var Zn=j.createContext(null);Zn.displayName="Navigation";var $u=j.createContext(null);$u.displayName="Location";var Ar=j.createContext({outlet:null,matches:[],isDataRoute:!1});Ar.displayName="Route";var xb=j.createContext(null);xb.displayName="RouteError";var Zk="REACT_ROUTER_ERROR",QL="REDIRECT",JL="ROUTE_ERROR_RESPONSE";function ez(e){if(e.startsWith(`${Zk}:${QL}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.location=="string"&&typeof t.reloadDocument=="boolean"&&typeof t.replace=="boolean")return t}catch{}}function tz(e){if(e.startsWith(`${Zk}:${JL}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new KL(t.status,t.statusText,t.data)}catch{}}function nz(e,{relative:t}={}){ft(Ks(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=j.useContext(Zn),{hash:l,pathname:o,search:c}=Bu(e,{relative:t}),d=o;return n!=="/"&&(d=o==="/"?n:Kr([n,o])),r.createHref({pathname:d,search:c,hash:l})}function Ks(){return j.useContext($u)!=null}function Tr(){return ft(Ks(),"useLocation() may be used only in the context of a component."),j.useContext($u).location}var Qk="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Jk(e){j.useContext(Zn).static||j.useLayoutEffect(e)}function hh(){let{isDataRoute:e}=j.useContext(Ar);return e?mz():rz()}function rz(){ft(Ks(),"useNavigate() may be used only in the context of a component.");let e=j.useContext(Fs),{basename:t,navigator:n}=j.useContext(Zn),{matches:r}=j.useContext(Ar),{pathname:l}=Tr(),o=JSON.stringify(bb(r)),c=j.useRef(!1);return Jk(()=>{c.current=!0}),j.useCallback((h,p={})=>{if(vr(c.current,Qk),!c.current)return;if(typeof h=="number"){n.go(h);return}let v=dh(h,JSON.parse(o),l,p.relative==="path");e==null&&t!=="/"&&(v.pathname=v.pathname==="/"?t:Kr([t,v.pathname])),(p.replace?n.replace:n.push)(v,p.state,p)},[t,n,o,l,e])}j.createContext(null);function Iu(){let{matches:e}=j.useContext(Ar),t=e[e.length-1];return t?t.params:{}}function Bu(e,{relative:t}={}){let{matches:n}=j.useContext(Ar),{pathname:r}=Tr(),l=JSON.stringify(bb(n));return j.useMemo(()=>dh(e,JSON.parse(l),r,t==="path"),[e,l,r,t])}function az(e,t){return eA(e,t)}function eA(e,t,n){var S;ft(Ks(),"useRoutes() may be used only in the context of a component.");let{navigator:r}=j.useContext(Zn),{matches:l}=j.useContext(Ar),o=l[l.length-1],c=o?o.params:{},d=o?o.pathname:"/",h=o?o.pathnameBase:"/",p=o&&o.route;{let N=p&&p.path||"";nA(d,!p||N.endsWith("*")||N.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + */var S1="popstate";function N1(e){return typeof e=="object"&&e!=null&&"pathname"in e&&"search"in e&&"hash"in e&&"state"in e&&"key"in e}function _L(e={}){function t(r,l){var p;let o=(p=l.state)==null?void 0:p.masked,{pathname:u,search:d,hash:h}=o||r.location;return vy("",{pathname:u,search:d,hash:h},l.state&&l.state.usr||null,l.state&&l.state.key||"default",o?{pathname:r.location.pathname,search:r.location.search,hash:r.location.hash}:void 0)}function n(r,l){return typeof l=="string"?l:jc(l)}return SL(t,n,null,e)}function ft(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function vr(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function wL(){return Math.random().toString(36).substring(2,10)}function O1(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.unstable_mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function vy(e,t,n=null,r,l){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?Hs(t):t,state:n,key:t&&t.key||r||wL(),unstable_mask:l}}function jc({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function Hs(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function SL(e,t,n,r={}){let{window:l=document.defaultView,v5Compat:o=!1}=r,u=l.history,d="POP",h=null,p=v();p==null&&(p=0,u.replaceState({...u.state,idx:p},""));function v(){return(u.state||{idx:null}).idx}function m(){d="POP";let S=v(),N=S==null?null:S-p;p=S,h&&h({action:d,location:w.location,delta:N})}function y(S,N){d="PUSH";let E=N1(S)?S:vy(w.location,S,N);p=v()+1;let A=O1(E,p),P=w.createHref(E.unstable_mask||E);try{u.pushState(A,"",P)}catch(k){if(k instanceof DOMException&&k.name==="DataCloneError")throw k;l.location.assign(P)}o&&h&&h({action:d,location:w.location,delta:1})}function x(S,N){d="REPLACE";let E=N1(S)?S:vy(w.location,S,N);p=v();let A=O1(E,p),P=w.createHref(E.unstable_mask||E);u.replaceState(A,"",P),o&&h&&h({action:d,location:w.location,delta:0})}function _(S){return NL(S)}let w={get action(){return d},get location(){return e(l,u)},listen(S){if(h)throw new Error("A history only accepts one active listener");return l.addEventListener(S1,m),h=S,()=>{l.removeEventListener(S1,m),h=null}},createHref(S){return t(l,S)},createURL:_,encodeLocation(S){let N=_(S);return{pathname:N.pathname,search:N.search,hash:N.hash}},push:y,replace:x,go(S){return u.go(S)}};return w}function NL(e,t=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),ft(n,"No window.location.(origin|href) available to create URL");let r=typeof e=="string"?e:jc(e);return r=r.replace(/ $/,"%20"),!t&&r.startsWith("//")&&(r=n+r),new URL(r,n)}function Fk(e,t,n="/"){return OL(e,t,n,!1)}function OL(e,t,n,r){let l=typeof t=="string"?Hs(t):t,o=Oa(l.pathname||"/",n);if(o==null)return null;let u=Kk(e);EL(u);let d=null;for(let h=0;d==null&&h{let v={relativePath:p===void 0?u.path||"":p,caseSensitive:u.caseSensitive===!0,childrenIndex:d,route:u};if(v.relativePath.startsWith("/")){if(!v.relativePath.startsWith(r)&&h)return;ft(v.relativePath.startsWith(r),`Absolute route path "${v.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),v.relativePath=v.relativePath.slice(r.length)}let m=Kr([r,v.relativePath]),y=n.concat(v);u.children&&u.children.length>0&&(ft(u.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${m}".`),Kk(u.children,t,y,m,h)),!(u.path==null&&!u.index)&&t.push({path:m,score:DL(m,u.index),routesMeta:y})};return e.forEach((u,d)=>{var h;if(u.path===""||!((h=u.path)!=null&&h.includes("?")))o(u,d);else for(let p of Yk(u.path))o(u,d,!0,p)}),t}function Yk(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,l=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return l?[o,""]:[o];let u=Yk(r.join("/")),d=[];return d.push(...u.map(h=>h===""?o:[o,h].join("/"))),l&&d.push(...u),d.map(h=>e.startsWith("/")&&h===""?"/":h)}function EL(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:RL(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var kL=/^:[\w-]+$/,AL=3,TL=2,CL=1,PL=10,ML=-2,E1=e=>e==="*";function DL(e,t){let n=e.split("/"),r=n.length;return n.some(E1)&&(r+=ML),t&&(r+=TL),n.filter(l=>!E1(l)).reduce((l,o)=>l+(kL.test(o)?AL:o===""?CL:PL),r)}function RL(e,t){return e.length===t.length&&e.slice(0,-1).every((r,l)=>r===t[l])?e[e.length-1]-t[t.length-1]:0}function LL(e,t,n=!1){let{routesMeta:r}=e,l={},o="/",u=[];for(let d=0;d{if(v==="*"){let _=d[y]||"";u=o.slice(0,o.length-_.length).replace(/(.)\/+$/,"$1")}const x=d[y];return m&&!x?p[v]=void 0:p[v]=(x||"").replace(/%2F/g,"/"),p},{}),pathname:o,pathnameBase:u,pattern:e}}function zL(e,t=!1,n=!0){vr(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],l="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(u,d,h,p,v)=>{if(r.push({paramName:d,isOptional:h!=null}),h){let m=v.charAt(p+u.length);return m&&m!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(r.push({paramName:"*"}),l+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?l+="\\/*$":e!==""&&e!=="/"&&(l+="(?:(?=\\/|$))"),[new RegExp(l,t?void 0:"i"),r]}function qL(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return vr(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Oa(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}var UL=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function $L(e,t="/"){let{pathname:n,search:r="",hash:l=""}=typeof e=="string"?Hs(e):e,o;return n?(n=n.replace(/\/\/+/g,"/"),n.startsWith("/")?o=k1(n.substring(1),"/"):o=k1(n,t)):o=t,{pathname:o,search:HL(r),hash:FL(l)}}function k1(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(l=>{l===".."?n.length>1&&n.pop():l!=="."&&n.push(l)}),n.length>1?n.join("/"):"/"}function jv(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function IL(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function bb(e){let t=IL(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function hh(e,t,n,r=!1){let l;typeof e=="string"?l=Hs(e):(l={...e},ft(!l.pathname||!l.pathname.includes("?"),jv("?","pathname","search",l)),ft(!l.pathname||!l.pathname.includes("#"),jv("#","pathname","hash",l)),ft(!l.search||!l.search.includes("#"),jv("#","search","hash",l)));let o=e===""||l.pathname==="",u=o?"/":l.pathname,d;if(u==null)d=n;else{let m=t.length-1;if(!r&&u.startsWith("..")){let y=u.split("/");for(;y[0]==="..";)y.shift(),m-=1;l.pathname=y.join("/")}d=m>=0?t[m]:"/"}let h=$L(l,d),p=u&&u!=="/"&&u.endsWith("/"),v=(o||u===".")&&n.endsWith("/");return!h.pathname.endsWith("/")&&(p||v)&&(h.pathname+="/"),h}var Kr=e=>e.join("/").replace(/\/\/+/g,"/"),BL=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),HL=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,FL=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,KL=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||"",this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function YL(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function GL(e){return e.map(t=>t.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var Gk=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Vk(e,t){let n=e;if(typeof n!="string"||!UL.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,l=!1;if(Gk)try{let o=new URL(window.location.href),u=n.startsWith("//")?new URL(o.protocol+n):new URL(n),d=Oa(u.pathname,t);u.origin===o.origin&&d!=null?n=d+u.search+u.hash:l=!0}catch{vr(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:l,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Xk=["POST","PUT","PATCH","DELETE"];new Set(Xk);var VL=["GET",...Xk];new Set(VL);var Fs=j.createContext(null);Fs.displayName="DataRouter";var ph=j.createContext(null);ph.displayName="DataRouterState";var XL=j.createContext(!1),Wk=j.createContext({isTransitioning:!1});Wk.displayName="ViewTransition";var WL=j.createContext(new Map);WL.displayName="Fetchers";var ZL=j.createContext(null);ZL.displayName="Await";var Zn=j.createContext(null);Zn.displayName="Navigation";var $c=j.createContext(null);$c.displayName="Location";var Ar=j.createContext({outlet:null,matches:[],isDataRoute:!1});Ar.displayName="Route";var xb=j.createContext(null);xb.displayName="RouteError";var Zk="REACT_ROUTER_ERROR",QL="REDIRECT",JL="ROUTE_ERROR_RESPONSE";function ez(e){if(e.startsWith(`${Zk}:${QL}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.location=="string"&&typeof t.reloadDocument=="boolean"&&typeof t.replace=="boolean")return t}catch{}}function tz(e){if(e.startsWith(`${Zk}:${JL}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new KL(t.status,t.statusText,t.data)}catch{}}function nz(e,{relative:t}={}){ft(Ks(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=j.useContext(Zn),{hash:l,pathname:o,search:u}=Hc(e,{relative:t}),d=o;return n!=="/"&&(d=o==="/"?n:Kr([n,o])),r.createHref({pathname:d,search:u,hash:l})}function Ks(){return j.useContext($c)!=null}function Tr(){return ft(Ks(),"useLocation() may be used only in the context of a component."),j.useContext($c).location}var Qk="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Jk(e){j.useContext(Zn).static||j.useLayoutEffect(e)}function Ic(){let{isDataRoute:e}=j.useContext(Ar);return e?mz():rz()}function rz(){ft(Ks(),"useNavigate() may be used only in the context of a component.");let e=j.useContext(Fs),{basename:t,navigator:n}=j.useContext(Zn),{matches:r}=j.useContext(Ar),{pathname:l}=Tr(),o=JSON.stringify(bb(r)),u=j.useRef(!1);return Jk(()=>{u.current=!0}),j.useCallback((h,p={})=>{if(vr(u.current,Qk),!u.current)return;if(typeof h=="number"){n.go(h);return}let v=hh(h,JSON.parse(o),l,p.relative==="path");e==null&&t!=="/"&&(v.pathname=v.pathname==="/"?t:Kr([t,v.pathname])),(p.replace?n.replace:n.push)(v,p.state,p)},[t,n,o,l,e])}j.createContext(null);function Bc(){let{matches:e}=j.useContext(Ar),t=e[e.length-1];return t?t.params:{}}function Hc(e,{relative:t}={}){let{matches:n}=j.useContext(Ar),{pathname:r}=Tr(),l=JSON.stringify(bb(n));return j.useMemo(()=>hh(e,JSON.parse(l),r,t==="path"),[e,l,r,t])}function az(e,t){return eA(e,t)}function eA(e,t,n){var S;ft(Ks(),"useRoutes() may be used only in the context of a component.");let{navigator:r}=j.useContext(Zn),{matches:l}=j.useContext(Ar),o=l[l.length-1],u=o?o.params:{},d=o?o.pathname:"/",h=o?o.pathnameBase:"/",p=o&&o.route;{let N=p&&p.path||"";nA(d,!p||N.endsWith("*")||N.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let v=Tr(),m;if(t){let N=typeof t=="string"?Hs(t):t;ft(h==="/"||((S=N.pathname)==null?void 0:S.startsWith(h)),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${h}" but pathname "${N.pathname}" was given in the \`location\` prop.`),m=N}else m=v;let y=m.pathname||"/",x=y;if(h!=="/"){let N=h.replace(/^\//,"").split("/");x="/"+y.replace(/^\//,"").split("/").slice(N.length).join("/")}let _=Fk(e,{pathname:x});vr(p||_!=null,`No routes matched location "${m.pathname}${m.search}${m.hash}" `),vr(_==null||_[_.length-1].route.element!==void 0||_[_.length-1].route.Component!==void 0||_[_.length-1].route.lazy!==void 0,`Matched leaf route at location "${m.pathname}${m.search}${m.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let w=uz(_&&_.map(N=>Object.assign({},N,{params:Object.assign({},c,N.params),pathname:Kr([h,r.encodeLocation?r.encodeLocation(N.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathname]),pathnameBase:N.pathnameBase==="/"?h:Kr([h,r.encodeLocation?r.encodeLocation(N.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:N.pathnameBase])})),l,n);return t&&w?j.createElement($u.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...m},navigationType:"POP"}},w):w}function iz(){let e=pz(),t=YL(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r="rgba(200,200,200, 0.5)",l={padding:"0.5rem",backgroundColor:r},o={padding:"2px 4px",backgroundColor:r},c=null;return console.error("Error handled by React Router default ErrorBoundary:",e),c=j.createElement(j.Fragment,null,j.createElement("p",null,"💿 Hey developer 👋"),j.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",j.createElement("code",{style:o},"ErrorBoundary")," or"," ",j.createElement("code",{style:o},"errorElement")," prop on your route.")),j.createElement(j.Fragment,null,j.createElement("h2",null,"Unexpected Application Error!"),j.createElement("h3",{style:{fontStyle:"italic"}},t),n?j.createElement("pre",{style:l},n):null,c)}var lz=j.createElement(iz,null),tA=class extends j.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error("React Router caught the following error during render",e)}render(){let e=this.state.error;if(this.context&&typeof e=="object"&&e&&"digest"in e&&typeof e.digest=="string"){const n=tz(e.digest);n&&(e=n)}let t=e!==void 0?j.createElement(Ar.Provider,{value:this.props.routeContext},j.createElement(xb.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?j.createElement(sz,{error:e},t):t}};tA.contextType=XL;var _v=new WeakMap;function sz({children:e,error:t}){let{basename:n}=j.useContext(Zn);if(typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){let r=ez(t.digest);if(r){let l=_v.get(t);if(l)throw l;let o=Vk(r.location,n);if(Gk&&!_v.get(t))if(o.isExternal||r.reloadDocument)window.location.href=o.absoluteURL||o.to;else{const c=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(o.to,{replace:r.replace}));throw _v.set(t,c),c}return j.createElement("meta",{httpEquiv:"refresh",content:`0;url=${o.absoluteURL||o.to}`})}}return e}function oz({routeContext:e,match:t,children:n}){let r=j.useContext(Fs);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),j.createElement(Ar.Provider,{value:e},n)}function uz(e,t=[],n){let r=n==null?void 0:n.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let l=e,o=r==null?void 0:r.errors;if(o!=null){let v=l.findIndex(m=>m.route.id&&(o==null?void 0:o[m.route.id])!==void 0);ft(v>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(",")}`),l=l.slice(0,Math.min(l.length,v+1))}let c=!1,d=-1;if(n&&r){c=r.renderFallback;for(let v=0;v=0?l=l.slice(0,d+1):l=[l[0]];break}}}}let h=n==null?void 0:n.onError,p=r&&h?(v,m)=>{var y,x;h(v,{location:r.location,params:((x=(y=r.matches)==null?void 0:y[0])==null?void 0:x.params)??{},unstable_pattern:GL(r.matches),errorInfo:m})}:void 0;return l.reduceRight((v,m,y)=>{let x,_=!1,w=null,S=null;r&&(x=o&&m.route.id?o[m.route.id]:void 0,w=m.route.errorElement||lz,c&&(d<0&&y===0?(nA("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),_=!0,S=null):d===y&&(_=!0,S=m.route.hydrateFallbackElement||null)));let N=t.concat(l.slice(0,y+1)),E=()=>{let T;return x?T=w:_?T=S:m.route.Component?T=j.createElement(m.route.Component,null):m.route.element?T=m.route.element:T=v,j.createElement(oz,{match:m,routeContext:{outlet:v,matches:N,isDataRoute:r!=null},children:T})};return r&&(m.route.ErrorBoundary||m.route.errorElement||y===0)?j.createElement(tA,{location:r.location,revalidation:r.revalidation,component:w,error:x,children:E(),routeContext:{outlet:null,matches:N,isDataRoute:!0},onError:p}):E()},null)}function jb(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function cz(e){let t=j.useContext(Fs);return ft(t,jb(e)),t}function dz(e){let t=j.useContext(fh);return ft(t,jb(e)),t}function fz(e){let t=j.useContext(Ar);return ft(t,jb(e)),t}function _b(e){let t=fz(e),n=t.matches[t.matches.length-1];return ft(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function hz(){return _b("useRouteId")}function pz(){var r;let e=j.useContext(xb),t=dz("useRouteError"),n=_b("useRouteError");return e!==void 0?e:(r=t.errors)==null?void 0:r[n]}function mz(){let{router:e}=cz("useNavigate"),t=_b("useNavigate"),n=j.useRef(!1);return Jk(()=>{n.current=!0}),j.useCallback(async(l,o={})=>{vr(n.current,Qk),n.current&&(typeof l=="number"?await e.navigate(l):await e.navigate(l,{fromRouteId:t,...o}))},[e,t])}var A1={};function nA(e,t,n){!t&&!A1[e]&&(A1[e]=!0,vr(!1,n))}j.memo(vz);function vz({routes:e,future:t,state:n,isStatic:r,onError:l}){return eA(e,void 0,{state:n,isStatic:r,onError:l})}function T1({to:e,replace:t,state:n,relative:r}){ft(Ks()," may be used only in the context of a component.");let{static:l}=j.useContext(Zn);vr(!l," must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.");let{matches:o}=j.useContext(Ar),{pathname:c}=Tr(),d=hh(),h=dh(e,bb(o),c,r==="path"),p=JSON.stringify(h);return j.useEffect(()=>{d(JSON.parse(p),{replace:t,state:n,relative:r})},[d,p,r,t,n]),null}function _t(e){ft(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function gz({basename:e="/",children:t=null,location:n,navigationType:r="POP",navigator:l,static:o=!1,unstable_useTransitions:c}){ft(!Ks(),"You cannot render a inside another . You should never have more than one in your app.");let d=e.replace(/^\/*/,"/"),h=j.useMemo(()=>({basename:d,navigator:l,static:o,unstable_useTransitions:c,future:{}}),[d,l,o,c]);typeof n=="string"&&(n=Hs(n));let{pathname:p="/",search:v="",hash:m="",state:y=null,key:x="default",unstable_mask:_}=n,w=j.useMemo(()=>{let S=Oa(p,d);return S==null?null:{location:{pathname:S,search:v,hash:m,state:y,key:x,unstable_mask:_},navigationType:r}},[d,p,v,m,y,x,r,_]);return vr(w!=null,` is not able to match the URL "${p}${v}${m}" because it does not start with the basename, so the won't render anything.`),w==null?null:j.createElement(Zn.Provider,{value:h},j.createElement($u.Provider,{children:t,value:w}))}function yz({children:e,location:t}){return az(gy(e),t)}function gy(e,t=[]){let n=[];return j.Children.forEach(e,(r,l)=>{if(!j.isValidElement(r))return;let o=[...t,l];if(r.type===j.Fragment){n.push.apply(n,gy(r.props.children,o));return}ft(r.type===_t,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),ft(!r.props.index||!r.props.children,"An index route cannot have child routes.");let c={id:r.props.id||o.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,middleware:r.props.middleware,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(c.children=gy(r.props.children,o)),n.push(c)}),n}var ef="get",tf="application/x-www-form-urlencoded";function ph(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function bz(e){return ph(e)&&e.tagName.toLowerCase()==="button"}function xz(e){return ph(e)&&e.tagName.toLowerCase()==="form"}function jz(e){return ph(e)&&e.tagName.toLowerCase()==="input"}function _z(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function wz(e,t){return e.button===0&&(!t||t==="_self")&&!_z(e)}function yy(e=""){return new URLSearchParams(typeof e=="string"||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,n)=>{let r=e[n];return t.concat(Array.isArray(r)?r.map(l=>[n,l]):[[n,r]])},[]))}function Sz(e,t){let n=yy(e);return t&&t.forEach((r,l)=>{n.has(l)||t.getAll(l).forEach(o=>{n.append(l,o)})}),n}var Cd=null;function Nz(){if(Cd===null)try{new FormData(document.createElement("form"),0),Cd=!1}catch{Cd=!0}return Cd}var Oz=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function wv(e){return e!=null&&!Oz.has(e)?(vr(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${tf}"`),null):e}function Ez(e,t){let n,r,l,o,c;if(xz(e)){let d=e.getAttribute("action");r=d?Oa(d,t):null,n=e.getAttribute("method")||ef,l=wv(e.getAttribute("enctype"))||tf,o=new FormData(e)}else if(bz(e)||jz(e)&&(e.type==="submit"||e.type==="image")){let d=e.form;if(d==null)throw new Error('Cannot submit a - +
{modelsUsage.length ? modelsUsage.map((model) => ( setModelEnabled(model.model, !model.enabled)} @@ -456,7 +459,7 @@ function ProviderProbeSuggestionPanel({ report, busy, onApply }) { ); } -function ProviderModelRow({ item, busy, deleting, onToggle, onDelete }) { +function ProviderModelRow({ item, providerEnabled, busy, deleting, onToggle, onDelete }) { const summary = item.summary || {}; const isDiscoveredDisabled = item.source === "discovered" && !item.enabled; const canDelete = item.source !== "trace"; @@ -465,10 +468,10 @@ function ProviderModelRow({ item, busy, deleting, onToggle, onDelete }) {
{item.model} - {isDiscoveredDisabled ? "discovered, awaiting enable" : modelSourceLabel(item.source)} + {isDiscoveredDisabled ? "discovered, disabled" : modelSourceLabel(item.source)}
- + {item.source !== "trace" ? : History only — add model to configure routing} {canDelete ? (
- {item.enabled ? "enabled" : "disabled"} - {isDiscoveredDisabled ? new : null} + {item.source === "trace" ? "history only" : item.enabled ? "enabled" : "disabled"} + {item.enabled && !providerEnabled ? blocked: provider disabled : null}
diff --git a/web/monitor-ui/src/routes/ChannelsPage.jsx b/web/monitor-ui/src/routes/ChannelsPage.jsx index 4db9cde..70eee46 100644 --- a/web/monitor-ui/src/routes/ChannelsPage.jsx +++ b/web/monitor-ui/src/routes/ChannelsPage.jsx @@ -1,6 +1,6 @@ import React, { useMemo, useRef, useState } from "react"; import { createPortal } from "react-dom"; -import { Link, useSearchParams } from "react-router-dom"; +import { Link, useNavigate, useSearchParams } from "react-router-dom"; import { StatCard } from "../components/common/Display"; import { DeleteIcon, InlineTag, PlusIcon } from "../components/common/Badges"; import { EmptyState } from "../components/common/EmptyState"; @@ -35,6 +35,7 @@ const DEFAULT_FORM = { }; export function ProvidersPage() { + const navigate = useNavigate(); const { t } = useI18n(); const [searchParams, setSearchParams] = useSearchParams(); const windowValue = normalizeAnalyticsWindow(searchParams.get("window")); @@ -126,9 +127,10 @@ export function ProvidersPage() { setFormOpen(false)} - onCreated={() => { + onCreated={(item) => { setFormOpen(false); setRefreshTick((tick) => tick + 1); + if (item?.id) navigate(buildProviderLink(item.id, windowValue)); }} /> ) : null} @@ -263,8 +265,8 @@ function CreateProviderDialog({ presetData, onClose, onCreated }) { setSaving(true); setError(""); try { - await postJSON(apiPaths.providerSetupApply, normalizeProviderPayload(form)); - onCreated(); + const result = await postJSON(apiPaths.providerSetupApply, normalizeProviderPayload(form)); + onCreated(result.channel); } catch (err) { setError(err.message || t("providers.validateRequiredReason")); } finally { @@ -317,14 +319,18 @@ function ProviderCard({ item, windowValue, onRefresh }) { const summary = item.summary || {}; const modeTag = providerModeTag(item.mode); const [saving, setSaving] = useState(false); + const [error, setError] = useState(""); const [probeOpen, setProbeOpen] = useState(false); const setEnabled = async (enabled, event) => { event?.preventDefault(); event?.stopPropagation(); setSaving(true); + setError(""); try { await patchJSON(apiPaths.provider(item.id), { enabled }); onRefresh?.(); + } catch (err) { + setError(err.message); } finally { setSaving(false); } @@ -336,9 +342,12 @@ function ProviderCard({ item, windowValue, onRefresh }) { return; } setSaving(true); + setError(""); try { await deleteJSON(apiPaths.provider(item.id)); onRefresh?.(); + } catch (err) { + setError(err.message); } finally { setSaving(false); } @@ -377,6 +386,8 @@ function ProviderCard({ item, windowValue, onRefresh }) {
+ {error ?

{error}

: null} +

{!item.enabled ? t("providers.routingDisabled") : !item.enabled_model_count && !item.allow_unknown_models ? t("providers.chooseModels") : t("providers.routingEnabled")}

{item.base_url} {formatDateTime(item.last_probe_at || item.updated_at)} diff --git a/web/monitor-ui/tests-real/monitor-real-server.spec.js b/web/monitor-ui/tests-real/monitor-real-server.spec.js index 497dbfd..6262038 100644 --- a/web/monitor-ui/tests-real/monitor-real-server.spec.js +++ b/web/monitor-ui/tests-real/monitor-real-server.spec.js @@ -41,8 +41,8 @@ test("real monitor server supports probe and manual model mutation", async ({ pa await page.getByRole("button", { name: "Probe provider" }).click(); await expect(page.getByText("success").first()).toBeVisible(); - await expect(page.getByText("discovered, awaiting enable").first()).toBeVisible(); - await page.getByRole("button", { name: "Enable new (1)" }).click(); + await expect(page.getByText("discovered, disabled").first()).toBeVisible(); + await page.getByRole("button", { name: "Enable discovered (1)" }).click(); await expect(page.getByText("gpt-new-real")).toBeVisible(); }); diff --git a/web/monitor-ui/tests/monitor-smoke.spec.js b/web/monitor-ui/tests/monitor-smoke.spec.js index 213bea2..b52934f 100644 --- a/web/monitor-ui/tests/monitor-smoke.spec.js +++ b/web/monitor-ui/tests/monitor-smoke.spec.js @@ -22,6 +22,9 @@ test.beforeEach(async ({ page }) => { expect(url.searchParams.get("status")).toBe("unread"); return route.fulfill({ json: eventListPayload() }); } + if (path === "/api/routing/summary") { + return route.fulfill({ json: {} }); + } if (path === "/api/models") { return route.fulfill({ json: modelListPayload() }); } @@ -65,7 +68,7 @@ test.beforeEach(async ({ page }) => { expect(body.api_key).toBe("sk-test-secret"); expect(body.api_type).toBe("chat_completions"); expect(body.protocol_family).toBe("openai_compatible"); - return route.fulfill({ json: channelDetailPayload() }); + return route.fulfill({ json: { applied: true, channel: channelDetailPayload() } }); } if (path === "/api/provider-presets") { return route.fulfill({ json: providerPresetPayload() }); @@ -192,7 +195,7 @@ test("provider management renders and supports core actions", async ({ page }) = await page.getByRole("button", { name: "Create provider" }).click(); await expect(page.getByRole("heading", { name: "Create provider" })).toBeHidden(); - await page.getByRole("link", { name: /OpenAI Primary/i }).first().click(); + await expect(page).toHaveURL(/providers\/openai-primary/); await expect(page.getByRole("heading", { name: "OpenAI Primary" })).toBeVisible(); await expect(page.getByText("config source").first()).toBeVisible(); await expect(page.getByText("web-managed").first()).toBeVisible(); @@ -200,7 +203,7 @@ test("provider management renders and supports core actions", async ({ page }) = await expect(page.getByText("responses_server").first()).toBeVisible(); await expect(page.getByText("1 missing usage").first()).toBeVisible(); await expect(page.getByText("encrypted-local").first()).toBeVisible(); - await expect(page.getByText("discovered, awaiting enable")).toBeVisible(); + await expect(page.getByText("discovered, disabled")).toBeVisible(); await page.getByRole("button", { name: "Edit provider" }).click(); await expect(page.getByRole("heading", { name: "Edit provider" })).toBeVisible(); @@ -225,7 +228,7 @@ test("provider management renders and supports core actions", async ({ page }) = await expect(page.getByRole("heading", { name: "Probe suggestions" })).toBeVisible(); await expect(page.getByText("chat_completions").first()).toBeVisible(); - await page.getByRole("button", { name: "Enable new (1)" }).click(); + await page.getByRole("button", { name: "Enable discovered (1)" }).click(); await expect(page.getByRole("button", { name: "Enabling" })).toBeHidden(); }); @@ -815,3 +818,31 @@ function usageSummary(overrides = {}) { ...overrides, }; } + + +test("disabled provider preserves model choices without claiming availability", async ({ page }) => { + await page.route("**/api/channels/openai-primary?*", (route) => { + const payload = channelDetailPayload(); + payload.enabled = false; + payload.models_usage.push({ model: "historical-model", source: "trace", enabled: false, summary: {} }); + return route.fulfill({ json: payload }); + }); + await page.goto("/providers/openai-primary"); + await expect(page.getByText("Provider disabled: all model routes are blocked. Model selections are preserved.")).toBeVisible(); + await expect(page.getByLabel("gpt-5 enabled", { exact: true })).toBeChecked(); + await expect(page.getByText("blocked: provider disabled").first()).toBeVisible(); + await expect(page.getByLabel("historical-model enabled", { exact: true })).toHaveCount(0); + await expect(page.getByText("History only — add model to configure routing")).toBeVisible(); + await expect(page.locator(".provider-model-card").getByText("new", { exact: true })).toHaveCount(0); +}); + +test("provider toggle failure is visible and preserves the displayed choice", async ({ page }) => { + await page.route("**/api/channels/openai-primary", (route) => { + if (route.request().method() === "PATCH") return route.fulfill({ status: 409, json: { error: "Upstreams are managed by YAML credentials" } }); + return route.fallback(); + }); + await page.goto("/providers"); + await page.getByLabel("OpenAI Primary enabled", { exact: true }).click(); + await expect(page.getByRole("alert")).toHaveText("Upstreams are managed by YAML credentials"); + await expect(page.getByLabel("OpenAI Primary enabled", { exact: true })).toBeChecked(); +});