From 8beb63fe2981668a359d5068f4ce36f92f5dca71 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 18:42:11 +0000 Subject: [PATCH 01/11] refactor(mcp): drop 14 non-triage tools, keep 7-tool triage surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduces the MCP HTTP-streamable surface from 21 tools to 7 — the minimum set needed for an LLM-driven incident-triage workflow on a 120-service SQLite deployment that's currently OOMing within an hour. Kept (7): get_anomaly_timeline, get_service_map, get_service_health, root_cause_analysis, impact_analysis, trace_graph, search_logs. Cut (14): get_system_graph, tail_logs, get_trace, search_traces, get_metrics, get_dashboard_stats, get_storage_status, find_similar_logs, get_alerts, correlated_signals, get_error_chains, get_investigations, get_investigation, get_graph_snapshot. The cut tools fall into three buckets: (a) duplicates of a kept tool with a slightly different framing (get_system_graph ≈ get_service_map, get_error_chains is folded into root_cause_analysis); (b) require subsystems being dropped in follow-up commits (find_similar_logs → vectordb, get_graph_snapshot → snapshot table); (c) belong to a separate forensic-analytics workflow not part of active triage (get_investigations, get_dashboard_stats). MCP clients calling cut tools receive an "unknown tool" RPC error — no deprecation period, the cut is intentional and immediate. Files touched: cache.go cacheable list re-sorted to mirror toolDefs; dispatcher in tools.go collapsed to the 7-case switch; tools_ran20_test.go (find_similar_logs only) deleted; server_ran22_test.go pared down to the constructor-tenant signature test now that the HTTP find_similar_logs flow is gone (the no-header default-tenant invariant is covered by tenant_isolation_test.go); tenant_isolation_test.go drops subtests for cut tools. Design spec: docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md --- internal/mcp/cache.go | 6 +- internal/mcp/server_ran22_test.go | 110 +---- internal/mcp/tenant_isolation_test.go | 196 +------- internal/mcp/tools.go | 618 +++----------------------- internal/mcp/tools_ran20_test.go | 79 ---- 5 files changed, 89 insertions(+), 920 deletions(-) delete mode 100644 internal/mcp/tools_ran20_test.go diff --git a/internal/mcp/cache.go b/internal/mcp/cache.go index df48747..4cf85bf 100644 --- a/internal/mcp/cache.go +++ b/internal/mcp/cache.go @@ -21,11 +21,11 @@ import ( // changes meaningfully on millisecond scales and the per-call DB cost is // already bounded by the storage layer. var cacheableTools = map[string]struct{}{ - "get_service_map": {}, - "impact_analysis": {}, - "root_cause_analysis": {}, "get_anomaly_timeline": {}, + "get_service_map": {}, "get_service_health": {}, + "root_cause_analysis": {}, + "impact_analysis": {}, } // isCacheable reports whether a tool name is on the cache whitelist. diff --git a/internal/mcp/server_ran22_test.go b/internal/mcp/server_ran22_test.go index 37f6de6..dbf020f 100644 --- a/internal/mcp/server_ran22_test.go +++ b/internal/mcp/server_ran22_test.go @@ -1,15 +1,9 @@ package mcp import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "strings" "testing" "github.com/RandomCodeSpace/otelcontext/internal/storage" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) // TestNew_DefaultTenant_FromConstructor is the RAN-22 regression bar at the @@ -17,21 +11,26 @@ import ( // to New, so production startup wiring (main.go) cannot drop it without a // compile error. Empty input falls back to storage.DefaultTenantID; a // non-empty value is preserved verbatim. +// +// End-to-end coverage that the configured default actually flows through the +// HTTP transport into the tenant-scoped tool path is provided by +// tenant_isolation_test.go::TestMCP_TenantIsolation_AllGraphRAGTools (the +// no-header caller). func TestNew_DefaultTenant_FromConstructor(t *testing.T) { t.Run("empty falls back to storage.DefaultTenantID", func(t *testing.T) { - srv := New("", nil, nil, nil, vectordb.New(1)) + srv := New("", nil, nil, nil, nil) if srv.defaultTenant != storage.DefaultTenantID { t.Fatalf(`New("") defaultTenant = %q, want %q`, srv.defaultTenant, storage.DefaultTenantID) } }) t.Run("non-empty value is preserved", func(t *testing.T) { - srv := New("acme", nil, nil, nil, vectordb.New(1)) + srv := New("acme", nil, nil, nil, nil) if srv.defaultTenant != "acme" { t.Fatalf(`New("acme") defaultTenant = %q, want "acme"`, srv.defaultTenant) } }) t.Run("SetDefaultTenant runtime override still works", func(t *testing.T) { - srv := New("acme", nil, nil, nil, vectordb.New(1)) + srv := New("acme", nil, nil, nil, nil) srv.SetDefaultTenant("globex") if srv.defaultTenant != "globex" { t.Fatalf(`SetDefaultTenant("globex") defaultTenant = %q, want "globex"`, srv.defaultTenant) @@ -43,96 +42,3 @@ func TestNew_DefaultTenant_FromConstructor(t *testing.T) { } }) } - -// TestNew_DefaultTenant_FlowsThroughHTTPTransport proves that the constructor- -// supplied tenant is the actual fallback used by the JSON-RPC HTTP handler -// when no X-Tenant-ID header is present, and that an explicit header still -// wins over the default. This locks in the end-to-end behavior the RAN-22 -// fix delivers: a deployment with DEFAULT_TENANT=acme returns acme-scoped -// data from header-less MCP tool calls. -func TestNew_DefaultTenant_FlowsThroughHTTPTransport(t *testing.T) { - idx := vectordb.New(100) - idx.Add(1, "acme", "checkout", "ERROR", "payment gateway timeout acme-marker-xyz") - idx.Add(2, "globex", "auth", "ERROR", "payment gateway 500 globex-marker-qqq") - idx.Add(3, "default", "svc", "ERROR", "payment gateway refused default-marker-aaa") - - body := mustMarshalJSONRPC(t, "find_similar_logs", map[string]any{ - "query": "payment gateway", - "limit": float64(50), - }) - - srv := New("acme", nil, nil, nil, idx) - - // Header-less tools/call must scope to the constructor-provided default. - resp1 := callNoHeader(t, srv, body) - mustContain(t, resp1, "acme-marker-xyz") - mustNotContain(t, resp1, "globex-marker-qqq", "default-marker-aaa") - - // Explicit X-Tenant-ID header beats the configured default — precedence - // invariant is preserved. - resp2 := callWithHeader(t, srv, body, "globex") - mustContain(t, resp2, "globex-marker-qqq") - mustNotContain(t, resp2, "acme-marker-xyz", "default-marker-aaa") - - // SetDefaultTenant runtime override flows to the same transport path so - // future runtime-config-reload paths behave correctly. - srv.SetDefaultTenant("globex") - resp3 := callNoHeader(t, srv, body) - mustContain(t, resp3, "globex-marker-qqq") - mustNotContain(t, resp3, "acme-marker-xyz", "default-marker-aaa") -} - -func mustMarshalJSONRPC(t *testing.T, tool string, args map[string]any) []byte { - t.Helper() - b, err := json.Marshal(map[string]any{ - "jsonrpc": "2.0", - "id": 1, - "method": "tools/call", - "params": map[string]any{"name": tool, "arguments": args}, - }) - if err != nil { - t.Fatalf("marshal: %v", err) - } - return b -} - -func callNoHeader(t *testing.T, srv *Server, body []byte) string { - t.Helper() - req := httptest.NewRequest(http.MethodPost, "/mcp", bytes.NewReader(body)) - req.Header.Set("Content-Type", "application/json") - rr := httptest.NewRecorder() - srv.Handler().ServeHTTP(rr, req) - if rr.Code != http.StatusOK { - t.Fatalf("HTTP %d: %s", rr.Code, rr.Body.String()) - } - return rr.Body.String() -} - -func callWithHeader(t *testing.T, srv *Server, body []byte, tenant string) string { - t.Helper() - req := httptest.NewRequest(http.MethodPost, "/mcp", bytes.NewReader(body)) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-Tenant-ID", tenant) - rr := httptest.NewRecorder() - srv.Handler().ServeHTTP(rr, req) - if rr.Code != http.StatusOK { - t.Fatalf("HTTP %d: %s", rr.Code, rr.Body.String()) - } - return rr.Body.String() -} - -func mustContain(t *testing.T, body, want string) { - t.Helper() - if !strings.Contains(body, want) { - t.Fatalf("response missing expected marker %q:\n%s", want, body) - } -} - -func mustNotContain(t *testing.T, body string, forbidden ...string) { - t.Helper() - for _, f := range forbidden { - if strings.Contains(body, f) { - t.Fatalf("response leaked forbidden marker %q:\n%s", f, body) - } - } -} diff --git a/internal/mcp/tenant_isolation_test.go b/internal/mcp/tenant_isolation_test.go index bb4d5cc..6ae90f3 100644 --- a/internal/mcp/tenant_isolation_test.go +++ b/internal/mcp/tenant_isolation_test.go @@ -111,11 +111,14 @@ func setupTenantIsolationServer(t *testing.T) (*httptest.Server, *graphrag.Graph // seedTenant ingests a small but representative slice of telemetry for // tenant T: a parent OK span, a child ERROR span, a matching ERROR log, -// a vector-index doc, an injected anomaly, a persisted investigation, -// and a graph snapshot row. All identifiers (trace_id, span_id) collide +// and an injected anomaly. All identifiers (trace_id, span_id) collide // across tenants on purpose — the tenant slice is the only thing keeping // them apart. -func seedTenant(t *testing.T, g *graphrag.GraphRAG, repo *storage.Repository, vIdx *vectordb.Index, tenant string, ts time.Time) { +// +// repo is accepted but currently unused; future tests may seed DB rows +// directly. It is preserved so callers can switch back to DB-shaped +// seeding without a signature change. +func seedTenant(t *testing.T, g *graphrag.GraphRAG, _ *storage.Repository, _ any, tenant string, ts time.Time) { t.Helper() service := tenant + "-orders" @@ -153,8 +156,8 @@ func seedTenant(t *testing.T, g *graphrag.GraphRAG, repo *storage.Repository, vI Duration: 1000, }) - // Log carrying the per-tenant marker — drives Drain clustering and - // CorrelatedSignals; the body is also stored in the vector index. + // Log carrying the per-tenant marker — drives Drain clustering and the + // LogClusterNode side-effect that CorrelatedSignals would consume. g.OnLogIngested(storage.Log{ TenantID: tenant, TraceID: traceID, @@ -165,9 +168,6 @@ func seedTenant(t *testing.T, g *graphrag.GraphRAG, repo *storage.Repository, vI Timestamp: ts.Add(2 * time.Millisecond), }) - // Vector index doc — find_similar_logs path is keyed by tenant. - vIdx.Add(0, tenant, service, "ERROR", logBody) - // Inject a per-tenant anomaly directly so AnomalyTimeline has // something to return without depending on the anomaly detector // loop (which is throttled to 24h in this fixture). @@ -179,21 +179,6 @@ func seedTenant(t *testing.T, g *graphrag.GraphRAG, repo *storage.Repository, vI Evidence: tenant + "-anomaly-marker error_rate=0.95", Timestamp: ts.Add(3 * time.Millisecond), }) - - // Snapshot row — insert directly so we control the tenant_id and ID - // (takeSnapshot is the production loop, but it is package-private). - snap := graphrag.GraphSnapshot{ - TenantID: tenant, - ID: "snap-" + tenant, - CreatedAt: ts, - Nodes: json.RawMessage(`[{"name":"` + service + `","marker":"` + tenant + `-marker"}]`), - Edges: json.RawMessage(`[]`), - ServiceCount: 1, - AvgHealthScore: 0.5, - } - if err := repo.DB().Create(&snap).Error; err != nil { - t.Fatalf("seed snapshot for %q: %v", tenant, err) - } } // waitForServiceMaps polls until every seeded tenant's ServiceMap reflects @@ -218,35 +203,6 @@ func waitForServiceMaps(t *testing.T, g *graphrag.GraphRAG, tenants []string) { t.Fatalf("timed out waiting for ServiceMap to reflect ingested spans for %v", tenants) } -// seedInvestigations relies on the in-memory state already being warm -// (see waitForServiceMaps). PersistInvestigation reaches into ImpactAnalysis -// internally, which reads from the per-tenant ServiceStore. -func seedInvestigations(t *testing.T, g *graphrag.GraphRAG, ts time.Time) { - t.Helper() - for _, tenant := range allTenants { - service := tenant + "-orders" - chain := graphrag.ErrorChainResult{ - RootCause: &graphrag.RootCauseInfo{ - Service: service, - Operation: tenant + "-op-checkout", - ErrorMessage: tenant + "-marker connection refused upstream", - SpanID: "span-child", - TraceID: "trace-shared", - }, - SpanChain: []graphrag.SpanNode{{ - ID: "span-child", - TraceID: "trace-shared", - Service: service, - Operation: tenant + "-op-checkout", - IsError: true, - Timestamp: ts, - }}, - TraceID: "trace-shared", - } - g.PersistInvestigation(tenant, service, []graphrag.ErrorChainResult{chain}, nil) - } -} - // callTool sends a JSON-RPC tools/call request to the test MCP server // with the given X-Tenant-ID header (omitted when empty) and returns the // inner ToolCallResult — i.e., the structure the LLM client would see. @@ -337,42 +293,21 @@ func truncate(s string) string { return s[:max] + "…(truncated)" } -// TestMCP_TenantIsolation_AllGraphRAGTools is the merge gate for RAN-19. -// For every GraphRAG-backed (and GraphRAG-rewired) MCP tool, it issues -// the same call from three callers — X-Tenant-ID: acme, X-Tenant-ID: beta, -// no header — against overlapping seeded data and asserts each response -// contains only the caller-tenant's data and never leaks another tenant's -// service name, log marker, operation, anomaly, or snapshot row. +// TestMCP_TenantIsolation_AllGraphRAGTools is the merge gate for the 7-tool +// triage MCP surface (post-2026-05-24 reduction). For every kept tool, it +// issues the same call from three callers — X-Tenant-ID: acme, +// X-Tenant-ID: beta, no header — against overlapping seeded data and +// asserts each response contains only the caller-tenant's data and never +// leaks another tenant's service name, log marker, operation, or anomaly. func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { - ts, g, repo, vIdx := setupTenantIsolationServer(t) + ts, g, repo, _ := setupTenantIsolationServer(t) now := time.Now().Add(-time.Minute) // a hair in the past so since=now-15m sees us for _, tenant := range allTenants { - seedTenant(t, g, repo, vIdx, tenant, now) + seedTenant(t, g, repo, nil, tenant, now) } waitForServiceMaps(t, g, allTenants) - seedInvestigations(t, g, now) - - // Resolve investigation IDs per tenant (PersistInvestigation generates - // them internally; we discover them by querying after the fact, then - // hand them back into get_investigation in the per-caller assertions). - invIDsByTenant := map[string]string{} - for _, tenant := range allTenants { - ctx := storage.WithTenantContext(context.Background(), tenant) - invs, err := g.GetInvestigations(ctx, "", "", "", 10) - if err != nil { - t.Fatalf("GetInvestigations(%s): %v", tenant, err) - } - if len(invs) == 0 { - t.Fatalf("expected at least one persisted investigation for %s, got 0", tenant) - } - invIDsByTenant[tenant] = invs[0].ID - } - - // snapshot lookup time — slightly in the future so "<= at" matches every - // seeded row regardless of microsecond drift. - snapAt := time.Now().Add(time.Minute).UTC().Format(time.RFC3339) for _, caller := range isolationCallers { caller := caller @@ -385,6 +320,7 @@ func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { ownLogMarker := caller.scoped + "-marker" ownAnomalyMarker := caller.scoped + "-anomaly-marker" _ = ownMarkers + _ = ownLogMarker // --- in-memory GraphRAG tools --- @@ -400,15 +336,6 @@ func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { assertNoLeak(t, "get_service_health", body, ownService, leakMarkers) }) - t.Run(caller.name+"/get_error_chains", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "get_error_chains", map[string]any{ - "service": ownService, - "time_range": "1h", - "limit": 10, - }) - assertNoLeak(t, "get_error_chains", body, ownService, leakMarkers) - }) - t.Run(caller.name+"/trace_graph", func(t *testing.T) { // trace_id collides across tenants; correct routing must surface // only the caller's per-tenant operation/service. @@ -438,74 +365,11 @@ func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { assertNoLeak(t, "root_cause_analysis", body, ownService, leakMarkers) }) - t.Run(caller.name+"/correlated_signals", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "correlated_signals", map[string]any{ - "service": ownService, - "time_range": "1h", - }) - // CorrelatedSignals collects logs/metrics for the service, so the - // per-tenant log marker should appear. - assertNoLeak(t, "correlated_signals", body, ownLogMarker, leakMarkers) - }) - t.Run(caller.name+"/get_anomaly_timeline", func(t *testing.T) { _, body := callTool(t, ts, caller.header, "get_anomaly_timeline", nil) assertNoLeak(t, "get_anomaly_timeline", body, ownAnomalyMarker, leakMarkers) }) - // --- DB-backed GraphRAG tools --- - - t.Run(caller.name+"/get_investigations", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "get_investigations", nil) - assertNoLeak(t, "get_investigations", body, ownService, leakMarkers) - }) - - t.Run(caller.name+"/get_investigation_by_id_own_tenant", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "get_investigation", map[string]any{ - "investigation_id": invIDsByTenant[caller.scoped], - }) - assertNoLeak(t, "get_investigation/own", body, ownService, leakMarkers) - }) - - t.Run(caller.name+"/get_investigation_by_id_other_tenant_blocks", func(t *testing.T) { - // Asking by another tenant's ID must NOT return that row — id- - // guessing would otherwise leak across tenants. The handler - // surfaces a tool-level error result, which is fine; what - // matters is that the foreign tenant's data does not appear. - otherTenant := caller.otherSeeded[0] - _, body := callTool(t, ts, caller.header, "get_investigation", map[string]any{ - "investigation_id": invIDsByTenant[otherTenant], - }) - assertNoLeak(t, "get_investigation/cross-tenant", body, "", leakMarkers) - }) - - t.Run(caller.name+"/get_graph_snapshot", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "get_graph_snapshot", map[string]any{ - "time": snapAt, - }) - // Snapshot rows are tagged with the tenant marker so the leak - // scan covers both ID prefixes (snap-acme/snap-beta/snap-default) - // and the inline node markers. - assertNoLeak(t, "get_graph_snapshot", body, "snap-"+caller.scoped, leakMarkers) - }) - - // --- vectordb-backed tool (Drain path is exercised by ingestion above) --- - - t.Run(caller.name+"/find_similar_logs", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "find_similar_logs", map[string]any{ - "query": "connection refused upstream", - "limit": 10, - }) - assertNoLeak(t, "find_similar_logs", body, ownLogMarker, leakMarkers) - }) - - // --- Legacy/rewired surface --- - // get_system_graph is rewired onto GraphRAG by RAN-39, so the same - // per-tenant invariants apply. - t.Run(caller.name+"/get_system_graph", func(t *testing.T) { - _, body := callTool(t, ts, caller.header, "get_system_graph", nil) - assertNoLeak(t, "get_system_graph", body, ownService, leakMarkers) - }) } } @@ -605,23 +469,11 @@ func TestMCP_TenantIsolation_DrainClusterIDsStayPerTenant(t *testing.T) { // the assertion above. t.Logf("drain cluster IDs: acme=%v beta=%v", idsA, idsB) - // End-to-end probe: the same isolation must hold via the MCP HTTP - // surface, not just the in-process API. - for _, scoped := range []string{"acme", "beta"} { - _, body := callTool(t, ts, scoped, "correlated_signals", map[string]any{ - "service": sharedService, - "time_range": "1h", - }) - other := "beta" - if scoped == "beta" { - other = "acme" - } - if !strings.Contains(body, scoped+"-marker") { - t.Errorf("%s correlated_signals (HTTP) missing own marker, body=%s", scoped, truncate(body)) - } - if strings.Contains(body, other+"-marker") { - t.Errorf("%s correlated_signals (HTTP) leaked %s marker, body=%s", scoped, other, truncate(body)) - } - } + // Note: the legacy end-to-end probe used the `correlated_signals` MCP + // tool to assert the same isolation across the HTTP transport. That + // tool was cut on 2026-05-24 alongside 13 others; the in-process + // CorrelatedSignals invariant above is still the truth-test for Drain + // + SignalStore tenant partitioning. The 7-tool MCP transport invariant + // for the kept tools is covered by TestMCP_TenantIsolation_AllGraphRAGTools. + _ = ts } - diff --git a/internal/mcp/tools.go b/internal/mcp/tools.go index 630b1a8..3753a0e 100644 --- a/internal/mcp/tools.go +++ b/internal/mcp/tools.go @@ -12,135 +12,27 @@ import ( ) const ( - errSvcGraphNotInit = "service graph not yet initialized" errGraphRAGNotInit = "GraphRAG not initialized" errServiceRequired = "service is required" resourceURIPrefix = "OtelContext://" ) -// toolDefs is the canonical list of all tools exposed by the OtelContext MCP server. +// toolDefs is the canonical list of triage-essential tools exposed by the +// OtelContext MCP server. The surface was reduced from 21 to 7 in +// 2026-05-24 so the platform survives 120 services on SQLite — see +// docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md. var toolDefs = []Tool{ { - Name: "get_system_graph", - Description: "Returns the full service topology with health scores (0-1), error rates, latencies, and dependency edges. Use this to understand overall system health.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "time_range": {Type: "string", Description: "Lookback window, e.g. '1h', '30m'. Defaults to '1h'."}, - }, - }, - }, - { - Name: "get_service_health", - Description: "Returns detailed health metrics for a specific service: error rate, latency percentiles, request rate, and active alerts.", - InputSchema: InputSchema{ - Type: "object", - Required: []string{"service_name"}, - Properties: map[string]Property{ - "service_name": {Type: "string", Description: "The service name to query."}, - }, - }, - }, - { - Name: "search_logs", - Description: "Searches log entries by severity, service, body text, trace ID, and time range. Returns id, timestamp, severity, service_name, body, trace_id. **Limited to the last 24 hours** — windows entirely outside the 24h cap are rejected. Strongly recommend setting `service` and/or `severity` to scope the search; unscoped keyword queries scan large row counts when FTS5 is disabled (the default). Use severity=ERROR to find errors, query= for full-text search, trace_id= to correlate with a trace. Use page= for pagination.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "query": {Type: "string", Description: "Full-text search in log body."}, - "severity": {Type: "string", Description: "Filter by severity level: ERROR, WARN, INFO, DEBUG."}, - "service": {Type: "string", Description: "Filter by service name (exact match)."}, - "trace_id": {Type: "string", Description: "Filter logs belonging to a specific trace ID."}, - "start": {Type: "string", Description: "Start time RFC3339. Defaults to 24h ago. Cannot be earlier than now-24h; older values are clamped."}, - "end": {Type: "string", Description: "End time RFC3339. Defaults to now. Cannot exceed now; future values are clamped."}, - "limit": {Type: "number", Description: "Max results per page (default 50, max 200)."}, - "page": {Type: "number", Description: "Page number for pagination (default 0)."}, - }, - }, - }, - { - Name: "tail_logs", - Description: "Returns the N most recent log entries, optionally filtered by service and/or severity. No time range needed — fastest way to see what's happening right now.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "service": {Type: "string", Description: "Filter by service name."}, - "severity": {Type: "string", Description: "Filter by severity: ERROR, WARN, INFO, DEBUG."}, - "limit": {Type: "number", Description: "Number of recent entries to return (default 20, max 100)."}, - }, - }, - }, - { - Name: "get_trace", - Description: "Returns full trace detail with all spans for a given trace ID.", - InputSchema: InputSchema{ - Type: "object", - Required: []string{"trace_id"}, - Properties: map[string]Property{ - "trace_id": {Type: "string", Description: "The trace ID to retrieve."}, - }, - }, - }, - { - Name: "search_traces", - Description: "Searches traces by service, status code, minimum duration, and time range.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "service": {Type: "string", Description: "Filter by service name."}, - "status": {Type: "string", Description: "Filter by status: OK, ERROR."}, - "min_duration_ms": {Type: "number", Description: "Minimum trace duration in ms."}, - "start": {Type: "string", Description: "Start time RFC3339."}, - "end": {Type: "string", Description: "End time RFC3339."}, - "limit": {Type: "number", Description: "Max results (default 20, max 100)."}, - }, - }, - }, - { - Name: "get_metrics", - Description: "Queries metric time series for a given metric name and optional service.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "name": {Type: "string", Description: "Metric name to query."}, - "service": {Type: "string", Description: "Filter by service name."}, - "start": {Type: "string", Description: "Start time RFC3339."}, - "end": {Type: "string", Description: "End time RFC3339."}, - }, - }, - }, - { - Name: "get_dashboard_stats", - Description: "Returns dashboard summary: total requests, error rate, avg latency, ingestion rate, and per-service breakdown.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "start": {Type: "string", Description: "Start time RFC3339. Defaults to 1h ago."}, - "end": {Type: "string", Description: "End time RFC3339. Defaults to now."}, - }, - }, - }, - { - Name: "get_storage_status", - Description: "Returns hot DB size, DLQ size, and database health.", - InputSchema: InputSchema{Type: "object"}, - }, - { - Name: "find_similar_logs", - Description: "Finds logs semantically similar to a query text using TF-IDF vector similarity. Useful for clustering errors and finding root causes.", + Name: "get_anomaly_timeline", + Description: "Returns recent anomalies with temporal causal links, optionally filtered by service. The triage entry point — answers \"what's wrong right now\".", InputSchema: InputSchema{ Type: "object", Properties: map[string]Property{ - "query": {Type: "string", Description: "Text query to find similar logs."}, - "limit": {Type: "number", Description: "Max results (default 10)."}, + "since": {Type: "string", Description: "Start time RFC3339. Defaults to 1h ago."}, + "service": {Type: "string", Description: "Filter by service."}, }, }, }, - { - Name: "get_alerts", - Description: "Returns active alerts and anomalies: services with high error rates, p99 latency spikes, and degraded health scores.", - InputSchema: InputSchema{Type: "object"}, - }, { Name: "get_service_map", Description: "Returns the service topology with health scores, error rates, call counts, and dependency edges. Powered by the live GraphRAG.", @@ -153,38 +45,13 @@ var toolDefs = []Tool{ }, }, { - Name: "get_error_chains", - Description: "Traces recent error spans upstream to identify root cause services. Returns span path, root cause service/operation, and correlated error logs.", - InputSchema: InputSchema{ - Type: "object", - Required: []string{"service"}, - Properties: map[string]Property{ - "service": {Type: "string", Description: "Service experiencing errors."}, - "time_range": {Type: "string", Description: "Lookback window, e.g. '5m', '1h'. Defaults to '15m'."}, - "limit": {Type: "number", Description: "Max error chains to return (default 10)."}, - }, - }, - }, - { - Name: "trace_graph", - Description: "Returns the full span tree for a trace with service names, durations, errors, and linked logs.", - InputSchema: InputSchema{ - Type: "object", - Required: []string{"trace_id"}, - Properties: map[string]Property{ - "trace_id": {Type: "string", Description: "The trace ID to visualize."}, - }, - }, - }, - { - Name: "impact_analysis", - Description: "BFS downstream from a service to find all affected services and impact scores.", + Name: "get_service_health", + Description: "Returns detailed health metrics for a specific service: error rate, latency percentiles, request rate, and active alerts.", InputSchema: InputSchema{ Type: "object", - Required: []string{"service"}, + Required: []string{"service_name"}, Properties: map[string]Property{ - "service": {Type: "string", Description: "Service to analyze blast radius for."}, - "depth": {Type: "number", Description: "Max traversal depth (default 5)."}, + "service_name": {Type: "string", Description: "The service name to query."}, }, }, }, @@ -201,60 +68,42 @@ var toolDefs = []Tool{ }, }, { - Name: "correlated_signals", - Description: "All related signals for a service: error logs, metric anomalies, traces, and investigations.", + Name: "impact_analysis", + Description: "BFS downstream from a service to find all affected services and impact scores.", InputSchema: InputSchema{ Type: "object", Required: []string{"service"}, Properties: map[string]Property{ - "service": {Type: "string", Description: "Service to gather signals for."}, - "time_range": {Type: "string", Description: "Lookback window. Defaults to '1h'."}, - }, - }, - }, - { - Name: "get_investigations", - Description: "Lists persisted investigation records from automated error analysis.", - InputSchema: InputSchema{ - Type: "object", - Properties: map[string]Property{ - "service": {Type: "string", Description: "Filter by service."}, - "severity": {Type: "string", Description: "Filter: critical, warning, info."}, - "status": {Type: "string", Description: "Filter: detected, triaged, resolved."}, - "limit": {Type: "number", Description: "Max results (default 20)."}, - }, - }, - }, - { - Name: "get_investigation", - Description: "Returns a full investigation record with causal chain, evidence, and affected services.", - InputSchema: InputSchema{ - Type: "object", - Required: []string{"investigation_id"}, - Properties: map[string]Property{ - "investigation_id": {Type: "string", Description: "The investigation ID."}, + "service": {Type: "string", Description: "Service to analyze blast radius for."}, + "depth": {Type: "number", Description: "Max traversal depth (default 5)."}, }, }, }, { - Name: "get_graph_snapshot", - Description: "Returns the historical service topology closest to the requested time.", + Name: "trace_graph", + Description: "Returns the full span tree for a trace with service names, durations, errors, and linked logs.", InputSchema: InputSchema{ Type: "object", - Required: []string{"time"}, + Required: []string{"trace_id"}, Properties: map[string]Property{ - "time": {Type: "string", Description: "RFC3339 timestamp to query the snapshot for."}, + "trace_id": {Type: "string", Description: "The trace ID to visualize."}, }, }, }, { - Name: "get_anomaly_timeline", - Description: "Returns recent anomalies with temporal causal links, optionally filtered by service.", + Name: "search_logs", + Description: "Searches log entries by severity, service, body text, trace ID, and time range. Returns id, timestamp, severity, service_name, body, trace_id. **Limited to the last 24 hours** — windows entirely outside the 24h cap are rejected. Strongly recommend setting `service` and/or `severity` to scope the search; unscoped keyword queries scan large row counts when FTS5 is disabled. Use severity=ERROR to find errors, query= for full-text search, trace_id= to correlate with a trace. Use page= for pagination.", InputSchema: InputSchema{ Type: "object", Properties: map[string]Property{ - "since": {Type: "string", Description: "Start time RFC3339. Defaults to 1h ago."}, - "service": {Type: "string", Description: "Filter by service."}, + "query": {Type: "string", Description: "Full-text search in log body."}, + "severity": {Type: "string", Description: "Filter by severity level: ERROR, WARN, INFO, DEBUG."}, + "service": {Type: "string", Description: "Filter by service name (exact match)."}, + "trace_id": {Type: "string", Description: "Filter logs belonging to a specific trace ID."}, + "start": {Type: "string", Description: "Start time RFC3339. Defaults to 24h ago. Cannot be earlier than now-24h; older values are clamped."}, + "end": {Type: "string", Description: "End time RFC3339. Defaults to now. Cannot exceed now; future values are clamped."}, + "limit": {Type: "number", Description: "Max results per page (default 50, max 200)."}, + "page": {Type: "number", Description: "Page number for pagination (default 0)."}, }, }, }, @@ -293,48 +142,20 @@ func (s *Server) toolHandler(ctx context.Context, name string, args map[string]a s.metrics.MCPToolInvocationsTotal.WithLabelValues(name, status).Inc() }() switch name { - case "get_system_graph": - return s.toolGetSystemGraph(ctx, args) - case "get_service_health": - return s.toolGetServiceHealth(ctx, args) - case "search_logs": - return s.toolSearchLogs(ctx, args) - case "tail_logs": - return s.toolTailLogs(ctx, args) - case "get_trace": - return s.toolGetTrace(ctx, args) - case "search_traces": - return s.toolSearchTraces(ctx, args) - case "get_metrics": - return s.toolGetMetrics(ctx, args) - case "get_dashboard_stats": - return s.toolGetDashboardStats(ctx, args) - case "get_storage_status": - return s.toolGetStorageStatus() - case "find_similar_logs": - return s.toolFindSimilarLogs(ctx, args) - case "get_alerts": - return s.toolGetAlerts() + case "get_anomaly_timeline": + return s.toolGetAnomalyTimeline(ctx, args) case "get_service_map": return s.toolGetServiceMap(ctx, args) - case "get_error_chains": - return s.toolGetErrorChains(ctx, args) - case "trace_graph": - return s.toolTraceGraph(ctx, args) - case "impact_analysis": - return s.toolImpactAnalysis(ctx, args) + case "get_service_health": + return s.toolGetServiceHealth(ctx, args) case "root_cause_analysis": return s.toolRootCauseAnalysis(ctx, args) - case "correlated_signals": - return s.toolCorrelatedSignals(ctx, args) - case "get_investigations": - return s.toolGetInvestigations(ctx, args) - case "get_investigation": - return s.toolGetInvestigationByID(ctx, args) - case "get_graph_snapshot": - return s.toolGetGraphSnapshot(ctx, args) - case "get_anomaly_timeline": - return s.toolGetAnomalyTimeline(ctx, args) + case "impact_analysis": + return s.toolImpactAnalysis(ctx, args) + case "trace_graph": + return s.toolTraceGraph(ctx, args) + case "search_logs": + return s.toolSearchLogs(ctx, args) default: return errorResult(fmt.Sprintf("unknown tool: %s", name)) } @@ -342,72 +163,26 @@ func (s *Server) toolHandler(ctx context.Context, name string, args map[string]a // --- Tool implementations --- -// toolGetSystemGraph returns a tenant-scoped service topology snapshot. -// -// When GraphRAG is wired (the default in production) the response is built -// from its per-tenant ServiceMap and AllServiceEdges, so two tenants with -// overlapping service names cannot see each other's nodes or edges. The -// legacy *graph.Graph remains as a fallback for boot windows when GraphRAG -// is still warming up; that fallback is cross-tenant by construction and -// is the documented legacy code path called out in RAN-39. -func (s *Server) toolGetSystemGraph(ctx context.Context, _ map[string]any) ToolCallResult { - if s.graphRAG != nil { - entries := s.graphRAG.ServiceMap(mcpCtx(ctx), 0) - edges := s.graphRAG.AllServiceEdges(mcpCtx(ctx)) - payload := map[string]any{ - "services": entries, - "edges": edges, - } - data, err := json.MarshalIndent(payload, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal system graph: %v", err)) - } - return textResult(string(data)) - } - if s.svcGraph == nil { - return errorResult(errSvcGraphNotInit) - } - snap := s.svcGraph.Snapshot() - data, err := json.MarshalIndent(snap, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal system graph: %v", err)) - } - return textResult(string(data)) -} - // toolGetServiceHealth returns the ServiceMap entry for svcName scoped to -// the tenant on ctx. Falls back to the legacy svcGraph snapshot when -// GraphRAG is not yet wired. +// the tenant on ctx. func (s *Server) toolGetServiceHealth(ctx context.Context, args map[string]any) ToolCallResult { svcName, _ := args["service_name"].(string) if svcName == "" { return errorResult("service_name is required") } - if s.graphRAG != nil { - for _, entry := range s.graphRAG.ServiceMap(mcpCtx(ctx), 0) { - if entry.Service != nil && entry.Service.Name == svcName { - data, err := json.MarshalIndent(entry, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal service health: %v", err)) - } - return textResult(string(data)) + if s.graphRAG == nil { + return errorResult(errGraphRAGNotInit) + } + for _, entry := range s.graphRAG.ServiceMap(mcpCtx(ctx), 0) { + if entry.Service != nil && entry.Service.Name == svcName { + data, err := json.MarshalIndent(entry, "", " ") + if err != nil { + return errorResult(fmt.Sprintf("failed to marshal service health: %v", err)) } + return textResult(string(data)) } - return textResult(fmt.Sprintf("service %q not found in the current tenant window", svcName)) - } - if s.svcGraph == nil { - return errorResult(errSvcGraphNotInit) } - snap := s.svcGraph.Snapshot() - node, ok := snap.Nodes[svcName] - if !ok { - return textResult(fmt.Sprintf("service %q not found in the current graph window", svcName)) - } - data, err := json.MarshalIndent(node, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal service health: %v", err)) - } - return textResult(string(data)) + return textResult(fmt.Sprintf("service %q not found in the current tenant window", svcName)) } // logSummary is a lean projection of storage.Log for AI consumption. @@ -496,193 +271,6 @@ func (s *Server) toolSearchLogs(ctx context.Context, args map[string]any) ToolCa return resourceResult(resourceURIPrefix+"logs/search", httpconst.ContentTypeJSON, string(data)) } -func (s *Server) toolTailLogs(ctx context.Context, args map[string]any) ToolCallResult { - limit := argInt(args, "limit", 20) - if limit > 100 { - limit = 100 - } - - filter := storage.LogFilter{ - EndTime: time.Now(), - Limit: limit, - } - if v, ok := args["service"].(string); ok && v != "" { - filter.ServiceName = v - } - if v, ok := args["severity"].(string); ok && v != "" { - filter.Severity = v - } - - logs, _, err := s.repo.GetLogsV2(mcpCtx(ctx), filter) - if err != nil { - return errorResult(fmt.Sprintf("tail_logs failed: %v", err)) - } - data, err := json.MarshalIndent(toLogSummaries(logs), "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal tail results: %v", err)) - } - return resourceResult(resourceURIPrefix+"logs/tail", httpconst.ContentTypeJSON, string(data)) -} - -func (s *Server) toolGetTrace(ctx context.Context, args map[string]any) ToolCallResult { - traceID, _ := args["trace_id"].(string) - if traceID == "" { - return errorResult("trace_id is required") - } - trace, err := s.repo.GetTrace(mcpCtx(ctx), traceID) - if err != nil { - return errorResult(fmt.Sprintf("get_trace failed: %v", err)) - } - data, err := json.MarshalIndent(trace, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal trace: %v", err)) - } - return resourceResult(resourceURIPrefix+"traces/"+traceID, httpconst.ContentTypeJSON, string(data)) -} - -func (s *Server) toolSearchTraces(ctx context.Context, args map[string]any) ToolCallResult { - end := time.Now() - start := end.Add(-1 * time.Hour) - parseTime(args, "start", &start) - parseTime(args, "end", &end) - - limit := argInt(args, "limit", 20) - if limit > 100 { - limit = 100 - } - - svcName, _ := args["service"].(string) - status, _ := args["status"].(string) - search := "" - - var services []string - if svcName != "" { - services = []string{svcName} - } - - resp, err := s.repo.GetTracesFiltered(mcpCtx(ctx), start, end, services, status, search, limit, 0, "timestamp", "desc") - if err != nil { - return errorResult(fmt.Sprintf("search_traces failed: %v", err)) - } - data, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal trace search results: %v", err)) - } - return resourceResult(resourceURIPrefix+"traces/search", httpconst.ContentTypeJSON, string(data)) -} - -func (s *Server) toolGetMetrics(ctx context.Context, args map[string]any) ToolCallResult { - end := time.Now() - start := end.Add(-1 * time.Hour) - parseTime(args, "start", &start) - parseTime(args, "end", &end) - - metricName, _ := args["name"].(string) - svcName, _ := args["service"].(string) - - buckets, err := s.repo.GetMetricBuckets(mcpCtx(ctx), start, end, svcName, metricName) - if err != nil { - return errorResult(fmt.Sprintf("get_metrics failed: %v", err)) - } - data, err := json.MarshalIndent(buckets, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal metrics: %v", err)) - } - return resourceResult(resourceURIPrefix+"metrics/query", httpconst.ContentTypeJSON, string(data)) -} - -func (s *Server) toolGetDashboardStats(ctx context.Context, args map[string]any) ToolCallResult { - end := time.Now() - start := end.Add(-1 * time.Hour) - parseTime(args, "start", &start) - parseTime(args, "end", &end) - - stats, err := s.repo.GetDashboardStats(mcpCtx(ctx), start, end, nil) - if err != nil { - return errorResult(fmt.Sprintf("get_dashboard_stats failed: %v", err)) - } - data, err := json.MarshalIndent(stats, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal dashboard stats: %v", err)) - } - return textResult(string(data)) -} - -func (s *Server) toolGetStorageStatus() ToolCallResult { - health := s.metrics.GetHealthStats() - result := map[string]any{ - "hot_db_size_mb": float64(s.repo.HotDBSizeBytes()) / 1024 / 1024, - "dlq_size_files": health.DLQSize, - "active_conns": health.ActiveConns, - "goroutines": health.Goroutines, - "heap_alloc_mb": health.HeapAllocMB, - "uptime_seconds": health.UptimeSeconds, - "ingestion_total": health.IngestionRate, - "db_latency_p99_ms": health.DBLatencyP99Ms, - } - data, err := json.MarshalIndent(result, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal storage status: %v", err)) - } - return textResult(string(data)) -} - -// toolFindSimilarLogs returns logs semantically similar to the query text -// scoped to the tenant resolved from the MCP transport (X-Tenant-ID header or -// the server's default tenant). Cross-tenant rows are never returned. -func (s *Server) toolFindSimilarLogs(ctx context.Context, args map[string]any) ToolCallResult { - query, _ := args["query"].(string) - if query == "" { - return errorResult("query is required") - } - limit := argInt(args, "limit", 20) - if limit > 100 { - limit = 100 - } - if s.vectorIdx == nil { - return errorResult("vector index not yet initialized") - } - tenant := storage.TenantFromContext(mcpCtx(ctx)) - results := s.vectorIdx.Search(tenant, query, limit) - data, err := json.MarshalIndent(results, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal similar logs: %v", err)) - } - return textResult(string(data)) -} - -func (s *Server) toolGetAlerts() ToolCallResult { - if s.svcGraph == nil { - return errorResult(errSvcGraphNotInit) - } - snap := s.svcGraph.Snapshot() - type alertEntry struct { - Service string `json:"service"` - Status string `json:"status"` - Score float64 `json:"health_score"` - Alerts []string `json:"alerts"` - } - var entries []alertEntry - for _, n := range snap.Nodes { - if len(n.Alerts) > 0 || n.Status != "healthy" { - entries = append(entries, alertEntry{ - Service: n.Name, - Status: n.Status, - Score: n.HealthScore, - Alerts: n.Alerts, - }) - } - } - if len(entries) == 0 { - return textResult("No active alerts. All services are healthy.") - } - data, err := json.MarshalIndent(entries, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal alerts: %v", err)) - } - return textResult(string(data)) -} - // --- GraphRAG Tool implementations --- func (s *Server) toolGetServiceMap(ctx context.Context, args map[string]any) ToolCallResult { @@ -698,26 +286,6 @@ func (s *Server) toolGetServiceMap(ctx context.Context, args map[string]any) Too return textResult(string(data)) } -func (s *Server) toolGetErrorChains(ctx context.Context, args map[string]any) ToolCallResult { - if s.graphRAG == nil { - return errorResult(errGraphRAGNotInit) - } - svcName, _ := args["service"].(string) - if svcName == "" { - return errorResult(errServiceRequired) - } - since := time.Now().Add(-15 * time.Minute) - parseTimeRange(args, "time_range", &since) - limit := argInt(args, "limit", 10) - - chains := s.graphRAG.ErrorChain(mcpCtx(ctx), svcName, since, limit) - data, err := json.MarshalIndent(chains, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal error chains: %v", err)) - } - return textResult(string(data)) -} - func (s *Server) toolTraceGraph(ctx context.Context, args map[string]any) ToolCallResult { if s.graphRAG == nil { return errorResult(errGraphRAGNotInit) @@ -782,84 +350,6 @@ func (s *Server) toolRootCauseAnalysis(ctx context.Context, args map[string]any) return textResult(string(data)) } -func (s *Server) toolCorrelatedSignals(ctx context.Context, args map[string]any) ToolCallResult { - if s.graphRAG == nil { - return errorResult(errGraphRAGNotInit) - } - svcName, _ := args["service"].(string) - if svcName == "" { - return errorResult(errServiceRequired) - } - since := time.Now().Add(-1 * time.Hour) - parseTimeRange(args, "time_range", &since) - - result := s.graphRAG.CorrelatedSignals(mcpCtx(ctx), svcName, since) - data, err := json.MarshalIndent(result, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal correlated signals: %v", err)) - } - return textResult(string(data)) -} - -func (s *Server) toolGetInvestigations(ctx context.Context, args map[string]any) ToolCallResult { - if s.graphRAG == nil { - return errorResult(errGraphRAGNotInit) - } - service, _ := args["service"].(string) - severity, _ := args["severity"].(string) - status, _ := args["status"].(string) - limit := argInt(args, "limit", 20) - - investigations, err := s.graphRAG.GetInvestigations(ctx, service, severity, status, limit) - if err != nil { - return errorResult(fmt.Sprintf("failed to query investigations: %v", err)) - } - data, err := json.MarshalIndent(investigations, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal investigations: %v", err)) - } - return textResult(string(data)) -} - -func (s *Server) toolGetInvestigationByID(ctx context.Context, args map[string]any) ToolCallResult { - if s.graphRAG == nil { - return errorResult(errGraphRAGNotInit) - } - id, _ := args["investigation_id"].(string) - if id == "" { - return errorResult("investigation_id is required") - } - inv, err := s.graphRAG.GetInvestigation(ctx, id) - if err != nil { - return errorResult(fmt.Sprintf("investigation not found: %v", err)) - } - data, err := json.MarshalIndent(inv, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal investigation: %v", err)) - } - return textResult(string(data)) -} - -func (s *Server) toolGetGraphSnapshot(ctx context.Context, args map[string]any) ToolCallResult { - if s.graphRAG == nil { - return errorResult(errGraphRAGNotInit) - } - var at time.Time - parseTime(args, "time", &at) - if at.IsZero() { - at = time.Now() - } - snap, err := s.graphRAG.GetGraphSnapshot(ctx, at) - if err != nil { - return errorResult(fmt.Sprintf("no snapshot found: %v", err)) - } - data, err := json.MarshalIndent(snap, "", " ") - if err != nil { - return errorResult(fmt.Sprintf("failed to marshal snapshot: %v", err)) - } - return textResult(string(data)) -} - func (s *Server) toolGetAnomalyTimeline(ctx context.Context, args map[string]any) ToolCallResult { if s.graphRAG == nil { return errorResult(errGraphRAGNotInit) @@ -893,9 +383,9 @@ func parseTimeRange(args map[string]any, key string, since *time.Time) { // --- Helpers --- // MaxToolResponseBytes caps the rendered length of any tool response. Without -// this, get_trace / get_graph_snapshot / correlated_signals can produce -// 100MB+ JSON on adversarial input, OOM the process, and stall every -// concurrent MCP call until MCP_CALL_TIMEOUT_MS fires. +// this, large in-memory GraphRAG dumps can produce 100MB+ JSON on adversarial +// input, OOM the process, and stall every concurrent MCP call until +// MCP_CALL_TIMEOUT_MS fires. // // The cap is intentionally set well above any legitimate row-capped tool // response (search_logs at 200 rows is typically <1 MB) so it triggers only diff --git a/internal/mcp/tools_ran20_test.go b/internal/mcp/tools_ran20_test.go deleted file mode 100644 index 7477ae5..0000000 --- a/internal/mcp/tools_ran20_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package mcp - -import ( - "context" - "strings" - "testing" - - "github.com/RandomCodeSpace/otelcontext/internal/storage" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" -) - -// TestFindSimilarLogs_TenantIsolation is the RAN-20 acceptance bar for the MCP -// surface. Two tenants with unique marker strings in their log bodies query -// find_similar_logs; each tenant's response must never contain the other's -// markers. -func TestFindSimilarLogs_TenantIsolation(t *testing.T) { - idx := vectordb.New(1_000) - idx.Add(101, "acme", "checkout", "ERROR", "payment gateway timeout acme-secret-charge-id-abc") - idx.Add(102, "acme", "checkout", "ERROR", "payment gateway refused acme-only-marker-xyz") - idx.Add(201, "globex", "auth", "ERROR", "payment gateway token expired globex-secret-session-123") - idx.Add(202, "globex", "auth", "ERROR", "payment gateway 500 internal globex-only-marker-qqq") - - srv := &Server{vectorIdx: idx, defaultTenant: storage.DefaultTenantID} - args := map[string]any{"query": "payment gateway", "limit": float64(50)} - - // Acme - acmeRes := srv.toolFindSimilarLogs(storage.WithTenantContext(context.Background(), "acme"), args) - if acmeRes.IsError { - t.Fatalf("acme call errored: %+v", acmeRes) - } - acmeBody := concatContent(acmeRes.Content) - for _, forbidden := range []string{"globex-secret-session-123", "globex-only-marker-qqq", `"LogID": 201`, `"LogID": 202`} { - if strings.Contains(acmeBody, forbidden) { - t.Fatalf("acme leaked globex content %q in body:\n%s", forbidden, acmeBody) - } - } - if !strings.Contains(acmeBody, "acme-secret-charge-id-abc") && !strings.Contains(acmeBody, "acme-only-marker-xyz") { - t.Fatalf("acme did not receive its own rows:\n%s", acmeBody) - } - - // Globex - gRes := srv.toolFindSimilarLogs(storage.WithTenantContext(context.Background(), "globex"), args) - if gRes.IsError { - t.Fatalf("globex call errored: %+v", gRes) - } - gBody := concatContent(gRes.Content) - for _, forbidden := range []string{"acme-secret-charge-id-abc", "acme-only-marker-xyz", `"LogID": 101`, `"LogID": 102`} { - if strings.Contains(gBody, forbidden) { - t.Fatalf("globex leaked acme content %q in body:\n%s", forbidden, gBody) - } - } -} - -// TestFindSimilarLogs_NoTenantFallsBackToDefault proves that a context with no -// tenant value is coerced to the server default — it must NOT bleed into -// another tenant's rows. -func TestFindSimilarLogs_NoTenantFallsBackToDefault(t *testing.T) { - idx := vectordb.New(100) - idx.Add(1, "acme", "svc", "ERROR", "acme secret body only") - - srv := &Server{vectorIdx: idx, defaultTenant: storage.DefaultTenantID} - args := map[string]any{"query": "secret body"} - - res := srv.toolFindSimilarLogs(context.Background(), args) - if res.IsError { - t.Fatalf("unexpected error: %+v", res) - } - if strings.Contains(concatContent(res.Content), "acme secret body only") { - t.Fatalf("no-tenant call leaked acme content:\n%s", concatContent(res.Content)) - } -} - -func concatContent(items []ContentItem) string { - var b strings.Builder - for _, c := range items { - b.WriteString(c.Text) - } - return b.String() -} From 2521663a067aa4e831ea8a4fa126b15802471af9 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 18:52:58 +0000 Subject: [PATCH 02/11] refactor(vectordb): drop package and TF-IDF semantic similarity path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vectordb package was a pure-Go TF-IDF index for semantic log search, backing one MCP tool (find_similar_logs, cut in the prior commit) and one HTTP endpoint (/api/logs/similar). With the kept search_logs MCP tool already routing through SQLite FTS5 / pg_trgm GIN, the in-memory TF-IDF index is no longer reachable by any survivor. Removing it reclaims ~5-15% of resident heap on a 120-service SQLite deployment that the maxSize=100000 index + 5-minute snapshot loop + startup ReplayFromDB hydrator otherwise consume — heap pressure that contributes to the OOM-within-an-hour failure mode this refactor is solving for. Deletions: - internal/vectordb/ — index.go, snapshot.go, replay.go + tests - internal/api/similar_handler.go + test — the /api/logs/similar route - internal/storage/log_repo_replay_test.go + LogsForVectorReplay() and ListRecentHighSeverityLogsAllTenants() (only the vectordb hydrator read these; no other caller) - internal/graphrag/clustering.go::SimilarErrors() — vectordb-dependent, no production caller; Drain template clustering is the survivor - Vector* fields on telemetry.Metrics + RecordVector* observer methods - VectorIndexMaxEntries / VectorIndexSnapshotPath / VectorIndexSnapshotInterval on config.Config Signature changes: - graphrag.New(repo, tsdbAgg, ringBuf, cfg) — vectordb arg removed - mcp.New(defaultTenant, repo, metrics, svcGraph) — vectordb arg removed - ui.NewServer(repo, metrics, topo) — vectordb arg removed - api.Server.SetVectorIndex removed Operator migration: - The data/vectordb.snapshot file is left in place on disk; the loader that read it at boot is deleted, so it becomes a stale file that is safe to remove by hand. No automatic cleanup. - MCP clients calling find_similar_logs already receive "unknown tool" after the prior commit; the HTTP /api/logs/similar route now 404s. --- internal/api/server.go | 22 +- internal/api/similar_handler.go | 44 --- internal/api/similar_handler_test.go | 117 -------- internal/config/config.go | 20 -- internal/graphrag/builder.go | 15 +- internal/graphrag/builder_test.go | 6 +- internal/graphrag/clustering.go | 88 +----- internal/graphrag/migrate_test.go | 2 +- internal/mcp/robustness_test.go | 2 +- internal/mcp/server.go | 8 +- internal/mcp/server_ran22_test.go | 6 +- internal/mcp/tenant_isolation_test.go | 15 +- internal/storage/log_repo.go | 55 ---- internal/storage/log_repo_replay_test.go | 138 ---------- internal/telemetry/metrics.go | 75 ----- internal/ui/ui.go | 9 +- internal/vectordb/index.go | 334 ----------------------- internal/vectordb/index_test.go | 136 --------- internal/vectordb/replay.go | 74 ----- internal/vectordb/replay_test.go | 161 ----------- internal/vectordb/snapshot.go | 317 --------------------- internal/vectordb/snapshot_test.go | 325 ---------------------- main.go | 109 +------- 23 files changed, 43 insertions(+), 2035 deletions(-) delete mode 100644 internal/api/similar_handler.go delete mode 100644 internal/api/similar_handler_test.go delete mode 100644 internal/storage/log_repo_replay_test.go delete mode 100644 internal/vectordb/index.go delete mode 100644 internal/vectordb/index_test.go delete mode 100644 internal/vectordb/replay.go delete mode 100644 internal/vectordb/replay_test.go delete mode 100644 internal/vectordb/snapshot.go delete mode 100644 internal/vectordb/snapshot_test.go diff --git a/internal/api/server.go b/internal/api/server.go index 4cd6318..1f838d0 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -10,19 +10,17 @@ import ( "github.com/RandomCodeSpace/otelcontext/internal/realtime" "github.com/RandomCodeSpace/otelcontext/internal/storage" "github.com/RandomCodeSpace/otelcontext/internal/telemetry" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) // Server handles HTTP API requests. type Server struct { - repo *storage.Repository - hub *realtime.Hub - eventHub *realtime.EventHub - metrics *telemetry.Metrics - cache *cache.TTLCache - graph *graph.Graph // in-memory service dependency graph (may be nil before first build) - graphRAG *graphrag.GraphRAG // layered GraphRAG for advanced queries - vectorIdx *vectordb.Index // TF-IDF semantic log search index + repo *storage.Repository + hub *realtime.Hub + eventHub *realtime.EventHub + metrics *telemetry.Metrics + cache *cache.TTLCache + graph *graph.Graph // in-memory service dependency graph (may be nil before first build) + graphRAG *graphrag.GraphRAG // layered GraphRAG for advanced queries // Saturation probes consulted by /ready. Each returns a fullness // fraction in [0.0, 1.0]; nil disables the corresponding check. @@ -53,11 +51,6 @@ func (s *Server) SetGraphRAG(g *graphrag.GraphRAG) { s.graphRAG = g } -// SetVectorIndex wires the TF-IDF vector index for semantic log search. -func (s *Server) SetVectorIndex(idx *vectordb.Index) { - s.vectorIdx = idx -} - // SetDLQSaturationProbe registers a callback returning DLQ disk fullness as // a fraction in [0.0, 1.0]. Used by /ready to flip to 503 when DLQ is at // risk of FIFO-evicting unflushed batches. Pass nil to disable the check. @@ -96,7 +89,6 @@ func (s *Server) RegisterRoutes(mux *http.ServeMux) { // Logs mux.HandleFunc("GET /api/logs", s.handleGetLogs) mux.HandleFunc("GET /api/logs/context", s.handleGetLogContext) - mux.HandleFunc("GET /api/logs/similar", s.handleGetSimilarLogs) mux.HandleFunc("GET /api/logs/{id}/insight", s.handleGetLogInsight) // Admin & System diff --git a/internal/api/similar_handler.go b/internal/api/similar_handler.go deleted file mode 100644 index ac0fe57..0000000 --- a/internal/api/similar_handler.go +++ /dev/null @@ -1,44 +0,0 @@ -package api - -import ( - "encoding/json" - "net/http" - "strconv" - - "github.com/RandomCodeSpace/otelcontext/internal/storage" -) - -// handleGetSimilarLogs handles GET /api/logs/similar?q=&limit=10 -// Returns logs semantically similar to the query string using TF-IDF cosine similarity. -func (s *Server) handleGetSimilarLogs(w http.ResponseWriter, r *http.Request) { - if s.vectorIdx == nil { - http.Error(w, "vector index not initialized", http.StatusServiceUnavailable) - return - } - - query := r.URL.Query().Get("q") - if query == "" { - http.Error(w, "q parameter is required", http.StatusBadRequest) - return - } - - limit := 10 - if lStr := r.URL.Query().Get("limit"); lStr != "" { - if n, err := strconv.Atoi(lStr); err == nil && n > 0 { - limit = n - } - } - if limit > 50 { - limit = 50 - } - - tenant := storage.TenantFromContext(r.Context()) - results := s.vectorIdx.Search(tenant, query, limit) - - w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(map[string]any{ - "query": query, - "count": len(results), - "results": results, - }) -} diff --git a/internal/api/similar_handler_test.go b/internal/api/similar_handler_test.go deleted file mode 100644 index 69af324..0000000 --- a/internal/api/similar_handler_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package api - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/RandomCodeSpace/otelcontext/internal/config" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" -) - -// TestSimilarHandler_TenantIsolation is the RAN-20 acceptance bar for the HTTP -// surface. Two tenants with distinct corpora query /api/logs/similar; each -// sees ZERO rows belonging to the other tenant. -func TestSimilarHandler_TenantIsolation(t *testing.T) { - idx := vectordb.New(1_000) - idx.Add(101, "acme", "checkout", "ERROR", "payment gateway timeout charging customer") - idx.Add(102, "acme", "checkout", "ERROR", "payment gateway refused charge insufficient funds") - idx.Add(201, "globex", "auth", "ERROR", "payment gateway token expired for session") - idx.Add(202, "globex", "auth", "ERROR", "payment gateway 500 internal error while authenticating") - - srv := &Server{vectorIdx: idx} - mux := http.NewServeMux() - mux.HandleFunc("GET /api/logs/similar", srv.handleGetSimilarLogs) - handler := TenantMiddleware(&config.Config{DefaultTenant: "default"})(mux) - - acmeIDs := map[float64]bool{101: true, 102: true} - globexIDs := map[float64]bool{201: true, 202: true} - - q := url.Values{} - q.Set("q", "payment gateway") - q.Set("limit", "50") - path := "/api/logs/similar?" + q.Encode() - - // Tenant A - aRec := httptest.NewRecorder() - aReq := httptest.NewRequest(http.MethodGet, path, nil) - aReq.Header.Set(TenantHeader, "acme") - handler.ServeHTTP(aRec, aReq) - if aRec.Code != http.StatusOK { - t.Fatalf("acme: want 200, got %d body=%q", aRec.Code, aRec.Body.String()) - } - acme := decodeResults(t, aRec) - if len(acme) == 0 { - t.Fatalf("acme got zero hits despite matching corpus") - } - for _, r := range acme { - if !acmeIDs[r.ID] { - t.Fatalf("acme leaked cross-tenant id=%v tenant=%q body=%q", r.ID, r.Tenant, r.Body) - } - } - - // Tenant B - gRec := httptest.NewRecorder() - gReq := httptest.NewRequest(http.MethodGet, path, nil) - gReq.Header.Set(TenantHeader, "globex") - handler.ServeHTTP(gRec, gReq) - if gRec.Code != http.StatusOK { - t.Fatalf("globex: want 200, got %d", gRec.Code) - } - globex := decodeResults(t, gRec) - if len(globex) == 0 { - t.Fatalf("globex got zero hits despite matching corpus") - } - for _, r := range globex { - if !globexIDs[r.ID] { - t.Fatalf("globex leaked cross-tenant id=%v tenant=%q body=%q", r.ID, r.Tenant, r.Body) - } - } -} - -// TestSimilarHandler_UnknownTenantReturnsEmpty confirms a request bearing an -// unknown tenant header returns zero results — the handler must not silently -// fall back to another tenant's rows. -func TestSimilarHandler_UnknownTenantReturnsEmpty(t *testing.T) { - idx := vectordb.New(100) - idx.Add(1, "acme", "svc", "ERROR", "database connection refused upstream") - - srv := &Server{vectorIdx: idx} - mux := http.NewServeMux() - mux.HandleFunc("GET /api/logs/similar", srv.handleGetSimilarLogs) - handler := TenantMiddleware(&config.Config{DefaultTenant: "default"})(mux) - - rec := httptest.NewRecorder() - req := httptest.NewRequest(http.MethodGet, "/api/logs/similar?q=database+connection", nil) - req.Header.Set(TenantHeader, "initech") - handler.ServeHTTP(rec, req) - - if rec.Code != http.StatusOK { - t.Fatalf("want 200, got %d", rec.Code) - } - if r := decodeResults(t, rec); len(r) != 0 { - t.Fatalf("unknown tenant saw %d cross-tenant hits", len(r)) - } -} - -type similarResult struct { - ID float64 `json:"LogID"` - Tenant string `json:"Tenant"` - ServiceName string `json:"ServiceName"` - Severity string `json:"Severity"` - Body string `json:"Body"` - Score float64 `json:"Score"` -} - -func decodeResults(t *testing.T, rec *httptest.ResponseRecorder) []similarResult { - t.Helper() - var env struct { - Results []similarResult `json:"results"` - } - if err := json.Unmarshal(rec.Body.Bytes(), &env); err != nil { - t.Fatalf("decode response: %v (body=%q)", err, rec.Body.String()) - } - return env.Results -} diff --git a/internal/config/config.go b/internal/config/config.go index 68c6423..ab6817d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -114,21 +114,6 @@ type Config struct { // Compression CompressionLevel string // "default", "fast", "best" - // Vector Index - VectorIndexMaxEntries int - - // VectorIndexSnapshotPath is the on-disk location for periodic vectordb - // snapshots. When empty, persistence is disabled and the index rebuilds - // from DB on every restart (legacy behaviour). Default - // "data/vectordb.snapshot". - VectorIndexSnapshotPath string - - // VectorIndexSnapshotInterval, e.g. "5m". When set and - // VectorIndexSnapshotPath is non-empty, the index serializes its state - // to disk on this cadence. "0" / empty disables periodic writes (a - // final snapshot still fires on graceful shutdown). Default "5m". - VectorIndexSnapshotInterval string - // LogFTSEnabled toggles SQLite FTS5 provisioning + querying. The FTS5 // inverted index typically consumes 30-40% of SQLite DB disk for // log-heavy workloads, while the LIKE fallback (log_repo.go:105) keeps @@ -302,11 +287,6 @@ func Load(customPath string) (*Config, error) { // Compression CompressionLevel: getEnv("COMPRESSION_LEVEL", "default"), - // Vector - VectorIndexMaxEntries: getEnvInt("VECTOR_INDEX_MAX_ENTRIES", 100000), - VectorIndexSnapshotPath: getEnv("VECTOR_INDEX_SNAPSHOT_PATH", "data/vectordb.snapshot"), - VectorIndexSnapshotInterval: getEnv("VECTOR_INDEX_SNAPSHOT_INTERVAL", "5m"), - // Log search FTS5 toggle (SQLite only). Default off — see field comment. LogFTSEnabled: parseTruthy(getEnv("LOG_FTS_ENABLED", "")), diff --git a/internal/graphrag/builder.go b/internal/graphrag/builder.go index 8be781f..e2b058e 100644 --- a/internal/graphrag/builder.go +++ b/internal/graphrag/builder.go @@ -11,7 +11,6 @@ import ( "github.com/RandomCodeSpace/otelcontext/internal/storage" "github.com/RandomCodeSpace/otelcontext/internal/telemetry" "github.com/RandomCodeSpace/otelcontext/internal/tsdb" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) // panicMetrics is an optional hook for incrementing the panics-recovered @@ -90,10 +89,9 @@ type GraphRAG struct { tenants map[string]*tenantStores tenantsMu sync.RWMutex - repo *storage.Repository - vectorIdx *vectordb.Index - tsdbAgg *tsdb.Aggregator - ringBuf *tsdb.RingBuffer + repo *storage.Repository + tsdbAgg *tsdb.Aggregator + ringBuf *tsdb.RingBuffer drain *Drain // Drain log-template miner (see drain.go) @@ -206,7 +204,11 @@ func DefaultConfig() Config { } // New creates a new GraphRAG coordinator. -func New(repo *storage.Repository, vectorIdx *vectordb.Index, tsdbAgg *tsdb.Aggregator, ringBuf *tsdb.RingBuffer, cfg Config) *GraphRAG { +// +// The vectordb-backed semantic similarity path was removed on 2026-05-24 +// along with the find_similar_logs MCP tool — log clustering now relies +// solely on the Drain template miner (see drain.go). +func New(repo *storage.Repository, tsdbAgg *tsdb.Aggregator, ringBuf *tsdb.RingBuffer, cfg Config) *GraphRAG { if cfg.TraceTTL == 0 { cfg.TraceTTL = defaultTraceTTL } @@ -229,7 +231,6 @@ func New(repo *storage.Repository, vectorIdx *vectordb.Index, tsdbAgg *tsdb.Aggr g := &GraphRAG{ tenants: make(map[string]*tenantStores), repo: repo, - vectorIdx: vectorIdx, tsdbAgg: tsdbAgg, ringBuf: ringBuf, drain: NewDrain(), diff --git a/internal/graphrag/builder_test.go b/internal/graphrag/builder_test.go index 3639c96..5c26222 100644 --- a/internal/graphrag/builder_test.go +++ b/internal/graphrag/builder_test.go @@ -30,7 +30,7 @@ func newTestRepo(t *testing.T) *storage.Repository { // events asynchronously; tests must call Stop() via t.Cleanup. func newTestGraphRAG(t *testing.T) *GraphRAG { t.Helper() - g := New(nil, nil, nil, nil, DefaultConfig()) + g := New(nil, nil, nil, DefaultConfig()) // Start only the event workers — the background refresh/snapshot/anomaly // loops require a repo, which this helper intentionally does not wire. ctx, cancel := context.WithCancel(context.Background()) @@ -112,7 +112,7 @@ func TestRefresh_PopulatesErrorCountFromDBStatus(t *testing.T) { // Build GraphRAG with the seeded repo, skip starting background loops; // invoke the rebuild path directly. - g := New(repo, nil, nil, nil, DefaultConfig()) + g := New(repo, nil, nil, DefaultConfig()) t.Cleanup(g.Stop) g.rebuildAllTenantsFromDB(context.Background()) @@ -134,7 +134,7 @@ func TestRefresh_PopulatesErrorCountFromDBStatus(t *testing.T) { func TestOnSpanIngested_DropsIncrementMetric(t *testing.T) { // Build a GraphRAG WITHOUT starting any event workers so the channel // fills up and overflows. - g := New(nil, nil, nil, nil, DefaultConfig()) + g := New(nil, nil, nil, DefaultConfig()) t.Cleanup(g.Stop) // Fill the buffer beyond capacity. Use the package constant so the test diff --git a/internal/graphrag/clustering.go b/internal/graphrag/clustering.go index 574a6ec..2745c7e 100644 --- a/internal/graphrag/clustering.go +++ b/internal/graphrag/clustering.go @@ -1,16 +1,12 @@ package graphrag -// Log clustering is now performed by the Drain template miner (see drain.go). +// Log clustering is performed by the Drain template miner (see drain.go). // processLog() in builder.go calls GraphRAG.clusterLog() which delegates to -// the shared *Drain instance. The vectordb.Index (TF-IDF) is still used for -// SimilarErrors — similarity search across mined templates. +// the shared *Drain instance. import ( - "context" "fmt" "time" - - "github.com/RandomCodeSpace/otelcontext/internal/storage" ) // clusterLog runs the log body through Drain and upserts a LogClusterNode @@ -53,83 +49,3 @@ func (g *GraphRAG) clusterLog(stores *tenantStores, service, body, severity stri ) return clusterID } - -// SimilarErrors finds log clusters similar to a given cluster using the vector -// index, scoped to the tenant carried on ctx. Cross-tenant hits are impossible -// because the underlying vectordb partitions docs per tenant and this lookup -// resolves the SignalStore through storesFor(ctx). -func (g *GraphRAG) SimilarErrors(ctx context.Context, clusterID string, k int) []LogClusterNode { - if k <= 0 { - k = 10 - } - - stores := g.storesFor(ctx) - - stores.signals.mu.RLock() - cluster, ok := stores.signals.LogClusters[clusterID] - stores.signals.mu.RUnlock() - if !ok { - return nil - } - - // Use vectordb to find similar logs based on the mined template. - if g.vectorIdx == nil { - return nil - } - query := cluster.Template - if query == "" && len(cluster.TemplateTokens) > 0 { - query = joinTokens(cluster.TemplateTokens) - } - // vectordb.Index.Search takes the tenant string directly; resolve it - // from ctx via the same storage helper used by storesFor so both sides - // agree on coercion rules (empty → DefaultTenantID). - tenant := storage.TenantFromContext(ctx) - results := g.vectorIdx.Search(tenant, query, k*2) // over-fetch to filter - - // Map results back to log clusters. - seen := map[string]bool{clusterID: true} - var similar []LogClusterNode - - stores.signals.mu.RLock() - defer stores.signals.mu.RUnlock() - - for _, r := range results { - for _, lc := range stores.signals.LogClusters { - if seen[lc.ID] { - continue - } - for _, e := range stores.signals.Edges { - if e.Type == EdgeEmittedBy && e.FromID == lc.ID && e.ToID == r.ServiceName { - seen[lc.ID] = true - similar = append(similar, *lc) - break - } - } - if len(similar) >= k { - break - } - } - if len(similar) >= k { - break - } - } - - return similar -} - -// joinTokens is a tiny helper to avoid importing strings in this file's -// hot path; equivalent to strings.Join(tokens, " "). -func joinTokens(tokens []string) string { - n := 0 - for _, t := range tokens { - n += len(t) + 1 - } - b := make([]byte, 0, n) - for i, t := range tokens { - if i > 0 { - b = append(b, ' ') - } - b = append(b, t...) - } - return string(b) -} diff --git a/internal/graphrag/migrate_test.go b/internal/graphrag/migrate_test.go index 2cc5df8..30762f6 100644 --- a/internal/graphrag/migrate_test.go +++ b/internal/graphrag/migrate_test.go @@ -31,7 +31,7 @@ func newTestGraphRAGWithDB(t *testing.T) (*GraphRAG, *gorm.DB) { t.Helper() db := newTestGraphRAGDB(t) repo := storage.NewRepositoryFromDB(db, "sqlite") - g := New(repo, nil, nil, nil, DefaultConfig()) + g := New(repo, nil, nil, DefaultConfig()) t.Cleanup(func() { g.Stop() }) return g, db } diff --git a/internal/mcp/robustness_test.go b/internal/mcp/robustness_test.go index 285d0f7..b5b3e53 100644 --- a/internal/mcp/robustness_test.go +++ b/internal/mcp/robustness_test.go @@ -20,7 +20,7 @@ import ( // not the tool internals. func minimalServer(t *testing.T) *Server { t.Helper() - return New("default", nil, nil, nil, nil) + return New("default", nil, nil, nil) } // jsonRPCCallToolBody marshals a tools/call envelope for a fake tool name. diff --git a/internal/mcp/server.go b/internal/mcp/server.go index b1feb68..c331eac 100644 --- a/internal/mcp/server.go +++ b/internal/mcp/server.go @@ -17,7 +17,6 @@ import ( "github.com/RandomCodeSpace/otelcontext/internal/httpconst" "github.com/RandomCodeSpace/otelcontext/internal/storage" "github.com/RandomCodeSpace/otelcontext/internal/telemetry" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) const ( @@ -71,7 +70,6 @@ type Server struct { repo *storage.Repository metrics *telemetry.Metrics svcGraph *graph.Graph - vectorIdx *vectordb.Index graphRAG *graphrag.GraphRAG defaultTenant string @@ -99,12 +97,15 @@ type Server struct { // storage.DefaultTenantID. Required at construction time so production startup // cannot accidentally drop cfg.DefaultTenant — a missing argument is a compile // error rather than a silent regression. +// +// The vectordb-backed semantic similarity argument was removed on 2026-05-24 +// when find_similar_logs was cut from the MCP surface and the vectordb package +// was deleted. func New( defaultTenant string, repo *storage.Repository, metrics *telemetry.Metrics, svcGraph *graph.Graph, - vectorIdx *vectordb.Index, ) *Server { if defaultTenant == "" { defaultTenant = storage.DefaultTenantID @@ -113,7 +114,6 @@ func New( repo: repo, metrics: metrics, svcGraph: svcGraph, - vectorIdx: vectorIdx, defaultTenant: defaultTenant, callSlots: make(chan struct{}, defaultMaxConcurrentCalls), callTimeout: defaultCallTimeout, diff --git a/internal/mcp/server_ran22_test.go b/internal/mcp/server_ran22_test.go index dbf020f..769fb69 100644 --- a/internal/mcp/server_ran22_test.go +++ b/internal/mcp/server_ran22_test.go @@ -18,19 +18,19 @@ import ( // no-header caller). func TestNew_DefaultTenant_FromConstructor(t *testing.T) { t.Run("empty falls back to storage.DefaultTenantID", func(t *testing.T) { - srv := New("", nil, nil, nil, nil) + srv := New("", nil, nil, nil) if srv.defaultTenant != storage.DefaultTenantID { t.Fatalf(`New("") defaultTenant = %q, want %q`, srv.defaultTenant, storage.DefaultTenantID) } }) t.Run("non-empty value is preserved", func(t *testing.T) { - srv := New("acme", nil, nil, nil, nil) + srv := New("acme", nil, nil, nil) if srv.defaultTenant != "acme" { t.Fatalf(`New("acme") defaultTenant = %q, want "acme"`, srv.defaultTenant) } }) t.Run("SetDefaultTenant runtime override still works", func(t *testing.T) { - srv := New("acme", nil, nil, nil, nil) + srv := New("acme", nil, nil, nil) srv.SetDefaultTenant("globex") if srv.defaultTenant != "globex" { t.Fatalf(`SetDefaultTenant("globex") defaultTenant = %q, want "globex"`, srv.defaultTenant) diff --git a/internal/mcp/tenant_isolation_test.go b/internal/mcp/tenant_isolation_test.go index 6ae90f3..d9c537f 100644 --- a/internal/mcp/tenant_isolation_test.go +++ b/internal/mcp/tenant_isolation_test.go @@ -19,7 +19,6 @@ import ( "github.com/RandomCodeSpace/otelcontext/internal/graphrag" "github.com/RandomCodeSpace/otelcontext/internal/storage" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) // tenants exercised by the test. The third row uses an empty header to @@ -67,7 +66,7 @@ func markersFor(scoped string, others []string) (own []string, leak []string) { // snapshot, and anomaly loops are stretched to "never" inside the test // window so the only state that lands in the stores is the data the test // seeds explicitly — making leak assertions deterministic. -func setupTenantIsolationServer(t *testing.T) (*httptest.Server, *graphrag.GraphRAG, *storage.Repository, *vectordb.Index) { +func setupTenantIsolationServer(t *testing.T) (*httptest.Server, *graphrag.GraphRAG, *storage.Repository) { t.Helper() db, err := storage.NewDatabase("sqlite", ":memory:") @@ -82,19 +81,17 @@ func setupTenantIsolationServer(t *testing.T) (*httptest.Server, *graphrag.Graph } repo := storage.NewRepositoryFromDB(db, "sqlite") - vIdx := vectordb.New(1000) - cfg := graphrag.DefaultConfig() cfg.RefreshEvery = 24 * time.Hour cfg.SnapshotEvery = 24 * time.Hour cfg.AnomalyEvery = 24 * time.Hour cfg.WorkerCount = 4 - g := graphrag.New(repo, vIdx, nil, nil, cfg) + g := graphrag.New(repo, nil, nil, cfg) bgCtx, cancel := context.WithCancel(context.Background()) go g.Start(bgCtx) - srv := New("", repo, nil, nil, vIdx) + srv := New("", repo, nil, nil) srv.SetGraphRAG(g) httpSrv := httptest.NewServer(srv.Handler()) @@ -106,7 +103,7 @@ func setupTenantIsolationServer(t *testing.T) (*httptest.Server, *graphrag.Graph _ = repo.Close() }) - return httpSrv, g, repo, vIdx + return httpSrv, g, repo } // seedTenant ingests a small but representative slice of telemetry for @@ -300,7 +297,7 @@ func truncate(s string) string { // asserts each response contains only the caller-tenant's data and never // leaks another tenant's service name, log marker, operation, or anomaly. func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { - ts, g, repo, _ := setupTenantIsolationServer(t) + ts, g, repo := setupTenantIsolationServer(t) now := time.Now().Add(-time.Minute) // a hair in the past so since=now-15m sees us @@ -382,7 +379,7 @@ func TestMCP_TenantIsolation_AllGraphRAGTools(t *testing.T) { // CorrelatedSignals (not just the response text) and asserts each tenant // only ever sees rows tagged with its own marker. func TestMCP_TenantIsolation_DrainClusterIDsStayPerTenant(t *testing.T) { - ts, g, _, _ := setupTenantIsolationServer(t) + ts, g, _ := setupTenantIsolationServer(t) now := time.Now().Add(-time.Minute) // Identical service AND identical log template across tenants — Drain diff --git a/internal/storage/log_repo.go b/internal/storage/log_repo.go index e26c2ad..83985ba 100644 --- a/internal/storage/log_repo.go +++ b/internal/storage/log_repo.go @@ -206,61 +206,6 @@ func (r *Repository) UpdateLogInsight(ctx context.Context, logID uint, insight s return nil } -// LogsForVectorReplay returns ERROR/WARN-family logs with id > sinceID, -// page-bounded by limit and ordered by id ASC. Used at startup by the -// vector-index tail-replay path to pick up DB rows inserted after the last -// snapshot. The id-ascending order lets the caller use the last row's id -// as the next page's sinceID — clean cursor pagination, no offset cost. -// -// Cross-tenant by design: vectordb is a global index with per-doc tenant -// tags enforced at Search time. Not exposed on any tenant-scoped API. -// -// Severity filter is intentionally narrow (ERROR / WARN / WARNING / FATAL / -// CRITICAL) so non-indexed rows don't waste page space; this matches -// vectordb.shouldIndex(). -func (r *Repository) LogsForVectorReplay(ctx context.Context, sinceID uint, limit int) ([]Log, error) { - if limit <= 0 || limit > 100_000 { - limit = 10_000 - } - var logs []Log - err := r.db.WithContext(ctx). - Where("id > ? AND severity IN ?", sinceID, []string{"ERROR", "WARN", "WARNING", "FATAL", "CRITICAL"}). - Order("id ASC"). - Limit(limit). - Find(&logs).Error - if err != nil { - return nil, fmt.Errorf("logs for vector replay: %w", err) - } - return logs, nil -} - -// ListRecentHighSeverityLogsAllTenants returns recent logs of the given -// severity across EVERY tenant, each row carrying its own TenantID. This is an -// administrative read used exclusively by the vector index's startup -// hydration path, which fans rows out to per-tenant shards. It is not exposed -// on any tenant-scoped API surface — tenant isolation for read paths must -// otherwise be preserved via the context-driven WHERE clause. -func (r *Repository) ListRecentHighSeverityLogsAllTenants(ctx context.Context, severity string, since, until time.Time, limit int) ([]Log, error) { - if limit <= 0 { - limit = 5000 - } - q := r.db.WithContext(ctx).Model(&Log{}) - if severity != "" { - q = q.Where(sqlWhereSeverity, severity) - } - if !since.IsZero() { - q = q.Where(sqlWhereTimestampGTE, since) - } - if !until.IsZero() { - q = q.Where(sqlWhereTimestampLTE, until) - } - var logs []Log - if err := q.Order(sqlOrderTimestampDesc).Limit(limit).Find(&logs).Error; err != nil { - return nil, fmt.Errorf("failed to list recent logs all tenants: %w", err) - } - return logs, nil -} - // PurgeLogs deletes logs older than the given timestamp in a single statement. // Suitable for SQLite; for Postgres at large retention volumes prefer PurgeLogsBatched. func (r *Repository) PurgeLogs(olderThan time.Time) (int64, error) { diff --git a/internal/storage/log_repo_replay_test.go b/internal/storage/log_repo_replay_test.go deleted file mode 100644 index 5b60cac..0000000 --- a/internal/storage/log_repo_replay_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package storage - -import ( - "context" - "testing" - "time" -) - -// TestLogsForVectorReplay_ReturnsErrorAndWarnOnly verifies the severity -// filter matches vectordb.shouldIndex (ERROR/WARN/WARNING/FATAL/CRITICAL). -// INFO and DEBUG rows must be excluded so the page isn't bloated with rows -// vectordb would drop anyway. -func TestLogsForVectorReplay_ReturnsErrorAndWarnOnly(t *testing.T) { - repo := newTestRepo(t) - now := time.Now().UTC() - rows := []Log{ - {TenantID: "default", Severity: "ERROR", Body: "panic", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "WARN", Body: "slow", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "WARNING", Body: "deprecated", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "FATAL", Body: "OOM", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "CRITICAL", Body: "deadlock", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "INFO", Body: "request handled", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "DEBUG", Body: "trace data", ServiceName: "svc", Timestamp: now}, - } - if err := repo.db.Create(&rows).Error; err != nil { - t.Fatalf("seed: %v", err) - } - - got, err := repo.LogsForVectorReplay(context.Background(), 0, 100) - if err != nil { - t.Fatalf("LogsForVectorReplay: %v", err) - } - if len(got) != 5 { - t.Errorf("got %d rows, want 5 (ERROR+WARN+WARNING+FATAL+CRITICAL)", len(got)) - } - for _, l := range got { - if l.Severity == "INFO" || l.Severity == "DEBUG" { - t.Errorf("unexpected severity in result: %q (id=%d)", l.Severity, l.ID) - } - } -} - -// TestLogsForVectorReplay_RespectsSinceID verifies the cursor pagination -// contract: rows with id <= sinceID are excluded so the caller can advance -// across pages without re-fetching. -func TestLogsForVectorReplay_RespectsSinceID(t *testing.T) { - repo := newTestRepo(t) - now := time.Now().UTC() - for range 5 { - repo.db.Create(&Log{TenantID: "default", Severity: "ERROR", Body: "x", ServiceName: "svc", Timestamp: now}) - } - - page1, err := repo.LogsForVectorReplay(context.Background(), 0, 2) - if err != nil { - t.Fatalf("page1: %v", err) - } - if len(page1) != 2 { - t.Fatalf("page1: got %d rows, want 2", len(page1)) - } - // IDs must be strictly ascending. - if page1[0].ID >= page1[1].ID { - t.Errorf("page1 not ascending: %d, %d", page1[0].ID, page1[1].ID) - } - - page2, err := repo.LogsForVectorReplay(context.Background(), page1[1].ID, 2) - if err != nil { - t.Fatalf("page2: %v", err) - } - if len(page2) != 2 { - t.Fatalf("page2: got %d rows, want 2", len(page2)) - } - for _, r := range page2 { - if r.ID <= page1[1].ID { - t.Errorf("page2 contains id=%d <= page1 cursor=%d", r.ID, page1[1].ID) - } - } - - page3, err := repo.LogsForVectorReplay(context.Background(), page2[1].ID, 2) - if err != nil { - t.Fatalf("page3: %v", err) - } - if len(page3) != 1 { - t.Errorf("page3: got %d rows, want 1 (final partial page)", len(page3)) - } -} - -// TestLogsForVectorReplay_CrossTenant verifies the replay is intentionally -// cross-tenant — vectordb is a global accelerator and per-doc tenant tags -// enforce isolation at Search time. -func TestLogsForVectorReplay_CrossTenant(t *testing.T) { - repo := newTestRepo(t) - now := time.Now().UTC() - repo.db.Create(&[]Log{ - {TenantID: "acme", Severity: "ERROR", Body: "a", ServiceName: "svc", Timestamp: now}, - {TenantID: "globex", Severity: "ERROR", Body: "b", ServiceName: "svc", Timestamp: now}, - {TenantID: "default", Severity: "ERROR", Body: "c", ServiceName: "svc", Timestamp: now}, - }) - - // No tenant context — replay is cross-tenant by design. - got, err := repo.LogsForVectorReplay(context.Background(), 0, 100) - if err != nil { - t.Fatalf("LogsForVectorReplay: %v", err) - } - if len(got) != 3 { - t.Errorf("got %d rows across tenants, want 3", len(got)) - } - tenants := map[string]int{} - for _, l := range got { - tenants[l.TenantID]++ - } - for _, name := range []string{"acme", "globex", "default"} { - if tenants[name] != 1 { - t.Errorf("tenant %q: got %d rows, want 1", name, tenants[name]) - } - } -} - -// TestLogsForVectorReplay_LimitClamp verifies the limit is clamped to a -// safe default when caller passes 0 / negative / absurdly large values. -func TestLogsForVectorReplay_LimitClamp(t *testing.T) { - repo := newTestRepo(t) - now := time.Now().UTC() - for range 3 { - repo.db.Create(&Log{TenantID: "default", Severity: "ERROR", Body: "x", ServiceName: "svc", Timestamp: now}) - } - - for _, lim := range []int{0, -1, 999_999} { - got, err := repo.LogsForVectorReplay(context.Background(), 0, lim) - if err != nil { - t.Errorf("limit=%d: unexpected err=%v", lim, err) - continue - } - // 3 rows seeded; default cap is 10k, so all 3 must come back. - if len(got) != 3 { - t.Errorf("limit=%d: got %d rows, want 3", lim, len(got)) - } - } -} diff --git a/internal/telemetry/metrics.go b/internal/telemetry/metrics.go index e6a3d54..44f0afc 100644 --- a/internal/telemetry/metrics.go +++ b/internal/telemetry/metrics.go @@ -127,26 +127,6 @@ type Metrics struct { // --- Dashboard p99 (Task 10) --- DashboardP99RowCapHitsTotal prometheus.Counter - // --- Vectordb persistence --- - // VectorSnapshotWritesTotal counts snapshot write attempts, labeled - // {result=success|failure}. Alert on rate(failure[10m]) > 0. - VectorSnapshotWritesTotal *prometheus.CounterVec - // VectorSnapshotDurationSeconds is the WriteSnapshot wall-clock - // duration. Histogram so operators can SLO p95 / p99. - VectorSnapshotDurationSeconds prometheus.Histogram - // VectorSnapshotSizeBytes gauges the on-disk size of the latest - // successful snapshot. Sudden growth signals a maxSize bump or a - // schema change worth investigating. - VectorSnapshotSizeBytes prometheus.Gauge - // VectorSnapshotLoadTotal counts startup snapshot loads, labeled - // {result=success|missing|corrupt}. corrupt = magic/version/crc/decode - // failure — caller falls back to a full DB rebuild. - VectorSnapshotLoadTotal *prometheus.CounterVec - // VectorReplayLogsTotal accumulates rows processed by ReplayFromDB - // across the daemon's lifetime. The rate spikes only at startup - // (catching the snapshot→now gap), then stays flat. - VectorReplayLogsTotal prometheus.Counter - // Atomic counters for JSON health endpoint (avoids scraping Prometheus) totalIngested atomic.Int64 activeConns atomic.Int64 @@ -391,64 +371,9 @@ func New() *Metrics { Name: "otelcontext_dashboard_p99_row_cap_hits_total", Help: "Number of dashboard p99 computations that hit the SQLite row cap (200k). Indicates the dataset is too large for in-memory p99 — use Postgres for prod.", }) - m.VectorSnapshotWritesTotal = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "otelcontext_vectordb_snapshot_writes_total", - Help: "Vectordb snapshot write attempts by result (success|failure). Alert on rate(...{result=\"failure\"}[10m]) > 0.", - }, []string{"result"}) - m.VectorSnapshotDurationSeconds = promauto.NewHistogram(prometheus.HistogramOpts{ - Name: "otelcontext_vectordb_snapshot_duration_seconds", - Help: "Wall-clock duration of WriteSnapshot, including encode + atomic rename.", - Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5}, - }) - m.VectorSnapshotSizeBytes = promauto.NewGauge(prometheus.GaugeOpts{ - Name: "otelcontext_vectordb_snapshot_size_bytes", - Help: "On-disk size of the latest successful vectordb snapshot.", - }) - m.VectorSnapshotLoadTotal = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "otelcontext_vectordb_snapshot_load_total", - Help: "Vectordb snapshot load attempts at startup by result (success|missing|corrupt).", - }, []string{"result"}) - m.VectorReplayLogsTotal = promauto.NewCounter(prometheus.CounterOpts{ - Name: "otelcontext_vectordb_replay_logs_total", - Help: "Total log rows processed by vectordb ReplayFromDB across the daemon's lifetime.", - }) return m } -// RecordVectorSnapshotWrite is the observer hook the vectordb snapshot -// path calls after each WriteSnapshot attempt. result is "success" or -// "failure"; size is the on-disk byte count after a successful rename -// (zero on failure). -func (m *Metrics) RecordVectorSnapshotWrite(result string, duration time.Duration, size int64) { - if m == nil || m.VectorSnapshotWritesTotal == nil { - return - } - m.VectorSnapshotWritesTotal.WithLabelValues(result).Inc() - m.VectorSnapshotDurationSeconds.Observe(duration.Seconds()) - if result == "success" && size > 0 { - m.VectorSnapshotSizeBytes.Set(float64(size)) - } -} - -// RecordVectorSnapshotLoad is the observer hook for startup snapshot -// loads. result is "success", "missing" (first start, no prior file), -// or "corrupt" (any decode/CRC/version error → full rebuild fallback). -func (m *Metrics) RecordVectorSnapshotLoad(result string) { - if m == nil || m.VectorSnapshotLoadTotal == nil { - return - } - m.VectorSnapshotLoadTotal.WithLabelValues(result).Inc() -} - -// RecordVectorReplayLogs adds rows processed by ReplayFromDB to the -// lifetime counter. Called once after the startup tail-replay completes. -func (m *Metrics) RecordVectorReplayLogs(count int) { - if m == nil || m.VectorReplayLogsTotal == nil || count <= 0 { - return - } - m.VectorReplayLogsTotal.Add(float64(count)) -} - // StartRuntimeMetrics samples Go runtime stats every 15 seconds. func (m *Metrics) StartRuntimeMetrics() { go func() { diff --git a/internal/ui/ui.go b/internal/ui/ui.go index b8b813d..1b1d9d8 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -11,7 +11,6 @@ import ( "github.com/RandomCodeSpace/otelcontext/internal/graph" "github.com/RandomCodeSpace/otelcontext/internal/storage" "github.com/RandomCodeSpace/otelcontext/internal/telemetry" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" ) // spaFS wraps an fs.FS so http.FileServer transparently serves index.html @@ -48,17 +47,19 @@ type Server struct { repo *storage.Repository metrics *telemetry.Metrics topo *graph.Graph - vidx *vectordb.Index mcpEnabled bool mcpPath string } -func NewServer(repo *storage.Repository, metrics *telemetry.Metrics, topo *graph.Graph, vidx *vectordb.Index) *Server { +// NewServer constructs the embedded-UI server. +// +// The vectordb argument was removed on 2026-05-24 when the vectordb package +// was deleted alongside the find_similar_logs MCP tool cut. +func NewServer(repo *storage.Repository, metrics *telemetry.Metrics, topo *graph.Graph) *Server { return &Server{ repo: repo, metrics: metrics, topo: topo, - vidx: vidx, mcpPath: "/mcp", } } diff --git a/internal/vectordb/index.go b/internal/vectordb/index.go deleted file mode 100644 index 13777f4..0000000 --- a/internal/vectordb/index.go +++ /dev/null @@ -1,334 +0,0 @@ -// Package vectordb provides an embedded TF-IDF / cosine-similarity vector index -// for semantic log search. It is a pure-Go, no-CGO, in-process accelerator. -// The relational DB remains the source of truth; this index is fully rebuildable. -package vectordb - -import ( - "math" - "sort" - "strings" - "sync" - "time" - "unicode" -) - -// defaultTenantID is the tenant assigned when the caller passes an empty -// tenant string. Mirrors storage.DefaultTenantID; duplicated here to avoid -// pulling internal/storage into vectordb's import graph. -const defaultTenantID = "default" - -// LogVector represents an indexed log entry. -// -// Tenant scopes the document so Search can return only the caller's tenant -// rows. The TF-IDF table is shared across tenants — global IDF still gives -// the right rarity signal — but the per-document tenant tag is enforced at -// query time so two tenants with overlapping log bodies stay isolated. -// -// All fields are exported so encoding/gob can serialize the type for -// snapshot persistence (snapshot.go). Vec is the per-doc TF map (term → -// frequency); IDF is held separately on the Index to avoid duplicating -// rarity weights across documents. -type LogVector struct { - LogID uint - Tenant string - ServiceName string - Severity string - Body string - Vec map[string]float64 // TF-IDF sparse vector -} - -// SearchResult is a single similarity hit. -type SearchResult struct { - LogID uint - Tenant string - ServiceName string - Severity string - Body string - Score float64 // cosine similarity 0.0–1.0 -} - -// Index is a thread-safe in-memory TF-IDF vector index for log bodies. -// Only ERROR and WARN logs are indexed to keep it small and relevant. -// -// lastIndexedID records the highest Log.ID Add() has accepted. Persisted -// in the snapshot so a startup tail-replay can pick up DB rows newer than -// this watermark without re-indexing rows already in the snapshot. Tracked -// only for rows that pass shouldIndex(); INFO/DEBUG rows interleaved in -// the same ID range are excluded by the severity filter on replay anyway. -type Index struct { - mu sync.RWMutex - docs []LogVector // indexed log vectors - idf map[string]float64 // global IDF table - maxSize int // FIFO eviction cap - dirty bool // IDF needs recompute - lastIndexedID uint // high watermark of indexed Log.ID - - // snapshotObserver is invoked at the end of each WriteSnapshot - // (success or failure). nil-safe — set via SetSnapshotObserver from - // the wiring layer so vectordb stays free of telemetry imports. - snapshotObserver func(result string, duration time.Duration, size int64) -} - -// New creates a new Index with the given maximum entry cap. -func New(maxSize int) *Index { - if maxSize <= 0 { - maxSize = 100_000 - } - return &Index{ - maxSize: maxSize, - idf: make(map[string]float64), - } -} - -// Add adds a log to the index. Thread-safe. Tenant is recorded with the -// document so Search can filter by it; an empty tenant collapses to -// the platform default at the boundary, matching storage.TenantFromContext. -func (idx *Index) Add(logID uint, tenant, serviceName, severity, body string) { - if !shouldIndex(severity) { - return - } - tokens := tokenize(body) - if len(tokens) == 0 { - return - } - tf := computeTF(tokens) - - if tenant == "" { - tenant = defaultTenantID - } - - idx.mu.Lock() - defer idx.mu.Unlock() - - // High watermark for tail-replay correctness. Bump only after the - // shouldIndex/tokenize gates pass — the replay query is severity- - // filtered too, so non-indexed rows interleaved in the same ID range - // are excluded by SQL anyway. - if logID > idx.lastIndexedID { - idx.lastIndexedID = logID - } - - // Tenant-aware FIFO eviction. When at cap, remove up to maxSize/10 of the - // oldest entries belonging to the inserting tenant so a noisy tenant - // cannot push another tenant's warm rows out of the index (availability - // isolation — the confidentiality invariant is enforced separately by - // doc.Tenant filtering in Search). The new backing slice also releases - // the old array memory on the next GC cycle. - if len(idx.docs) >= idx.maxSize { - toDrop := idx.maxSize / 10 - if toDrop < 1 { - toDrop = 1 - } - kept := make([]LogVector, 0, idx.maxSize) - droppedSame := 0 - for _, d := range idx.docs { - if droppedSame < toDrop && d.Tenant == tenant { - droppedSame++ - continue - } - kept = append(kept, d) - } - // Edge case: the inserting tenant has no prior entries while the - // index is at cap with other tenants' rows. Drop one globally-oldest - // entry so the new tenant can take its first slot. This is the only - // path where a tenant's entry can be evicted by another tenant, and - // it costs at most one row per brand-new tenant. - if droppedSame == 0 && len(kept) > 0 { - kept = kept[1:] - } - idx.docs = kept - idx.dirty = true - } - - idx.docs = append(idx.docs, LogVector{ - LogID: logID, - Tenant: tenant, - ServiceName: serviceName, - Severity: severity, - Body: body, - Vec: tf, - }) - idx.dirty = true -} - -// Search finds the top-k logs most similar to the query string within -// tenant. Documents from other tenants are excluded — the IDF table stays -// global so rarity is computed against the whole corpus, but result rows -// are filtered to the caller's tenant. -func (idx *Index) Search(tenant, query string, k int) []SearchResult { - if k <= 0 { - k = 10 - } - if tenant == "" { - tenant = defaultTenantID - } - tokens := tokenize(query) - if len(tokens) == 0 { - return nil - } - queryTF := computeTF(tokens) - - idx.mu.Lock() - if idx.dirty { - idx.recomputeIDF() - idx.dirty = false - } - // Snapshot IDF and docs for the query (avoids holding lock during scoring). - idfSnap := make(map[string]float64, len(idx.idf)) - for k, v := range idx.idf { - idfSnap[k] = v - } - docs := make([]LogVector, len(idx.docs)) - copy(docs, idx.docs) - idx.mu.Unlock() - - // Build TF-IDF query vector. - queryVec := make(map[string]float64, len(queryTF)) - for term, tf := range queryTF { - queryVec[term] = tf * idfSnap[term] - } - queryNorm := vecNorm(queryVec) - if queryNorm == 0 { - return nil - } - - type scored struct { - doc LogVector - score float64 - } - results := make([]scored, 0, len(docs)) - for _, doc := range docs { - if doc.Tenant != tenant { - continue - } - docVec := make(map[string]float64, len(doc.Vec)) - for term, tf := range doc.Vec { - docVec[term] = tf * idfSnap[term] - } - score := cosineSimilarity(queryVec, queryNorm, docVec) - if score > 0 { - results = append(results, scored{doc, score}) - } - } - - sort.Slice(results, func(i, j int) bool { - return results[i].score > results[j].score - }) - if len(results) > k { - results = results[:k] - } - - out := make([]SearchResult, len(results)) - for i, r := range results { - out[i] = SearchResult{ - LogID: r.doc.LogID, - Tenant: r.doc.Tenant, - ServiceName: r.doc.ServiceName, - Severity: r.doc.Severity, - Body: r.doc.Body, - Score: r.score, - } - } - return out -} - -// Size returns the current number of indexed documents. -func (idx *Index) Size() int { - idx.mu.RLock() - defer idx.mu.RUnlock() - return len(idx.docs) -} - -// LastIndexedID returns the highest Log.ID that has been successfully indexed -// (i.e. passed shouldIndex + tokenize gates and was appended to docs). -// Used by the startup tail-replay path to query DB rows newer than this -// watermark; persisted in the snapshot so replay survives restarts. -func (idx *Index) LastIndexedID() uint { - idx.mu.RLock() - defer idx.mu.RUnlock() - return idx.lastIndexedID -} - -// recomputeIDF rebuilds the IDF table from current docs. Must be called with mu held. -func (idx *Index) recomputeIDF() { - df := make(map[string]int, len(idx.idf)) - for _, doc := range idx.docs { - for term := range doc.Vec { - df[term]++ - } - } - n := float64(len(idx.docs)) - // Replace the entire IDF map to drop stale terms from evicted docs - newIDF := make(map[string]float64, len(df)) - for term, count := range df { - newIDF[term] = math.Log(n/float64(count)) + 1 - } - idx.idf = newIDF -} - -// shouldIndex returns true for severity levels worth indexing. -func shouldIndex(severity string) bool { - s := strings.ToUpper(severity) - return s == "ERROR" || s == "WARN" || s == "WARNING" || s == "FATAL" || s == "CRITICAL" -} - -// tokenize splits text into lowercase alpha tokens, removing stop words. -func tokenize(text string) []string { - words := strings.FieldsFunc(strings.ToLower(text), func(r rune) bool { - return !unicode.IsLetter(r) && !unicode.IsDigit(r) - }) - out := make([]string, 0, len(words)) - for _, w := range words { - if len(w) > 2 && !isStopWord(w) { - out = append(out, w) - } - } - return out -} - -// computeTF returns term-frequency (count / total) for a token list. -func computeTF(tokens []string) map[string]float64 { - counts := make(map[string]int, len(tokens)) - for _, t := range tokens { - counts[t]++ - } - total := float64(len(tokens)) - tf := make(map[string]float64, len(counts)) - for term, count := range counts { - tf[term] = float64(count) / total - } - return tf -} - -func vecNorm(v map[string]float64) float64 { - var sum float64 - for _, val := range v { - sum += val * val - } - return math.Sqrt(sum) -} - -func cosineSimilarity(a map[string]float64, normA float64, b map[string]float64) float64 { - normB := vecNorm(b) - if normA == 0 || normB == 0 { - return 0 - } - var dot float64 - for term, va := range a { - if vb, ok := b[term]; ok { - dot += va * vb - } - } - return dot / (normA * normB) -} - -var stopWords = map[string]struct{}{ - "the": {}, "and": {}, "for": {}, "are": {}, "was": {}, "not": {}, - "with": {}, "this": {}, "that": {}, "from": {}, "has": {}, "but": {}, - "have": {}, "its": {}, "been": {}, "also": {}, "than": {}, "into": {}, -} - -func isStopWord(w string) bool { - _, ok := stopWords[w] - return ok -} diff --git a/internal/vectordb/index_test.go b/internal/vectordb/index_test.go deleted file mode 100644 index 9b9186c..0000000 --- a/internal/vectordb/index_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package vectordb - -import ( - "strconv" - "sync" - "testing" -) - -// TestTenantIsolation_Search is the RAN-20 confidentiality bar: a query on -// tenant A never returns a document indexed under tenant B, even when the -// vocabularies collide on the query terms. -func TestTenantIsolation_Search(t *testing.T) { - idx := New(1_000) - - idx.Add(1, "acme", "checkout", "ERROR", "payment gateway timeout upstream") - idx.Add(2, "acme", "checkout", "ERROR", "payment gateway refused charge") - idx.Add(10, "globex", "auth", "ERROR", "payment gateway token expired") - idx.Add(11, "globex", "auth", "ERROR", "payment gateway 500 internal error") - - acmeHits := idx.Search("acme", "payment gateway timeout", 10) - if len(acmeHits) == 0 { - t.Fatalf("acme search returned zero hits despite matching docs") - } - for _, h := range acmeHits { - if h.Tenant != "acme" || h.LogID >= 10 { - t.Fatalf("acme search leaked id=%d tenant=%q body=%q", h.LogID, h.Tenant, h.Body) - } - } - - globexHits := idx.Search("globex", "payment gateway token", 10) - if len(globexHits) == 0 { - t.Fatalf("globex search returned zero hits despite matching docs") - } - for _, h := range globexHits { - if h.Tenant != "globex" || h.LogID < 10 { - t.Fatalf("globex search leaked id=%d tenant=%q body=%q", h.LogID, h.Tenant, h.Body) - } - } -} - -// TestUnknownTenantReturnsEmpty proves a tenant with no indexed docs returns -// nothing even when other tenants have matching content. -func TestUnknownTenantReturnsEmpty(t *testing.T) { - idx := New(100) - idx.Add(1, "acme", "svc", "ERROR", "database connection refused upstream") - - if got := idx.Search("initech", "database connection", 10); len(got) != 0 { - t.Fatalf("unknown tenant saw %d cross-tenant hits", len(got)) - } -} - -// TestEmptyTenantCoercedToDefault verifies Add and Search coerce an empty -// tenant to the platform default so untenanted callers stay isolated from -// real tenants. -func TestEmptyTenantCoercedToDefault(t *testing.T) { - idx := New(100) - idx.Add(1, "", "svc", "ERROR", "network unreachable upstream host") - - if hits := idx.Search("", "network unreachable", 10); len(hits) != 1 { - t.Fatalf("search with empty tenant: want 1 hit, got %d", len(hits)) - } - if hits := idx.Search(defaultTenantID, "network unreachable", 10); len(hits) != 1 { - t.Fatalf("search with default tenant id: want 1 hit, got %d", len(hits)) - } - if hits := idx.Search("acme", "network unreachable", 10); len(hits) != 0 { - t.Fatalf("acme saw %d cross-tenant hits for default-tenant doc", len(hits)) - } -} - -// TestFIFOEvictionFairness is TechLead's requested assertion: a tenant that -// writes near-cap volume cannot evict another tenant's documents from the -// shared index. Under a naive global-FIFO policy tenant B's flood would -// remove tenant A's older entries and A would silently "lose" its warm -// rows — a confidentiality-safe but availability-breaking failure mode. -func TestFIFOEvictionFairness(t *testing.T) { - const cap = 200 - idx := New(cap) - - // Tenant A writes a small set of distinctive markers. - for i := 0; i < 5; i++ { - idx.Add(uint(1+i), "acme", "checkout", "ERROR", "acme-canary-marker alpha beta gamma "+strconv.Itoa(i)) - } - - // Tenant B floods the index well past the cap — enough to trigger - // multiple eviction cycles. - for i := 0; i < cap*4; i++ { - idx.Add(uint(10_000+i), "globex", "svc", "ERROR", "globex chatter filling the index "+strconv.Itoa(i)) - } - - // Every one of acme's canary rows must still be findable. - hits := idx.Search("acme", "acme-canary-marker alpha beta gamma", 20) - if len(hits) < 5 { - t.Fatalf("eviction unfairness: acme canaries evicted by globex flood. want >=5 hits, got %d", len(hits)) - } - seen := map[uint]bool{} - for _, h := range hits { - if h.Tenant != "acme" { - t.Fatalf("cross-tenant leak during eviction test: id=%d tenant=%q", h.LogID, h.Tenant) - } - seen[h.LogID] = true - } - for id := uint(1); id <= 5; id++ { - if !seen[id] { - t.Fatalf("acme canary id=%d missing after globex flood", id) - } - } -} - -// TestConcurrentTenantAddSearch pins down race-detector cleanliness and -// cross-tenant isolation under concurrent readers/writers. -func TestConcurrentTenantAddSearch(t *testing.T) { - idx := New(5_000) - var wg sync.WaitGroup - - for _, tenant := range []string{"acme", "globex"} { - wg.Add(2) - go func(ten string) { - defer wg.Done() - for i := 0; i < 500; i++ { - idx.Add(uint(i), ten, "svc", "ERROR", ten+" error kafka partition "+strconv.Itoa(i)) - } - }(tenant) - go func(ten string) { - defer wg.Done() - for i := 0; i < 500; i++ { - for _, h := range idx.Search(ten, "kafka partition", 5) { - if h.Tenant != ten { - t.Errorf("tenant %s saw cross-tenant hit tenant=%q body=%q", ten, h.Tenant, h.Body) - return - } - } - } - }(tenant) - } - wg.Wait() -} diff --git a/internal/vectordb/replay.go b/internal/vectordb/replay.go deleted file mode 100644 index 5ec9de5..0000000 --- a/internal/vectordb/replay.go +++ /dev/null @@ -1,74 +0,0 @@ -package vectordb - -import "context" - -// ReplaySource is the minimal contract a backing store fulfills to hydrate -// this Index on startup. Pages are pulled in id-ascending order; the source -// signals end-of-data by returning a slice shorter than the requested limit. -// ReplayFromDB walks pages starting from LastIndexedID() until the source -// returns no more rows. -// -// Vectordb intentionally does NOT import the storage package — keeping it as -// a leaf accelerator means tests can wire any in-memory source without a -// SQLite dependency, and storage is free to evolve its row type without -// breaking vectordb. The wiring layer (cmd/main.go) is responsible for -// projecting storage.Log into ReplayRow. -type ReplaySource interface { - LogsForVectorReplay(ctx context.Context, sinceID uint, limit int) ([]ReplayRow, error) -} - -// ReplayRow is the minimum field set Add() needs. Mirrors the projection a -// storage adapter performs at the boundary. -type ReplayRow struct { - ID uint - Tenant string - ServiceName string - Severity string - Body string -} - -// replayPageSize bounds memory during tail-replay. 10k rows is a reasonable -// trade-off between query overhead per page and peak heap; at typical body -// sizes this stays well under 50 MB resident per page. -const replayPageSize = 10_000 - -// ReplayFromDB walks ReplaySource pages starting from LastIndexedID() and -// feeds each row through Add(). Returns the count of rows processed (Add -// filters by severity, so processed ≠ indexed when the source loosens its -// filter — but the standard storage implementation already pre-filters to -// ERROR/WARN/family so the counts match in practice). -// -// Termination contract: the source signals end-of-data by returning a -// zero-length slice. This lets sources page however they want without -// having to fill every page exactly to replayPageSize — the trade-off is -// one extra round-trip at the tail (fine for a one-shot startup call). -// -// Caller passes a derived ctx so SIGTERM during boot cancels the replay -// cleanly. On any source error, returns the partial count + error so the -// caller can log and proceed with a partially-warm index. -func (idx *Index) ReplayFromDB(ctx context.Context, src ReplaySource) (int, error) { - if src == nil { - return 0, nil - } - sinceID := idx.LastIndexedID() - total := 0 - for { - if err := ctx.Err(); err != nil { - return total, err - } - rows, err := src.LogsForVectorReplay(ctx, sinceID, replayPageSize) - if err != nil { - return total, err - } - if len(rows) == 0 { - return total, nil - } - for _, row := range rows { - idx.Add(row.ID, row.Tenant, row.ServiceName, row.Severity, row.Body) - if row.ID > sinceID { - sinceID = row.ID - } - } - total += len(rows) - } -} diff --git a/internal/vectordb/replay_test.go b/internal/vectordb/replay_test.go deleted file mode 100644 index 28b829a..0000000 --- a/internal/vectordb/replay_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package vectordb - -import ( - "context" - "errors" - "testing" -) - -// fakeSource is an in-memory ReplaySource for unit-testing the page loop -// without a real DB. Pages are produced by a closure so each test can shape -// the source however it likes (multi-page, errors, end-of-data). -type fakeSource struct { - pages [][]ReplayRow // queued pages; consumed in order - calls int - fail error -} - -func (s *fakeSource) LogsForVectorReplay(_ context.Context, sinceID uint, limit int) ([]ReplayRow, error) { - s.calls++ - if s.fail != nil { - return nil, s.fail - } - if s.calls > len(s.pages) { - return nil, nil - } - page := s.pages[s.calls-1] - // Filter to "rows newer than sinceID" so the test verifies the loop - // passes the right cursor across iterations. - out := make([]ReplayRow, 0, len(page)) - for _, r := range page { - if r.ID > sinceID { - out = append(out, r) - } - } - if len(out) > limit { - out = out[:limit] - } - return out, nil -} - -// TestReplayFromDB_AdvancesCursor verifies multi-page replay calls the -// source with monotonically-increasing sinceID values and indexes every -// row, with no duplicates by LogID. -func TestReplayFromDB_AdvancesCursor(t *testing.T) { - src := &fakeSource{ - pages: [][]ReplayRow{ - { - {ID: 10, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "boom"}, - {ID: 20, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "kaboom"}, - }, - { - {ID: 30, Tenant: "t", ServiceName: "svc", Severity: "WARN", Body: "third page row tokenizes fine"}, - }, - }, - } - idx := New(100) - total, err := idx.ReplayFromDB(context.Background(), src) - if err != nil { - t.Fatalf("ReplayFromDB: %v", err) - } - if total != 3 { - t.Errorf("processed: got %d, want 3", total) - } - if idx.Size() != 3 { - t.Errorf("indexed Size: got %d, want 3", idx.Size()) - } - if idx.LastIndexedID() != 30 { - t.Errorf("LastIndexedID: got %d, want 30", idx.LastIndexedID()) - } - // Two data pages + one empty page that signals end-of-data. - if src.calls != 3 { - t.Errorf("source calls: got %d, want 3 (2 data + 1 empty terminator)", src.calls) - } -} - -// TestReplayFromDB_StartsFromLastIndexedID verifies the loop seeds sinceID -// from the existing high watermark, so a snapshot's tail can be picked up -// without re-indexing rows already in the index. -func TestReplayFromDB_StartsFromLastIndexedID(t *testing.T) { - idx := New(100) - idx.Add(50, "t", "svc", "ERROR", "already indexed") - if got := idx.LastIndexedID(); got != 50 { - t.Fatalf("seed LastIndexedID: got %d, want 50", got) - } - - src := &fakeSource{ - pages: [][]ReplayRow{ - // Page contains both pre-watermark and post-watermark rows; the - // fake's filter mimics SQL's WHERE id > sinceID, so only post-50 - // rows leave the source. - { - {ID: 30, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "old"}, - {ID: 50, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "boundary"}, - {ID: 60, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "new"}, - }, - }, - } - total, err := idx.ReplayFromDB(context.Background(), src) - if err != nil { - t.Fatalf("ReplayFromDB: %v", err) - } - if total != 1 { - t.Errorf("processed: got %d, want 1 (only id=60 is post-watermark)", total) - } - if idx.Size() != 2 { - t.Errorf("indexed Size: got %d, want 2 (seed + replayed)", idx.Size()) - } - if idx.LastIndexedID() != 60 { - t.Errorf("LastIndexedID: got %d, want 60", idx.LastIndexedID()) - } -} - -// TestReplayFromDB_PropagatesError verifies a source error is returned -// alongside the partial count so the caller can log and continue. -func TestReplayFromDB_PropagatesError(t *testing.T) { - src := &fakeSource{fail: errors.New("db gone")} - idx := New(100) - total, err := idx.ReplayFromDB(context.Background(), src) - if err == nil { - t.Fatal("want error, got nil") - } - if total != 0 { - t.Errorf("partial count: got %d, want 0", total) - } - if idx.Size() != 0 { - t.Errorf("error path must not corrupt index: Size=%d", idx.Size()) - } -} - -// TestReplayFromDB_RespectsCancellation verifies a cancelled ctx aborts -// the loop without making another source call. -func TestReplayFromDB_RespectsCancellation(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - src := &fakeSource{ - pages: [][]ReplayRow{ - {{ID: 1, Tenant: "t", ServiceName: "svc", Severity: "ERROR", Body: "x"}}, - }, - } - idx := New(100) - _, err := idx.ReplayFromDB(ctx, src) - if !errors.Is(err, context.Canceled) { - t.Fatalf("want context.Canceled, got %v", err) - } - if src.calls != 0 { - t.Errorf("source called despite cancelled ctx: calls=%d", src.calls) - } -} - -// TestReplayFromDB_NilSource is a smoke test for the nil-safe early return. -func TestReplayFromDB_NilSource(t *testing.T) { - idx := New(100) - total, err := idx.ReplayFromDB(context.Background(), nil) - if err != nil { - t.Fatalf("nil source: unexpected err=%v", err) - } - if total != 0 { - t.Errorf("nil source: total=%d, want 0", total) - } -} diff --git a/internal/vectordb/snapshot.go b/internal/vectordb/snapshot.go deleted file mode 100644 index 87c12d0..0000000 --- a/internal/vectordb/snapshot.go +++ /dev/null @@ -1,317 +0,0 @@ -package vectordb - -import ( - "bytes" - "context" - "encoding/binary" - "encoding/gob" - "errors" - "fmt" - "hash/crc32" - "io" - "log/slog" - "os" - "syscall" - "time" -) - -// Snapshot is the persisted state of an Index. -// -// Only the fields needed to reconstruct an equivalent Index are captured — -// transient state (mu, dirty) is intentionally absent. LastIndexedID is the -// high watermark of indexed Log.IDs so a startup tail-replay can query DB -// rows newer than the snapshot without double-indexing rows already in -// Docs. -// -// Field changes break the format — bump snapshotVersion when the wire -// shape changes. Old snapshots whose magic+version don't match are -// rejected on load and the caller falls back to a full DB rebuild. -type Snapshot struct { - LastIndexedID uint - MaxSize int - Docs []LogVector - IDF map[string]float64 - WrittenAt int64 // unix seconds, observability only -} - -const ( - // snapshotMagic is a 4-byte file header so a corrupt or stray file is - // rejected before we attempt the more expensive gob decode. - snapshotMagic = "VDB1" - // snapshotVersion travels alongside the magic. Bump on any LogVector - // or Snapshot field shape change so loaders fall back to rebuild - // instead of producing silently-wrong index state. - snapshotVersion uint32 = 1 -) - -// EncodeSnapshot writes a versioned, CRC32-protected snapshot to w. -// -// Wire format (big-endian for portability): -// -// bytes[0:4] magic "VDB1" -// bytes[4:8] version uint32 -// bytes[8:12] CRC32-IEEE uint32 (over bytes[12:]) -// bytes[12:] gob payload Snapshot -func EncodeSnapshot(w io.Writer, snap Snapshot) error { - var payload bytes.Buffer - if err := gob.NewEncoder(&payload).Encode(snap); err != nil { - return fmt.Errorf("encode snapshot payload: %w", err) - } - crc := crc32.ChecksumIEEE(payload.Bytes()) - - if _, err := w.Write([]byte(snapshotMagic)); err != nil { - return fmt.Errorf("write magic: %w", err) - } - if err := binary.Write(w, binary.BigEndian, snapshotVersion); err != nil { - return fmt.Errorf("write version: %w", err) - } - if err := binary.Write(w, binary.BigEndian, crc); err != nil { - return fmt.Errorf("write crc: %w", err) - } - if _, err := w.Write(payload.Bytes()); err != nil { - return fmt.Errorf("write payload: %w", err) - } - return nil -} - -// DecodeSnapshot reads + validates a snapshot from r. -// -// All errors are caller-visible. The expected handling is: log a warning -// and proceed with a full DB rebuild — never silently load partial state. -// Errors include short header, wrong magic, unsupported version, CRC -// mismatch, and gob decode failure. -func DecodeSnapshot(r io.Reader) (Snapshot, error) { - var ( - magic [4]byte - version uint32 - crc uint32 - ) - if _, err := io.ReadFull(r, magic[:]); err != nil { - return Snapshot{}, fmt.Errorf("read magic: %w", err) - } - if string(magic[:]) != snapshotMagic { - return Snapshot{}, fmt.Errorf("unexpected snapshot magic %q (want %q)", magic[:], snapshotMagic) - } - if err := binary.Read(r, binary.BigEndian, &version); err != nil { - return Snapshot{}, fmt.Errorf("read version: %w", err) - } - if version != snapshotVersion { - return Snapshot{}, fmt.Errorf("unsupported snapshot version %d (current %d)", version, snapshotVersion) - } - if err := binary.Read(r, binary.BigEndian, &crc); err != nil { - return Snapshot{}, fmt.Errorf("read crc: %w", err) - } - payload, err := io.ReadAll(r) - if err != nil { - return Snapshot{}, fmt.Errorf("read payload: %w", err) - } - if got := crc32.ChecksumIEEE(payload); got != crc { - return Snapshot{}, fmt.Errorf("snapshot crc mismatch: got %08x want %08x", got, crc) - } - var snap Snapshot - if err := gob.NewDecoder(bytes.NewReader(payload)).Decode(&snap); err != nil { - return Snapshot{}, fmt.Errorf("decode payload: %w", err) - } - return snap, nil -} - -// writeAtomic writes data to path via tmp+sync+rename. -// -// Mode 0o600: snapshots persist log bodies which can carry sensitive -// operational data — owner-only is the conservative default. Operators -// who need shared read can chmod externally. -// -// On EXDEV (cross-device rename, e.g. when data dir is on a separate -// mount than the binary's tmp dir), falls back to a non-atomic -// os.WriteFile at the destination. Cross-device deployments are rare and -// documented; the fallback at least ensures the snapshot is written, with -// last-writer-wins replacing the atomicity guarantee. -// -// On any error during the write/fsync phase, the .tmp file is removed so -// a partial file does not poison the next startup's load attempt. -func writeAtomic(path string, data []byte) error { - tmp := path + ".tmp" - f, err := os.OpenFile(tmp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) - if err != nil { - return fmt.Errorf("create tmp %s: %w", tmp, err) - } - if _, err := f.Write(data); err != nil { - _ = f.Close() - _ = os.Remove(tmp) - return fmt.Errorf("write tmp: %w", err) - } - if err := f.Sync(); err != nil { - _ = f.Close() - _ = os.Remove(tmp) - return fmt.Errorf("fsync tmp: %w", err) - } - if err := f.Close(); err != nil { - _ = os.Remove(tmp) - return fmt.Errorf("close tmp: %w", err) - } - if err := os.Rename(tmp, path); err != nil { - if isEXDEV(err) { - data, readErr := os.ReadFile(tmp) - if readErr != nil { - _ = os.Remove(tmp) - return fmt.Errorf("rename EXDEV + readback: %w", readErr) - } - if writeErr := os.WriteFile(path, data, 0o600); writeErr != nil { - _ = os.Remove(tmp) - return fmt.Errorf("rename EXDEV + writefile: %w", writeErr) - } - _ = os.Remove(tmp) - return nil - } - _ = os.Remove(tmp) - return fmt.Errorf("rename %s: %w", path, err) - } - return nil -} - -// isEXDEV reports whether err is a cross-device link/rename error. -func isEXDEV(err error) bool { - if err == nil { - return false - } - var le *os.LinkError - if errors.As(err, &le) { - return errors.Is(le.Err, syscall.EXDEV) - } - return errors.Is(err, syscall.EXDEV) -} - -// LoadSnapshot reads a snapshot from path and replaces the Index's state. -// -// Caller must ensure no concurrent Add()/Search() is in flight — this is -// the typical startup wiring (fresh Index, before ingest accept). Errors -// are returned as-is so the caller can distinguish os.IsNotExist (no -// previous snapshot — first start) from corruption/format errors (log -// warn + proceed with full DB rebuild). -// -// On error the Index state is left untouched. -func (idx *Index) LoadSnapshot(path string) error { - f, err := os.Open(path) // #nosec G304 -- operator-supplied snapshot path - if err != nil { - return err - } - defer func() { _ = f.Close() }() - snap, err := DecodeSnapshot(f) - if err != nil { - return err - } - idx.mu.Lock() - defer idx.mu.Unlock() - idx.docs = snap.Docs - idx.idf = snap.IDF - if idx.idf == nil { - idx.idf = make(map[string]float64) - } - if snap.MaxSize > 0 { - idx.maxSize = snap.MaxSize - } - idx.lastIndexedID = snap.LastIndexedID - idx.dirty = false - return nil -} - -// SetSnapshotObserver registers a callback invoked at the end of each -// WriteSnapshot. result is "success" or "failure"; size is the on-disk -// size of the latest written snapshot (0 on failure). -// -// Set from the wiring layer (main.go) so vectordb stays free of -// telemetry imports. Safe to call before SnapshotLoop starts. -func (idx *Index) SetSnapshotObserver(fn func(result string, duration time.Duration, size int64)) { - idx.mu.Lock() - defer idx.mu.Unlock() - idx.snapshotObserver = fn -} - -// WriteSnapshot serializes the current Index state to path atomically. -// -// Safe to call concurrently with Add()/Search(): the docs slice and IDF -// map are copied under the index lock and serialization runs lock-free -// after release. Critical section is sub-millisecond at the 100k cap -// because slice copy is O(1) per-element header (LogVector strings/maps -// are shared by reference, and Add() never mutates an existing -// LogVector.Vec — it only appends new entries). -func (idx *Index) WriteSnapshot(path string) error { - start := time.Now() - err := idx.writeSnapshot(path) - - idx.mu.RLock() - obs := idx.snapshotObserver - idx.mu.RUnlock() - if obs != nil { - result := "success" - var size int64 - if err != nil { - result = "failure" - } else if fi, statErr := os.Stat(path); statErr == nil { - size = fi.Size() - } - obs(result, time.Since(start), size) - } - return err -} - -func (idx *Index) writeSnapshot(path string) error { - idx.mu.Lock() - if idx.dirty { - idx.recomputeIDF() - idx.dirty = false - } - docs := make([]LogVector, len(idx.docs)) - copy(docs, idx.docs) - idfCopy := make(map[string]float64, len(idx.idf)) - for k, v := range idx.idf { - idfCopy[k] = v - } - snap := Snapshot{ - LastIndexedID: idx.lastIndexedID, - MaxSize: idx.maxSize, - Docs: docs, - IDF: idfCopy, - WrittenAt: time.Now().Unix(), - } - idx.mu.Unlock() - - var buf bytes.Buffer - if err := EncodeSnapshot(&buf, snap); err != nil { - return err - } - return writeAtomic(path, buf.Bytes()) -} - -// SnapshotLoop writes a snapshot to path on every interval tick until ctx is -// done. On context cancel, fires one final WriteSnapshot before returning so -// graceful shutdowns capture the maximum in-memory state. -// -// Transient write failures (disk full, fsync errors, EXDEV warnings) are -// logged via slog but do not break the loop — vectordb is a rebuildable -// accelerator, and silently dropping a tick beats taking the daemon down. -// -// Safe to call with empty path / zero interval — both disable the loop and -// return immediately. -func (idx *Index) SnapshotLoop(ctx context.Context, path string, interval time.Duration) { - if path == "" || interval <= 0 { - return - } - ticker := time.NewTicker(interval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - if err := idx.WriteSnapshot(path); err != nil { - slog.Warn("vectordb final snapshot on shutdown failed", "path", path, "error", err) - } else { - slog.Info("vectordb final snapshot written", "path", path, "size", idx.Size()) - } - return - case <-ticker.C: - if err := idx.WriteSnapshot(path); err != nil { - slog.Warn("vectordb periodic snapshot failed", "path", path, "error", err) - } - } - } -} diff --git a/internal/vectordb/snapshot_test.go b/internal/vectordb/snapshot_test.go deleted file mode 100644 index 9df3a67..0000000 --- a/internal/vectordb/snapshot_test.go +++ /dev/null @@ -1,325 +0,0 @@ -package vectordb - -import ( - "bytes" - "context" - "encoding/binary" - "errors" - "os" - "path/filepath" - "syscall" - "testing" - "time" -) - -// TestSnapshotRoundTrip verifies an encoded snapshot decodes back to the -// same logical state across all populated fields. -func TestSnapshotRoundTrip(t *testing.T) { - in := Snapshot{ - LastIndexedID: 42, - MaxSize: 1000, - Docs: []LogVector{ - {LogID: 1, Tenant: "acme", ServiceName: "api", Severity: "ERROR", Body: "panic at startup", Vec: map[string]float64{"panic": 0.5, "startup": 0.5}}, - {LogID: 2, Tenant: "globex", ServiceName: "db", Severity: "WARN", Body: "timeout connecting", Vec: map[string]float64{"timeout": 1.0}}, - }, - IDF: map[string]float64{"panic": 1.5, "startup": 1.0, "timeout": 1.2}, - WrittenAt: 1714464000, - } - var buf bytes.Buffer - if err := EncodeSnapshot(&buf, in); err != nil { - t.Fatalf("encode: %v", err) - } - out, err := DecodeSnapshot(&buf) - if err != nil { - t.Fatalf("decode: %v", err) - } - if out.LastIndexedID != in.LastIndexedID { - t.Errorf("LastIndexedID: got %d, want %d", out.LastIndexedID, in.LastIndexedID) - } - if out.MaxSize != in.MaxSize { - t.Errorf("MaxSize: got %d, want %d", out.MaxSize, in.MaxSize) - } - if len(out.Docs) != len(in.Docs) { - t.Fatalf("Docs length: got %d, want %d", len(out.Docs), len(in.Docs)) - } - if out.Docs[0].Body != in.Docs[0].Body || out.Docs[0].LogID != in.Docs[0].LogID { - t.Errorf("Doc[0]: got %+v, want %+v", out.Docs[0], in.Docs[0]) - } - if got, want := out.Docs[0].Vec["panic"], in.Docs[0].Vec["panic"]; got != want { - t.Errorf("Doc[0].Vec[panic]: got %v, want %v", got, want) - } - if got, want := out.IDF["panic"], in.IDF["panic"]; got != want { - t.Errorf("IDF[panic]: got %v, want %v", got, want) - } -} - -// TestDecodeSnapshot_EmptyReader verifies graceful failure on truncation -// at the very first read (magic). -func TestDecodeSnapshot_EmptyReader(t *testing.T) { - if _, err := DecodeSnapshot(bytes.NewReader(nil)); err == nil { - t.Fatal("decoding empty reader must fail") - } -} - -// TestDecodeSnapshot_WrongMagic verifies the magic check rejects stray files. -func TestDecodeSnapshot_WrongMagic(t *testing.T) { - var buf bytes.Buffer - buf.WriteString("BAD!") - _ = binary.Write(&buf, binary.BigEndian, snapshotVersion) - _ = binary.Write(&buf, binary.BigEndian, uint32(0)) - if _, err := DecodeSnapshot(&buf); err == nil { - t.Fatal("wrong magic must fail") - } -} - -// TestDecodeSnapshot_WrongVersion verifies version-bump reads are refused -// — the loader should fall back to full rebuild on any version mismatch. -func TestDecodeSnapshot_WrongVersion(t *testing.T) { - var buf bytes.Buffer - buf.WriteString(snapshotMagic) - _ = binary.Write(&buf, binary.BigEndian, uint32(999)) - if _, err := DecodeSnapshot(&buf); err == nil { - t.Fatal("wrong version must fail") - } -} - -// TestDecodeSnapshot_CRCMismatch verifies bit-rot or partial writes are -// caught before the gob decoder produces silently-wrong state. -func TestDecodeSnapshot_CRCMismatch(t *testing.T) { - in := Snapshot{LastIndexedID: 1, MaxSize: 100, IDF: map[string]float64{}} - var buf bytes.Buffer - if err := EncodeSnapshot(&buf, in); err != nil { - t.Fatalf("encode: %v", err) - } - raw := buf.Bytes() - // Header is 12 bytes (magic+version+crc); flip a payload byte. - if len(raw) < 13 { - t.Fatalf("encoded snapshot too short: %d bytes", len(raw)) - } - raw[12] ^= 0xff - if _, err := DecodeSnapshot(bytes.NewReader(raw)); err == nil { - t.Fatal("CRC mismatch must fail") - } -} - -// TestWriteAtomic_RoundTrip writes a payload and reads it back via the -// public path, then asserts the .tmp sibling is gone. -func TestWriteAtomic_RoundTrip(t *testing.T) { - dir := t.TempDir() - p := filepath.Join(dir, "snap.bin") - payload := []byte("hello world") - if err := writeAtomic(p, payload); err != nil { - t.Fatalf("writeAtomic: %v", err) - } - got, err := os.ReadFile(p) - if err != nil { - t.Fatalf("ReadFile: %v", err) - } - if !bytes.Equal(got, payload) { - t.Fatalf("round-trip: got %q, want %q", got, payload) - } - if _, err := os.Stat(p + ".tmp"); !os.IsNotExist(err) { - t.Fatalf(".tmp must be removed after rename, got err=%v", err) - } -} - -// TestIsEXDEV_Detection verifies the helper recognizes wrapped EXDEV from -// os.Rename and ignores arbitrary errors. -func TestIsEXDEV_Detection(t *testing.T) { - le := &os.LinkError{Op: "rename", Old: "a", New: "b", Err: syscall.EXDEV} - if !isEXDEV(le) { - t.Fatal("isEXDEV should detect *os.LinkError{Err: EXDEV}") - } - if isEXDEV(errors.New("other error")) { - t.Fatal("isEXDEV should not flag arbitrary errors") - } - if isEXDEV(nil) { - t.Fatal("isEXDEV(nil) must be false") - } -} - -// TestIndexWriteAndLoadSnapshot exercises the full Index → file → Index -// round trip: build, snapshot, load into a fresh Index, verify state. -func TestIndexWriteAndLoadSnapshot(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "vectordb.snapshot") - - src := New(1000) - src.Add(101, "acme", "checkout", "ERROR", "payment gateway timeout charging customer") - src.Add(102, "acme", "checkout", "ERROR", "payment gateway refused charge insufficient funds") - src.Add(203, "globex", "auth", "WARN", "session token nearing expiry") - if got, want := src.Size(), 3; got != want { - t.Fatalf("seed Size: got %d, want %d", got, want) - } - if got := src.LastIndexedID(); got != 203 { - t.Fatalf("LastIndexedID: got %d, want 203", got) - } - - if err := src.WriteSnapshot(path); err != nil { - t.Fatalf("WriteSnapshot: %v", err) - } - - // Verify file written + .tmp gone - if st, err := os.Stat(path); err != nil { - t.Fatalf("stat snapshot: %v", err) - } else if st.Size() == 0 { - t.Fatal("snapshot file is empty") - } - if _, err := os.Stat(path + ".tmp"); !os.IsNotExist(err) { - t.Fatalf(".tmp must be gone after WriteSnapshot, got err=%v", err) - } - - dst := New(500) // different cap; load should restore src's cap - if err := dst.LoadSnapshot(path); err != nil { - t.Fatalf("LoadSnapshot: %v", err) - } - if got, want := dst.Size(), 3; got != want { - t.Fatalf("loaded Size: got %d, want %d", got, want) - } - if got := dst.LastIndexedID(); got != 203 { - t.Fatalf("loaded LastIndexedID: got %d, want 203", got) - } - // Search should work on the restored index — the IDF table came along - // with the snapshot, so cosine ranking still has rarity weights. - hits := dst.Search("acme", "payment gateway", 5) - if len(hits) != 2 { - t.Fatalf("Search after load: got %d hits, want 2", len(hits)) - } -} - -// TestLoadSnapshot_MissingFile verifies the loader propagates os-level -// errors so callers can distinguish "first start, no snapshot" via -// os.IsNotExist from real corruption. -func TestLoadSnapshot_MissingFile(t *testing.T) { - dir := t.TempDir() - idx := New(100) - err := idx.LoadSnapshot(filepath.Join(dir, "does-not-exist")) - if err == nil { - t.Fatal("LoadSnapshot of missing file must error") - } - if !os.IsNotExist(err) { - t.Fatalf("want os.IsNotExist, got %v", err) - } -} - -// TestSnapshotLoop_FinalWriteOnCancel verifies the loop fires a final -// WriteSnapshot when ctx is cancelled — captures the maximum in-memory -// state at graceful shutdown. -func TestSnapshotLoop_FinalWriteOnCancel(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "snap.bin") - - idx := New(100) - idx.Add(1, "t", "svc", "ERROR", "preserved across shutdown final write") - - ctx, cancel := context.WithCancel(context.Background()) - done := make(chan struct{}) - go func() { - defer close(done) - // 1h interval — the loop should never tick during this test, only - // the cancel path fires the write. - idx.SnapshotLoop(ctx, path, 1*time.Hour) - }() - - // Sanity: file does not yet exist. - if _, err := os.Stat(path); !os.IsNotExist(err) { - t.Fatalf("snapshot must not exist before cancel, got err=%v", err) - } - - cancel() - select { - case <-done: - case <-time.After(2 * time.Second): - t.Fatal("SnapshotLoop did not return within 2s of cancel") - } - - // Verify final write happened. - if st, err := os.Stat(path); err != nil { - t.Fatalf("final snapshot missing after cancel: %v", err) - } else if st.Size() == 0 { - t.Fatal("final snapshot file is empty") - } - - // Round-trip: load into a fresh index and confirm state matches. - dst := New(100) - if err := dst.LoadSnapshot(path); err != nil { - t.Fatalf("LoadSnapshot of final write: %v", err) - } - if dst.Size() != 1 || dst.LastIndexedID() != 1 { - t.Fatalf("loaded state mismatch: Size=%d LastIndexedID=%d", dst.Size(), dst.LastIndexedID()) - } -} - -// TestSnapshotLoop_PeriodicWrite verifies a tick fires WriteSnapshot. -// Uses a tight interval so the test runs in <50ms; the loop fires at -// least once before we cancel + drain. -func TestSnapshotLoop_PeriodicWrite(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "snap.bin") - - idx := New(100) - idx.Add(7, "t", "svc", "ERROR", "periodic snapshot tick body") - - ctx, cancel := context.WithCancel(context.Background()) - done := make(chan struct{}) - go func() { - defer close(done) - idx.SnapshotLoop(ctx, path, 10*time.Millisecond) - }() - - // Wait long enough for at least one tick to fire. - deadline := time.Now().Add(500 * time.Millisecond) - for time.Now().Before(deadline) { - if st, err := os.Stat(path); err == nil && st.Size() > 0 { - break - } - time.Sleep(10 * time.Millisecond) - } - - cancel() - <-done - - if _, err := os.Stat(path); err != nil { - t.Fatalf("expected at least one periodic snapshot to land at %s, got err=%v", path, err) - } -} - -// TestSnapshotLoop_DisabledByEmptyPath verifies the no-op path so config -// disable doesn't accidentally start a tight-loop goroutine. -func TestSnapshotLoop_DisabledByEmptyPath(t *testing.T) { - idx := New(100) - ctx, cancel := context.WithCancel(context.Background()) - done := make(chan struct{}) - go func() { - defer close(done) - idx.SnapshotLoop(ctx, "", 10*time.Millisecond) - }() - // Loop should return immediately when path is empty — no need to cancel. - select { - case <-done: - case <-time.After(500 * time.Millisecond): - cancel() - t.Fatal("SnapshotLoop with empty path must return immediately") - } - cancel() -} - -// TestLoadSnapshot_CorruptFileLeavesStateAlone verifies that a corrupt -// snapshot does NOT clobber existing index state — the caller is meant to -// log the warning and proceed with a full rebuild. -func TestLoadSnapshot_CorruptFileLeavesStateAlone(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "snap.bin") - if err := os.WriteFile(path, []byte("not a valid snapshot file"), 0o600); err != nil { - t.Fatalf("seed corrupt file: %v", err) - } - idx := New(100) - idx.Add(1, "t", "svc", "ERROR", "preexisting body content") - sizeBefore := idx.Size() - if err := idx.LoadSnapshot(path); err == nil { - t.Fatal("LoadSnapshot of corrupt file must fail") - } - if got := idx.Size(); got != sizeBefore { - t.Fatalf("corrupt load corrupted state: Size went %d → %d", sizeBefore, got) - } -} diff --git a/main.go b/main.go index 7bd412f..a0b938a 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,6 @@ import ( tlsbootstrap "github.com/RandomCodeSpace/otelcontext/internal/tls" "github.com/RandomCodeSpace/otelcontext/internal/tsdb" "github.com/RandomCodeSpace/otelcontext/internal/ui" - "github.com/RandomCodeSpace/otelcontext/internal/vectordb" "runtime/debug" "sync" @@ -366,75 +365,12 @@ func main() { go svcGraph.Start(ctxGraph) slog.Info("🕸️ In-memory service graph started (5m window, 30s refresh)") - // 4f. Initialize vector index for semantic log search. - vectorIdx := vectordb.New(cfg.VectorIndexMaxEntries) - slog.Info("🔍 Vector index initialized", "max_entries", cfg.VectorIndexMaxEntries) - - // Vector index hydration: - // 1) LoadSnapshot — restores the prior process's state in O(file size) - // so find_similar_logs returns useful results in <1s after restart - // instead of the legacy minutes of cold-start blindness. - // 2) ReplayFromDB — picks up any DB rows ingested after the last - // snapshot. Severity-filtered + cursor-paged from LastIndexedID. - // - // Both run in a boot goroutine so a slow disk doesn't delay listener - // startup. SIGTERM during boot cancels via appCtx — bootWG ensures the - // hydrator finishes (or aborts cleanly) before DB close at shutdown. - // Wire snapshot write observer before any WriteSnapshot can fire (the - // hydrator goroutine doesn't write, but SnapshotLoop below will). - vectorIdx.SetSnapshotObserver(metrics.RecordVectorSnapshotWrite) - - bootWG.Add(1) - go func() { - defer bootWG.Done() - if cfg.VectorIndexSnapshotPath != "" { - if err := vectorIdx.LoadSnapshot(cfg.VectorIndexSnapshotPath); err != nil { - if os.IsNotExist(err) { - metrics.RecordVectorSnapshotLoad("missing") - slog.Info("🔍 Vector index: no prior snapshot, will hydrate from DB", "path", cfg.VectorIndexSnapshotPath) - } else { - metrics.RecordVectorSnapshotLoad("corrupt") - slog.Warn("🔍 Vector index: snapshot load failed, will rebuild from DB", "path", cfg.VectorIndexSnapshotPath, "error", err) - } - } else { - metrics.RecordVectorSnapshotLoad("success") - slog.Info("🔍 Vector index: loaded snapshot", "path", cfg.VectorIndexSnapshotPath, "entries", vectorIdx.Size(), "since_id", vectorIdx.LastIndexedID()) - } - } - replayed, err := vectorIdx.ReplayFromDB(appCtx, vectorReplayAdapter{repo: repo}) - metrics.RecordVectorReplayLogs(replayed) - if err != nil { - slog.Warn("🔍 Vector index: tail replay errored", "replayed", replayed, "error", err) - } else if replayed > 0 { - slog.Info("🔍 Vector index: tail replay complete", "rows", replayed, "size", vectorIdx.Size(), "since_id", vectorIdx.LastIndexedID()) - } - }() - - // Periodic snapshot loop. Empty path or non-positive interval disables. - // snapCtx is cancelled in the shutdown sequence right after graphRAG.Stop() - // so the loop's ctx-done branch fires the final write before exit. - snapCtx, snapCancel := context.WithCancel(appCtx) - snapDone := make(chan struct{}) - go func() { - defer close(snapDone) - if cfg.VectorIndexSnapshotPath == "" { - return - } - interval, err := time.ParseDuration(cfg.VectorIndexSnapshotInterval) - if err != nil || interval <= 0 { - slog.Info("🔍 Vector index: periodic snapshot disabled", "interval", cfg.VectorIndexSnapshotInterval) - return - } - slog.Info("🔍 Vector index: periodic snapshot enabled", "interval", interval, "path", cfg.VectorIndexSnapshotPath) - vectorIdx.SnapshotLoop(snapCtx, cfg.VectorIndexSnapshotPath, interval) - }() - // 4g. Initialize GraphRAG (replaces simple graph for advanced queries) graphrag.SetPanicMetrics(metrics) graphRAGCfg := graphrag.DefaultConfig() graphRAGCfg.WorkerCount = cfg.GraphRAGWorkerCount graphRAGCfg.ChannelSize = cfg.GraphRAGEventQueueSize - graphRAG := graphrag.New(repo, vectorIdx, tsdbAgg, ringBuf, graphRAGCfg) + graphRAG := graphrag.New(repo, tsdbAgg, ringBuf, graphRAGCfg) graphRAG.SetMetrics(metrics) ctxGraphRAG, cancelGraphRAG := context.WithCancel(context.Background()) go graphRAG.Start(ctxGraphRAG) @@ -461,10 +397,9 @@ func main() { apiServer := api.NewServer(repo, hub, eventHub, metrics) apiServer.SetGraph(svcGraph) apiServer.SetGraphRAG(graphRAG) - apiServer.SetVectorIndex(vectorIdx) // 6b. Initialize MCP Server (HTTP Streamable, JSON-RPC 2.0 + SSE) - mcpServer := mcp.New(cfg.DefaultTenant, repo, metrics, svcGraph, vectorIdx) + mcpServer := mcp.New(cfg.DefaultTenant, repo, metrics, svcGraph) mcpServer.SetGraphRAG(graphRAG) mcpServer.SetCallLimit(cfg.MCPMaxConcurrent) mcpServer.SetCallTimeout(time.Duration(cfg.MCPCallTimeoutMs) * time.Millisecond) @@ -578,7 +513,6 @@ func main() { Timestamp: l.Timestamp, }) aiService.EnqueueLog(l) - vectorIdx.Add(l.ID, l.TenantID, l.ServiceName, l.Severity, l.Body) eventHub.NotifyRefresh() if time.Since(start) > 100*time.Millisecond { slog.Warn("Slow broadcast/enqueue", "duration", time.Since(start)) @@ -753,7 +687,7 @@ func main() { } // Embedded UI Server - uiServer := ui.NewServer(repo, metrics, svcGraph, vectorIdx) + uiServer := ui.NewServer(repo, metrics, svcGraph) uiServer.SetMCPConfig(cfg.MCPEnabled, cfg.MCPPath) if err := uiServer.RegisterRoutes(mux); err != nil { fatal("Failed to register UI routes", err) @@ -936,19 +870,6 @@ func main() { graphRAG.Stop() cancelGraphRAG() - // 3a. Cancel vectordb snapshot loop. The loop's ctx.Done branch fires a - // final WriteSnapshot before exit, capturing the maximum in-memory state - // (every Add() that drained from GraphRAG above is persisted). We wait - // briefly so the final snapshot hits disk before DB close — the snapshot - // is independent of repo, but ordered shutdown is cheaper than a stale - // snapshot on the next boot. - snapCancel() - select { - case <-snapDone: - case <-time.After(5 * time.Second): - slog.Warn("vectordb snapshot loop did not finish in 5s; final snapshot may be incomplete") - } - // 3a. Drain async ingest pipeline. gRPC GracefulStop above guarantees // no new Submits land; this blocks until workers finish in-flight // batches so a graceful shutdown doesn't lose buffered ingest. @@ -1083,30 +1004,6 @@ func initTracerProvider(endpoint string) (*sdktrace.TracerProvider, error) { return tp, nil } -// vectorReplayAdapter projects storage.Log into vectordb.ReplayRow so the -// vectordb package stays free of storage imports while still consuming the -// repository's tail-replay query. Lives at the wiring layer because both -// packages can be imported here, but neither imports the other. -type vectorReplayAdapter struct{ repo *storage.Repository } - -func (a vectorReplayAdapter) LogsForVectorReplay(ctx context.Context, sinceID uint, limit int) ([]vectordb.ReplayRow, error) { - logs, err := a.repo.LogsForVectorReplay(ctx, sinceID, limit) - if err != nil { - return nil, err - } - out := make([]vectordb.ReplayRow, len(logs)) - for i, l := range logs { - out[i] = vectordb.ReplayRow{ - ID: l.ID, - Tenant: l.TenantID, - ServiceName: l.ServiceName, - Severity: l.Severity, - Body: l.Body, - } - } - return out, nil -} - func printBanner() { banner := ` ___ _____ _____ _ From f8a6fa137eaf4e7b45a18d607620cd5f5c9fd896 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 18:57:26 +0000 Subject: [PATCH 03/11] refactor(graphrag): drop graph_snapshots table and snapshot scheduler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `graph_snapshots` table backed exactly one MCP tool (get_graph_snapshot, cut earlier in this PR) — no UI surface or REST endpoint reads it. With the tool gone the table is pure write amplification: at 15-minute cadence × ~100 tenants × per-row JSON nodes+edges blob it adds ~67k rows/week even after the 7-day age prune, and the row-count backstop only kicks in above 100k. On the SQLite OOM-within-an-hour deployment this contributes meaningfully to the 2 TB/day disk growth. Deletions: - internal/graphrag/snapshot.go (entire file): GraphSnapshot GORM model, takeSnapshot / takeSnapshotForTenant, pruneOldSnapshots, GetGraphSnapshot, maxSnapshotRows constant. - views.GraphSnapshot type + GraphSnapshotFromModel converter (only used by the removed test). - TestGraphRAG_GetGraphSnapshot_TenantScoped + the GraphSnapshot wire- shape leak test in views_test.go. Updates: - AutoMigrateGraphRAG no longer creates the table on fresh installs. graphRAGTables slice drops "graph_snapshots" so tenant-backfill skips it and the test asserting the per-table backfill no longer expects the row. - refresh.go::snapshotLoop now only calls persistDrainTemplates; the snapshotEvery field and the loop name are kept for wiring stability so external Config.SnapshotEvery still tunes the drain-persist cadence. Operator migration: existing graph_snapshots tables are LEFT IN PLACE on upgrade — AutoMigrate's IF NOT EXISTS semantics mean a populated table is not touched. Operators wanting to reclaim disk should `DROP TABLE graph_snapshots; VACUUM;` after upgrading. The table will stop receiving new writes immediately. --- internal/api/views/views.go | 24 ---- internal/api/views/views_test.go | 7 -- internal/graphrag/migrate.go | 10 +- internal/graphrag/migrate_test.go | 50 +------- internal/graphrag/refresh.go | 11 +- internal/graphrag/snapshot.go | 203 ------------------------------ main.go | 2 +- 7 files changed, 20 insertions(+), 287 deletions(-) delete mode 100644 internal/graphrag/snapshot.go diff --git a/internal/api/views/views.go b/internal/api/views/views.go index 270d9df..ccd40c4 100644 --- a/internal/api/views/views.go +++ b/internal/api/views/views.go @@ -198,17 +198,6 @@ type Investigation struct { SpanChain any `json:"span_chain"` } -// GraphSnapshot is the wire shape of a persisted topology snapshot. -type GraphSnapshot struct { - ID string `json:"id"` - CreatedAt time.Time `json:"created_at"` - Nodes any `json:"nodes"` - Edges any `json:"edges"` - ServiceCount int `json:"service_count"` - TotalCalls int64 `json:"total_calls"` - AvgHealthScore float64 `json:"avg_health_score"` -} - // --- Conversion functions --- // TraceFromModel converts a storage.Trace (with possibly-Preloaded children) @@ -469,19 +458,6 @@ func InvestigationFromModel(m graphrag.Investigation) Investigation { } } -// GraphSnapshotFromModel converts a persisted GraphRAG snapshot into its view. -func GraphSnapshotFromModel(m graphrag.GraphSnapshot) GraphSnapshot { - return GraphSnapshot{ - ID: m.ID, - CreatedAt: m.CreatedAt, - Nodes: rawToAny(m.Nodes), - Edges: rawToAny(m.Edges), - ServiceCount: m.ServiceCount, - TotalCalls: m.TotalCalls, - AvgHealthScore: m.AvgHealthScore, - } -} - // InvestigationsFromModels is the slice form of InvestigationFromModel. func InvestigationsFromModels(ms []graphrag.Investigation) []Investigation { out := make([]Investigation, len(ms)) diff --git a/internal/api/views/views_test.go b/internal/api/views/views_test.go index 99074fa..48d7eb3 100644 --- a/internal/api/views/views_test.go +++ b/internal/api/views/views_test.go @@ -164,13 +164,6 @@ func TestViews_NoGormBookkeepingLeaksThroughJSON(t *testing.T) { SpanChain: json.RawMessage(`[]`), }) assertNoLeak(t, "Investigation", inv, "tenant_id") - - gs := GraphSnapshotFromModel(graphrag.GraphSnapshot{ - ID: "snap1", CreatedAt: ts, - Nodes: json.RawMessage(`[]`), Edges: json.RawMessage(`[]`), - ServiceCount: 1, TotalCalls: 10, AvgHealthScore: 0.9, - }) - assertNoLeak(t, "GraphSnapshot", gs, "tenant_id") } // TestTraceView_PreservesJSONFieldNames asserts the exact JSON shape consumed by diff --git a/internal/graphrag/migrate.go b/internal/graphrag/migrate.go index 133593c..bab16d2 100644 --- a/internal/graphrag/migrate.go +++ b/internal/graphrag/migrate.go @@ -30,9 +30,13 @@ import ( "gorm.io/gorm" ) -// graphRAGTables are the three persisted tables that carry tenant_id after +// graphRAGTables are the persisted tables that carry tenant_id after // RAN-38. Order matches AutoMigrate order so log lines line up. -var graphRAGTables = []string{"investigations", "graph_snapshots", "drain_templates"} +// +// `graph_snapshots` was dropped from the AutoMigrate slice on 2026-05-24; +// existing tables are left in place on operator databases (drop manually +// with `DROP TABLE graph_snapshots` to reclaim disk). +var graphRAGTables = []string{"investigations", "drain_templates"} // AutoMigrateGraphRAG runs GORM auto-migration for GraphRAG models and // applies tenant backfill + drain_templates composite-PK promotion. Safe to @@ -41,7 +45,7 @@ func AutoMigrateGraphRAG(db *gorm.DB) error { if db == nil { return nil } - if err := db.AutoMigrate(&Investigation{}, &GraphSnapshot{}, &DrainTemplateRow{}); err != nil { + if err := db.AutoMigrate(&Investigation{}, &DrainTemplateRow{}); err != nil { return fmt.Errorf("graphrag automigrate: %w", err) } if err := backfillTenantIDs(db); err != nil { diff --git a/internal/graphrag/migrate_test.go b/internal/graphrag/migrate_test.go index 30762f6..031b762 100644 --- a/internal/graphrag/migrate_test.go +++ b/internal/graphrag/migrate_test.go @@ -2,7 +2,6 @@ package graphrag import ( "context" - "strings" "testing" "time" @@ -50,7 +49,6 @@ func TestAutoMigrateGraphRAG_CreatesTenantCompositeIndexes(t *testing.T) { index string }{ {"investigations", "idx_investigations_tenant_created"}, - {"graph_snapshots", "idx_graph_snapshots_tenant_created"}, } for _, tc := range expected { var count int @@ -115,16 +113,13 @@ func TestAutoMigrateGraphRAG_BackfillsLegacyRows(t *testing.T) { if err := AutoMigrateGraphRAG(db); err != nil { t.Fatalf("first migrate: %v", err) } - // Insert rows with empty tenant_id directly via raw SQL — Investigation, - // GraphSnapshot and DrainTemplateRow's GORM defaults would otherwise fill - // the column on insert. + // Insert rows with empty tenant_id directly via raw SQL — Investigation and + // DrainTemplateRow's GORM defaults would otherwise fill the column on + // insert. now := time.Now().UTC() if err := db.Exec(`INSERT INTO investigations (tenant_id, id, created_at, status, severity, trigger_service, trigger_operation, error_message, root_service, root_operation, causal_chain, trace_ids, error_logs, anomalous_metrics, affected_services, span_chain) VALUES ('', 'inv_legacy', ?, 'detected', 'warning', 'svc', 'op', 'boom', 'svc', 'op', '[]', '[]', '[]', '[]', '[]', '[]')`, now).Error; err != nil { t.Fatalf("seed legacy investigation: %v", err) } - if err := db.Exec(`INSERT INTO graph_snapshots (tenant_id, id, created_at, nodes, edges, service_count, total_calls, avg_health_score) VALUES ('', 'snap_legacy', ?, '[]', '[]', 0, 0, 0)`, now).Error; err != nil { - t.Fatalf("seed legacy snapshot: %v", err) - } // Drain rows: tenant_id is part of the PK so we must give it *something* // — empty string is allowed by SQLite. The backfill is expected to fix it. if err := db.Exec(`INSERT INTO drain_templates (tenant_id, id, tokens, count, first_seen, last_seen, sample) VALUES ('', 1, '["a","b"]', 1, ?, ?, 'sample')`, now, now).Error; err != nil { @@ -138,7 +133,7 @@ func TestAutoMigrateGraphRAG_BackfillsLegacyRows(t *testing.T) { for _, tbl := range graphRAGTables { var stragglers int - if err := db.Raw(`SELECT COUNT(*) FROM `+tbl+` WHERE tenant_id IS NULL OR tenant_id = ''`).Scan(&stragglers).Error; err != nil { + if err := db.Raw(`SELECT COUNT(*) FROM ` + tbl + ` WHERE tenant_id IS NULL OR tenant_id = ''`).Scan(&stragglers).Error; err != nil { t.Fatalf("count empty tenant in %s: %v", tbl, err) } if stragglers != 0 { @@ -258,40 +253,3 @@ func TestGraphRAG_GetInvestigations_TenantScoped(t *testing.T) { t.Errorf("expected globex row; got tenant=%q", got.TenantID) } } - -// TestGraphRAG_GetGraphSnapshot_TenantScoped seeds two snapshots (one per -// tenant) at the same instant and asserts each tenant only retrieves its own. -func TestGraphRAG_GetGraphSnapshot_TenantScoped(t *testing.T) { - g, db := newTestGraphRAGWithDB(t) - if err := AutoMigrateGraphRAG(db); err != nil { - t.Fatalf("migrate: %v", err) - } - now := time.Now().UTC() - for _, tenant := range []string{"acme", "globex"} { - snap := GraphSnapshot{ - TenantID: tenant, - ID: "snap_" + tenant, - CreatedAt: now, - Nodes: []byte(`[]`), - Edges: []byte(`[]`), - ServiceCount: 1, - AvgHealthScore: 1, - } - if err := db.Create(&snap).Error; err != nil { - t.Fatalf("seed %s: %v", tenant, err) - } - } - for _, tenant := range []string{"acme", "globex"} { - ctx := storage.WithTenantContext(context.Background(), tenant) - snap, err := g.GetGraphSnapshot(ctx, now.Add(time.Second)) - if err != nil { - t.Fatalf("get %s: %v", tenant, err) - } - if snap.TenantID != tenant { - t.Errorf("ctx %s returned snapshot for tenant %q", tenant, snap.TenantID) - } - if !strings.HasSuffix(snap.ID, tenant) { - t.Errorf("ctx %s returned snapshot id %s", tenant, snap.ID) - } - } -} diff --git a/internal/graphrag/refresh.go b/internal/graphrag/refresh.go index b16d8bc..14b5974 100644 --- a/internal/graphrag/refresh.go +++ b/internal/graphrag/refresh.go @@ -49,7 +49,14 @@ func (g *GraphRAG) refreshLoop(ctx context.Context) { } } -// snapshotLoop takes periodic snapshots and prunes old ones. +// snapshotLoop persists Drain templates on the configured cadence so a +// restart recovers the learned templates instead of rebuilding from scratch. +// +// Historically this loop also captured a periodic GraphSnapshot row into +// the `graph_snapshots` table and pruned aged-out snapshots; both were +// removed on 2026-05-24 alongside the get_graph_snapshot MCP tool. The +// `snapshotLoop` / `snapshotEvery` names are retained for wiring stability +// — callers still tune the persistence cadence via `Config.SnapshotEvery`. func (g *GraphRAG) snapshotLoop(ctx context.Context) { ticker := time.NewTicker(g.snapshotEvery) defer ticker.Stop() @@ -60,8 +67,6 @@ func (g *GraphRAG) snapshotLoop(ctx context.Context) { case <-g.stopCh: return case <-ticker.C: - g.takeSnapshot(ctx) - g.pruneOldSnapshots() g.persistDrainTemplates() } } diff --git a/internal/graphrag/snapshot.go b/internal/graphrag/snapshot.go deleted file mode 100644 index da13598..0000000 --- a/internal/graphrag/snapshot.go +++ /dev/null @@ -1,203 +0,0 @@ -package graphrag - -import ( - "context" - "encoding/json" - "fmt" - "log/slog" - "time" - - "github.com/RandomCodeSpace/otelcontext/internal/storage" -) - -// GraphSnapshot is a periodic snapshot of the service topology persisted to DB. -// -// TenantID scopes the row to the tenant slice it was captured from. The -// composite (tenant_id, created_at) index supports the -// "most recent snapshot at-or-before T for tenant X" lookup that -// GetGraphSnapshot runs on every read. -type GraphSnapshot struct { - TenantID string `gorm:"size:64;default:'default';not null;index:idx_graph_snapshots_tenant_created,priority:1" json:"tenant_id"` - ID string `gorm:"primaryKey;size:64" json:"id"` - CreatedAt time.Time `gorm:"index:idx_graph_snapshots_tenant_created,priority:2" json:"created_at"` - Nodes json.RawMessage `gorm:"type:text" json:"nodes"` - Edges json.RawMessage `gorm:"type:text" json:"edges"` - ServiceCount int `json:"service_count"` - TotalCalls int64 `json:"total_calls"` - AvgHealthScore float64 `json:"avg_health_score"` -} - -// TableName overrides GORM's default table name. -func (GraphSnapshot) TableName() string { - return "graph_snapshots" -} - -// snapshotNode is a lightweight node representation for snapshots. -type snapshotNode struct { - ID string `json:"id"` - Type string `json:"type"` - Name string `json:"name"` - HealthScore float64 `json:"health_score"` - ErrorRate float64 `json:"error_rate"` - AvgLatency float64 `json:"avg_latency_ms"` -} - -// snapshotEdge is a lightweight edge representation for snapshots. -type snapshotEdge struct { - From string `json:"from"` - To string `json:"to"` - Type string `json:"type"` - Weight float64 `json:"weight"` - CallCount int64 `json:"call_count"` - ErrorRate float64 `json:"error_rate"` -} - -// takeSnapshot captures each tenant's current service topology and persists -// one row per tenant per tick. See the note on GraphSnapshot regarding the -// upcoming tenant_id column in Subtask B. -func (g *GraphRAG) takeSnapshot(ctx context.Context) { - for tenant, stores := range g.snapshotTenants() { - tctx := storage.WithTenantContext(ctx, tenant) - g.takeSnapshotForTenant(tctx, tenant, stores) - } -} - -func (g *GraphRAG) takeSnapshotForTenant(_ context.Context, tenant string, stores *tenantStores) { - services := stores.service.AllServices() - edges := stores.service.AllEdges() - - if len(services) == 0 { - return - } - - var nodes []snapshotNode - var totalCalls int64 - var totalHealth float64 - - for _, svc := range services { - nodes = append(nodes, snapshotNode{ - ID: svc.ID, - Type: "service", - Name: svc.Name, - HealthScore: svc.HealthScore, - ErrorRate: svc.ErrorRate, - AvgLatency: svc.AvgLatency, - }) - totalCalls += svc.CallCount - totalHealth += svc.HealthScore - } - - // Also include operations for this tenant. - stores.service.mu.RLock() - for _, op := range stores.service.Operations { - nodes = append(nodes, snapshotNode{ - ID: op.ID, - Type: "operation", - Name: op.Operation, - HealthScore: op.HealthScore, - ErrorRate: op.ErrorRate, - AvgLatency: op.AvgLatency, - }) - } - stores.service.mu.RUnlock() - - var snapEdges []snapshotEdge - for _, e := range edges { - snapEdges = append(snapEdges, snapshotEdge{ - From: e.FromID, - To: e.ToID, - Type: string(e.Type), - Weight: e.Weight, - CallCount: e.CallCount, - ErrorRate: e.ErrorRate, - }) - } - - nodesJSON, _ := json.Marshal(nodes) - edgesJSON, _ := json.Marshal(snapEdges) - - snap := GraphSnapshot{ - TenantID: tenant, - ID: fmt.Sprintf("snap_%s_%d", tenant, time.Now().UnixNano()), - CreatedAt: time.Now(), - Nodes: nodesJSON, - Edges: edgesJSON, - ServiceCount: len(services), - TotalCalls: totalCalls, - AvgHealthScore: totalHealth / float64(len(services)), - } - - if g.repo == nil || g.repo.DB() == nil { - return - } - if err := g.repo.DB().Create(&snap).Error; err != nil { - slog.Error("Failed to persist graph snapshot", "tenant", tenant, "error", err) - return - } - - slog.Debug("Graph snapshot persisted", - "tenant", tenant, - "services", len(services), - "edges", len(snapEdges), - ) -} - -// maxSnapshotRows is a row-count backstop on `graph_snapshots` to prevent -// unbounded disk growth when the write rate outruns the 7-day age prune. -// Steady state at 15-min cadence × 100 tenants is ~67k rows/week, so 100k -// gives ~50% headroom — high enough to never trigger under normal operation, -// low enough to bound disk if a misconfig or tenant explosion runs the -// snapshotter hot. -const maxSnapshotRows = 100_000 - -// pruneOldSnapshots removes snapshots older than 7 days, then enforces a -// row-count backstop in case the by-age prune isn't keeping up. -func (g *GraphRAG) pruneOldSnapshots() { - if g.repo == nil || g.repo.DB() == nil { - return - } - cutoff := time.Now().AddDate(0, 0, -7) - result := g.repo.DB().Where("created_at < ?", cutoff).Delete(&GraphSnapshot{}) - if result.Error != nil { - slog.Error("Failed to prune old snapshots", "error", result.Error) - } else if result.RowsAffected > 0 { - slog.Info("Pruned old graph snapshots", "count", result.RowsAffected) - } - - var count int64 - if err := g.repo.DB().Model(&GraphSnapshot{}).Count(&count).Error; err != nil { - slog.Error("Failed to count snapshots for row-cap prune", "error", err) - return - } - if count <= maxSnapshotRows { - return - } - excess := count - maxSnapshotRows - // Subquery selects the N oldest IDs, then deletes that set. Portable - // across SQLite and Postgres; avoids a multi-statement transaction. - sub := g.repo.DB().Model(&GraphSnapshot{}).Select("id").Order("created_at ASC").Limit(int(excess)) - if err := g.repo.DB().Where("id IN (?)", sub).Delete(&GraphSnapshot{}).Error; err != nil { - slog.Error("Failed to row-cap prune snapshots", "error", err) - return - } - slog.Warn("graphrag: row-cap pruned snapshots (write rate exceeded by-age prune)", - "deleted", excess, - "cap", maxSnapshotRows, - ) -} - -// GetGraphSnapshot retrieves the snapshot closest to the requested time, -// scoped to the tenant carried by ctx. The composite (tenant_id, created_at) -// index supports the descending lookup. -func (g *GraphRAG) GetGraphSnapshot(ctx context.Context, at time.Time) (*GraphSnapshot, error) { - tenant := storage.TenantFromContext(ctx) - var snap GraphSnapshot - err := g.repo.DB(). - Where("tenant_id = ? AND created_at <= ?", tenant, at). - Order("created_at DESC"). - First(&snap).Error - if err != nil { - return nil, err - } - return &snap, nil -} diff --git a/main.go b/main.go index a0b938a..217e887 100644 --- a/main.go +++ b/main.go @@ -379,7 +379,7 @@ func main() { "event_queue_size", cfg.GraphRAGEventQueueSize, ) - // Auto-migrate GraphRAG models (Investigation, GraphSnapshot) + // Auto-migrate GraphRAG models (Investigation, DrainTemplateRow) if err := graphrag.AutoMigrateGraphRAG(repo.DB()); err != nil { slog.Error("Failed to migrate GraphRAG models", "error", err) } From 385b0151aae6649a8d7bd71ff61266d9c4dc25e6 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 19:00:05 +0000 Subject: [PATCH 04/11] feat(sqlite): PRAGMA tuning + per-driver config defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the platform survivable at 120 services on SQLite, the target the prior commits in this PR have been shaving heap and disk pressure for. Two coordinated changes: 1. SQLite PRAGMA stanza in factory.go is hardened from 3 to 8 settings and made fail-closed: PRAGMA journal_mode=WAL PRAGMA synchronous=NORMAL PRAGMA cache_size=-262144 # 256 MB page cache PRAGMA temp_store=MEMORY PRAGMA mmap_size=1073741824 # 1 GB mmap PRAGMA wal_autocheckpoint=10000 # checkpoint after 10k pages PRAGMA journal_size_limit=67108864 # cap WAL at 64 MB PRAGMA busy_timeout=5000 Each PRAGMA failure now aborts startup with a wrapped error (`sqlite pragma %q failed: %w`) so an unexpected SQLite build that doesn't honour, e.g. mmap_size, can't silently regress the platform to default-tuned behaviour. 2. config.Load now runs `applyDriverDefaults(cfg)` after constructing the Config struct. When DBDriver=sqlite (case-insensitive) AND the operator did not explicitly set the env var (detected via os.LookupEnv presence — value comparison would falsely treat operator-set Postgres-default values as "unset"), the following defaults flip: DB_MAX_OPEN_CONNS 50 → 1 DB_MAX_IDLE_CONNS 10 → 1 INGEST_PIPELINE_WORKERS 8 → 2 INGEST_PIPELINE_QUEUE_SIZE 50000 → 10000 METRIC_MAX_CARDINALITY 10000 → 3000 STORE_MIN_SEVERITY "" → "WARN" SAMPLING_RATE 1.0 → 0.05 GRPC_MAX_CONCURRENT_STREAMS 1000 → 240 LOG_FTS_ENABLED false → true Postgres/MSSQL/MySQL paths are unchanged bit-for-bit (early-return in applyDriverDefaults). The applyDriverDefaults override is unit-tested for: the all-flip path, the "respect explicit operator override" path, the Postgres no-op path, and case-insensitive driver matching. Design rationale and per-default justification: docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md --- internal/config/config.go | 53 +++++++- internal/config/driver_defaults_test.go | 154 ++++++++++++++++++++++++ internal/storage/factory.go | 30 ++++- 3 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 internal/config/driver_defaults_test.go diff --git a/internal/config/config.go b/internal/config/config.go index ab6817d..4acb6be 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -225,7 +225,7 @@ func Load(customPath string) (*Config, error) { } env := getEnv("APP_ENV", "development") - return &Config{ + cfg := &Config{ Env: env, DevMode: env == "development", LogLevel: getEnv("LOG_LEVEL", "INFO"), @@ -326,7 +326,56 @@ func Load(customPath string) (*Config, error) { // Production safety guard for SQLite AllowSqliteProd: parseTruthy(getEnv("OTELCONTEXT_ALLOW_SQLITE_PROD", "")), - }, nil + } + applyDriverDefaults(cfg) + return cfg, nil +} + +// applyDriverDefaults flips defaults on a freshly-Load()'d Config when the +// driver is SQLite AND the operator did not explicitly set the env var. +// Postgres/MSSQL/MySQL defaults are unchanged. +// +// The platform's stock defaults are tuned for Postgres at 100k events/sec +// with a parallel writer pool. On SQLite those same defaults overrun the +// single-writer lock and inflate heap until the process OOMs — see +// docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md. +// This override gives the SQLite path a survivable starting point at +// 120 services while preserving the existing Postgres path bit-for-bit. +// +// "Explicit operator override" is detected via os.LookupEnv (presence) +// rather than value comparison so that, e.g., DB_MAX_OPEN_CONNS=50 set by +// hand is still honoured even though it equals the Postgres default. +func applyDriverDefaults(cfg *Config) { + if !strings.EqualFold(cfg.DBDriver, "sqlite") { + return + } + if _, ok := os.LookupEnv("DB_MAX_OPEN_CONNS"); !ok { + cfg.DBMaxOpenConns = 1 + } + if _, ok := os.LookupEnv("DB_MAX_IDLE_CONNS"); !ok { + cfg.DBMaxIdleConns = 1 + } + if _, ok := os.LookupEnv("INGEST_PIPELINE_WORKERS"); !ok { + cfg.IngestPipelineWorkers = 2 + } + if _, ok := os.LookupEnv("INGEST_PIPELINE_QUEUE_SIZE"); !ok { + cfg.IngestPipelineQueueSize = 10000 + } + if _, ok := os.LookupEnv("METRIC_MAX_CARDINALITY"); !ok { + cfg.MetricMaxCardinality = 3000 + } + if _, ok := os.LookupEnv("STORE_MIN_SEVERITY"); !ok { + cfg.StoreMinSeverity = "WARN" + } + if _, ok := os.LookupEnv("SAMPLING_RATE"); !ok { + cfg.SamplingRate = 0.05 + } + if _, ok := os.LookupEnv("GRPC_MAX_CONCURRENT_STREAMS"); !ok { + cfg.GRPCMaxConcurrentStreams = 240 + } + if _, ok := os.LookupEnv("LOG_FTS_ENABLED"); !ok { + cfg.LogFTSEnabled = true + } } func getEnv(key, fallback string) string { diff --git a/internal/config/driver_defaults_test.go b/internal/config/driver_defaults_test.go new file mode 100644 index 0000000..baa6407 --- /dev/null +++ b/internal/config/driver_defaults_test.go @@ -0,0 +1,154 @@ +package config + +import ( + "os" + "testing" +) + +// sqliteEnvKeys is the set of env vars whose defaults applyDriverDefaults +// flips when the driver is SQLite. Cleared via t.Setenv before each test so a +// stray host-env value doesn't leak in. +var sqliteEnvKeys = []string{ + "DB_MAX_OPEN_CONNS", + "DB_MAX_IDLE_CONNS", + "INGEST_PIPELINE_WORKERS", + "INGEST_PIPELINE_QUEUE_SIZE", + "METRIC_MAX_CARDINALITY", + "STORE_MIN_SEVERITY", + "SAMPLING_RATE", + "GRPC_MAX_CONCURRENT_STREAMS", + "LOG_FTS_ENABLED", +} + +// clearSQLiteEnv unsets every env var consulted by applyDriverDefaults so +// the test starts from a deterministic "operator set nothing" baseline. +func clearSQLiteEnv(t *testing.T) { + t.Helper() + for _, k := range sqliteEnvKeys { + // Unsetenv is reverted by the Go runtime when the test ends only when + // paired with Setenv("") first. Use Setenv("") then explicit Unsetenv + // via a deferred cleanup so concurrent tests do not see leaked state. + if _, ok := os.LookupEnv(k); ok { + old := os.Getenv(k) + t.Setenv(k, old) // record original for revert + if err := os.Unsetenv(k); err != nil { + t.Fatalf("unset %s: %v", k, err) + } + } + } +} + +// TestApplyDriverDefaults_SQLite_FlipsAllWhenNoEnv proves the post-Load() +// override fires when the driver is SQLite and the operator did not set +// any of the overridable env vars. +func TestApplyDriverDefaults_SQLite_FlipsAllWhenNoEnv(t *testing.T) { + clearSQLiteEnv(t) + cfg := &Config{ + DBDriver: "sqlite", + DBMaxOpenConns: 50, // Postgres default + DBMaxIdleConns: 10, // Postgres default + IngestPipelineWorkers: 8, // Postgres default + IngestPipelineQueueSize: 50000, // Postgres default + MetricMaxCardinality: 10000, // Postgres default + StoreMinSeverity: "", // same-as-ingest default + SamplingRate: 1.0, // keep-all default + GRPCMaxConcurrentStreams: 1000, // Postgres default + LogFTSEnabled: false, // FTS5 opt-in default + } + applyDriverDefaults(cfg) + + cases := []struct { + name string + got any + want any + }{ + {"DBMaxOpenConns", cfg.DBMaxOpenConns, 1}, + {"DBMaxIdleConns", cfg.DBMaxIdleConns, 1}, + {"IngestPipelineWorkers", cfg.IngestPipelineWorkers, 2}, + {"IngestPipelineQueueSize", cfg.IngestPipelineQueueSize, 10000}, + {"MetricMaxCardinality", cfg.MetricMaxCardinality, 3000}, + {"StoreMinSeverity", cfg.StoreMinSeverity, "WARN"}, + {"SamplingRate", cfg.SamplingRate, 0.05}, + {"GRPCMaxConcurrentStreams", cfg.GRPCMaxConcurrentStreams, 240}, + {"LogFTSEnabled", cfg.LogFTSEnabled, true}, + } + for _, c := range cases { + if c.got != c.want { + t.Errorf("%s: SQLite override = %v, want %v", c.name, c.got, c.want) + } + } +} + +// TestApplyDriverDefaults_SQLite_RespectsExplicitOverride proves that an +// operator-set env var is preserved even when its value equals the Postgres +// default. The presence check is via os.LookupEnv, not a value comparison. +func TestApplyDriverDefaults_SQLite_RespectsExplicitOverride(t *testing.T) { + clearSQLiteEnv(t) + t.Setenv("DB_MAX_OPEN_CONNS", "50") // explicit override, equal to Postgres default + t.Setenv("SAMPLING_RATE", "1.0") // explicit "keep all" + + cfg := &Config{ + DBDriver: "sqlite", + DBMaxOpenConns: 50, // operator-set value + SamplingRate: 1.0, // operator-set value + // rest unset so we can confirm the others still flip + } + applyDriverDefaults(cfg) + + if cfg.DBMaxOpenConns != 50 { + t.Errorf("explicit DB_MAX_OPEN_CONNS=50 was clobbered to %d", cfg.DBMaxOpenConns) + } + if cfg.SamplingRate != 1.0 { + t.Errorf("explicit SAMPLING_RATE=1.0 was clobbered to %f", cfg.SamplingRate) + } + // And a field with no env override still flips + if cfg.MetricMaxCardinality != 3000 { + t.Errorf("MetricMaxCardinality should have flipped to 3000, got %d", cfg.MetricMaxCardinality) + } +} + +// TestApplyDriverDefaults_Postgres_NoChange proves the Postgres / Postgresql +// drivers are untouched by this override regardless of env state. +func TestApplyDriverDefaults_Postgres_NoChange(t *testing.T) { + clearSQLiteEnv(t) + for _, drv := range []string{"postgres", "postgresql", "Postgres", "POSTGRES"} { + t.Run(drv, func(t *testing.T) { + cfg := &Config{ + DBDriver: drv, + DBMaxOpenConns: 50, + DBMaxIdleConns: 10, + IngestPipelineWorkers: 8, + IngestPipelineQueueSize: 50000, + MetricMaxCardinality: 10000, + StoreMinSeverity: "", + SamplingRate: 1.0, + GRPCMaxConcurrentStreams: 1000, + LogFTSEnabled: false, + } + before := *cfg + applyDriverDefaults(cfg) + if *cfg != before { + t.Errorf("Postgres driver %q was mutated by SQLite override: %+v → %+v", drv, before, *cfg) + } + }) + } +} + +// TestApplyDriverDefaults_SQLite_CaseInsensitive proves the driver-name +// match is case-insensitive so SQLite / sqlite / SQLITE all trip the +// override. +func TestApplyDriverDefaults_SQLite_CaseInsensitive(t *testing.T) { + clearSQLiteEnv(t) + for _, drv := range []string{"sqlite", "SQLite", "SQLITE"} { + t.Run(drv, func(t *testing.T) { + cfg := &Config{ + DBDriver: drv, + DBMaxOpenConns: 50, + } + applyDriverDefaults(cfg) + if cfg.DBMaxOpenConns != 1 { + t.Errorf("driver=%q SQLite override missed; DBMaxOpenConns=%d", drv, cfg.DBMaxOpenConns) + } + }) + } +} diff --git a/internal/storage/factory.go b/internal/storage/factory.go index 8ba94a9..8e4f178 100644 --- a/internal/storage/factory.go +++ b/internal/storage/factory.go @@ -96,11 +96,33 @@ func NewDatabase(driver, dsn string) (*gorm.DB, error) { return nil, fmt.Errorf("failed to connect to database (%s): %s", driver, scrubDSN(err.Error())) } - // SQLite pragmas must be set via Exec (glebarez/sqlite doesn't support _pragma DSN params) + // SQLite pragmas — set via Exec because glebarez/sqlite doesn't honour + // _pragma DSN params. Applied fail-closed: any PRAGMA failure aborts + // startup with a wrapped error so an unexpected SQLite build that doesn't + // support, e.g. mmap_size cannot silently regress the platform to + // default-tuned behaviour. The set was hardened on 2026-05-24 to make + // the platform survivable at 120 services on SQLite. + // + // cache_size=-262144 = 256 MB page cache (negative = KB). + // mmap_size=1073741824 = 1 GB memory-mapped read window. + // wal_autocheckpoint=10000 = checkpoint after 10k pages so WAL stays bounded. + // journal_size_limit=67108864 = hard-cap the WAL file at 64 MB. if strings.ToLower(driver) == "sqlite" || driver == "" { - db.Exec("PRAGMA journal_mode=WAL") - db.Exec("PRAGMA busy_timeout=5000") - db.Exec("PRAGMA synchronous=NORMAL") + pragmas := []string{ + "PRAGMA journal_mode=WAL", + "PRAGMA synchronous=NORMAL", + "PRAGMA cache_size=-262144", + "PRAGMA temp_store=MEMORY", + "PRAGMA mmap_size=1073741824", + "PRAGMA wal_autocheckpoint=10000", + "PRAGMA journal_size_limit=67108864", + "PRAGMA busy_timeout=5000", + } + for _, p := range pragmas { + if err := db.Exec(p).Error; err != nil { + return nil, fmt.Errorf("sqlite pragma %q failed: %w", p, err) + } + } } // Configure Connection Pool — configurable via env vars for non-SQLite drivers. From 01a84ed6cb1ff25c62da6befa47f0e3eabe29645 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 19:06:44 +0000 Subject: [PATCH 05/11] docs: 7-tool MCP surface and SQLite operator notes Updates the operator-facing documentation to reflect the refactor in this PR: - CLAUDE.md "MCP Server" section rewritten to describe the 7-tool triage surface (kept + cut lists). The architecture diagram drops the legacy Vector accelerator layer. The "Storage Architecture", "GraphRAG Architecture" (background processes, persistence models, log clustering), and "Key Directories" sections drop their vectordb / graph_snapshots mentions. A new "SQLite per-driver defaults" section documents the nine env-var overrides flipped by applyDriverDefaults and the eight PRAGMAs applied at startup. - LOG_FTS_ENABLED entry rewritten to document the new SQLite-default `true` (with the LIKE-fallback / drop_fts reclaim path preserved). - STORE_MIN_SEVERITY entry notes the new SQLite-default `"WARN"`. - README.md "Features" bullet swaps "21 tools" for the 7-tool triage surface and inlines the kept tool names. - .env.example drops the VECTOR_INDEX_* block, adds a "SQLite Tuning" block listing every auto-flipped default, and notes the 7-tool MCP surface under the MCP section. - The design spec at docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md is the canonical record of the refactor's rationale, decision matrix, per-default justification, migration notes, and risk/mitigation table. --- .env.example | 33 ++- CLAUDE.md | 86 +++++--- README.md | 2 +- ...-05-24-mcp-7tool-sqlite-survival-design.md | 201 ++++++++++++++++++ 4 files changed, 282 insertions(+), 40 deletions(-) create mode 100644 docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md diff --git a/.env.example b/.env.example index 8ef86d5..c893ff0 100644 --- a/.env.example +++ b/.env.example @@ -35,10 +35,29 @@ # DB_AUTOMIGRATE=true # GORM AutoMigrate on startup. Set false in Postgres prod (schema out-of-band) # ---- Database Pool ---------------------------------------------------------- -# DB_MAX_OPEN_CONNS=50 # Max concurrent DB connections -# DB_MAX_IDLE_CONNS=10 # Idle connections kept in pool +# DB_MAX_OPEN_CONNS=50 # Max concurrent DB connections (SQLite default 1; SQLite is single-writer) +# DB_MAX_IDLE_CONNS=10 # Idle connections kept in pool (SQLite default 1) # DB_CONN_MAX_LIFETIME=1h # Conn recycle window. Internally capped to 30m when DB_AZURE_AUTH=true +# ---- SQLite Tuning (auto-applied when DB_DRIVER=sqlite) --------------------- +# The platform flips several defaults when running on SQLite so a 100+ service +# deployment survives without OOM. Each override is skipped if the operator +# explicitly sets the env var. Postgres/MSSQL paths are untouched. +# +# DB_MAX_OPEN_CONNS 50 → 1 +# DB_MAX_IDLE_CONNS 10 → 1 +# INGEST_PIPELINE_WORKERS 8 → 2 +# INGEST_PIPELINE_QUEUE_SIZE 50000 → 10000 +# METRIC_MAX_CARDINALITY 10000 → 3000 +# STORE_MIN_SEVERITY "" → "WARN" (INFO/DEBUG still flow to GraphRAG/Drain, just not persisted) +# SAMPLING_RATE 1.0 → 0.05 (errors and slow spans always kept) +# GRPC_MAX_CONCURRENT_STREAMS 1000 → 240 (~2 streams per service at 120 services) +# LOG_FTS_ENABLED false → true (FTS5 BM25 search; ~30% disk overhead — set false to reclaim) +# +# Override by setting the env var explicitly. See +# docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md for +# per-default rationale and the SQLite PRAGMA stanza applied at startup. + # ---- Azure Entra (passwordless Postgres) ------------------------------------ # DB_AZURE_AUTH=false # Enables DefaultAzureCredential for Postgres. Requires strict TLS # # (sslmode=require|verify-ca|verify-full). DSN must omit password. @@ -73,10 +92,9 @@ # ---- TSDB ------------------------------------------------------------------- # TSDB_RING_BUFFER_DURATION=1h # In-memory metric ring buffer window (e.g. 30m, 2h) -# ---- GraphRAG / Cardinality / Vector ---------------------------------------- +# ---- GraphRAG / Cardinality ------------------------------------------------- # METRIC_ATTRIBUTE_KEYS= # CSV allowlist of attribute keys included in metric series key -# METRIC_MAX_CARDINALITY=10000 # Max unique series per metric; new series dropped above this -# VECTOR_INDEX_MAX_ENTRIES=100000 # TF-IDF index capacity (FIFO eviction) +# METRIC_MAX_CARDINALITY=10000 # Max unique series per metric (Postgres default; SQLite default 3000) # ---- DLQ (Dead Letter Queue) ------------------------------------------------ # DLQ_PATH=./data/dlq # Directory for typed-envelope files @@ -91,6 +109,11 @@ # ---- MCP Server ------------------------------------------------------------- # MCP_ENABLED=true # Expose MCP JSON-RPC 2.0 (POST) + SSE (GET) for AI agents # MCP_PATH=/mcp # Mount path +# +# Triage surface (7 tools): get_anomaly_timeline, get_service_map, +# get_service_health, root_cause_analysis, impact_analysis, trace_graph, +# search_logs. Cut in 2026-05-24 reduction from 21 → 7; see +# docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md. # ---- Compression ------------------------------------------------------------ # COMPRESSION_LEVEL=default # default|fast|best — zstd level for compressed columns diff --git a/CLAUDE.md b/CLAUDE.md index a410516..a12f397 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,12 +25,11 @@ HTTP :8080/v1/* (OTLP HTTP)─┘ │ │ ▼ ▼ In-Memory Accel. Relational DB (TSDB Ring, (Source of Truth, - GraphRAG, 7-15 day retention) - Vector) + GraphRAG) 7-15 day retention) │ HTTP :8080 ◄── REST API ◄───────────┘ ◄── WebSocket (real-time) - ◄── MCP Server (AI agents, 21 tools) + ◄── MCP Server (AI agents, 7-tool triage surface) ◄── Prometheus /metrics ``` @@ -59,8 +58,7 @@ When none are present, `DEFAULT_TENANT` (default `"default"`) is assigned. Every | GraphRAG (in-memory) | `internal/graphrag/` | Layered graph: 4 typed stores, error chains, root cause analysis, anomaly detection | | Time Series (in-memory) | `internal/tsdb/` | Ring buffer, sliding windows, pre-computed percentiles | | Graph (in-memory, legacy) | `internal/graph/` | Simple service topology — **being replaced by GraphRAG** | -| Vector (embedded) | `internal/vectordb/` | TF-IDF index for semantic log search (pure Go, no CGO). Persisted across restarts via gob+CRC32 snapshot (default `data/vectordb.snapshot`, 5m interval) plus a startup tail-replay from the DB so the index is warm before listeners accept traffic — eliminating the legacy minutes of cold-start blindness. `find_similar_logs` and `SimilarErrors` (within a Drain template cluster) are the read-side consumers. | -| Relational (persistent) | `internal/storage/` | GORM-based, multi-DB, single source of truth. Driven by `RetentionScheduler` (hourly batched purge + daily VACUUM/ANALYZE). `logs.body` is plain TEXT. **Log search**: vectordb (TF-IDF) is the default semantic-search path. Optional SQLite FTS5 (`logs_fts`, porter+unicode61, ordered by `bm25()`, AFTER INSERT/DELETE/UPDATE triggers) is **opt-in via `LOG_FTS_ENABLED=true`** and disabled by default — operators who toggle it off can reclaim the FTS table + indexes via `POST /api/admin/drop_fts`. Postgres uses `pg_trgm` GIN on `logs.body` and `logs.service_name`. `AttributesJSON` and `AIInsight` remain `CompressedText`. The `search_logs` MCP tool and the API `/api/logs?q=…` filter are clamped to the **last 24 hours** to bound the LIKE-fallback worst case. | +| Relational (persistent) | `internal/storage/` | GORM-based, multi-DB, single source of truth. Driven by `RetentionScheduler` (hourly batched purge + daily VACUUM/ANALYZE). `logs.body` is plain TEXT. **Log search**: SQLite FTS5 (`logs_fts`, porter+unicode61, ordered by `bm25()`, AFTER INSERT/DELETE/UPDATE triggers) is the default path — `LOG_FTS_ENABLED` defaults to `true` when `DB_DRIVER=sqlite` and `false` otherwise. Operators who want the ~30% disk savings can set `LOG_FTS_ENABLED=false` and reclaim the FTS table + indexes via `POST /api/admin/drop_fts`. Postgres uses `pg_trgm` GIN on `logs.body` and `logs.service_name`. `AttributesJSON` and `AIInsight` remain `CompressedText`. The `search_logs` MCP tool and the API `/api/logs?q=…` filter are clamped to the **last 24 hours** to bound the LIKE-fallback worst case. The `vectordb` package (TF-IDF semantic search) was removed on 2026-05-24 alongside the `find_similar_logs` MCP tool — `data/vectordb.snapshot` is left on disk for operators to delete by hand. | ## GraphRAG Architecture @@ -91,23 +89,23 @@ The `internal/graphrag/` package is the core intelligence layer. It replaces the | `CorrelatedSignals(service, timeRange)` | Gather all edges | Related logs/metrics/traces | | `ShortestPath(from, to)` | Dijkstra weighted by inverse call freq | Service communication path | | `AnomalyTimeline(since)` | Time-sorted anomalies + PRECEDED_BY | Recent anomaly overview | -| `SimilarErrors(clusterID, k)` | k-NN cosine similarity via vectordb | Related error patterns | | `ServiceMap(depth)` | Full topology dump | Service topology + health | ### Background Processes - **4 event workers** consume from a 10,000-capacity buffered channel (best-effort; DB is source of truth) - **Refresh loop** (60s) — rebuilds from DB, prunes expired TraceStore nodes, cleans old anomalies -- **Snapshot loop** (15min) — persists topology snapshot to DB, prunes snapshots > 7 days +- **Snapshot loop** (15min) — persists Drain templates so cluster IDs survive restart (the `graph_snapshots` write side was removed on 2026-05-24; the loop name is retained for wiring stability) - **Anomaly loop** (10s) — detects error spikes, latency degradation, metric z-score anomalies ### Persistence Models (GORM) - `Investigation` — automated error analysis records (trigger, root cause, causal chain, evidence) -- `GraphSnapshot` — periodic topology snapshots (nodes, edges, health scores) - `DrainTemplateRow` — persisted Drain log templates (table `drain_templates`), loaded on startup to warm the miner +> Note: `GraphSnapshot` (table `graph_snapshots`) was removed on 2026-05-24. AutoMigrate no longer creates the table on fresh deploys; existing populated tables are left in place — operators can `DROP TABLE graph_snapshots; VACUUM;` to reclaim disk. + ### Log Clustering (Drain) -Log clustering uses **Drain** template mining (`internal/graphrag/drain.go`) — a deterministic fixed-depth prefix tree with O(1) LRU via `container/list`. It replaces the older hash-based clustering. Templates are persisted to the `drain_templates` table and reloaded on startup so cluster IDs stay stable across restarts. The TF-IDF `vectordb` is retained as a fallback similarity ranker inside a template bucket (`SimilarErrors`). +Log clustering uses **Drain** template mining (`internal/graphrag/drain.go`) — a deterministic fixed-depth prefix tree with O(1) LRU via `container/list`. Templates are persisted to the `drain_templates` table and reloaded on startup so cluster IDs stay stable across restarts. ### Ingestion Callbacks ``` @@ -116,26 +114,31 @@ LogsServer.Export() → DB persist → logCallback → GraphRAG.OnLogIngested( MetricsServer.Export() → TSDB → metricCallback → GraphRAG.OnMetricIngested() ``` -## MCP Server — 21 Tools - -The MCP server (`internal/mcp/`) exposes tools via HTTP Streamable MCP (JSON-RPC 2.0 POST + SSE GET). +## MCP Server — 7-Tool Triage Surface -### Legacy Tools (11) -`get_system_graph`, `get_service_health`, `search_logs`, `tail_logs`, `get_trace`, `search_traces`, `get_metrics`, `get_dashboard_stats`, `get_storage_status`, `find_similar_logs`, `get_alerts` +The MCP server (`internal/mcp/`) exposes a focused 7-tool triage surface via +HTTP Streamable MCP (JSON-RPC 2.0 POST + SSE GET). The surface was reduced +from 21 → 7 on 2026-05-24 so the platform survives 120 services on SQLite — +see `docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md` +for the full rationale. -### GraphRAG Tools (10) | Tool | Input | Source | |------|-------|--------| -| `get_service_map` | `{depth?, service?}` | In-memory (instant) | -| `get_error_chains` | `{service, time_range?, limit?}` | In-memory + DB fallback | -| `trace_graph` | `{trace_id}` | In-memory + DB fallback | -| `impact_analysis` | `{service, depth?}` | In-memory (instant) | -| `root_cause_analysis` | `{service, time_range?}` | In-memory (instant) | -| `correlated_signals` | `{service, time_range?}` | In-memory + DB | -| `get_investigations` | `{service?, severity?, status?, limit?}` | DB query | -| `get_investigation` | `{investigation_id}` | DB query | -| `get_graph_snapshot` | `{time}` | DB query | -| `get_anomaly_timeline` | `{since?, service?}` | In-memory (instant) | +| `get_anomaly_timeline` | `{since?, service?}` | In-memory (instant) — triage entry point | +| `get_service_map` | `{depth?, service?}` | In-memory (instant) — topology + health overlay | +| `get_service_health` | `{service_name}` | In-memory (instant) — per-service drill-down | +| `root_cause_analysis` | `{service, time_range?}` | In-memory (instant) — ranked probable causes | +| `impact_analysis` | `{service, depth?}` | In-memory (instant) — blast radius | +| `trace_graph` | `{trace_id}` | In-memory + DB fallback — trace tree visualisation | +| `search_logs` | `{query?, severity?, service?, trace_id?, start?, end?, limit?, page?}` | DB (FTS5 default on SQLite, LIKE fallback, 24h-clamped) | + +Cut tools (clients now receive an `unknown tool` RPC error): `get_system_graph`, +`tail_logs`, `get_trace`, `search_traces`, `get_metrics`, `get_dashboard_stats`, +`get_storage_status`, `find_similar_logs`, `get_alerts`, `correlated_signals`, +`get_error_chains`, `get_investigations`, `get_investigation`, `get_graph_snapshot`. + +Cacheable surface (5s TTL via `MCP_CACHE_TTL_MS`): `get_anomaly_timeline`, +`get_service_map`, `get_service_health`, `root_cause_analysis`, `impact_analysis`. Every error-identifying tool returns a `root_cause` block: ```json @@ -176,23 +179,21 @@ internal/ builder.go # Event workers, ingestion callbacks, GraphRAG coordinator queries.go # ErrorChain, ImpactAnalysis, RootCause, ShortestPath, etc. investigation.go # GORM Investigation model + persistence - snapshot.go # GORM GraphSnapshot model + scheduler anomaly.go # Z-score, error spike, latency degradation detection drain.go # Log clustering via Drain template mining — pure-Go, stdlib-only, deterministic fixed-depth prefix tree - refresh.go # Periodic DB rebuild + pruning + refresh.go # Periodic DB rebuild + pruning + Drain template persistence ingest/ # OTLP receivers (gRPC + HTTP), adaptive sampling otlp.go # gRPC TraceServer, LogsServer, MetricsServer otlp_http.go # HTTP OTLP handler (protobuf + JSON, gzip, 4MB limit) sampler.go # Per-service token bucket sampler - mcp/ # MCP server (21 tools, JSON-RPC 2.0 + SSE) + mcp/ # MCP server (7-tool triage surface, JSON-RPC 2.0 + SSE) queue/ # Dead Letter Queue (typed envelopes, bounded disk, exp backoff) realtime/ # WebSocket hub + event streaming - storage/ # GORM repository, models, migrations, Close() method + storage/ # GORM repository, models, migrations, Close() method, SQLite PRAGMA stanza telemetry/ # Prometheus metrics + health (19 metrics) tsdb/ # Time series aggregator + ring buffer (lock-free Windows()) - vectordb/ # Embedded TF-IDF vector index (FIFO eviction with copy, clean IDF rebuild). Persisted via gob+CRC32 snapshot + startup DB tail-replay (snapshot.go, replay.go). ui/ # Embedded React frontend -ui/ # React frontend (Vite + Mantine) +ui/ # React frontend (Vite + @ossrandom/design-system) test/ # Microservice simulation (7 services) docs/ # Specifications and plans ``` @@ -213,17 +214,34 @@ Key settings in `internal/config/config.go`: - `METRIC_MAX_CARDINALITY` (10000), `METRIC_MAX_CARDINALITY_PER_TENANT` (0 = unlimited), `API_RATE_LIMIT_RPS` (100). The per-tenant cap is checked first; when set, a noisy tenant cannot exhaust the global pool. Overflow is labeled by tenant via `otelcontext_tsdb_cardinality_overflow_by_tenant_total{tenant_id}` (`__global__` sentinel when the global cap was the trigger). - `MCP_ENABLED` (true), `MCP_PATH` (/mcp) - `MCP_MAX_CONCURRENT` (32), `MCP_CALL_TIMEOUT_MS` (30000), `MCP_CACHE_TTL_MS` (5000) — MCP HTTP streamable robustness. Counting semaphore gates concurrent `tools/call` (JSON-RPC `-32000` past the cap), per-call deadlines abort runaway handlers (JSON-RPC `-32001`), and a 5s TTL cache memoizes the cheap in-memory GraphRAG tools (`get_service_map`, `impact_analysis`, `root_cause_analysis`, `get_anomaly_timeline`, `get_service_health`). SSE GET sends a `: keep-alive\n\n` comment every 25s to keep the stream alive across reverse-proxy idle timeouts. Set any to 0 to disable. -- `VECTOR_INDEX_MAX_ENTRIES` (100000), `VECTOR_INDEX_SNAPSHOT_PATH` (`data/vectordb.snapshot`), `VECTOR_INDEX_SNAPSHOT_INTERVAL` (`5m`) — vectordb persistence. Empty `VECTOR_INDEX_SNAPSHOT_PATH` or non-positive interval disables the snapshot loop. The snapshot file uses a magic+version+CRC32 wire format with gob payload; corrupt or version-mismatched files are rejected and the loader falls back to a full DB rebuild via `ReplayFromDB`. Watch `otelcontext_vectordb_snapshot_writes_total{result}`, `otelcontext_vectordb_snapshot_load_total{result}`, `otelcontext_vectordb_snapshot_size_bytes`, and `otelcontext_vectordb_replay_logs_total`. -- `LOG_FTS_ENABLED` (false) — when truthy (`true`/`yes`/`on`/`1`), provisions the SQLite FTS5 `logs_fts` virtual table + sync triggers at startup; when false, log-search uses vectordb (semantic) plus a 24h-clamped LIKE fallback. Toggle off and reclaim disk via `POST /api/admin/drop_fts` (refused while the flag is on). +- `LOG_FTS_ENABLED` — when truthy (`true`/`yes`/`on`/`1`), provisions the SQLite FTS5 `logs_fts` virtual table + sync triggers at startup; when false, log-search uses a 24h-clamped LIKE fallback. **Defaults to `true` when `DB_DRIVER=sqlite`** (BM25 is dramatically faster than LIKE on the kept `search_logs` MCP tool) and `false` otherwise. Toggle off and reclaim the ~30% disk overhead via `POST /api/admin/drop_fts` (refused while the flag is on). The vectordb-backed semantic-search path was removed on 2026-05-24. - `DLQ_MAX_FILES` (1000), `DLQ_MAX_DISK_MB` (500), `DLQ_MAX_RETRIES` (10) - `GRAPHRAG_WORKER_COUNT` (16), `GRAPHRAG_EVENT_QUEUE_SIZE` (100000) — sized for 100–200 services; raise further if `otelcontext_graphrag_events_dropped_total` climbs -- `INGEST_MIN_SEVERITY` (`INFO`), `STORE_MIN_SEVERITY` (`""` = same as ingest) — two-tier log severity gate. The ingest gate runs at the OTLP receiver and **drops the log entirely** below the threshold (no in-memory enrichment either). The store gate runs at the persist boundary inside the async pipeline (`internal/ingest/pipeline.go:process`) and **only skips the DB row write** — the log still flows through `LogCallback` so vectordb indexing, GraphRAG Drain template mining, and span/trace correlation see it. Use case: `INGEST_MIN_SEVERITY=DEBUG STORE_MIN_SEVERITY=WARN` keeps SQLite small while letting in-memory anomaly detection benefit from the verbose stream. Setting `STORE_MIN_SEVERITY` ≤ `INGEST_MIN_SEVERITY` is a no-op (logged as a warning at startup). Drops surface via `Pipeline.Stats().StoreFiltered`. +- `INGEST_MIN_SEVERITY` (`INFO`), `STORE_MIN_SEVERITY` (`""` = same as ingest; **defaults to `"WARN"` when `DB_DRIVER=sqlite`**) — two-tier log severity gate. The ingest gate runs at the OTLP receiver and **drops the log entirely** below the threshold (no in-memory enrichment either). The store gate runs at the persist boundary inside the async pipeline (`internal/ingest/pipeline.go:process`) and **only skips the DB row write** — the log still flows through `LogCallback` so GraphRAG Drain template mining and span/trace correlation see it. Use case: `INGEST_MIN_SEVERITY=DEBUG STORE_MIN_SEVERITY=WARN` keeps SQLite small while letting in-memory anomaly detection benefit from the verbose stream. Setting `STORE_MIN_SEVERITY` ≤ `INGEST_MIN_SEVERITY` is a no-op (logged as a warning at startup). Drops surface via `Pipeline.Stats().StoreFiltered`. - `INGEST_ASYNC_ENABLED` (true), `INGEST_PIPELINE_QUEUE_SIZE` (50000), `INGEST_PIPELINE_WORKERS` (8) — async ingest pipeline (`internal/ingest/pipeline.go`). Hybrid backpressure: <90% accept all, 90–100% drop healthy batches (errors/slow always pass), 100% return gRPC `RESOURCE_EXHAUSTED`. Set `INGEST_ASYNC_ENABLED=false` to revert to synchronous DB writes inside `Export()`. Drops surface as `otelcontext_ingest_pipeline_dropped_total{signal,reason}`. - `GRPC_MAX_RECV_MB` (16), `GRPC_MAX_CONCURRENT_STREAMS` (1000) — OTLP gRPC server caps, validated to 1..256 and 1..1_000_000 - `RETENTION_BATCH_SIZE` (50000), `RETENTION_BATCH_SLEEP_MS` (1) — purge pacing; raise the sleep on busy production DBs - `DB_POSTGRES_PARTITIONING` (`""`), `DB_PARTITION_LOOKAHEAD_DAYS` (3) — opt-in Postgres declarative range partitioning of the `logs` table by day. When `daily`, `logs` is provisioned as a partitioned parent (greenfield only — refuses to start if `logs` already exists unpartitioned), the `PartitionScheduler` maintains lookahead partitions and drops expired ones via `DROP TABLE`, and `RetentionScheduler` skips the row-level DELETE for `logs`. Watch `otelcontext_partitions_dropped_total` and `otelcontext_partitions_active`. - `APP_ENV` (`"development"`), `OTELCONTEXT_ALLOW_SQLITE_PROD` (false) — SQLite is refused when `APP_ENV=production` unless the allow flag is set +### SQLite per-driver defaults (auto-flipped when DB_DRIVER=sqlite) + +So a 100+ service deployment on SQLite survives without OOM, `config.Load()` overrides nine defaults at the end of the Load() pass — but **only when the operator did not explicitly set the env var** (detected via `os.LookupEnv` presence, not value comparison). Postgres/MSSQL/MySQL paths are untouched. + +| Env var | SQLite default | Postgres default | Rationale | +|---|---|---|---| +| `DB_MAX_OPEN_CONNS` | 1 | 50 | SQLite is single-writer; extra conns are wasted slots. | +| `DB_MAX_IDLE_CONNS` | 1 | 10 | Match open conns. | +| `INGEST_PIPELINE_WORKERS` | 2 | 8 | Workers all serialise through the SQLite writer lock; 2 is enough to keep the queue non-empty. | +| `INGEST_PIPELINE_QUEUE_SIZE` | 10000 | 50000 | Lower heap watermark; backpressure kicks in earlier so OTLP clients back off. | +| `METRIC_MAX_CARDINALITY` | 3000 | 10000 | Bound the in-memory TSDB series map. | +| `STORE_MIN_SEVERITY` | `"WARN"` | `""` | Skip INFO/DEBUG persists; in-memory GraphRAG/Drain still sees them. | +| `SAMPLING_RATE` | 0.05 | 1.0 | Errors and slow spans are always kept by `SAMPLING_ALWAYS_ON_ERRORS`. | +| `GRPC_MAX_CONCURRENT_STREAMS` | 240 | 1000 | ~2 streams per service at 120 services with headroom. | +| `LOG_FTS_ENABLED` | `true` | n/a | FTS5 BM25 is dramatically faster than LIKE on the kept `search_logs` path. | + +Also at SQLite startup, `internal/storage/factory.go` applies a fail-closed PRAGMA stanza: `journal_mode=WAL`, `synchronous=NORMAL`, `cache_size=-262144` (256 MB page cache), `temp_store=MEMORY`, `mmap_size=1073741824` (1 GB mmap), `wal_autocheckpoint=10000`, `journal_size_limit=67108864` (64 MB WAL cap), `busy_timeout=5000`. Any PRAGMA failure aborts startup with a wrapped error — these are not optional. See `docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md` for per-default reasoning. + ### Authentication **API auth (platform).** `API_KEY` gates `/api/*`, OTLP HTTP (`/v1/*`), and the MCP endpoint via `Authorization: Bearer `. When empty, the middleware is a pass-through (dev only). Unprotected paths: `/live`, `/ready`, `/metrics*`, `/ws*`. A shared `API_KEY` grants access to every tenant — there is no per-tenant-key file in the current code; isolate tenants at the network/auth layer if that matters. (If an `API_TENANT_KEYS_FILE` override lands later, re-check `internal/api/auth.go` for the flag name.) diff --git a/README.md b/README.md index 927cf93..dc1053e 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ See `docs/otel-collector-example.yaml` for a complete example. - **OTLP gRPC + HTTP ingest** — traces, logs, metrics; gzip and protobuf/JSON supported. - **GraphRAG** — layered in-memory graph with error-chain, impact, and root-cause queries. - **Drain log clustering** — deterministic template mining, persisted across restarts. -- **MCP server** — 21 tools exposing the platform to AI agents over JSON-RPC 2.0 + SSE. +- **MCP server** — 7-tool triage surface for AI agents over JSON-RPC 2.0 + SSE (get_anomaly_timeline, get_service_map, get_service_health, root_cause_analysis, impact_analysis, trace_graph, search_logs). - **Multi-tenancy** — per-row `tenant_id`, `X-Tenant-ID` header / `x-tenant-id` gRPC metadata. - **Adaptive sampling** — always-on for errors and slow spans, probabilistic otherwise. - **DLQ** — durable typed envelopes with disk-bounded replay. diff --git a/docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md b/docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md new file mode 100644 index 0000000..28aa5a0 --- /dev/null +++ b/docs/superpowers/specs/2026-05-24-mcp-7tool-sqlite-survival-design.md @@ -0,0 +1,201 @@ +# MCP 7-Tool Triage Surface + SQLite Survival Tuning + +**Date:** 2026-05-24 +**Branch:** `feat/mcp-7tool-sqlite-survival` +**Status:** Implementation +**Authors:** OtelContext platform team + +## Problem statement + +A production OtelContext deployment with 120 services ingesting OTel data on the +SQLite backend OOMs within 1 hour and grows the on-disk DB at roughly 2 TB/day. +The platform is not survivable on its default-recommended single-binary setup +once service count crosses ~20, well below the documented "small deployment" +guidance of "~5 services". + +## Investigation summary + +A 7-agent parallel investigation (5 Explore subagents, plus Codex/GPT-5 and +Antigravity/Gemini cross-checks) identified four primary OOM culprits: + +1. **In-memory pipeline queue saturation under SQLite WAL contention.** The + default `INGEST_PIPELINE_QUEUE_SIZE=50000` × per-batch dozens-of-KB + payloads is sized for a Postgres deployment that can absorb 8 worker + threads in parallel. SQLite's single-writer lock serializes everything + into one writer, so the queue fills, retains all batches in heap, and + the soft-backpressure 90% threshold never relieves pressure fast enough. +2. **GraphRAG permanent stores with no TTL.** `ServiceStore` and `SignalStore` + are permanent; `AnomalyStore` is 24h. With 120 services × N operations + × M log clusters × cross-service edges, the in-memory node count grows + monotonically until heap pressure triggers full GC stalls. +3. **TSDB ring at default cardinality.** `METRIC_MAX_CARDINALITY=10000` is + per-series, and with 120 services emitting heterogeneous attribute sets + the in-memory ring buffer plus the series → bucket map dominates heap. +4. **Span AttributesJSON duplicating resource attributes on every row.** + Compressed-text column is still tens-of-KB per span; resource attrs are + ~80% of each row's payload and are duplicated unconditionally. + +Secondary findings: + +- The `vectordb` TF-IDF index is held entirely in memory (`maxSize=100000` + documents × per-doc TF map + IDF table) and persists on a 5-minute snapshot + loop. It accounts for ~5-15% of resident heap depending on log volume. +- The `graph_snapshots` table grows by ~67k rows/week at 100 tenants × 15-min + cadence × N services, contributing meaningfully to the 2 TB/day disk + growth on SQLite (every row carries a compressed JSON nodes+edges blob). +- 14 of the 21 MCP tools are operationally non-essential during a triage + workflow — they wrap full-text trace search, dashboard stats, and + investigation history that an LLM caller almost never reaches for + inside an active incident response. + +## Decision + +Three coordinated changes, none of which touch GraphRAG core query logic, +TSDB core, or ingest pipeline core: + +1. **Cut the 21-tool MCP surface to 7 triage-essential tools.** No + deprecation period — production is already failing; the cut is + immediate. Kept tools cover the full Linear-scan triage workflow + (anomaly timeline → service map → root cause → impact → trace). +2. **Drop subsystems no longer reachable by any kept tool.** The + `vectordb` package, the `graph_snapshots` GORM model + scheduler, and + the `SimilarErrors` function (vectordb-dependent, no production caller) + are deleted. Removing them reclaims heap on SQLite and stops the + `graph_snapshots` row growth dead. +3. **Tune SQLite via PRAGMAs + per-driver config defaults.** Apply the + community-standard WAL + 256 MB page-cache + 1 GB mmap pragmas at + `gorm.Open`. Override eight config defaults when `DB_DRIVER=sqlite` + so the rest of the platform stops pushing more load at SQLite than + it can absorb. Postgres defaults are unchanged. + +### 7-tool MCP triage surface (kept) + +| Tool | Source | Why kept | +|---|---|---| +| `get_anomaly_timeline` | in-mem GraphRAG | The triage entry point — "what's wrong right now". | +| `get_service_map` | in-mem GraphRAG | Topology + health overlay drives every UI service-graph view. | +| `get_service_health` | in-mem GraphRAG | Per-service drill-down from the service map. | +| `root_cause_analysis` | in-mem GraphRAG | Ranked probable causes — the LLM's primary "why" tool. | +| `impact_analysis` | in-mem GraphRAG | Blast-radius for incident scoping. | +| `trace_graph` | in-mem GraphRAG (+ DB fallback) | Trace tree visualisation — the "show me the bad trace" path. | +| `search_logs` | DB (FTS5 default on SQLite, LIKE fallback) | The "show me the error logs around the incident" path. | + +### Tools cut (14) + +`get_system_graph`, `tail_logs`, `get_trace`, `search_traces`, `get_metrics`, +`get_dashboard_stats`, `get_storage_status`, `find_similar_logs`, +`get_alerts`, `correlated_signals`, `get_error_chains`, `get_investigations`, +`get_investigation`, `get_graph_snapshot`. + +Rationale: each of these either (a) duplicates a kept tool with a slightly +different framing (`get_system_graph` ≈ `get_service_map`, +`get_error_chains` is folded into `root_cause_analysis`), (b) requires +subsystems being dropped (`find_similar_logs` → vectordb, +`get_graph_snapshot` → snapshot table), or (c) belongs to a separate +forensic-analytics workflow (`get_investigations`, `get_investigation`, +`get_dashboard_stats`) that is not part of active triage. + +### Subsystem deletions + +| Subsystem | Files / artifacts | Reason | +|---|---|---| +| `vectordb` package | `internal/vectordb/` (index.go, snapshot.go, replay.go + tests) | No surviving MCP tool consumes it; ~5-15% of heap; snapshot+replay loops are dead weight under triage workload. | +| Snapshot scheduler | `internal/graphrag/snapshot.go`; `GraphSnapshot` GORM model; snapshot loop in builder.go; `get_graph_snapshot` MCP tool already cut | `graph_snapshots` table is the second-largest disk-growth contributor after raw spans/logs. No kept tool reads it. | +| `SimilarErrors` | `internal/graphrag/clustering.go::SimilarErrors` | Vectordb-dependent, has no production caller, only used by the cut `find_similar_logs` tool path historically. | +| `/api/logs/similar` | `internal/api/similar_handler.go` + test | Same vectordb dependency; same triage non-essential. | +| `tools.go` cuts | 14 handler funcs deleted | One-line follow-on per dropped tool. | + +### SQLite tuning + +After `gorm.Open` succeeds with `DB_DRIVER=sqlite`, apply these PRAGMAs in +order with fail-closed error handling: + +```go +pragmas := []string{ + "PRAGMA journal_mode=WAL", // existing + "PRAGMA synchronous=NORMAL", // existing + "PRAGMA cache_size=-262144", // 256 MB page cache (new) + "PRAGMA temp_store=MEMORY", // new + "PRAGMA mmap_size=1073741824", // 1 GB mmap (new) + "PRAGMA wal_autocheckpoint=10000", // new — keeps WAL bounded + "PRAGMA journal_size_limit=67108864", // cap WAL at 64 MB (new) + "PRAGMA busy_timeout=5000", // existing +} +``` + +A PRAGMA failure is fatal — these are not optional, and silent fallback +to defaults defeats the survivability goal. + +### Per-driver config defaults + +The following defaults override the Postgres-tuned defaults when +`DB_DRIVER=sqlite`, only if the operator has not explicitly set the env +var (detected via `os.LookupEnv`, not value comparison): + +| Env var | SQLite default | Postgres/MSSQL default | Reason | +|---|---|---|---| +| `DB_MAX_OPEN_CONNS` | 1 | 50 | SQLite single-writer; multiple open conns are wasted slots. | +| `DB_MAX_IDLE_CONNS` | 1 | 10 | Match open conns. | +| `INGEST_PIPELINE_WORKERS` | 2 | 8 | 8 workers all serialize through the SQLite writer lock anyway; 2 is enough to keep the writer queue non-empty without pushing extra work into heap. | +| `INGEST_PIPELINE_QUEUE_SIZE` | 10000 | 50000 | Smaller queue = lower heap watermark; backpressure kicks in earlier so OTLP clients back off rather than us OOMing. | +| `METRIC_MAX_CARDINALITY` | 3000 | 10000 | Bound the TSDB series map. 120 services × 25 series/service still fits. | +| `STORE_MIN_SEVERITY` | `WARN` | `""` (== ingest) | Skip INFO/DEBUG persists on the SQLite path — in-memory GraphRAG/anomaly detection still benefits from the full stream. | +| `SAMPLING_RATE` | 0.05 | 1.0 | Trace volume is the primary disk-growth contributor. 5% sample at 120 services ≈ what 1.0 used to do at 6 services. | +| `GRPC_MAX_CONCURRENT_STREAMS` | 240 | 1000 | Each stream costs heap; 120 services × 2 = 240 covers the deployment with no overhead. | +| `LOG_FTS_ENABLED` | `true` | n/a | FTS5 is dramatically faster than LIKE on the kept `search_logs` path; operators who want the ~30% disk savings can opt out. | + +### `search_logs` backend swap + +The kept `search_logs` MCP tool drops the vectordb dispatch branch entirely +(the dispatch was previously vectordb-first for free-form text queries on +SQLite). On SQLite the path is FTS5-when-enabled-else-LIKE; both honour the +existing 24h time-window clamp. + +## Migration notes for existing DBs + +- **`graph_snapshots` table is left in place.** AutoMigrate stops *creating* + it on fresh deploys (the model is deleted) but existing tables are not + dropped. Operators on populated SQLite DBs can reclaim disk with + `DROP TABLE graph_snapshots; VACUUM;` after upgrade. +- **`vectordb.snapshot` file is left in place.** The hydration code that + reads it at boot is deleted, so it becomes a stale file in `data/`. Safe + to delete by hand. +- **No schema changes to traces, spans, logs, metric_buckets, investigations, + drain_templates.** All historical data remains queryable via the kept + MCP surface. +- **MCP clients calling cut tools will receive an `unknown tool` RPC error.** + No graceful degradation; the cut is intentional and immediate. + +## Risk + mitigation table + +| Risk | Likelihood | Impact | Mitigation | +|---|---|---|---| +| Cut tool was actually load-bearing for some user's workflow | Low | Medium | The kept 7 cover all triage paths; forensic workflows can use the SQL DB directly or wait for re-introduction with a clearer scope. | +| FTS5 default-on bumps SQLite disk by 30-40% | Medium | Low | Documented opt-out (`LOG_FTS_ENABLED=false`) + `POST /api/admin/drop_fts` reclaim path already exists. | +| SQLite `synchronous=NORMAL` + `mmap_size=1GB` is more sensitive to host OOM-kill | Low | Medium | These are the SQLite community's standard "make it survive write-heavy workloads" pragmas; the alternative (silent throughput collapse) is strictly worse. | +| `STORE_MIN_SEVERITY=WARN` default surprises an operator who needs INFO logs persisted | Medium | Low | Documented in `.env.example` + `CLAUDE.md`; setting `STORE_MIN_SEVERITY=INFO` explicitly restores legacy behaviour. | +| `SAMPLING_RATE=0.05` default loses too many spans for some debugging | Medium | Low | Always-on errors + slow spans are preserved (existing config); 5% normal-path sampling still gives enough signal for triage. Operator can set `SAMPLING_RATE=1.0` to revert. | +| Deleted `graph_snapshots` causes existing UI views to break | Low | Medium | No UI view consumes the table — verified by grep before cut. | + +## Acceptance criterion + +Survives 120 services on SQLite for 7-day continuous load without OOM and +without disk growth exceeding the documented hot retention (7d × ~50 GB/d +after sampling and STORE_MIN_SEVERITY = ~350 GB steady-state, down from +~14 TB unbounded growth). + +## Commit structure + +Five logical commits on `feat/mcp-7tool-sqlite-survival`: + +1. `refactor(mcp): drop 14 non-triage tools, keep 7-tool triage surface` +2. `refactor(vectordb): drop package; FTS5 + recent-N-in-cluster replace semantic similarity` +3. `refactor(graphrag): drop graph_snapshots table + scheduler` +4. `feat(sqlite): PRAGMA tuning + per-driver config defaults for 120-service survival` +5. `docs: 7-tool MCP surface + SQLite operator notes` + +## Verification + +`gofmt -l .`, `go vet ./...`, `go build .`, `go test ./...`, and a UI +`npm install && npm run build && npm test -- --run` pass before each +commit lands. From 6b76f0c0bac02c700e03b107553e7d67b0202b82 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Fri, 5 Jun 2026 06:58:17 +0000 Subject: [PATCH 06/11] refactor: drop central-ops private dependency The github.com/RandomCodeSpace/central-ops module is private and 404s for this account, breaking offline/air-gapped builds. Only two symbols were used, both trivially replaceable in-tree: - main.go: version.Detect() -> local detectVersion() via runtime/debug (runtime/debug was already imported); falls back to "local". - internal/mcp/server.go: httputil.CORSMiddleware -> local corsMiddleware that sets Access-Control-Allow-* and answers OPTIONS preflight. go mod edit -droprequire + go.sum cleanup. go build and go vet pass. Co-Authored-By: Claude Opus 4.8 --- go.mod | 2 -- go.sum | 2 -- internal/mcp/server.go | 20 ++++++++++++++++++-- main.go | 15 ++++++++++++--- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index da4d77e..fd5ebc8 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/RandomCodeSpace/otelcontext go 1.25.9 -require github.com/RandomCodeSpace/central-ops v0.1.0 - require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.1 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 diff --git a/go.sum b/go.sum index 122bef9..4091401 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,6 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgv github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/RandomCodeSpace/central-ops v0.1.0 h1:HAM/dRRiY399EutNEGJO+JmT0lyJ/faIYcIiepY++VA= -github.com/RandomCodeSpace/central-ops v0.1.0/go.mod h1:CgzQCG56F8uyUAxBA5wWBgqDeXQMl/vYCK9Yetuau2o= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= diff --git a/internal/mcp/server.go b/internal/mcp/server.go index c331eac..90282fb 100644 --- a/internal/mcp/server.go +++ b/internal/mcp/server.go @@ -11,7 +11,6 @@ import ( "sync/atomic" "time" - "github.com/RandomCodeSpace/central-ops/pkg/httputil" "github.com/RandomCodeSpace/otelcontext/internal/graph" "github.com/RandomCodeSpace/otelcontext/internal/graphrag" "github.com/RandomCodeSpace/otelcontext/internal/httpconst" @@ -193,7 +192,24 @@ func (s *Server) SetGraphRAG(g *graphrag.GraphRAG) { // Handler returns an http.Handler for the MCP server with CORS applied. // Works correctly when mounted with http.StripPrefix. func (s *Server) Handler() http.Handler { - return httputil.CORSMiddleware("*", http.HandlerFunc(s.ServeHTTP)) + return corsMiddleware("*", http.HandlerFunc(s.ServeHTTP)) +} + +// corsMiddleware wraps next with permissive CORS headers and answers preflight +// OPTIONS requests. Replaces the former central-ops httputil.CORSMiddleware so +// the project carries no private-module dependency. +func corsMiddleware(allowOrigin string, next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := w.Header() + h.Set("Access-Control-Allow-Origin", allowOrigin) + h.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") + h.Set("Access-Control-Allow-Headers", "*") + if r.Method == http.MethodOptions { + w.WriteHeader(http.StatusNoContent) + return + } + next.ServeHTTP(w, r) + }) } // ServeHTTP dispatches by HTTP method — no path routing needed. diff --git a/main.go b/main.go index 217e887..12355e8 100644 --- a/main.go +++ b/main.go @@ -14,8 +14,6 @@ import ( "syscall" "time" - "github.com/RandomCodeSpace/central-ops/pkg/version" - "github.com/RandomCodeSpace/otelcontext/internal/ai" "github.com/RandomCodeSpace/otelcontext/internal/api" "github.com/RandomCodeSpace/otelcontext/internal/config" @@ -55,7 +53,18 @@ import ( // Version is detected from build info at startup. // Returns the real tag when installed via `go install`, "local" otherwise. -var Version = version.Detect() +var Version = detectVersion() + +// detectVersion reads the module version from build info, falling back to +// "local" for ad-hoc `go build` invocations that don't stamp a version. +func detectVersion() string { + if bi, ok := debug.ReadBuildInfo(); ok { + if v := bi.Main.Version; v != "" && v != "(devel)" { + return v + } + } + return "local" +} // cleanupStack is an ordered LIFO list of cleanup closures registered during // startup. fatal() walks it before os.Exit so DBs, DLQs, and tracer providers From 47b2d6fc72f0b6ac577c9ba741eb66612a0ec06f Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Fri, 5 Jun 2026 06:58:34 +0000 Subject: [PATCH 07/11] =?UTF-8?q?feat(ui):=20rebuild=20frontend=20?= =?UTF-8?q?=E2=80=94=20dashboard,=20scalable=20service=20map,=20MCP=20cons?= =?UTF-8?q?ole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full frontend overhaul on React 19 + @ossrandom/design-system. Dashboard (new default view): - 12-col bento grid, 5 bands: hero health gauge, traffic/errors, top failing services, recent anomalies, platform health. - Uptime stat + readiness probe dots + DB size. - Recent anomalies clamped to a 15-minute window, deduped by service|type to the 20 most recent. Service map: - Raw cytoscape (cose-bilkent) topology scaling 1–200 services with every node on screen; node size = degree (edge count). - Hover/click reveals a node's edges + stats; label LOD past 120 nodes. - Graph/List segmented toggle (list is the accessible default on touch/small screens). MCP Trial console: - List-detail layout over the 7-tool triage surface via JSON-RPC. - Dynamic tool forms, result views, history, live SSE stream, settings. Platform: - TopNav segmented tabs (Dashboard/Services/MCP); removed Logs & Traces. - ErrorBoundary mounted; theme race fixed in main.tsx. - ServicesView and MCPConsoleView lazy-loaded to keep cytoscape out of the initial bundle (206KB / 65KB gz). - Re-embedded internal/ui/dist. tsc -b, vitest, and eslint pass. Co-Authored-By: Claude Opus 4.8 --- .../ui/dist/assets/MCPConsoleView-BXQJGMyT.js | 4 + .../ui/dist/assets/ServicesView-n3l2yFxx.js | 321 +++++++++++++++ .../assets/cytoscape-cose-bilkent-CEIBo6Gj.js | 1 - .../ui/dist/assets/cytoscape.esm-Dm6iss-N.js | 321 --------------- .../ui/dist/assets/design-system-BNhP-Tae.js | 1 - .../ui/dist/assets/design-system-DFjB0sSn.js | 1 - .../ui/dist/assets/design-system-IOKLDoaG.js | 1 - internal/ui/dist/assets/index-B9ZFj2IV.js | 9 - internal/ui/dist/assets/index-D7nwP4LR.js | 10 + internal/ui/dist/assets/inputs-DxVBbFvb.js | 1 + .../ui/dist/assets/useMediaQuery-D3Mg-H7H.js | 1 + internal/ui/dist/index.html | 3 +- ui/eslint.config.js | 40 ++ ui/src/App.tsx | 51 ++- ui/src/components/common/Truncate.tsx | 28 ++ ui/src/components/dashboard/DashboardView.tsx | 370 +++++++++++++++++ ui/src/components/dashboard/dashTypes.test.ts | 73 ++++ ui/src/components/dashboard/dashTypes.ts | 78 ++++ ui/src/components/mcp/LiveStream.tsx | 72 ++++ ui/src/components/mcp/MCPConsole.tsx | 45 -- ui/src/components/mcp/MCPConsoleView.tsx | 278 +++++++++++++ ui/src/components/mcp/SettingsDrawer.tsx | 103 +++++ ui/src/components/mcp/ToolForm.tsx | 282 +++++++++++++ ui/src/components/mcp/ToolHistory.tsx | 88 ++++ ui/src/components/mcp/ToolResult.tsx | 201 +++++++++ ui/src/components/mcp/ToolResultViews.tsx | 306 ++++++++++++++ .../mcp/__tests__/mcpParsing.test.ts | 122 ++++++ ui/src/components/mcp/mcpTypes.ts | 189 +++++++++ ui/src/components/mcp/toolFields.ts | 116 ++++++ ui/src/components/nav/TopNav.tsx | 135 ++---- ui/src/components/observability/LogsView.tsx | 222 ---------- .../components/observability/ServiceGraph.tsx | 384 ++++++++++++++++++ .../components/observability/ServiceList.tsx | 92 +++++ .../observability/ServiceSidePanel.tsx | 4 +- .../components/observability/ServicesView.tsx | 135 +++--- .../components/observability/TracesView.tsx | 217 ---------- .../__tests__/ServiceSidePanel.test.tsx | 12 +- ui/src/hooks/useAnomalies.ts | 80 ++++ ui/src/hooks/useLogs.ts | 43 -- ui/src/hooks/useMcpCall.ts | 164 ++++++++ ui/src/hooks/useMcpTools.ts | 59 +++ ui/src/hooks/useReady.ts | 40 ++ ui/src/hooks/useTheme.ts | 27 +- ui/src/hooks/useTraces.ts | 38 -- ui/src/hooks/useTraffic.ts | 35 ++ ui/src/lib/breakpoints.ts | 14 + ui/src/lib/layers.ts | 14 + ui/src/lib/mcpClient.ts | 82 ++++ ui/src/main.tsx | 21 +- ui/src/types/cytoscape-cose-bilkent.d.ts | 9 + ui/tsconfig.app.json | 1 - 51 files changed, 3853 insertions(+), 1091 deletions(-) create mode 100644 internal/ui/dist/assets/MCPConsoleView-BXQJGMyT.js create mode 100644 internal/ui/dist/assets/ServicesView-n3l2yFxx.js delete mode 100644 internal/ui/dist/assets/cytoscape-cose-bilkent-CEIBo6Gj.js delete mode 100644 internal/ui/dist/assets/cytoscape.esm-Dm6iss-N.js delete mode 100644 internal/ui/dist/assets/design-system-BNhP-Tae.js delete mode 100644 internal/ui/dist/assets/design-system-DFjB0sSn.js delete mode 100644 internal/ui/dist/assets/design-system-IOKLDoaG.js delete mode 100644 internal/ui/dist/assets/index-B9ZFj2IV.js create mode 100644 internal/ui/dist/assets/index-D7nwP4LR.js create mode 100644 internal/ui/dist/assets/inputs-DxVBbFvb.js create mode 100644 internal/ui/dist/assets/useMediaQuery-D3Mg-H7H.js create mode 100644 ui/eslint.config.js create mode 100644 ui/src/components/common/Truncate.tsx create mode 100644 ui/src/components/dashboard/DashboardView.tsx create mode 100644 ui/src/components/dashboard/dashTypes.test.ts create mode 100644 ui/src/components/dashboard/dashTypes.ts create mode 100644 ui/src/components/mcp/LiveStream.tsx delete mode 100644 ui/src/components/mcp/MCPConsole.tsx create mode 100644 ui/src/components/mcp/MCPConsoleView.tsx create mode 100644 ui/src/components/mcp/SettingsDrawer.tsx create mode 100644 ui/src/components/mcp/ToolForm.tsx create mode 100644 ui/src/components/mcp/ToolHistory.tsx create mode 100644 ui/src/components/mcp/ToolResult.tsx create mode 100644 ui/src/components/mcp/ToolResultViews.tsx create mode 100644 ui/src/components/mcp/__tests__/mcpParsing.test.ts create mode 100644 ui/src/components/mcp/mcpTypes.ts create mode 100644 ui/src/components/mcp/toolFields.ts delete mode 100644 ui/src/components/observability/LogsView.tsx create mode 100644 ui/src/components/observability/ServiceGraph.tsx create mode 100644 ui/src/components/observability/ServiceList.tsx delete mode 100644 ui/src/components/observability/TracesView.tsx create mode 100644 ui/src/hooks/useAnomalies.ts delete mode 100644 ui/src/hooks/useLogs.ts create mode 100644 ui/src/hooks/useMcpCall.ts create mode 100644 ui/src/hooks/useMcpTools.ts create mode 100644 ui/src/hooks/useReady.ts delete mode 100644 ui/src/hooks/useTraces.ts create mode 100644 ui/src/hooks/useTraffic.ts create mode 100644 ui/src/lib/breakpoints.ts create mode 100644 ui/src/lib/layers.ts create mode 100644 ui/src/lib/mcpClient.ts create mode 100644 ui/src/types/cytoscape-cose-bilkent.d.ts diff --git a/internal/ui/dist/assets/MCPConsoleView-BXQJGMyT.js b/internal/ui/dist/assets/MCPConsoleView-BXQJGMyT.js new file mode 100644 index 0000000..0b1c529 --- /dev/null +++ b/internal/ui/dist/assets/MCPConsoleView-BXQJGMyT.js @@ -0,0 +1,4 @@ +import{A as e,C as t,D as n,E as r,M as i,O as a,P as o,T as s,_ as c,c as l,d as u,f as d,h as f,i as p,j as m,k as h,l as g,m as _,n as v,o as y,r as b,s as x,t as S,u as C,v as w,w as T,y as E}from"./useMediaQuery-D3Mg-H7H.js";import{n as D,r as O,t as k}from"./inputs-DxVBbFvb.js";import{n as ee,r as A,t as j}from"./index-D7nwP4LR.js";var M=m(),N=o(i(),1);function P(e,t){N.useEffect(()=>{let n=n=>{e.current&&!e.current.contains(n.target)&&t()};return document.addEventListener(`mousedown`,n),()=>document.removeEventListener(`mousedown`,n)},[e,t])}function F(e){let{options:t,value:n,defaultValue:r,placeholder:i=`Select…`,searchable:a=!1,clearable:o=!1,disabled:s=!1,status:c=`default`,size:l=`md`,onChange:u,className:d,style:f,id:p,"data-testid":m}=e,g=n!==void 0,[_,v]=N.useState(r),y=g?n:_,[b,x]=N.useState(!1),[S,C]=N.useState(``),w=N.useRef(null);P(w,()=>x(!1));let T=t.find(e=>e.value===y),E=a&&S?t.filter(e=>String(e.label).toLowerCase().includes(S.toLowerCase())):t,D=e=>{e.disabled||(g||v(e.value),u?.(e.value,e),x(!1),C(``))};return(0,M.jsxs)(`div`,{ref:w,id:p,"data-testid":m,className:h(`rcs-select`,d),style:f,"data-open":b||void 0,children:[(0,M.jsxs)(`button`,{type:`button`,className:h(`rcs-select-trigger`,`rcs-select-trigger--${l}`),"data-status":c,disabled:s,"aria-haspopup":`listbox`,"aria-expanded":b,onClick:()=>!s&&x(e=>!e),children:[(0,M.jsx)(`span`,{className:h(`rcs-select-value`,!T&&`rcs-select-placeholder`),children:T?T.label:i}),o&&T&&!s&&(0,M.jsx)(`button`,{type:`button`,className:`rcs-input-clear`,"aria-label":`Clear`,onClick:e=>{e.stopPropagation(),g||v(void 0),u?.(void 0,{value:void 0,label:``})},children:`×`}),(0,M.jsx)(`span`,{className:`rcs-select-caret`,"aria-hidden":!0,children:`▾`})]}),b&&(0,M.jsxs)(`div`,{className:`rcs-select-menu`,role:`listbox`,children:[a&&(0,M.jsx)(`input`,{autoFocus:!0,className:`rcs-select-search`,placeholder:`Search…`,value:S,onChange:e=>C(e.target.value)}),E.length===0?(0,M.jsx)(`div`,{className:`rcs-select-empty`,children:`No results`}):E.map(e=>(0,M.jsxs)(`div`,{role:`option`,"aria-selected":e.value===y,className:`rcs-select-option`,"data-selected":e.value===y||void 0,"data-disabled":e.disabled||void 0,onClick:()=>D(e),children:[e.icon&&(0,M.jsx)(`span`,{"aria-hidden":!0,children:e.icon}),(0,M.jsx)(`span`,{children:e.label}),e.description&&(0,M.jsx)(`span`,{className:`rcs-select-option-desc`,children:e.description})]},String(e.value)))]})]})}function I(e){let{checked:t,defaultChecked:n,size:r=`md`,disabled:i=!1,loading:a=!1,label:o,onChange:s,className:c,style:l,id:u}=e,d=t!==void 0,[f,p]=N.useState(n??!1),m=d?t:f;return(0,M.jsxs)(`label`,{id:u,className:h(`rcs-switch`,`rcs-switch--${r}`,c),style:l,"data-checked":m||void 0,"data-disabled":i||void 0,children:[(0,M.jsx)(`input`,{type:`checkbox`,role:`switch`,checked:m,disabled:i||a,onChange:e=>{d||p(e.target.checked),s?.(e.target.checked)}}),(0,M.jsx)(`span`,{className:`rcs-switch-track`,"aria-hidden":!0,children:(0,M.jsx)(`span`,{className:`rcs-switch-thumb`})}),o&&(0,M.jsx)(`span`,{className:`rcs-switch-label`,children:o})]})}function L(e,t=`YYYY-MM-DD`){if(!e)return``;let n=e.getFullYear(),r=String(e.getMonth()+1).padStart(2,`0`),i=String(e.getDate()).padStart(2,`0`);return t.replace(`YYYY`,String(n)).replace(`MM`,r).replace(`DD`,i)}function R(e){if(!e)return null;let t=new Date(e);return Number.isNaN(t.getTime())?null:t}function z(e){let{value:t,defaultValue:n,min:r,max:i,format:a=`YYYY-MM-DD`,placeholder:o,disabled:s,onChange:c,className:l,style:u,id:d}=e,f=t!==void 0,[p,m]=N.useState(n??null);return(0,M.jsx)(k,{id:d,className:l,style:u,type:`text`,placeholder:o??a,disabled:s,value:L(f?t??null:p,a),onChange:e=>{let t=R(e);f||m(t),c?.(t)},suffix:(0,M.jsx)(`span`,{style:{fontSize:12},children:`📅`})})}function B(t){let{label:n,hint:r,error:i,required:a,optional:o,htmlFor:s,children:c,className:l,style:u,id:d}=t,f=s??d??e(`field`);return(0,M.jsxs)(`div`,{id:d,className:h(`rcs-form-field`,l),style:u,children:[n&&(0,M.jsxs)(`label`,{htmlFor:f,className:`rcs-form-label`,children:[n,a&&(0,M.jsx)(`span`,{className:`rcs-form-required`,"aria-label":`required`,children:`*`}),o&&!a&&(0,M.jsx)(`span`,{className:`rcs-form-optional`,children:`(optional)`})]}),c,i?(0,M.jsx)(`span`,{className:`rcs-form-error`,role:`alert`,children:i}):r?(0,M.jsx)(`span`,{className:`rcs-form-hint`,children:r}):null]})}function V(e){let{code:t,language:n=`plain`,filename:r,showLineNumbers:i=!1,highlightLines:a,copyable:o=!0,wrap:s=!1,onCopy:c,className:l,style:u,id:d}=e,f=t.split(` +`),p=new Set(a??[]);return(0,M.jsxs)(`div`,{id:d,className:h(`rcs-codeblock`,l),style:u,children:[(r||n||o)&&(0,M.jsxs)(`div`,{className:`rcs-codeblock-header`,children:[(0,M.jsx)(`span`,{children:r??n}),o&&(0,M.jsx)(`button`,{className:`rcs-codeblock-copy`,onClick:async()=>{try{await navigator.clipboard.writeText(t),c?.()}catch{}},children:`Copy`})]}),(0,M.jsx)(`pre`,{className:`rcs-codeblock-pre`,"data-wrap":s||void 0,children:(0,M.jsx)(`code`,{"data-language":n,children:i||p.size>0?f.map((e,t)=>(0,M.jsxs)(`span`,{className:`rcs-codeblock-line`,"data-highlight":p.has(t+1)||void 0,children:[i&&(0,M.jsx)(`span`,{className:`rcs-codeblock-lineno`,children:t+1}),(0,M.jsxs)(`span`,{children:[e,` +`]})]},t)):t})})]})}function H(e){let{title:t,lines:n,streaming:r=!1,height:i=320,searchable:a=!1,tabs:o,onInput:s,onTabChange:c,className:l,style:u,id:d}=e,[f,p]=N.useState(``),[m,g]=N.useState(``),_=N.useRef(null);N.useEffect(()=>{let e=_.current;e&&(e.scrollTop=e.scrollHeight)},[n.length,r]);let v=f?n.filter(e=>e.text.toLowerCase().includes(f.toLowerCase())):n;return(0,M.jsxs)(`div`,{id:d,className:h(`rcs-terminal`,l),style:{height:i,...u},children:[(o||t||a)&&(0,M.jsxs)(`div`,{className:`rcs-terminal-tabs`,children:[t&&(0,M.jsx)(`span`,{className:`rcs-terminal-tab`,"data-active":!0,children:t}),o?.map(e=>(0,M.jsx)(`button`,{className:`rcs-terminal-tab`,"data-active":e.active||void 0,onClick:()=>c?.(e.key),style:{background:`transparent`,border:0,cursor:`pointer`,color:`inherit`},children:e.label},e.key)),a&&(0,M.jsx)(`input`,{placeholder:`filter…`,value:f,onChange:e=>p(e.target.value),style:{marginLeft:`auto`,background:`#0F0F0F`,color:`#E5E5E5`,border:`1px solid #2B2B2B`,borderRadius:3,fontSize:11,fontFamily:`inherit`,padding:`2px 6px`,outline:0}})]}),(0,M.jsxs)(`div`,{ref:_,className:`rcs-terminal-body`,children:[v.map((e,t)=>(0,M.jsx)(`div`,{className:`rcs-terminal-line`,"data-type":e.type,children:e.text},t)),r&&(0,M.jsx)(`span`,{className:`rcs-terminal-cursor`})]}),s&&(0,M.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),m.trim()&&(s(m),g(``))},style:{display:`flex`,padding:`8px 12px`,borderTop:`1px solid #2B2B2B`,gap:8},children:[(0,M.jsx)(`span`,{style:{color:`#1F9E5C`},children:`$`}),(0,M.jsx)(`input`,{value:m,onChange:e=>g(e.target.value),style:{flex:1,background:`transparent`,border:0,outline:0,color:`#E5E5E5`,fontFamily:`inherit`,fontSize:13},placeholder:`Type a command…`})]})]})}var te=p(`Settings`,[[`path`,{d:`M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z`,key:`1qme2f`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]);function ne(e){let[t,n]=(0,N.useState)([]),[r,i]=(0,N.useState)(!0),[a,o]=(0,N.useState)(null),s=e?.apiKey,c=e?.tenant,l=(0,N.useCallback)(()=>{let e=new AbortController;return i(!0),A({apiKey:s,tenant:c,signal:e.signal}).then(e=>{n(e),o(null)}).catch(t=>{e.signal.aborted||(t instanceof j?o(`MCP ${t.code}: ${t.message}`):o(t instanceof Error?t.message:`failed to reach /mcp`),n([]))}).finally(()=>{e.signal.aborted||i(!1)}),()=>e.abort()},[s,c]);return(0,N.useEffect)(()=>l(),[l]),{tools:t,loading:r,error:a,reload:l}}function U(e){let t=e.content?.[0];if(!t)return``;if(typeof t.text==`string`&&t.text.length>0)return t.text;let n=t.resource;return n&&typeof n.text==`string`?n.text:``}function W(e,t=0){if(t>6||typeof e!=`object`||!e)return null;if(Array.isArray(e)){for(let n of e){let e=W(n,t+1);if(e)return e}return null}let n=e,r=n.root_cause;if(r&&typeof r==`object`&&`service`in r)return r;for(let e of Object.keys(n)){let r=W(n[e],t+1);if(r)return r}return null}function G(e){let t=U(e),n;try{n=t?JSON.parse(t):void 0}catch{n=void 0}return{isError:e.isError===!0,payload:n,text:t,rootCause:n===void 0?null:W(n)}}var K=`otelcontext.mcp.history`,q=50;function re(){try{let e=sessionStorage.getItem(K);if(!e)return[];let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function J(e){try{sessionStorage.setItem(K,JSON.stringify(e.slice(0,q)))}catch{}}function ie(e,t){return JSON.stringify({jsonrpc:`2.0`,id:1,method:`tools/call`,params:{name:e,arguments:t}},null,2)}var Y=0;function X(){return Y+=1,`${Date.now().toString(36)}-${Y}`}function ae(e){let[t,n]=(0,N.useState)({loading:!1}),[r,i]=(0,N.useState)(()=>re()),a=(0,N.useRef)(null),o=e?.apiKey,s=e?.tenant;(0,N.useEffect)(()=>()=>a.current?.abort(),[]);let c=(0,N.useCallback)(e=>{i(t=>{let n=[e,...t].slice(0,q);return J(n),n})},[]);return{state:t,call:(0,N.useCallback)(async(e,t)=>{a.current?.abort();let r=new AbortController;a.current=r;let i=ie(e,t),l=performance.now();n({loading:!0,requestBody:i});try{let a=await ee(e,t,{apiKey:o,tenant:s,signal:r.signal});if(r.signal.aborted)return;let u=Math.round(performance.now()-l),d=G(a);n({loading:!1,result:a,parsed:d,requestBody:i,latencyMs:u}),c({id:X(),tool:e,args:t,requestBody:i,status:d.isError?`tool_error`:`success`,latencyMs:u,timestamp:Date.now()})}catch(a){if(r.signal.aborted)return;let o=Math.round(performance.now()-l);n({loading:!1,error:a instanceof j?{kind:`rpc`,code:a.code,message:a.message}:{kind:`transport`,message:a instanceof Error?a.message:`request failed`},requestBody:i,latencyMs:o}),c({id:X(),tool:e,args:t,requestBody:i,status:`rpc_error`,latencyMs:o,timestamp:Date.now()})}},[o,s,c]),reset:(0,N.useCallback)(()=>n({loading:!1}),[]),history:r,clearHistory:(0,N.useCallback)(()=>{i([]),J([])},[])}}var oe=[`ERROR`,`WARN`,`INFO`,`DEBUG`];function se(e,t){switch(e){case`service`:case`service_name`:return`service`;case`severity`:return`severity`;case`since`:case`start`:case`end`:return`datetime`;case`time_range`:return`duration`;case`depth`:case`limit`:case`page`:return`number`;default:return t===`number`?`number`:`text`}}function ce(e){let t=e.inputSchema?.properties??{},n=new Set(e.inputSchema?.required??[]);return Object.keys(t).map(e=>{let r=se(e,t[e]?.type),i={name:e,kind:r,required:n.has(e),description:t[e]?.description};return e===`limit`&&(i.max=200),r===`number`&&(i.min=0),i})}function le(e,t){let n={};for(let r of e){let e=t[r.name];if(!(e===void 0||e===``))if(r.kind===`number`){let t=Number(e);Number.isNaN(t)||(n[r.name]=t)}else n[r.name]=e}return n}var ue=[{label:`15m`,ms:15*6e4},{label:`1h`,ms:60*6e4},{label:`24h`,ms:1440*6e4}];function de(e,t){let n=(()=>{try{return JSON.stringify(JSON.parse(e))}catch{return e}})(),r=[`curl -sS http://localhost:8080/mcp \\`,` -H 'Content-Type: application/json' \\`,` -H "Authorization: Bearer $API_KEY" \\`];return t&&r.push(` -H 'X-Tenant-ID: ${t}' \\`),r.push(` -d '${n.replace(/'/g,`'\\''`)}'`),r.join(` +`)}var fe={display:`grid`,gap:12,gridTemplateColumns:`minmax(0, 1fr)`},pe={display:`flex`,gap:8,marginTop:6};function me(e){return e?e.toISOString():``}function he(){let[e,t]=(0,N.useState)([]);return(0,N.useEffect)(()=>{let e=new AbortController;return fetch(`/api/metadata/services`,{signal:e.signal}).then(e=>e.ok?e.json():[]).then(e=>{Array.isArray(e)&&t(e.filter(e=>typeof e==`string`))}).catch(()=>{}),()=>e.abort()},[]),e}function ge({tool:e,running:n,onRun:i,initialValues:a}){let o=(0,N.useMemo)(()=>ce(e),[e]),s=he(),[c,l]=(0,N.useState)(a??{}),[u,d]=(0,N.useState)(!1),[f,p]=(0,N.useState)(``),[m,h]=(0,N.useState)(null),g=(0,N.useCallback)((e,t)=>{l(n=>({...n,[e]:t}))},[]),_=(0,N.useMemo)(()=>le(o,c),[o,c]);(0,N.useEffect)(()=>{u&&p(JSON.stringify(_,null,2))},[u]);let v=(0,N.useCallback)(e=>{p(e);try{let t=e.trim()?JSON.parse(e):{};if(typeof t!=`object`||!t||Array.isArray(t)){h(`Arguments must be a JSON object.`);return}let n={};for(let[e,r]of Object.entries(t))n[e]=typeof r==`string`?r:String(r);l(n),h(null)}catch{h(`Invalid JSON.`)}},[]),y=o.filter(e=>e.required&&!c[e.name]).map(e=>e.name);return(0,M.jsxs)(t,{direction:`vertical`,size:`md`,style:{width:`100%`},children:[(0,M.jsxs)(`div`,{style:fe,children:[o.length===0&&(0,M.jsx)(C,{severity:`info`,title:`No parameters`,children:`This tool takes no arguments — run it directly.`}),o.map(e=>(0,M.jsx)(_e,{field:e,value:c[e.name]??``,services:s,onChange:t=>g(e.name,t)},e.name))]}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(r,{variant:`link`,size:`sm`,onClick:()=>d(e=>!e),children:u?`Hide raw arguments`:`Edit raw arguments`}),u&&(0,M.jsxs)(`div`,{style:{marginTop:8},children:[(0,M.jsx)(O,{value:f,rows:6,status:m?`error`:`default`,onChange:e=>v(e)}),m&&(0,M.jsx)(C,{severity:`danger`,style:{marginTop:8},children:m})]})]}),(0,M.jsxs)(t,{direction:`horizontal`,size:`sm`,align:`center`,children:[(0,M.jsx)(r,{variant:`primary`,loading:n,disabled:y.length>0,onClick:()=>{y.length>0||i(_)},children:`Run tool`}),y.length>0&&(0,M.jsxs)(`span`,{style:{fontSize:13,opacity:.7},children:[`Required: `,y.join(`, `)]})]})]})}function _e({field:e,value:t,services:i,onChange:a}){let o=e.required,s;switch(e.kind){case`service`:s=i.length>0?(0,M.jsx)(F,{options:i.map(e=>({label:e,value:e})),value:t||void 0,searchable:!0,clearable:!0,placeholder:`Select a service`,onChange:e=>a(String(e))}):(0,M.jsx)(k,{value:t,placeholder:`service name`,onChange:e=>a(e)});break;case`severity`:s=(0,M.jsx)(F,{options:oe.map(e=>({label:e,value:e})),value:t||void 0,clearable:!0,placeholder:`Any severity`,onChange:e=>a(String(e))});break;case`datetime`:s=(0,M.jsxs)(`div`,{children:[(0,M.jsx)(z,{value:t?new Date(t):void 0,format:`yyyy-MM-dd HH:mm`,placeholder:`now`,onChange:e=>a(me(e))}),(0,M.jsxs)(`div`,{style:pe,children:[(0,M.jsx)(n,{size:`sm`,children:ue.map(e=>(0,M.jsxs)(r,{variant:`secondary`,size:`sm`,onClick:()=>a(new Date(Date.now()-e.ms).toISOString()),children:[`-`,e.label]},e.label))}),t&&(0,M.jsx)(r,{variant:`ghost`,size:`sm`,onClick:()=>a(``),children:`Clear`})]})]});break;case`duration`:s=(0,M.jsx)(k,{value:t,placeholder:`15m`,onChange:e=>a(e)});break;case`number`:s=(0,M.jsx)(D,{value:t===``?void 0:Number(t),min:e.min,max:e.max,onChange:t=>{let n=t;e.max!==void 0&&n>e.max&&(n=e.max),e.min!==void 0&&na(e),placeholder:e.name})}return(0,M.jsx)(B,{label:e.name,required:o,hint:e.description,children:s})}var Z=100,ve={display:`grid`,gap:12,gridTemplateColumns:`repeat(auto-fit, minmax(160px, 1fr))`};function Q({shown:e,total:t}){return t<=e?null:(0,M.jsxs)(`div`,{style:{fontSize:12,opacity:.7,marginTop:8},children:[`Showing `,e,` of `,t,` — open Raw JSON for the full payload.`]})}function ye(e){let t=e.toUpperCase();return t===`ERROR`||t===`FATAL`||t===`CRITICAL`?`danger`:t===`WARN`||t===`WARNING`?`warning`:t===`INFO`?`info`:`neutral`}function be(e){return e>=.85?`running`:e>=.5?`degraded`:`failed`}function xe(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function Se({data:e}){if(e.length===0)return(0,M.jsx)(C,{severity:`success`,title:`No anomalies in window`});let t=e.slice(0,Z);return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(g,{items:t.map(e=>({key:e.id,title:`${e.service} — ${e.type}`,description:e.evidence,time:xe(e.timestamp),tone:e.severity?.toLowerCase()===`critical`?`danger`:`warning`}))}),(0,M.jsx)(Q,{shown:t.length,total:e.length})]})}function Ce({data:e}){let t=e.filter(e=>e.service).slice(0,Z).map(e=>{let t=e.service;return{name:t.name,health_score:t.health_score,error_rate:t.error_rate,call_count:t.call_count,avg_latency_ms:t.avg_latency_ms,deps:e.calls_to?.length??0}});return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(l,{columns:[{key:`name`,title:`Service`,render:(e,t)=>(0,M.jsxs)(`span`,{style:{display:`flex`,alignItems:`center`,gap:8,minWidth:0},children:[(0,M.jsx)(s,{status:be(t.health_score)}),(0,M.jsx)(b,{text:t.name})]})},{key:`health`,title:`Health`,align:`right`,render:(e,t)=>t.health_score.toFixed(2)},{key:`err`,title:`Error rate`,align:`right`,render:(e,t)=>`${(t.error_rate*100).toFixed(1)}%`},{key:`calls`,title:`Calls`,align:`right`,dataKey:`call_count`},{key:`lat`,title:`Avg ms`,align:`right`,render:(e,t)=>t.avg_latency_ms.toFixed(1)},{key:`deps`,title:`Deps`,align:`right`,dataKey:`deps`}],data:t,rowKey:`name`,density:`compact`,striped:!0}),(0,M.jsx)(Q,{shown:t.length,total:e.filter(e=>e.service).length})]})}function we({data:e}){let t=e.service;return t?(0,M.jsxs)(`div`,{style:ve,children:[(0,M.jsx)(x,{label:`Health score`,value:t.health_score.toFixed(2)}),(0,M.jsx)(x,{label:`Error rate`,value:`${(t.error_rate*100).toFixed(1)}`,unit:`%`}),(0,M.jsx)(x,{label:`Requests`,value:t.call_count}),(0,M.jsx)(x,{label:`Errors`,value:t.error_count}),(0,M.jsx)(x,{label:`Avg latency`,value:t.avg_latency_ms.toFixed(1),unit:`ms`}),(0,M.jsx)(x,{label:`Operations`,value:e.operations?.length??0})]}):(0,M.jsx)(C,{severity:`warning`,title:`Service not found in current window`})}function Te({data:e}){let t=e.affected_services??[];if(t.length===0)return(0,M.jsx)(C,{severity:`success`,title:`No downstream impact from ${e.service}`});let n=t.slice(0,Z);return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`div`,{style:{marginBottom:8},children:(0,M.jsxs)(T,{tone:`warning`,children:[e.total_downstream,` downstream affected`]})}),(0,M.jsx)(l,{columns:[{key:`service`,title:`Service`,render:(e,t)=>(0,M.jsx)(b,{text:t.service})},{key:`depth`,title:`Depth`,align:`right`,dataKey:`depth`},{key:`calls`,title:`Calls`,align:`right`,dataKey:`call_count`},{key:`impact`,title:`Impact`,align:`right`,render:(e,t)=>t.impact_score.toFixed(2)}],data:n,rowKey:`service`,density:`compact`,striped:!0}),(0,M.jsx)(Q,{shown:n.length,total:t.length})]})}function Ee({data:e}){if(e.length===0)return(0,M.jsx)(C,{severity:`info`,title:`No ranked causes found`});let t=e.slice(0,Z);return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(g,{items:t.map((e,t)=>({key:`${e.service}|${e.operation}|${t}`,title:`${e.service}${e.operation?` · ${e.operation}`:``}`,description:(e.evidence??[]).join(` · `)||`score ${e.score.toFixed(2)}`,time:`score ${e.score.toFixed(2)}`,tone:t===0?`danger`:`warning`}))}),(0,M.jsx)(Q,{shown:t.length,total:e.length})]})}function De(e){let t=new Map;for(let n of e)t.set(n.id,{span:n,children:[]});let n=[];for(let e of t.values()){let r=e.span.parent_span_id?t.get(e.span.parent_span_id):void 0;r?r.children.push(e):n.push(e)}return{roots:n,count:t.size}}var Oe={display:`flex`,alignItems:`center`,gap:8,padding:`3px 0`,minWidth:0,fontVariantNumeric:`tabular-nums`};function ke({data:e}){if(!Array.isArray(e)||e.length===0)return(0,M.jsx)(C,{severity:`info`,title:`No spans for this trace`});let{roots:t,count:n}=De(e),r=0,i=[],a=(e,t)=>{if(r>=Z)return;r+=1;let n=e.span;i.push((0,M.jsxs)(`div`,{style:{...Oe,paddingLeft:t*18},children:[(0,M.jsx)(s,{status:n.is_error?`failed`:`running`}),(0,M.jsx)(`span`,{style:{flex:`0 0 auto`,fontSize:13,fontWeight:500},children:n.service}),(0,M.jsx)(`span`,{style:{minWidth:0,flex:1,opacity:.8},children:(0,M.jsx)(b,{text:n.operation||`—`})}),(0,M.jsxs)(`span`,{style:{flex:`0 0 auto`,fontSize:12,opacity:.7},children:[n.duration_ms.toFixed(1),`ms`]})]},n.id));for(let n of e.children)a(n,t+1)};for(let e of t)a(e,0);return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`div`,{children:i}),(0,M.jsx)(Q,{shown:r,total:n})]})}function Ae({data:e}){let t=e.entries??[];if(t.length===0)return(0,M.jsx)(C,{severity:`info`,title:`No matching logs`});let n=t.slice(0,Z);return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(l,{columns:[{key:`ts`,title:`Time`,width:180,render:(e,t)=>(0,M.jsx)(`span`,{style:{fontSize:12},children:xe(t.timestamp)})},{key:`sev`,title:`Severity`,width:96,render:(e,t)=>(0,M.jsx)(T,{tone:ye(t.severity),children:t.severity||`—`})},{key:`svc`,title:`Service`,width:160,render:(e,t)=>(0,M.jsx)(b,{text:t.service_name})},{key:`body`,title:`Message`,render:(e,t)=>(0,M.jsx)(b,{text:t.body})}],data:n,rowKey:`id`,density:`compact`,striped:!0}),(0,M.jsx)(Q,{shown:n.length,total:e.total??t.length})]})}var $={fontSize:12,fontWeight:600,textTransform:`uppercase`,letterSpacing:.4,opacity:.6,marginBottom:6};function je({rc:e}){return(0,M.jsx)(C,{severity:`danger`,title:`Root cause`,children:(0,M.jsxs)(`div`,{style:{display:`grid`,gap:2,fontSize:13},children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:e.service}),e.operation?` · ${e.operation}`:``]}),e.error_message&&(0,M.jsx)(`div`,{style:{opacity:.85},children:e.error_message}),(e.trace_id||e.span_id)&&(0,M.jsxs)(`div`,{style:{fontSize:12,opacity:.7,fontFamily:`monospace`},children:[e.trace_id&&`trace ${e.trace_id}`,e.trace_id&&e.span_id?` · `:``,e.span_id&&`span ${e.span_id}`]})]})})}function Me({tool:e,payload:t}){if(t==null)return(0,M.jsx)(C,{severity:`info`,title:`No structured payload`});switch(e){case`get_anomaly_timeline`:return(0,M.jsx)(Se,{data:t??[]});case`get_service_map`:return(0,M.jsx)(Ce,{data:t??[]});case`get_service_health`:return(0,M.jsx)(we,{data:t});case`impact_analysis`:return(0,M.jsx)(Te,{data:t});case`root_cause_analysis`:return(0,M.jsx)(Ee,{data:t??[]});case`trace_graph`:return(0,M.jsx)(ke,{data:t});case`search_logs`:return(0,M.jsx)(Ae,{data:t});default:return(0,M.jsx)(C,{severity:`info`,title:`No friendly renderer — see Raw JSON`})}}function Ne({state:e}){let t=e.error;return t?t.kind===`rpc`?t.code===-32e3?(0,M.jsx)(C,{severity:`warning`,title:`Server at capacity, retry shortly`,children:`JSON-RPC −32000 — the MCP concurrency cap was hit.`}):t.code===-32001?(0,M.jsx)(C,{severity:`warning`,title:`Tool exceeded 30s deadline`,children:`JSON-RPC −32001 — narrow the time range or arguments and retry.`}):(0,M.jsx)(C,{severity:`danger`,title:`MCP error ${t.code}`,children:t.message}):(0,M.jsx)(C,{severity:`danger`,title:`Request failed`,children:t.message}):null}function Pe({tool:e,state:n}){let[r,i]=(0,N.useState)(`friendly`);if(n.loading)return(0,M.jsx)(`div`,{style:{padding:24,display:`flex`,justifyContent:`center`},children:(0,M.jsx)(f,{label:`Calling tool…`})});if(!n.result&&!n.error)return(0,M.jsx)(C,{severity:`info`,title:`Run a tool to see results`,icon:!1,children:`Fill in the form and hit Run tool. The request and decoded response will appear here.`});let a=n.parsed;return(0,M.jsxs)(t,{direction:`vertical`,size:`md`,style:{width:`100%`},children:[(0,M.jsx)(Ne,{state:n}),a?.isError&&(0,M.jsx)(C,{severity:`warning`,title:`Tool returned an error`,children:a.text||`The tool reported isError without a message.`}),a?.rootCause&&(0,M.jsx)(je,{rc:a.rootCause}),n.requestBody&&(0,M.jsxs)(`div`,{children:[(0,M.jsxs)(`div`,{style:$,children:[`Request`,typeof n.latencyMs==`number`?` · ${n.latencyMs}ms`:``]}),(0,M.jsx)(V,{code:n.requestBody,language:`json`,copyable:!0,wrap:!0})]}),a&&!a.isError&&n.result&&(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`div`,{style:$,children:`Response`}),(0,M.jsx)(E,{variant:`segment`,value:r,items:[{key:`friendly`,label:`Friendly`},{key:`raw`,label:`Raw JSON`}],onChange:e=>i(e)}),(0,M.jsx)(`div`,{style:{marginTop:12},children:r===`friendly`?(0,M.jsx)(Me,{tool:e,payload:a.payload}):(0,M.jsx)(V,{code:a.text||JSON.stringify(n.result,null,2),language:`json`,copyable:!0,wrap:!0})})]}),a?.isError&&n.result&&(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`div`,{style:$,children:`Raw response`}),(0,M.jsx)(V,{code:JSON.stringify(n.result,null,2),language:`json`,copyable:!0,wrap:!0})]})]})}var Fe={display:`flex`,alignItems:`center`,gap:12,padding:`8px 0`,borderBottom:`1px solid var(--rcs-color-border, rgba(127,127,127,0.18))`};function Ie(e){return e===`success`?(0,M.jsx)(T,{tone:`info`,children:`ok`}):e===`tool_error`?(0,M.jsx)(T,{tone:`warning`,children:`tool error`}):(0,M.jsx)(T,{tone:`danger`,children:`rpc error`})}function Le({history:e,tenant:n,onClear:i,onRerun:a}){let[o,s]=(0,N.useState)(null);return e.length===0?(0,M.jsx)(C,{severity:`info`,title:`No calls yet`,icon:!1,children:`History is session-scoped and clears when the tab closes.`}):(0,M.jsxs)(t,{direction:`vertical`,size:`sm`,style:{width:`100%`},children:[(0,M.jsx)(`div`,{style:{display:`flex`,justifyContent:`flex-end`},children:(0,M.jsx)(r,{variant:`ghost`,size:`sm`,onClick:i,children:`Clear history`})}),e.map(e=>(0,M.jsxs)(`div`,{style:Fe,children:[(0,M.jsx)(`span`,{style:{flex:`0 0 auto`},children:Ie(e.status)}),(0,M.jsx)(`span`,{style:{flex:`0 0 auto`,fontWeight:500,fontSize:13},children:e.tool}),(0,M.jsx)(`span`,{style:{minWidth:0,flex:1,opacity:.7,fontSize:12},children:(0,M.jsx)(b,{text:JSON.stringify(e.args)})}),(0,M.jsxs)(`span`,{style:{flex:`0 0 auto`,fontSize:12,opacity:.6},children:[e.latencyMs,`ms`]}),(0,M.jsxs)(`span`,{style:{flex:`0 0 auto`,display:`flex`,gap:6},children:[(0,M.jsx)(r,{variant:`secondary`,size:`sm`,onClick:()=>a(e),children:`Re-run`}),(0,M.jsx)(r,{variant:`ghost`,size:`sm`,onClick:()=>s({title:`JSON-RPC request`,code:e.requestBody,lang:`json`}),children:`JSON-RPC`}),(0,M.jsx)(r,{variant:`ghost`,size:`sm`,onClick:()=>s({title:`curl`,code:de(e.requestBody,n),lang:`bash`}),children:`curl`})]})]},e.id)),(0,M.jsx)(d,{open:o!==null,title:o?.title,size:`lg`,onClose:()=>s(null),children:o&&(0,M.jsx)(V,{code:o.code,language:o.lang,copyable:!0,wrap:!0})})]})}var Re=200;function ze({apiKey:e}){let[n,r]=(0,N.useState)(!1),[i,a]=(0,N.useState)([]),o=(0,N.useRef)(null),s=e.length>0;return(0,N.useEffect)(()=>{if(!n||s){o.current?.close(),o.current=null;return}let e=e=>a(t=>[...t,e].slice(-Re)),t=new EventSource(`/mcp`);return o.current=t,e({type:`info`,text:`opening /mcp SSE stream…`,timestamp:new Date}),t.onopen=()=>e({type:`info`,text:`stream open — waiting for events`,timestamp:new Date}),t.onmessage=t=>e({type:`stdout`,text:t.data||`(empty event)`,timestamp:new Date}),t.onerror=()=>e({type:`warn`,text:`stream error / reconnecting (keep-alive every 25s)`,timestamp:new Date}),()=>{t.close(),o.current=null}},[n,s]),(0,M.jsxs)(t,{direction:`vertical`,size:`sm`,style:{width:`100%`},children:[(0,M.jsx)(`div`,{style:{display:`flex`,alignItems:`center`,gap:12},children:s?(0,M.jsx)(c,{content:`EventSource can't send an Authorization header. Clear the API key to use the live stream.`,children:(0,M.jsx)(`span`,{style:{display:`inline-flex`},children:(0,M.jsx)(I,{checked:!1,disabled:!0,label:`Live stream`})})}):(0,M.jsx)(I,{checked:n,label:`Live stream`,onChange:r})}),n&&!s&&(0,M.jsx)(H,{title:`/mcp SSE`,lines:i.length>0?i:[{type:`info`,text:`connecting…`}],streaming:!0,height:220})]})}var Be=`otelcontext.mcp.settings`;function Ve(){try{let e=sessionStorage.getItem(Be);if(!e)return{apiKey:``,tenant:``};let t=JSON.parse(e);return{apiKey:t.apiKey??``,tenant:t.tenant??``}}catch{return{apiKey:``,tenant:``}}}function He(){let[e,t]=(0,N.useState)(()=>Ve());return{settings:e,save:(0,N.useCallback)(e=>{t(e);try{sessionStorage.setItem(Be,JSON.stringify(e))}catch{}},[])}}function Ue({open:e,settings:n,onClose:i,onSave:a}){let[o,s]=(0,N.useState)(n.apiKey),[c,l]=(0,N.useState)(n.tenant);return(0,N.useEffect)(()=>{e&&(s(n.apiKey),l(n.tenant))},[e,n.apiKey,n.tenant]),(0,M.jsx)(u,{open:e,title:`Connection settings`,placement:`right`,width:400,onClose:i,footer:(0,M.jsxs)(t,{direction:`horizontal`,size:`sm`,justify:`end`,children:[(0,M.jsx)(r,{variant:`ghost`,onClick:i,children:`Cancel`}),(0,M.jsx)(r,{variant:`primary`,onClick:()=>{a({apiKey:o.trim(),tenant:c.trim()}),i()},children:`Save`})]}),children:(0,M.jsxs)(t,{direction:`vertical`,size:`md`,style:{width:`100%`},children:[(0,M.jsx)(C,{severity:`info`,icon:!1,children:`Stored in sessionStorage only — cleared when this tab closes. Leave the API key empty for dev servers with auth disabled.`}),(0,M.jsx)(B,{label:`API key`,hint:`Sent as Authorization: Bearer .`,children:(0,M.jsx)(k,{type:`password`,value:o,placeholder:`(none)`,onChange:e=>s(e)})}),(0,M.jsx)(B,{label:`Tenant`,hint:`Sent as X-Tenant-ID. Defaults to the server's default tenant.`,children:(0,M.jsx)(k,{value:c,placeholder:`default`,onChange:e=>l(e)})})]})})}var We=[`get_anomaly_timeline`,`get_service_map`,`get_service_health`,`root_cause_analysis`,`impact_analysis`],Ge=[`trace_graph`,`search_logs`],Ke={display:`flex`,height:`100%`,minHeight:0},qe={width:280,flex:`0 0 280px`,borderRight:`1px solid var(--rcs-color-border, rgba(127,127,127,0.18))`,overflowY:`auto`,padding:12},Je={flex:1,minWidth:0,display:`flex`,flexDirection:`column`,overflow:`hidden`},Ye={flex:1,minHeight:0,overflowY:`auto`,padding:16};function Xe(e){let t=new Map(e.map(e=>[e.name,e])),n=We.filter(e=>t.has(e)).map(e=>t.get(e)),r=Ge.filter(e=>t.has(e)).map(e=>t.get(e)),i=new Set([...We,...Ge]);return{instant:n,db:r,other:e.filter(e=>!i.has(e.name))}}function Ze(){let e=S(v.coarse),{settings:n,save:i}=He(),o=(0,N.useMemo)(()=>({apiKey:n.apiKey||void 0,tenant:n.tenant||void 0}),[n.apiKey,n.tenant]),{tools:s,loading:c,error:l,reload:u}=ne(o),{state:d,call:f,reset:p,history:m,clearHistory:h}=ae(o),[g,b]=(0,N.useState)(null),[x,D]=(0,N.useState)(`run`),[O,k]=(0,N.useState)(!1),[ee,A]=(0,N.useState)(void 0),[j,P]=(0,N.useState)(0),I=(0,N.useMemo)(()=>Xe(s),[s]),L=g&&s.some(e=>e.name===g)?g:s[0]?.name??null,R=s.find(e=>e.name===L)??null,z=e=>{b(e),D(`run`),A(void 0),P(e=>e+1),p()},B=e=>{let t={};for(let[n,r]of Object.entries(e.args))t[n]=typeof r==`string`?r:String(r);b(e.tool),A(t),D(`run`),P(e=>e+1),p()},H=(0,N.useMemo)(()=>{let e=[];if(I.instant.length>0){e.push({type:`label`,label:`In-memory (instant)`});for(let t of I.instant)e.push({key:t.name,label:t.name})}if(I.db.length>0){e.push({type:`label`,label:`DB / fallback`});for(let t of I.db)e.push({key:t.name,label:t.name})}if(I.other.length>0){e.push({type:`label`,label:`Other`});for(let t of I.other)e.push({key:t.name,label:t.name})}return e},[I]),U=(0,N.useMemo)(()=>s.map(e=>({label:e.name,value:e.name})),[s]),W=c?(0,M.jsx)(t,{direction:`vertical`,size:`sm`,style:{width:`100%`},children:(0,M.jsx)(_,{variant:`text`,lines:7})}):(0,M.jsx)(w,{items:H,mode:`inline`,selectedKeys:L?[L]:[],onSelect:z}),G=(0,M.jsxs)(t,{direction:`horizontal`,size:`sm`,align:`center`,children:[n.apiKey&&(0,M.jsx)(T,{tone:`info`,children:`auth on`}),n.tenant&&(0,M.jsxs)(T,{tone:`subtle`,children:[`tenant: `,n.tenant]}),(0,M.jsx)(a,{"aria-label":`Connection settings`,variant:`ghost`,size:`sm`,icon:(0,M.jsx)(te,{size:15}),onClick:()=>k(!0)})]});return(0,M.jsxs)(`div`,{style:Ke,children:[!e&&(0,M.jsx)(`div`,{style:qe,children:W}),(0,M.jsxs)(`div`,{style:Je,children:[(0,M.jsx)(y,{size:`sm`,title:R?R.name:`MCP console`,subtitle:R?.description,actions:G}),(0,M.jsxs)(`div`,{style:Ye,children:[l&&(0,M.jsxs)(C,{severity:`danger`,title:`Can't reach the MCP endpoint`,action:(0,M.jsx)(r,{size:`sm`,variant:`secondary`,onClick:u,children:`Retry`}),style:{marginBottom:16},children:[l,` — POST /mcp failed. Check the server is up and your API key under settings.`]}),e&&!c&&s.length>0&&(0,M.jsx)(`div`,{style:{marginBottom:16},children:(0,M.jsx)(F,{options:U,value:L??void 0,searchable:!0,placeholder:`Select a tool`,onChange:e=>z(String(e))})}),c&&(0,M.jsx)(_,{variant:`rect`,height:160}),!c&&s.length===0&&!l&&(0,M.jsx)(C,{severity:`warning`,title:`No tools advertised`,children:`tools/list returned an empty surface.`}),R&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(E,{variant:`line`,value:x,items:[{key:`run`,label:`Run`},{key:`definition`,label:`Definition`},{key:`history`,label:`History`}],onChange:e=>D(e)}),(0,M.jsxs)(`div`,{style:{marginTop:16},children:[x===`run`&&(0,M.jsxs)(t,{direction:`vertical`,size:`lg`,style:{width:`100%`},children:[(0,M.jsx)(ge,{tool:R,running:d.loading,initialValues:ee,onRun:e=>f(R.name,e)},`${R.name}#${j}`),(0,M.jsx)(Pe,{tool:R.name,state:d}),(0,M.jsx)(ze,{apiKey:n.apiKey})]}),x===`definition`&&(0,M.jsx)(V,{code:JSON.stringify(R,null,2),language:`json`,copyable:!0,wrap:!0}),x===`history`&&(0,M.jsx)(Le,{history:m,tenant:n.tenant||void 0,onClear:h,onRerun:B})]})]})]})]}),(0,M.jsx)(Ue,{open:O,settings:n,onClose:()=>k(!1),onSave:i})]})}export{Ze as default}; \ No newline at end of file diff --git a/internal/ui/dist/assets/ServicesView-n3l2yFxx.js b/internal/ui/dist/assets/ServicesView-n3l2yFxx.js new file mode 100644 index 0000000..a778974 --- /dev/null +++ b/internal/ui/dist/assets/ServicesView-n3l2yFxx.js @@ -0,0 +1,321 @@ +import{C as e,E as t,M as n,N as r,O as i,P as a,S as o,T as s,b as c,c as l,d as u,h as d,i as f,j as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b,w as x,x as S,y as C}from"./useMediaQuery-D3Mg-H7H.js";import{t as w}from"./inputs-DxVBbFvb.js";import{a as T,c as E,i as D,o as O,s as k}from"./index-D7nwP4LR.js";var A=f(`Search`,[[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`path`,{d:`m21 21-4.3-4.3`,key:`1qie3q`}]]),j=f(`X`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),M=a(n(),1);function N(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var a,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,a=e},f:function(){try{o||n.return==null||n.return()}finally{if(s)throw a}}}}function B(e,t,n){return(t=te(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function V(e){if(typeof Symbol<`u`&&e[Symbol.iterator]!=null||e[`@@iterator`]!=null)return Array.from(e)}function H(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function U(){throw TypeError(`Invalid attempt to destructure non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function W(){throw TypeError(`Invalid attempt to spread non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function G(e,t){return P(e)||H(e,t)||ne(e,t)||U()}function K(e){return F(e)||V(e)||ne(e)||W()}function ee(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return String(e)}function te(e){var t=ee(e,`string`);return typeof t==`symbol`?t:t+``}function q(e){"@babel/helpers - typeof";return q=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},q(e)}function ne(e,t){if(e){if(typeof e==`string`)return N(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?N(e,t):void 0}}var re=typeof window>`u`?null:window,ie=re?re.navigator:null;re&&re.document;var ae=q(``),oe=q({}),se=q(function(){}),ce=typeof HTMLElement>`u`?`undefined`:q(HTMLElement),le=function(e){return e&&e.instanceString&&ue(e.instanceString)?e.instanceString():null},J=function(e){return e!=null&&q(e)==ae},ue=function(e){return e!=null&&q(e)===se},de=function(e){return!he(e)&&(Array.isArray?Array.isArray(e):e!=null&&e instanceof Array)},Y=function(e){return e!=null&&q(e)===oe&&!de(e)&&e.constructor===Object},fe=function(e){return e!=null&&q(e)===oe},X=function(e){return e!=null&&q(e)===q(1)&&!isNaN(e)},pe=function(e){return X(e)&&Math.floor(e)===e},me=function(e){if(ce!==`undefined`)return e!=null&&e instanceof HTMLElement},he=function(e){return ge(e)||_e(e)},ge=function(e){return le(e)===`collection`&&e._private.single},_e=function(e){return le(e)===`collection`&&!e._private.single},ve=function(e){return le(e)===`core`},ye=function(e){return le(e)===`stylesheet`},be=function(e){return le(e)===`event`},xe=function(e){return e==null?!0:!!(e===``||e.match(/^\s+$/))},Se=function(e){return typeof HTMLElement>`u`?!1:e instanceof HTMLElement},Ce=function(e){return Y(e)&&X(e.x1)&&X(e.x2)&&X(e.y1)&&X(e.y2)},we=function(e){return fe(e)&&ue(e.then)},Te=function(){return ie&&ie.userAgent.match(/msie|trident|edge/i)},Ee=function(e,t){t||=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return`undefined`;for(var e=[],t=0;tt)},Be=function(e,t){return-1*ze(e,t)},Z=Object.assign==null?function(e){for(var t=arguments,n=1;n1&&--n,n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var u=RegExp(`^`+Fe+`$`).exec(e);if(u){if(n=parseInt(u[1]),n<0?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,r=parseFloat(u[2]),r<0||r>100||(r/=100,i=parseFloat(u[3]),i<0||i>100)||(i/=100,a=u[4],a!==void 0&&(a=parseFloat(a),a<0||a>1)))return;if(r===0)o=s=c=Math.round(i*255);else{var d=i<.5?i*(1+r):i+r-i*r,f=2*i-d;o=Math.round(255*l(f,d,n+1/3)),s=Math.round(255*l(f,d,n)),c=Math.round(255*l(f,d,n-1/3))}t=[o,s,c,a]}return t},Ue=function(e){var t,n=RegExp(`^`+Ne+`$`).exec(e);if(n){t=[];for(var r=[],i=1;i<=3;i++){var a=n[i];if(a[a.length-1]===`%`&&(r[i]=!0),a=parseFloat(a),r[i]&&(a=a/100*255),a<0||a>255)return;t.push(Math.floor(a))}var o=r[1]||r[2]||r[3],s=r[1]&&r[2]&&r[3];if(o&&!s)return;var c=n[4];if(c!==void 0){if(c=parseFloat(c),c<0||c>1)return;t.push(c)}}return t},We=function(e){return Ke[e.toLowerCase()]},Ge=function(e){return(de(e)?e:null)||We(e)||Ve(e)||Ue(e)||He(e)},Ke={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},qe=function(e){for(var t=e.map,n=e.keys,r=n.length,i=0;i=s||t<0||_&&n>=d}function C(){var e=t();if(S(e))return w(e);p=setTimeout(C,x(e))}function w(e){return p=void 0,v&&l?y(e):(l=u=void 0,f)}function T(){p!==void 0&&clearTimeout(p),h=0,l=m=u=p=void 0}function E(){return p===void 0?f:w(t())}function D(){var e=t(),n=S(e);if(l=arguments,u=this,m=e,n){if(p===void 0)return b(m);if(_)return clearTimeout(p),p=setTimeout(C,s),y(m)}return p===void 0&&(p=setTimeout(C,s)),f}return D.cancel=T,D.flush=E,D}return It=o,It}var zt=Xe(Rt()),Bt=re?re.performance:null,Vt=Bt&&Bt.now?function(){return Bt.now()}:function(){return Date.now()},Ht=function(){if(re){if(re.requestAnimationFrame)return function(e){re.requestAnimationFrame(e)};if(re.mozRequestAnimationFrame)return function(e){re.mozRequestAnimationFrame(e)};if(re.webkitRequestAnimationFrame)return function(e){re.webkitRequestAnimationFrame(e)};if(re.msRequestAnimationFrame)return function(e){re.msRequestAnimationFrame(e)}}return function(e){e&&setTimeout(function(){e(Vt())},1e3/60)}}(),Ut=function(e){return Ht(e)},Wt=Vt,Gt=9261,Kt=65599,qt=5381,Jt=function(e){for(var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Gt,n;n=e.next(),!n.done;)t=t*Kt+n.value|0;return t},Yt=function(e){return(arguments.length>1&&arguments[1]!==void 0?arguments[1]:Gt)*Kt+e|0},Xt=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:qt;return(t<<5)+t+e|0},Zt=function(e,t){return e*2097152+t},Qt=function(e){return e[0]*2097152+e[1]},$t=function(e,t){return[Yt(e[0],t[0]),Xt(e[1],t[1])]},en=function(e,t){var n={value:0,done:!1},r=0,i=e.length;return Jt({next:function(){return r=0;r--)e[r]===t&&e.splice(r,1)},Dn=function(e){e.splice(0,e.length)},On=function(e,t){for(var n=0;n`u`?`undefined`:q(Set))===Mn?Nn:Set,Fn=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(e===void 0||t===void 0||!ve(e)){gn(`An element must have a core reference and parameters set`);return}var r=t.group;if(r??=t.data&&t.data.source!=null&&t.data.target!=null?`edges`:`nodes`,r!==`nodes`&&r!==`edges`){gn("An element must be of type `nodes` or `edges`; you specified `"+r+"`");return}this.length=1,this[0]=this;var i=this._private={cy:e,single:!0,data:t.data||{},position:t.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:r,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!t.selected,selectable:t.selectable===void 0?!0:!!t.selectable,locked:!!t.locked,grabbed:!1,grabbable:t.grabbable===void 0?!0:!!t.grabbable,pannable:t.pannable===void 0?r===`edges`:!!t.pannable,active:!1,classes:new Pn,animation:{current:[],queue:[]},rscratch:{},scratch:t.scratch||{},edges:[],children:[],parent:t.parent&&t.parent.isNode()?t.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(i.position.x??(i.position.x=0),i.position.y??(i.position.y=0),t.renderedPosition){var a=t.renderedPosition,o=e.pan(),s=e.zoom();i.position={x:(a.x-o.x)/s,y:(a.y-o.y)/s}}var c=[];de(t.classes)?c=t.classes:J(t.classes)&&(c=t.classes.split(/\s+/));for(var l=0,u=c.length;lt)},l=function(e,t,i,a,o){var s;if(i??=0,o??=n,i<0)throw Error(`lo must be non-negative`);for(a??=e.length;in;0<=n?t++:t--)l.push(t);return l}).apply(this).reverse(),c=[],a=0,o=s.length;ah;0<=h?++f:--f)g.push(a(e,r));return g},m=function(e,t,r,i){var a,o,s;for(i??=n,a=e[r];r>t;){if(s=r-1>>1,o=e[s],i(a,o)<0){e[r]=o,r=s;continue}break}return e[r]=a},h=function(e,t,r){var i,a,o,s,c;for(r??=n,a=e.length,c=t,o=e[t],i=2*t+1;i0;){var x=_.pop(),S=h(x),C=x.id();if(d[C]=S,S!==1/0)for(var w=x.neighborhood().intersect(p),T=0;T0)for(n.unshift(t);u[i];){var a=u[i];n.unshift(a.edge),n.unshift(a.node),r=a.node,i=r.id()}return o.spawn(n)}}}},Jn={kruskal:function(e){e||=function(e){return 1};for(var t=this.byGroup(),n=t.nodes,r=t.edges,i=n.length,a=Array(i),o=n,s=function(e){for(var t=0;t0;){if(b(),S++,y===l){for(var C=[],w=i,T=l,E=g[T];C.unshift(w),E!=null&&C.unshift(E),w=h[T],w!=null;)T=w.id(),E=g[T];return{found:!0,distance:u[y],path:this.spawn(C),steps:S}}f[y]=!0;for(var D=v._private.edges,O=0;OT&&(p[w]=T,g[w]=C,_[w]=y),!i){var E=C*l+S;!i&&p[E]>T&&(p[E]=T,g[E]=S,_[E]=y)}}}for(var D=0;D1&&arguments[1]!==void 0?arguments[1]:a,r=v(e),i=[],o=r;;){if(o==null)return t.spawn();var c=_(o),l=c.edge,u=c.pred;if(i.unshift(o[0]),o.same(n)&&i.length>0)break;l!=null&&i.unshift(l),o=u}return s.spawn(i)},x=0;x=0;l--){var u=c[l],d=u[1],f=u[2];(t[d]===o&&t[f]===s||t[d]===s&&t[f]===o)&&c.splice(l,1)}for(var p=0;pr;)t=nr(Math.floor(Math.random()*t.length),e,t),n--;return t},ir={kargerStein:function(){var e=this,t=this.byGroup(),n=t.nodes,r=t.edges;r.unmergeBy(function(e){return e.isLoop()});var i=n.length,a=r.length,o=Math.ceil((Math.log(i)/Math.LN2)**2),s=Math.floor(i/tr);if(i<2){gn(`At least 2 nodes are required for Karger-Stein algorithm`);return}for(var c=[],l=0;l1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=1/0,i=t;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=-1/0,i=t;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=0,i=0,a=t;a1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;r?e=e.slice(t,n):(n0&&e.splice(0,t));for(var o=0,s=e.length-1;s>=0;s--){var c=e[s];a?isFinite(c)||(e[s]=-1/0,o++):e.splice(s,1)}i&&e.sort(function(e,t){return e-t});var l=e.length,u=Math.floor(l/2);return l%2==0?(e[u-1+o]+e[u+o])/2:e[u+1+o]},pr=function(e){return Math.PI*e/180},mr=function(e,t){return Math.atan2(t,e)-Math.PI/2},hr=Math.log2||function(e){return Math.log(e)/Math.log(2)},gr=function(e){return e>0?1:e<0?-1:0},_r=function(e,t){return Math.sqrt(vr(e,t))},vr=function(e,t){var n=t.x-e.x,r=t.y-e.y;return n*n+r*r},yr=function(e){for(var t=e.length,n=0,r=0;r=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(e.w!=null&&e.h!=null&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},Tr=function(e){return{x1:e.x1,x2:e.x2,w:e.w,y1:e.y1,y2:e.y2,h:e.h}},Er=function(e){e.x1=1/0,e.y1=1/0,e.x2=-1/0,e.y2=-1/0,e.w=0,e.h=0},Dr=function(e,t){e.x1=Math.min(e.x1,t.x1),e.x2=Math.max(e.x2,t.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,t.y1),e.y2=Math.max(e.y2,t.y2),e.h=e.y2-e.y1},Or=function(e,t,n){e.x1=Math.min(e.x1,t),e.x2=Math.max(e.x2,t),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,n),e.y2=Math.max(e.y2,n),e.h=e.y2-e.y1},kr=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return e.x1-=t,e.x2+=t,e.y1-=t,e.y2+=t,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Ar=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],n,r,i,a;if(t.length===1)n=r=i=a=t[0];else if(t.length===2)n=i=t[0],a=r=t[1];else if(t.length===4){var o=G(t,4);n=o[0],r=o[1],i=o[2],a=o[3]}return e.x1-=a,e.x2+=r,e.y1-=n,e.y2+=i,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},jr=function(e,t){e.x1=t.x1,e.y1=t.y1,e.x2=t.x2,e.y2=t.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1},Mr=function(e,t){return!(e.x1>t.x2||t.x1>e.x2||e.x2t.y2||t.y1>e.y2)},Nr=function(e,t,n){return e.x1<=t&&t<=e.x2&&e.y1<=n&&n<=e.y2},Pr=function(e,t){return Nr(e,t.x,t.y)},Fr=function(e,t){return Nr(e,t.x1,t.y1)&&Nr(e,t.x2,t.y2)},Ir=Math.hypot??function(e,t){return Math.sqrt(e*e+t*t)};function Lr(e,t){if(e.length<3)throw Error(`Need at least 3 vertices`);var n=function(e,t){return{x:e.x+t.x,y:e.y+t.y}},r=function(e,t){return{x:e.x-t.x,y:e.y-t.y}},i=function(e,t){return{x:e.x*t,y:e.y*t}},a=function(e,t){return e.x*t.y-e.y*t.x},o=function(e){var t=Ir(e.x,e.y);return t===0?{x:0,y:0}:{x:e.x/t,y:e.y/t}},s=function(e){for(var t=0,n=0;n7&&arguments[7]!==void 0?arguments[7]:`auto`,c=s===`auto`?li(i,a):s,l=i/2,u=a/2;c=Math.min(c,l,u);var d=c!==l,f=c!==u,p;if(d){var m=n-l+c-o,h=r-u-o;if(p=ti(e,t,n,r,m,h,n+l-c+o,h,!1),p.length>0)return p}if(f){var g=n+l+o;if(p=ti(e,t,n,r,g,r-u+c-o,g,r+u-c+o,!1),p.length>0)return p}if(d){var _=n-l+c-o,v=r+u+o;if(p=ti(e,t,n,r,_,v,n+l-c+o,v,!1),p.length>0)return p}if(f){var y=n-l-o;if(p=ti(e,t,n,r,y,r-u+c-o,y,r+u-c+o,!1),p.length>0)return p}var b,x=n-l+c,S=r-u+c;if(b=$r(e,t,n,r,x,S,c+o),b.length>0&&b[0]<=x&&b[1]<=S)return[b[0],b[1]];var C=n+l-c,w=r-u+c;if(b=$r(e,t,n,r,C,w,c+o),b.length>0&&b[0]>=C&&b[1]<=w)return[b[0],b[1]];var T=n+l-c,E=r+u-c;if(b=$r(e,t,n,r,T,E,c+o),b.length>0&&b[0]>=T&&b[1]>=E)return[b[0],b[1]];var D=n-l+c,O=r+u-c;return b=$r(e,t,n,r,D,O,c+o),b.length>0&&b[0]<=D&&b[1]>=O?[b[0],b[1]]:[]},Br=function(e,t,n,r,i,a,o){var s=o,c=Math.min(n,i),l=Math.max(n,i),u=Math.min(r,a),d=Math.max(r,a);return c-s<=e&&e<=l+s&&u-s<=t&&t<=d+s},Vr=function(e,t,n,r,i,a,o,s,c){var l={x1:Math.min(n,o,i)-c,x2:Math.max(n,o,i)+c,y1:Math.min(r,s,a)-c,y2:Math.max(r,s,a)+c};return!(el.x2||tl.y2)},Hr=function(e,t,n,r){n-=r;var i=t*t-4*e*n;if(i<0)return[];var a=Math.sqrt(i),o=2*e;return[(-t+a)/o,(-t-a)/o]},Ur=function(e,t,n,r,i){e===0&&(e=1e-5),t/=e,n/=e,r/=e;var a,o=(3*n-t*t)/9,s=-(27*r)+t*(9*n-t*t*2),c,l,u,d,f;if(s/=54,a=o*o*o+s*s,i[1]=0,d=t/3,a>0){l=s+Math.sqrt(a),l=l<0?-((-l)**(1/3)):l**(1/3),u=s-Math.sqrt(a),u=u<0?-((-u)**(1/3)):u**(1/3),i[0]=-d+l+u,d+=(l+u)/2,i[4]=i[2]=-d,d=Math.sqrt(3)*(-u+l)/2,i[3]=d,i[5]=-d;return}if(i[5]=i[3]=0,a===0){f=s<0?-((-s)**(1/3)):s**(1/3),i[0]=-d+2*f,i[4]=i[2]=-(f+d);return}o=-o,c=o*o*o,c=Math.acos(s/Math.sqrt(c)),f=2*Math.sqrt(o),i[0]=-d+f*Math.cos(c/3),i[2]=-d+f*Math.cos((c+2*Math.PI)/3),i[4]=-d+f*Math.cos((c+4*Math.PI)/3)},Wr=function(e,t,n,r,i,a,o,s){var c=1*n*n-4*n*i+2*n*o+4*i*i-4*i*o+o*o+r*r-4*r*a+2*r*s+4*a*a-4*a*s+s*s,l=9*n*i-3*n*n-3*n*o-6*i*i+3*i*o+9*r*a-3*r*r-3*r*s-6*a*a+3*a*s,u=3*n*n-6*n*i+n*o-n*e+2*i*i+2*i*e-o*e+3*r*r-6*r*a+r*s-r*t+2*a*a+2*a*t-s*t,d=1*n*i-n*n+n*e-i*e+r*a-r*r+r*t-a*t,f=[];Ur(c,l,u,d,f);for(var p=1e-7,m=[],h=0;h<6;h+=2)Math.abs(f[h+1])=0&&f[h]<=1&&m.push(f[h]);m.push(1),m.push(0);for(var g=-1,_,v,y,b=0;b=0?yc?(e-i)*(e-i)+(t-a)*(t-a):l-d},Kr=function(e,t,n){for(var r,i,a,o,s,c=0,l=0;l=e&&e>=a||r<=e&&e<=a)s=(e-r)/(a-r)*(o-i)+i,s>t&&c++;else continue;return c%2!=0},qr=function(e,t,n,r,i,a,o,s,c){var l=Array(n.length),u;s[0]==null?u=s:(u=Math.atan(s[1]/s[0]),s[0]<0?u+=Math.PI/2:u=-u-Math.PI/2);for(var d=Math.cos(-u),f=Math.sin(-u),p=0;p0?Yr(Xr(l,-c)):l)},Jr=function(e,t,n,r,i,a,o,s){for(var c=Array(n.length*2),l=0;l=0&&h<=1&&_.push(h),g>=0&&g<=1&&_.push(g),_.length===0)return[];var v=_[0]*s[0]+e,y=_[0]*s[1]+t;return _.length>1?_[0]==_[1]?[v,y]:[v,y,_[1]*s[0]+e,_[1]*s[1]+t]:[v,y]},ei=function(e,t,n){return t<=e&&e<=n||n<=e&&e<=t?e:e<=t&&t<=n||n<=t&&t<=e?t:n},ti=function(e,t,n,r,i,a,o,s,c){var l=e-i,u=n-e,d=o-i,f=t-a,p=r-t,m=s-a,h=d*f-m*l,g=u*f-p*l,_=m*u-d*p;if(_!==0){var v=h/_,y=g/_,b=.001,x=0-b,S=1+b;return x<=v&&v<=S&&x<=y&&y<=S||c?[e+v*u,t+v*p]:[]}else if(h===0||g===0)return ei(e,n,o)===o?[o,s]:ei(e,n,i)===i?[i,a]:ei(i,o,n)===n?[n,r]:[];else return[]},ni=function(e,t,n,r,i){var a=[],o=r/2,s=i/2,c=t,l=n;a.push({x:c+o*e[0],y:l+s*e[1]});for(var u=1;u0?Yr(Xr(u,-s)):u}else f=n;for(var m,h,g,_,v=0;v2){for(var p=[l[0],l[1]],m=(p[0]-e)**2+(p[1]-t)**2,h=1;hl&&(l=t)},get:function(e){return c[e]}},d=0;d0?v.edgesTo(_)[0]:_.edgesTo(v)[0];var b=r(y);_=_.id(),l[_]>l[m]+b&&(l[_]=l[m]+b,d.nodes.indexOf(_)<0?d.push(_):d.updateItem(_),c[_]=0,n[_]=[]),l[_]==l[m]+b&&(c[_]=c[_]+c[m],n[_].push(m))}else for(var x=0;x0;){for(var T=t.pop(),E=0;E0&&o.push(n[s]);o.length!==0&&i.push(r.collection(o))}return i},Ni=function(e,t){for(var n=0;n5&&arguments[5]!==void 0?arguments[5]:Li,o=r,s,c,l=0;l=2?Ui(e,t,n,0,Bi,Vi):Ui(e,t,n,0,zi)},squaredEuclidean:function(e,t,n){return Ui(e,t,n,0,Bi)},manhattan:function(e,t,n){return Ui(e,t,n,0,zi)},max:function(e,t,n){return Ui(e,t,n,-1/0,Hi)}};Wi[`squared-euclidean`]=Wi.squaredEuclidean,Wi.squaredeuclidean=Wi.squaredEuclidean;function Gi(e,t,n,r,i,a){var o=ue(e)?e:Wi[e]||Wi.euclidean;return t===0&&ue(e)?o(i,a):o(t,n,r,i,a)}var Ki=Tn({k:2,m:2,sensitivityThreshold:1e-4,distance:`euclidean`,maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),qi=function(e){return Ki(e)},Ji=function(e,t,n,r,i){var a=i===`kMedoids`?function(e){return r[e](n)}:function(e){return n[e]},o=function(e){return r[e](t)},s=n,c=t;return Gi(e,r.length,a,o,s,c)},Yi=function(e,t,n){for(var r=n.length,i=Array(r),a=Array(r),o=Array(t),s=null,c=0;cn)return!1;return!0},ea=function(e,t,n){for(var r=0;ro&&(o=t[c][l],s=l);i[s].push(e[c])}for(var u=0;u=i.threshold||i.mode===`dendrogram`&&e.length===1)return!1;var p=t[a],m=t[r[a]],h=i.mode===`dendrogram`?{left:p,right:m,key:p.key}:{value:p.value.concat(m.value),key:p.key};e[p.index]=h,e.splice(m.index,1),t[p.key]=h;for(var g=0;gn[m.key][_.key]&&(s=n[m.key][_.key])):i.linkage===`max`?(s=n[p.key][_.key],n[p.key][_.key]0&&r.push(i);return r},wa=function(e,t,n){for(var r=[],i=0;io&&(a=c,o=t[i*e+c])}a>0&&r.push(a)}for(var l=0;lc&&(s=l,c=u)}n[i]=a[s]}return r=wa(e,t,n),r},Ea=function(e){for(var t=this.cy(),n=this.nodes(),r=ba(e),i={},a=0;a=E?(D=E,E=k,O=A):k>D&&(D=k);for(var j=0;j0);S[w%r.minIterations*o+L]=R,I+=R}if(I>0&&(w>=r.minIterations-1||w==r.maxIterations-1)){for(var z=0,B=0;B1||i>1)&&(o=!0),u[t]=[],e.outgoers().forEach(function(e){e.isEdge()&&u[t].push(e.id())})}else d[t]=[void 0,e.target().id()]}):a.forEach(function(e){var t=e.id();e.isNode()?(e.degree(!0)%2&&(s?c?o=!0:c=t:s=t),u[t]=[],e.connectedEdges().forEach(function(e){return u[t].push(e.id())})):d[t]=[e.source().id(),e.target().id()]});var f={found:!1,trail:void 0};if(o)return f;if(c&&s)if(i){if(l&&c!=l)return f;l=c}else if(l&&c!=l&&s!=l)return f;else l||=c;else l||=a[0].id();var p=function(e){for(var t=e,n=[e],r,a,o;u[t].length;)r=u[t].shift(),a=d[r][0],o=d[r][1],t==o?!i&&t!=a&&(u[a]=u[a].filter(function(e){return e!=r}),t=a):(u[o]=u[o].filter(function(e){return e!=r}),t=o),n.unshift(r),n.unshift(t);return n},m=[],h=[];for(h=p(l);h.length!=1;)u[h[0]].length==0?(m.unshift(a.getElementById(h.shift())),m.unshift(a.getElementById(h.shift()))):h=p(h.shift()).concat(h);for(var g in m.unshift(a.getElementById(h.shift())),u)if(u[g].length)return f;return f.found=!0,f.trail=this.spawn(m,!0),f}},Aa=function(){var e=this,t={},n=0,r=0,i=[],a=[],o={},s=function(n,r){for(var o=a.length-1,s=[],c=e.spawn();a[o].x!=n||a[o].y!=r;)s.push(a.pop().edge),o--;s.push(a.pop().edge),s.forEach(function(n){var r=n.connectedNodes().intersection(e);c.merge(n),r.forEach(function(n){var r=n.id(),i=n.connectedEdges().intersection(e);c.merge(n),t[r].cutVertex?c.merge(i.filter(function(e){return e.isLoop()})):c.merge(i)})}),i.push(c)},c=function(l,u,d){l===d&&(r+=1),t[u]={id:n,low:n++,cutVertex:!1};var f=e.getElementById(u).connectedEdges().intersection(e);if(f.size()===0)i.push(e.spawn(e.getElementById(u)));else{var p,m,h,g;f.forEach(function(e){p=e.source().id(),m=e.target().id(),h=p===u?m:p,h!==d&&(g=e.id(),o[g]||(o[g]=!0,a.push({x:u,y:h,edge:e})),h in t?t[u].low=Math.min(t[u].low,t[h].id):(c(l,h,u),t[u].low=Math.min(t[u].low,t[h].low),t[u].id<=t[h].low&&(t[u].cutVertex=!0,s(u,h))))})}};e.forEach(function(e){if(e.isNode()){var n=e.id();n in t||(r=0,c(n,n),t[n].cutVertex=r>1)}});var l=Object.keys(t).filter(function(e){return t[e].cutVertex}).map(function(t){return e.getElementById(t)});return{cut:e.spawn(l),components:i}},ja={hopcroftTarjanBiconnected:Aa,htbc:Aa,htb:Aa,hopcroftTarjanBiconnectedComponents:Aa},Ma=function(){var e=this,t={},n=0,r=[],i=[],a=e.spawn(e),o=function(s){if(i.push(s),t[s]={index:n,low:n++,explored:!1},e.getElementById(s).connectedEdges().intersection(e).forEach(function(e){var n=e.target().id();n!==s&&(n in t||o(n),t[n].explored||(t[s].low=Math.min(t[s].low,t[n].low)))}),t[s].index===t[s].low){for(var c=e.spawn();;){var l=i.pop();if(c.merge(e.getElementById(l)),t[l].low=t[s].index,t[l].explored=!0,l===s)break}var u=c.edgesWith(c),d=c.merge(u);r.push(d),a=a.difference(d)}};return e.forEach(function(e){if(e.isNode()){var n=e.id();n in t||o(n)}}),{cut:a,components:r}},Na={tarjanStronglyConnected:Ma,tsc:Ma,tscc:Ma,tarjanStronglyConnectedComponents:Ma},Pa={};[Ln,qn,Jn,Xn,Qn,er,ir,gi,vi,bi,Si,Ii,la,va,Da,ka,ja,Na].forEach(function(e){Z(Pa,e)});var Fa=0,Ia=1,La=2,Ra=function(e){if(!(this instanceof Ra))return new Ra(e);this.id=`Thenable/1.0.7`,this.state=Fa,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},typeof e==`function`&&e.call(this,this.fulfill.bind(this),this.reject.bind(this))};Ra.prototype={fulfill:function(e){return za(this,Ia,`fulfillValue`,e)},reject:function(e){return za(this,La,`rejectReason`,e)},then:function(e,t){var n=this,r=new Ra;return n.onFulfilled.push(Ha(e,r,`fulfill`)),n.onRejected.push(Ha(t,r,`reject`)),Ba(n),r.proxy}};var za=function(e,t,n,r){return e.state===Fa&&(e.state=t,e[n]=r,Ba(e)),e},Ba=function(e){e.state===Ia?Va(e,`onFulfilled`,e.fulfillValue):e.state===La&&Va(e,`onRejected`,e.rejectReason)},Va=function(e,t,n){if(e[t].length!==0){var r=e[t];e[t]=[];var i=function(){for(var e=0;e0}},clearQueue:function(){return function(){var e=this,t=e.length===void 0?[e]:e;if(!(this._private.cy||this).styleEnabled())return this;for(var n=0;n-1}return is=t,is}var ss,cs;function ls(){if(cs)return ss;cs=1;var e=Zo();function t(t,n){var r=this.__data__,i=e(r,t);return i<0?(++this.size,r.push([t,n])):r[i][1]=n,this}return ss=t,ss}var us,ds;function fs(){if(ds)return us;ds=1;var e=Go(),t=es(),n=rs(),r=os(),i=ls();function a(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t-1&&n%1==0&&n0&&this.spawn(r).updateStyle().emit(`class`),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return t!=null&&t._private.classes.has(e)},toggleClass:function(e,t){de(e)||(e=e.match(/\S+/g)||[]);for(var n=this,r=t===void 0,i=[],a=0,o=n.length;a0&&this.spawn(i).updateStyle().emit(`class`),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var n=this;if(t==null)t=250;else if(t===0)return n;return n.addClass(e),setTimeout(function(){n.removeClass(e)},t),n}};qc.className=qc.classNames=qc.classes;var Jc={metaChar:`[\\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\\`\\{\\|\\}\\~]`,comparatorOp:`=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=`,boolOp:`\\?|\\!|\\^`,string:`"(?:\\\\"|[^"])*"|'(?:\\\\'|[^'])*'`,number:Me,meta:`degree|indegree|outdegree`,separator:`\\s*,\\s*`,descendant:`\\s+`,child:`\\s+>\\s+`,subject:`\\$`,group:`node|edge|\\*`,directedEdge:`\\s+->\\s+`,undirectedEdge:`\\s+<->\\s+`};Jc.variable=`(?:[\\w-.]|(?:\\\\`+Jc.metaChar+`))+`,Jc.className=`(?:[\\w-]|(?:\\\\`+Jc.metaChar+`))+`,Jc.value=Jc.string+`|`+Jc.number,Jc.id=Jc.variable,(function(){var e=Jc.comparatorOp.split(`|`),t,n;for(n=0;n=0)&&t!==`=`&&(Jc.comparatorOp+=`|\\!`+t)})();var Yc=function(){return{checks:[]}},Q={GROUP:0,COLLECTION:1,FILTER:2,DATA_COMPARE:3,DATA_EXIST:4,DATA_BOOL:5,META_COMPARE:6,STATE:7,ID:8,CLASS:9,UNDIRECTED_EDGE:10,DIRECTED_EDGE:11,NODE_SOURCE:12,NODE_TARGET:13,NODE_NEIGHBOR:14,CHILD:15,DESCENDANT:16,PARENT:17,ANCESTOR:18,COMPOUND_SPLIT:19,TRUE:20},Xc=[{selector:`:selected`,matches:function(e){return e.selected()}},{selector:`:unselected`,matches:function(e){return!e.selected()}},{selector:`:selectable`,matches:function(e){return e.selectable()}},{selector:`:unselectable`,matches:function(e){return!e.selectable()}},{selector:`:locked`,matches:function(e){return e.locked()}},{selector:`:unlocked`,matches:function(e){return!e.locked()}},{selector:`:visible`,matches:function(e){return e.visible()}},{selector:`:hidden`,matches:function(e){return!e.visible()}},{selector:`:transparent`,matches:function(e){return e.transparent()}},{selector:`:grabbed`,matches:function(e){return e.grabbed()}},{selector:`:free`,matches:function(e){return!e.grabbed()}},{selector:`:removed`,matches:function(e){return e.removed()}},{selector:`:inside`,matches:function(e){return!e.removed()}},{selector:`:grabbable`,matches:function(e){return e.grabbable()}},{selector:`:ungrabbable`,matches:function(e){return!e.grabbable()}},{selector:`:animated`,matches:function(e){return e.animated()}},{selector:`:unanimated`,matches:function(e){return!e.animated()}},{selector:`:parent`,matches:function(e){return e.isParent()}},{selector:`:childless`,matches:function(e){return e.isChildless()}},{selector:`:child`,matches:function(e){return e.isChild()}},{selector:`:orphan`,matches:function(e){return e.isOrphan()}},{selector:`:nonorphan`,matches:function(e){return e.isChild()}},{selector:`:compound`,matches:function(e){return e.isNode()?e.isParent():e.source().isParent()||e.target().isParent()}},{selector:`:loop`,matches:function(e){return e.isLoop()}},{selector:`:simple`,matches:function(e){return e.isSimple()}},{selector:`:active`,matches:function(e){return e.active()}},{selector:`:inactive`,matches:function(e){return!e.active()}},{selector:`:backgrounding`,matches:function(e){return e.backgrounding()}},{selector:`:nonbackgrounding`,matches:function(e){return!e.backgrounding()}}].sort(function(e,t){return Be(e.selector,t.selector)}),Zc=function(){for(var e={},t,n=0;n0&&l.edgeCount>0)return vn("The selector `"+e+"` is invalid because it uses both a compound selector and an edge selector"),!1;if(l.edgeCount>1)return vn("The selector `"+e+"` is invalid because it uses multiple edge selectors"),!1;l.edgeCount===1&&vn("The selector `"+e+"` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.")}return!0},toString:function(){if(this.toStringCache!=null)return this.toStringCache;for(var e=function(e){return e??``},t=function(t){return J(t)?`"`+t+`"`:e(t)},n=function(e){return` `+e+` `},r=function(r,a){var o=r.type,s=r.value;switch(o){case Q.GROUP:var c=e(s);return c.substring(0,c.length-1);case Q.DATA_COMPARE:var l=r.field,u=r.operator;return`[`+l+n(e(u))+t(s)+`]`;case Q.DATA_BOOL:var d=r.operator,f=r.field;return`[`+e(d)+f+`]`;case Q.DATA_EXIST:return`[`+r.field+`]`;case Q.META_COMPARE:var p=r.operator;return`[[`+r.field+n(e(p))+t(s)+`]]`;case Q.STATE:return s;case Q.ID:return`#`+s;case Q.CLASS:return`.`+s;case Q.PARENT:case Q.CHILD:return i(r.parent,a)+n(`>`)+i(r.child,a);case Q.ANCESTOR:case Q.DESCENDANT:return i(r.ancestor,a)+` `+i(r.descendant,a);case Q.COMPOUND_SPLIT:var m=i(r.left,a),h=i(r.subject,a),g=i(r.right,a);return m+(m.length>0?` `:``)+h+g;case Q.TRUE:return``}},i=function(e,t){return e.checks.reduce(function(n,i,a){return n+(t===e&&a===0?`$`:``)+r(i,t)},``)},a=``,o=0;o1&&o=0&&(t=t.replace(`!`,``),u=!0),t.indexOf(`@`)>=0&&(t=t.replace(`@`,``),l=!0),(i||o||l)&&(s=!i&&!a?``:``+e,c=``+n),l&&(e=s=s.toLowerCase(),n=c=c.toLowerCase()),t){case`*=`:r=s.indexOf(c)>=0;break;case`$=`:r=s.indexOf(c,s.length-c.length)>=0;break;case`^=`:r=s.indexOf(c)===0;break;case`=`:r=e===n;break;case`>`:d=!0,r=e>n;break;case`>=`:d=!0,r=e>=n;break;case`<`:d=!0,r=e0;){var l=i.shift();t(l),a.add(l.id()),o&&r(i,a,l)}return e}function bl(e,t,n){if(n.isParent())for(var r=n._private.children,i=0;i1&&arguments[1]!==void 0?arguments[1]:!0;return yl(this,e,t,bl)};function xl(e,t,n){if(n.isChild()){var r=n._private.parent;t.has(r.id())||e.push(r)}}vl.forEachUp=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return yl(this,e,t,xl)};function Sl(e,t,n){xl(e,t,n),bl(e,t,n)}vl.forEachUpAndDown=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return yl(this,e,t,Sl)},vl.ancestors=vl.parents;var Cl=wl={data:Gc.data({field:`data`,bindingEvent:`data`,allowBinding:!0,allowSetting:!0,settingEvent:`data`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:Gc.removeData({field:`data`,event:`data`,triggerFnName:`trigger`,triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:Gc.data({field:`scratch`,bindingEvent:`scratch`,allowBinding:!0,allowSetting:!0,settingEvent:`scratch`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeScratch:Gc.removeData({field:`scratch`,event:`scratch`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0}),rscratch:Gc.data({field:`rscratch`,allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:Gc.removeData({field:`rscratch`,triggerEvent:!1}),id:function(){var e=this[0];if(e)return e._private.data.id}},wl;Cl.attr=Cl.data,Cl.removeAttr=Cl.removeData;var Tl=wl,El={};function Dl(e){return function(t){var n=this;if(t===void 0&&(t=!0),n.length!==0)if(n.isNode()&&!n.removed()){for(var r=0,i=n[0],a=i._private.edges,o=0;ot}),minIndegree:Ol(`indegree`,function(e,t){return et}),minOutdegree:Ol(`outdegree`,function(e,t){return et})}),Z(El,{totalDegree:function(e){for(var t=0,n=this.nodes(),r=0;r0,d=u;u&&(l=l[0]);var f=d?l.position():{x:0,y:0};t===void 0?i!==void 0&&c.position({x:i.x+f.x,y:i.y+f.y}):c.position(e,t+f[e])}else{var p=n.position(),m=o?n.parent():null,h=m&&m.length>0,g=h;h&&(m=m[0]);var _=g?m.position():{x:0,y:0};return i={x:p.x-_.x,y:p.y-_.y},e===void 0?i:i[e]}else if(!a)return;return this}},kl.modelPosition=kl.point=kl.position,kl.modelPositions=kl.points=kl.positions,kl.renderedPoint=kl.renderedPosition,kl.relativePoint=kl.relativePosition;var Nl=Al,Pl=Fl={},Fl;Fl.renderedBoundingBox=function(e){var t=this.boundingBox(e),n=this.cy(),r=n.zoom(),i=n.pan(),a=t.x1*r+i.x,o=t.x2*r+i.x,s=t.y1*r+i.y,c=t.y2*r+i.y;return{x1:a,x2:o,y1:s,y2:c,w:o-a,h:c-s}},Fl.dirtyCompoundBoundsCache=function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,t=this.cy();return!t.styleEnabled()||!t.hasCompoundNodes()||this.forEachUp(function(t){if(t.isParent()){var n=t._private;n.compoundBoundsClean=!1,n.bbCache=null,e||t.emitAndNotify(`bounds`)}}),this},Fl.updateCompoundBounds=function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes()||!e&&t.batching())return this;function n(e){if(!e.isParent())return;var t=e._private,n=e.children(),r=e.pstyle(`compound-sizing-wrt-labels`).value===`include`,i={width:{val:e.pstyle(`min-width`).pfValue,left:e.pstyle(`min-width-bias-left`),right:e.pstyle(`min-width-bias-right`)},height:{val:e.pstyle(`min-height`).pfValue,top:e.pstyle(`min-height-bias-top`),bottom:e.pstyle(`min-height-bias-bottom`)}},a=n.boundingBox({includeLabels:r,includeOverlays:!1,useCache:!1}),o=t.position;(a.w===0||a.h===0)&&(a={w:e.pstyle(`width`).pfValue,h:e.pstyle(`height`).pfValue},a.x1=o.x-a.w/2,a.x2=o.x+a.w/2,a.y1=o.y-a.h/2,a.y2=o.y+a.h/2);function s(e,t,n){var r=0,i=0,a=t+n;return e>0&&a>0&&(r=t/a*e,i=n/a*e),{biasDiff:r,biasComplementDiff:i}}function c(e,t,n,r){if(n.units===`%`)switch(r){case`width`:return e>0?n.pfValue*e:0;case`height`:return t>0?n.pfValue*t:0;case`average`:return e>0&&t>0?n.pfValue*(e+t)/2:0;case`min`:return e>0&&t>0?e>t?n.pfValue*t:n.pfValue*e:0;case`max`:return e>0&&t>0?e>t?n.pfValue*e:n.pfValue*t:0;default:return 0}else if(n.units===`px`)return n.pfValue;else return 0}var l=i.width.left.value;i.width.left.units===`px`&&i.width.val>0&&(l=l*100/i.width.val);var u=i.width.right.value;i.width.right.units===`px`&&i.width.val>0&&(u=u*100/i.width.val);var d=i.height.top.value;i.height.top.units===`px`&&i.height.val>0&&(d=d*100/i.height.val);var f=i.height.bottom.value;i.height.bottom.units===`px`&&i.height.val>0&&(f=f*100/i.height.val);var p=s(i.width.val-a.w,l,u),m=p.biasDiff,h=p.biasComplementDiff,g=s(i.height.val-a.h,d,f),_=g.biasDiff,v=g.biasComplementDiff;t.autoPadding=c(a.w,a.h,e.pstyle(`padding`),e.pstyle(`padding-relative-to`).value),t.autoWidth=Math.max(a.w,i.width.val),o.x=(-m+a.x1+a.x2+h)/2,t.autoHeight=Math.max(a.h,i.height.val),o.y=(-_+a.y1+a.y2+v)/2}for(var r=0;re.x2?r:e.x2,e.y1=ne.y2?i:e.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1)},Rl=function(e,t){return t==null?e:Ll(e,t.x1,t.y1,t.x2,t.y2)},zl=function(e,t,n){return kn(e,t,n)},Bl=function(e,t,n){if(!t.cy().headless()){var r=t._private,i=r.rstyle,a=i.arrowWidth/2,o=t.pstyle(n+`-arrow-shape`).value,s,c;if(o!==`none`){n===`source`?(s=i.srcX,c=i.srcY):n===`target`?(s=i.tgtX,c=i.tgtY):(s=i.midX,c=i.midY);var l=r.arrowBounds=r.arrowBounds||{},u=l[n]=l[n]||{};u.x1=s-a,u.y1=c-a,u.x2=s+a,u.y2=c+a,u.w=u.x2-u.x1,u.h=u.y2-u.y1,kr(u,1),Ll(e,u.x1,u.y1,u.x2,u.y2)}}},Vl=function(e,t,n){if(!t.cy().headless()){var r=n?n+`-`:``,i=t._private,a=i.rstyle;if(t.pstyle(r+`label`).strValue){var o=t.pstyle(`text-halign`),s=t.pstyle(`text-valign`),c=zl(a,`labelWidth`,n),l=zl(a,`labelHeight`,n),u=zl(a,`labelX`,n),d=zl(a,`labelY`,n),f=t.pstyle(r+`text-margin-x`).pfValue,p=t.pstyle(r+`text-margin-y`).pfValue,m=t.isEdge(),h=t.pstyle(r+`text-rotation`),g=t.pstyle(`text-outline-width`).pfValue,_=t.pstyle(`text-border-width`).pfValue/2,v=t.pstyle(`text-background-padding`).pfValue,y=2,b=l,x=c,S=x/2,C=b/2,w,T,E,D;if(m)w=u-S,T=u+S,E=d-C,D=d+C;else{switch(o.value){case`left`:w=u-x,T=u;break;case`center`:w=u-S,T=u+S;break;case`right`:w=u,T=u+x;break}switch(s.value){case`top`:E=d-b,D=d;break;case`center`:E=d-C,D=d+C;break;case`bottom`:E=d,D=d+b;break}}var O=f-Math.max(g,_)-v-y,k=f+Math.max(g,_)+v+y,A=p-Math.max(g,_)-v-y,j=p+Math.max(g,_)+v+y;w+=O,T+=k,E+=A,D+=j;var M=n||`main`,N=i.labelBounds,P=N[M]=N[M]||{};P.x1=w,P.y1=E,P.x2=T,P.y2=D,P.w=T-w,P.h=D-E,P.leftPad=O,P.rightPad=k,P.topPad=A,P.botPad=j;var F=m&&h.strValue===`autorotate`,I=h.pfValue!=null&&h.pfValue!==0;if(F||I){var L=F?zl(i.rstyle,`labelAngle`,n):h.pfValue,R=Math.cos(L),z=Math.sin(L),B=(w+T)/2,V=(E+D)/2;if(!m){switch(o.value){case`left`:B=T;break;case`right`:B=w;break}switch(s.value){case`top`:V=D;break;case`bottom`:V=E;break}}var H=function(e,t){return e-=B,t-=V,{x:e*R-t*z+B,y:e*z+t*R+V}},U=H(w,E),W=H(w,D),G=H(T,E),K=H(T,D);w=Math.min(U.x,W.x,G.x,K.x),T=Math.max(U.x,W.x,G.x,K.x),E=Math.min(U.y,W.y,G.y,K.y),D=Math.max(U.y,W.y,G.y,K.y)}var ee=M+`Rot`,te=N[ee]=N[ee]||{};te.x1=w,te.y1=E,te.x2=T,te.y2=D,te.w=T-w,te.h=D-E,Ll(e,w,E,T,D),Ll(i.labelBounds.all,w,E,T,D)}return e}},Hl=function(e,t){if(!t.cy().headless()){var n=t.pstyle(`outline-opacity`).value,r=t.pstyle(`outline-width`).value+t.pstyle(`outline-offset`).value;Ul(e,t,n,r,`outside`,r/2)}},Ul=function(e,t,n,r,i,a){if(!(n===0||r<=0||i===`inside`)){var o=t.cy().renderer(),s=o.nodeShapes[o.getNodeShape(t)];if(s){var c=t.position(),l=c.x,u=c.y,d=t.width(),f=t.height();s.hasMiterBounds?(i===`center`&&(r/=2),Rl(e,s.miterBounds(l,u,d,f,r))):a!=null&&a>0&&Ar(e,[a,a,a,a])}}},Wl=function(e,t){if(!t.cy().headless()){var n=t.pstyle(`border-opacity`).value,r=t.pstyle(`border-width`).pfValue,i=t.pstyle(`border-position`).value;Ul(e,t,n,r,i)}},Gl=function(e,t){var n=e._private.cy,r=n.styleEnabled(),i=n.headless(),a=wr(),o=e._private,s=e.isNode(),c=e.isEdge(),l,u,d,f,p,m,h=o.rstyle,g=s&&r?e.pstyle(`bounds-expansion`).pfValue:[0],_=function(e){return e.pstyle(`display`).value!==`none`},v=!r||_(e)&&(!c||_(e.source())&&_(e.target()));if(v){var y=0,b=0;r&&t.includeOverlays&&(y=e.pstyle(`overlay-opacity`).value,y!==0&&(b=e.pstyle(`overlay-padding`).value));var x=0,S=0;r&&t.includeUnderlays&&(x=e.pstyle(`underlay-opacity`).value,x!==0&&(S=e.pstyle(`underlay-padding`).value));var C=Math.max(b,S),w=0,T=0;if(r&&(w=e.pstyle(`width`).pfValue,T=w/2),s&&t.includeNodes){var E=e.position();p=E.x,m=E.y;var D=e.outerWidth()/2,O=e.outerHeight()/2;l=p-D,u=p+D,d=m-O,f=m+O,Ll(a,l,d,u,f),r&&Hl(a,e),r&&t.includeOutlines&&!i&&Hl(a,e),r&&Wl(a,e)}else if(c&&t.includeEdges)if(r&&!i){var k=e.pstyle(`curve-style`).strValue;if(l=Math.min(h.srcX,h.midX,h.tgtX),u=Math.max(h.srcX,h.midX,h.tgtX),d=Math.min(h.srcY,h.midY,h.tgtY),f=Math.max(h.srcY,h.midY,h.tgtY),l-=T,u+=T,d-=T,f+=T,Ll(a,l,d,u,f),k===`haystack`){var A=h.haystackPts;if(A&&A.length===2){if(l=A[0].x,d=A[0].y,u=A[1].x,f=A[1].y,l>u){var j=l;l=u,u=j}if(d>f){var M=d;d=f,f=M}Ll(a,l-T,d-T,u+T,f+T)}}else if(k===`bezier`||k===`unbundled-bezier`||je(k,`segments`)||je(k,`taxi`)){var N;switch(k){case`bezier`:case`unbundled-bezier`:N=h.bezierPts;break;case`segments`:case`taxi`:case`round-segments`:case`round-taxi`:N=h.linePts;break}if(N!=null)for(var P=0;Pu){var R=l;l=u,u=R}if(d>f){var z=d;d=f,f=z}l-=T,u+=T,d-=T,f+=T,Ll(a,l,d,u,f)}if(r&&t.includeEdges&&c&&(Bl(a,e,`mid-source`),Bl(a,e,`mid-target`),Bl(a,e,`source`),Bl(a,e,`target`)),r&&e.pstyle(`ghost`).value===`yes`){var B=e.pstyle(`ghost-offset-x`).pfValue,V=e.pstyle(`ghost-offset-y`).pfValue;Ll(a,a.x1+B,a.y1+V,a.x2+B,a.y2+V)}var H=o.bodyBounds=o.bodyBounds||{};jr(H,a),Ar(H,g),kr(H,1),r&&(l=a.x1,u=a.x2,d=a.y1,f=a.y2,Ll(a,l-C,d-C,u+C,f+C));var U=o.overlayBounds=o.overlayBounds||{};jr(U,a),Ar(U,g),kr(U,1);var W=o.labelBounds=o.labelBounds||{};W.all==null?W.all=wr():Er(W.all),r&&t.includeLabels&&(t.includeMainLabels&&Vl(a,e,null),c&&(t.includeSourceLabels&&Vl(a,e,`source`),t.includeTargetLabels&&Vl(a,e,`target`)))}return a.x1=Il(a.x1),a.y1=Il(a.y1),a.x2=Il(a.x2),a.y2=Il(a.y2),a.w=Il(a.x2-a.x1),a.h=Il(a.y2-a.y1),a.w>0&&a.h>0&&v&&(Ar(a,g),kr(a,1)),a},Kl=function(e){var t=0,n=function(e){return+!!e<0&&arguments[0]!==void 0?arguments[0]:gu,t=arguments.length>1?arguments[1]:void 0,n=0;n=0;s--)o(s);return this},vu.removeAllListeners=function(){return this.removeListener(`*`)},vu.emit=vu.trigger=function(e,t,n){var r=this.listeners,i=r.length;return this.emitting++,de(t)||(t=[t]),xu(this,function(e,a){n!=null&&(r=[{event:a.event,type:a.type,namespace:a.namespace,callback:n}],i=r.length);for(var o=function(){var n=r[s];if(n.type===a.type&&(!n.namespace||n.namespace===a.namespace||n.namespace===pu)&&e.eventMatches(e.context,n,a)){var i=[a];t!=null&&On(i,t),e.beforeEmit(e.context,n,a),n.conf&&n.conf.one&&(e.listeners=e.listeners.filter(function(e){return e!==n}));var o=e.callbackContext(e.context,n,a),c=n.callback.apply(o,i);e.afterEmit(e.context,n,a),c===!1&&(a.stopPropagation(),a.preventDefault())}},s=0;s1&&!r){var i=this.length-1,a=this[i],o=a._private.data.id;this[i]=void 0,this[e]=a,n.set(o,{ele:a,index:e})}return this.length--,this},unmergeOne:function(e){e=e[0];var t=this._private,n=e._private.data.id,r=t.map.get(n);if(!r)return this;var i=r.index;return this.unmergeAt(i),this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(e&&J(e)){var n=e;e=t.mutableElements().filter(n)}for(var r=0;r=0;t--){var n=this[t];e(n)&&this.unmergeAt(t)}return this},map:function(e,t){for(var n=[],r=this,i=0;in&&(n=s,r=o)}return{value:n,ele:r}},min:function(e,t){for(var n=1/0,r,i=this,a=0;a=0&&i`u`?`undefined`:q(Symbol))!=e&&q(Symbol.iterator)!=e&&(ku[Symbol.iterator]=function(){var e=this,t={value:void 0,done:!1},n=0,r=this.length;return B({next:function(){return n1&&arguments[1]!==void 0?arguments[1]:!0,n=this[0],r=n.cy();if(r.styleEnabled()&&n)return n._private.styleDirty&&(n._private.styleDirty=!1,r.style().apply(n)),n._private.style[e]??(t?r.style().getDefaultProperty(e):null)},numericStyle:function(e){var t=this[0];if(t.cy().styleEnabled()&&t){var n=t.pstyle(e);return n.pfValue===void 0?n.value:n.pfValue}},numericStyleUnits:function(e){var t=this[0];if(t.cy().styleEnabled()&&t)return t.pstyle(e).units},renderedStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=this[0];if(n)return t.style().getRenderedStyle(n,e)},style:function(e,t){var n=this.cy();if(!n.styleEnabled())return this;var r=!1,i=n.style();if(Y(e)){var a=e;i.applyBypass(this,a,r),this.emitAndNotify(`style`)}else if(J(e))if(t===void 0){var o=this[0];return o?i.getStylePropertyValue(o,e):void 0}else i.applyBypass(this,e,t,r),this.emitAndNotify(`style`);else if(e===void 0){var s=this[0];return s?i.getRawStyle(s):void 0}return this},removeStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=!1,r=t.style(),i=this;if(e===void 0)for(var a=0;a0&&t.push(u[0]),t.push(s[0])}return this.spawn(t,!0).filter(e)},`neighborhood`),closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),Hu.neighbourhood=Hu.neighborhood,Hu.closedNeighbourhood=Hu.closedNeighborhood,Hu.openNeighbourhood=Hu.openNeighborhood,Z(Hu,{source:_l(function(e){var t=this[0],n;return t&&(n=t._private.source||t.cy().collection()),n&&e?n.filter(e):n},`source`),target:_l(function(e){var t=this[0],n;return t&&(n=t._private.target||t.cy().collection()),n&&e?n.filter(e):n},`target`),sources:Ku({attr:`source`}),targets:Ku({attr:`target`})});function Ku(e){return function(t){for(var n=[],r=0;r0);return a},component:function(){var e=this[0];return e.cy().mutableElements().components(e)[0]}}),Hu.componentsOf=Hu.components;var Yu=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!1;if(e===void 0){gn(`A collection must have a reference to the core`);return}var i=new jn,a=!1;if(!t)t=[];else if(t.length>0&&Y(t[0])&&!ge(t[0])){a=!0;for(var o=[],s=new Pn,c=0,l=t.length;c0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,n=this,r=n.cy(),i=r._private,a=[],o=[],s,c=0,l=n.length;c0){for(var P=s.length===n.length?n:new Yu(r,s),F=0;F0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,n=this,r=[],i={},a=n._private.cy;function o(e){for(var t=e._private.edges,n=0;n0&&(e?E.emitAndNotify(`remove`):t&&E.emit(`remove`));for(var D=0;D0?i=c:r=c;while(Math.abs(a)>o&&++l=a?v(t,u):d===0?u:b(t,r,r+l)}var S=!1;function C(){S=!0,(e!==t||n!==r)&&y()}var w=function(i){return S||C(),e===t&&n===r?i:i===0?0:i===1?1:g(x(i),t,r)};w.getControlPoints=function(){return[{x:e,y:t},{x:n,y:r}]};var T=`generateBezier(`+[e,t,n,r]+`)`;return w.toString=function(){return T},w}var $u=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,n,r){var i={x:t.x+r.dx*n,v:t.v+r.dv*n,tension:t.tension,friction:t.friction};return{dx:i.v,dv:e(i)}}function n(n,r){var i={dx:n.v,dv:e(n)},a=t(n,r*.5,i),o=t(n,r*.5,a),s=t(n,r,o),c=1/6*(i.dx+2*(a.dx+o.dx)+s.dx),l=1/6*(i.dv+2*(a.dv+o.dv)+s.dv);return n.x+=c*r,n.v+=l*r,n}return function e(t,r,i){var a={x:-1,v:0,tension:null,friction:null},o=[0],s=0,c=1/1e4,l=16/1e3,u,d,f;for(t=parseFloat(t)||500,r=parseFloat(r)||20,i||=null,a.tension=t,a.friction=r,u=i!==null,u?(s=e(t,r),d=s/i*l):d=l;f=n(f||a,d),o.push(1+f.x),s+=16,Math.abs(f.x)>c&&Math.abs(f.v)>c;);return u?function(e){return o[e*(o.length-1)|0]}:s}}(),ed=function(e,t,n,r){var i=Qu(e,t,n,r);return function(e,t,n){return e+(t-e)*i(n)}},td={linear:function(e,t,n){return e+(t-e)*n},ease:ed(.25,.1,.25,1),"ease-in":ed(.42,0,1,1),"ease-out":ed(0,0,.58,1),"ease-in-out":ed(.42,0,.58,1),"ease-in-sine":ed(.47,0,.745,.715),"ease-out-sine":ed(.39,.575,.565,1),"ease-in-out-sine":ed(.445,.05,.55,.95),"ease-in-quad":ed(.55,.085,.68,.53),"ease-out-quad":ed(.25,.46,.45,.94),"ease-in-out-quad":ed(.455,.03,.515,.955),"ease-in-cubic":ed(.55,.055,.675,.19),"ease-out-cubic":ed(.215,.61,.355,1),"ease-in-out-cubic":ed(.645,.045,.355,1),"ease-in-quart":ed(.895,.03,.685,.22),"ease-out-quart":ed(.165,.84,.44,1),"ease-in-out-quart":ed(.77,0,.175,1),"ease-in-quint":ed(.755,.05,.855,.06),"ease-out-quint":ed(.23,1,.32,1),"ease-in-out-quint":ed(.86,0,.07,1),"ease-in-expo":ed(.95,.05,.795,.035),"ease-out-expo":ed(.19,1,.22,1),"ease-in-out-expo":ed(1,0,0,1),"ease-in-circ":ed(.6,.04,.98,.335),"ease-out-circ":ed(.075,.82,.165,1),"ease-in-out-circ":ed(.785,.135,.15,.86),spring:function(e,t,n){if(n===0)return td.linear;var r=$u(e,t,n);return function(e,t,n){return e+(t-e)*r(n)}},"cubic-bezier":ed};function nd(e,t,n,r,i){if(r===1||t===n)return n;var a=i(t,n,r);return e==null?a:((e.roundValue||e.color)&&(a=Math.round(a)),e.min!==void 0&&(a=Math.max(a,e.min)),e.max!==void 0&&(a=Math.min(a,e.max)),a)}function rd(e,t){return e.pfValue!=null||e.value!=null?e.pfValue!=null&&(t==null||t.type.units!==`%`)?e.pfValue:e.value:e}function id(e,t,n,r,i){var a=i==null?null:i.type;n<0?n=0:n>1&&(n=1);var o=rd(e,i),s=rd(t,i);if(X(o)&&X(s))return nd(a,o,s,n,r);if(de(o)&&de(s)){for(var c=[],l=0;l0?(d===`spring`&&f.push(o.duration),o.easingImpl=td[d].apply(null,f)):o.easingImpl=td[d]}var p=o.easingImpl,m=o.duration===0?1:(n-c)/o.duration;if(o.applying&&(m=o.progress),m<0?m=0:m>1&&(m=1),o.delay==null){var h=o.startPosition,g=o.position;if(g&&i&&!e.locked()){var _={};od(h.x,g.x)&&(_.x=id(h.x,g.x,m,p)),od(h.y,g.y)&&(_.y=id(h.y,g.y,m,p)),e.position(_)}var v=o.startPan,y=o.pan,b=a.pan,x=y!=null&&r;x&&(od(v.x,y.x)&&(b.x=id(v.x,y.x,m,p)),od(v.y,y.y)&&(b.y=id(v.y,y.y,m,p)),e.emit(`pan`));var S=o.startZoom,C=o.zoom,w=C!=null&&r;w&&(od(S,C)&&(a.zoom=Cr(a.minZoom,id(S,C,m,p),a.maxZoom)),e.emit(`zoom`)),(x||w)&&e.emit(`viewport`);var T=o.style;if(T&&T.length>0&&i){for(var E=0;E=0;t--){var n=e[t];n()}e.splice(0,e.length)},u=a.length-1;u>=0;u--){var d=a[u],f=d._private;if(f.stopped){a.splice(u,1),f.hooked=!1,f.playing=!1,f.started=!1,l(f.frames);continue}!f.playing&&!f.applying||(f.playing&&f.applying&&(f.applying=!1),f.started||sd(t,d,e),ad(t,d,e,n),f.applying&&=!1,l(f.frames),f.step!=null&&f.step(e),d.completed()&&(a.splice(u,1),f.hooked=!1,f.playing=!1,f.started=!1,l(f.completes)),s=!0)}return!n&&a.length===0&&o.length===0&&r.push(t),s}for(var a=!1,o=0;o0?t.notify(`draw`,n):t.notify(`draw`)),n.unmerge(r),t.emit(`step`)}var ld={animate:Gc.animate(),animation:Gc.animation(),animated:Gc.animated(),clearQueue:Gc.clearQueue(),delay:Gc.delay(),delayAnimation:Gc.delayAnimation(),stop:Gc.stop(),addToAnimationPool:function(e){var t=this;t.styleEnabled()&&t._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){var e=this;if(e._private.animationsRunning=!0,!e.styleEnabled())return;function t(){e._private.animationsRunning&&Ut(function(n){cd(n,e),t()})}var n=e.renderer();n&&n.beforeRender?n.beforeRender(function(t,n){cd(n,e)},n.beforeRenderPriorities.animations):t()}},ud={qualifierCompare:function(e,t){return e==null||t==null?e==null&&t==null:e.sameText(t)},eventMatches:function(e,t,n){var r=t.qualifier;return r==null?!0:e!==n.target&&ge(n.target)&&r.matches(n.target)},addEventFields:function(e,t){t.cy=e,t.target=e},callbackContext:function(e,t,n){return t.qualifier==null?e:n.target}},dd=function(e){return J(e)?new ml(e):e},fd={createEmitter:function(){var e=this._private;return e.emitter||=new _u(ud,this),this},emitter:function(){return this._private.emitter},on:function(e,t,n){return this.emitter().on(e,dd(t),n),this},removeListener:function(e,t,n){return this.emitter().removeListener(e,dd(t),n),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},one:function(e,t,n){return this.emitter().one(e,dd(t),n),this},once:function(e,t,n){return this.emitter().one(e,dd(t),n),this},emit:function(e,t){return this.emitter().emit(e,t),this},emitAndNotify:function(e,t){return this.emit(e),this.notify(e,t),this}};Gc.eventAliasesOn(fd);var pd={png:function(e){var t=this._private.renderer;return e||={},t.png(e)},jpg:function(e){var t=this._private.renderer;return e||={},e.bg=e.bg||`#fff`,t.jpg(e)}};pd.jpeg=pd.jpg;var md={layout:function(e){var t=this;if(e==null){gn(`Layout options must be specified to make a layout`);return}if(e.name==null){gn("A `name` must be specified to make a layout");return}var n=e.name,r=t.extension(`layout`,n);if(r==null){gn("No such layout `"+n+"` found. Did you forget to import it and `cytoscape.use()` it?");return}return new r(Z({},e,{cy:t,eles:J(e.eles)?t.$(e.eles):e.eles==null?t.$():e.eles}))}};md.createLayout=md.makeLayout=md.layout;var hd={notify:function(e,t){var n=this._private;if(this.batching()){n.batchNotifications=n.batchNotifications||{};var r=n.batchNotifications[e]=n.batchNotifications[e]||this.collection();t!=null&&r.merge(t);return}if(n.notificationsEnabled){var i=this.renderer();this.destroyed()||!i||i.notify(e,t)}},notifications:function(e){var t=this._private;return e===void 0?t.notificationsEnabled:(t.notificationsEnabled=!!e,this)},noNotifications:function(e){this.notifications(!1),e(),this.notifications(!0)},batching:function(){return this._private.batchCount>0},startBatch:function(){var e=this._private;return e.batchCount??=0,e.batchCount===0&&(e.batchStyleEles=this.collection(),e.batchNotifications={}),e.batchCount++,this},endBatch:function(){var e=this._private;if(e.batchCount===0)return this;if(e.batchCount--,e.batchCount===0){e.batchStyleEles.updateStyle();var t=this.renderer();Object.keys(e.batchNotifications).forEach(function(n){var r=e.batchNotifications[n];r.empty()?t.notify(n):t.notify(n,r)})}return this},batch:function(e){return this.startBatch(),e(),this.endBatch(),this},batchData:function(e){var t=this;return this.batch(function(){for(var n=Object.keys(e),r=0;r0;)t.removeChild(t.childNodes[0]);e._private.renderer=null,e.mutableElements().forEach(function(e){var t=e._private;t.rscratch={},t.rstyle={},t.animation.current=[],t.animation.queue=[]})},onRender:function(e){return this.on(`render`,e)},offRender:function(e){return this.off(`render`,e)}};_d.invalidateDimensions=_d.resize;var vd={collection:function(e,t){return J(e)?this.$(e):he(e)?e.collection():de(e)?(t||={},new Yu(this,e,t.unique,t.removed)):new Yu(this)},nodes:function(e){var t=this.$(function(e){return e.isNode()});return e?t.filter(e):t},edges:function(e){var t=this.$(function(e){return e.isEdge()});return e?t.filter(e):t},$:function(e){var t=this._private.elements;return e?t.filter(e):t.spawnSelf()},mutableElements:function(){return this._private.elements}};vd.elements=vd.filter=vd.$;var yd={},bd=`t`,xd=`f`;yd.apply=function(e){for(var t=this,n=t._private.cy.collection(),r=0;r0;if(f||d&&p){var m=void 0;f&&p||f?m=l.properties:p&&(m=l.mappedProperties);for(var h=0;h1&&(b=1),s.color){var S=r.valueMin[0],C=r.valueMax[0],w=r.valueMin[1],T=r.valueMax[1],E=r.valueMin[2],D=r.valueMax[2],O=r.valueMin[3]==null?1:r.valueMin[3],k=r.valueMax[3]==null?1:r.valueMax[3],A=[Math.round(S+(C-S)*b),Math.round(w+(T-w)*b),Math.round(E+(D-E)*b),Math.round(O+(k-O)*b)];a={bypass:r.bypass,name:r.name,value:A,strValue:`rgb(`+A[0]+`, `+A[1]+`, `+A[2]+`)`}}else if(s.number){var j=r.valueMin+(r.valueMax-r.valueMin)*b;a=this.parse(r.name,j,r.bypass,f)}else return!1;if(!a)return h(),!1;a.mapping=r,r=a;break;case o.data:for(var M=r.field.split(`.`),N=d.data,P=0;P0&&a>0){for(var s={},c=!1,l=0;l0?e.delayAnimation(o).play().promise().then(t):t()}).then(function(){return e.animation({style:s,duration:a,easing:e.pstyle(`transition-timing-function`).value,queue:!1}).play().promise()}).then(function(){n.removeBypasses(e,i),e.emitAndNotify(`style`),r.transitioning=!1})}else r.transitioning&&=(this.removeBypasses(e,i),e.emitAndNotify(`style`),!1)},yd.checkTrigger=function(e,t,n,r,i,a){var o=this.properties[t],s=i(o);e.removed()||s!=null&&s(n,r,e)&&a(o)},yd.checkZOrderTrigger=function(e,t,n,r){var i=this;this.checkTrigger(e,t,n,r,function(e){return e.triggersZOrder},function(){i._private.cy.notify(`zorder`,e)})},yd.checkBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBounds},function(t){e.dirtyCompoundBoundsCache(),e.dirtyBoundingBoxCache()})},yd.checkConnectedEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBoundsOfConnectedEdges},function(t){e.connectedEdges().forEach(function(e){e.dirtyBoundingBoxCache()})})},yd.checkParallelEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBoundsOfParallelEdges},function(t){e.parallelEdges().forEach(function(e){e.dirtyBoundingBoxCache()})})},yd.checkTriggers=function(e,t,n,r){e.dirtyStyleCache(),this.checkZOrderTrigger(e,t,n,r),this.checkBoundsTrigger(e,t,n,r),this.checkConnectedEdgesBoundsTrigger(e,t,n,r),this.checkParallelEdgesBoundsTrigger(e,t,n,r)};var Sd={};Sd.applyBypass=function(e,t,n,r){var i=this,a=[],o=!0;if(t===`*`||t===`**`){if(n!==void 0)for(var s=0;si.length?r.substr(i.length):``}function c(){a=a.length>o.length?a.substr(o.length):``}for(;!r.match(/^\s*$/);){var l=r.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!l){vn(`Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: `+r);break}i=l[0];var u=l[1];if(u!==`core`&&new ml(u).invalid){vn(`Skipping parsing of block: Invalid selector found in string stylesheet: `+u),s();continue}var d=l[2],f=!1;a=d;for(var p=[];!a.match(/^\s*$/);){var m=a.match(/^\s*(.+?)\s*:\s*(.+?)(?:\s*;|\s*$)/);if(!m){vn(`Skipping parsing of block: Invalid formatting of style property and value definitions found in:`+d),f=!0;break}o=m[0];var h=m[1],g=m[2];if(!t.properties[h]){vn(`Skipping property: Invalid property name in: `+o),c();continue}if(!n.parse(h,g)){vn(`Skipping property: Invalid property definition in: `+o),c();continue}p.push({name:h,val:g}),c()}if(f){s();break}n.selector(u);for(var _=0;_=7&&t[0]===`d`&&(u=new RegExp(s.data.regex).exec(t))){if(n)return!1;var f=s.data;return{name:e,value:u,strValue:``+t,mapped:f,field:u[1],bypass:n}}else if(t.length>=10&&t[0]===`m`&&(d=new RegExp(s.mapData.regex).exec(t))){if(n||l.multiple)return!1;var p=s.mapData;if(!(l.color||l.number))return!1;var m=this.parse(e,d[4]);if(!m||m.mapped)return!1;var h=this.parse(e,d[5]);if(!h||h.mapped)return!1;if(m.pfValue===h.pfValue||m.strValue===h.strValue)return vn("`"+e+`: `+t+"` is not a valid mapper because the output range is zero; converting to `"+e+`: `+m.strValue+"`"),this.parse(e,m.strValue);if(l.color){var g=m.value,_=h.value;if(g[0]===_[0]&&g[1]===_[1]&&g[2]===_[2]&&(g[3]===_[3]||(g[3]==null||g[3]===1)&&(_[3]==null||_[3]===1)))return!1}return{name:e,value:d,strValue:``+t,mapped:p,field:d[1],fieldMin:parseFloat(d[2]),fieldMax:parseFloat(d[3]),valueMin:m.value,valueMax:h.value,bypass:n}}}if(l.multiple&&r!==`multiple`){var v=c?t.split(/\s+/):de(t)?t:[t];if(l.evenMultiple&&v.length%2!=0)return null;for(var y=[],b=[],x=[],S=``,C=!1,w=0;w0?` `:``)+T.strValue}return l.validate&&!l.validate(y,b)?null:l.singleEnum&&C?y.length===1&&J(y[0])?{name:e,value:y[0],strValue:y[0],bypass:n}:null:{name:e,value:y,pfValue:x,strValue:S,bypass:n,units:b}}var E=function(){for(var r=0;rl.max||l.strictMax&&t===l.max))return null;var j={name:e,value:t,strValue:``+t+(D||``),units:D,bypass:n};return l.unitless||D!==`px`&&D!==`em`?j.pfValue=t:j.pfValue=D===`px`||!D?t:this.getEmSizeInPixels()*t,(D===`ms`||D===`s`)&&(j.pfValue=D===`ms`?t:1e3*t),(D===`deg`||D===`rad`)&&(j.pfValue=D===`rad`?t:pr(t)),D===`%`&&(j.pfValue=t/100),j}else if(l.propList){var M=[],N=``+t;if(N!==`none`){for(var P=N.split(/\s*,\s*|\s+/),F=0;F0&&o>0&&!isNaN(n.w)&&!isNaN(n.h)&&n.w>0&&n.h>0){s=Math.min((a-2*t)/n.w,(o-2*t)/n.h),s=s>this._private.maxZoom?this._private.maxZoom:s,s=s=n.minZoom&&(n.maxZoom=t),this},minZoom:function(e){return e===void 0?this._private.minZoom:this.zoomRange({min:e})},maxZoom:function(e){return e===void 0?this._private.maxZoom:this.zoomRange({max:e})},getZoomedViewport:function(e){var t=this._private,n=t.pan,r=t.zoom,i,a,o=!1;if(t.zoomingEnabled||(o=!0),X(e)?a=e:Y(e)&&(a=e.level,e.position==null?e.renderedPosition!=null&&(i=e.renderedPosition):i=or(e.position,r,n),i!=null&&!t.panningEnabled&&(o=!0)),a=a>t.maxZoom?t.maxZoom:a,a=at.maxZoom||!t.zoomingEnabled?a=!0:(t.zoom=s,i.push(`zoom`))}if(r&&(!a||!e.cancelOnFailedZoom)&&t.panningEnabled){var c=e.pan;X(c.x)&&(t.pan.x=c.x,o=!1),X(c.y)&&(t.pan.y=c.y,o=!1),o||i.push(`pan`)}return i.length>0&&(i.push(`viewport`),this.emit(i.join(` `)),this.notify(`viewport`)),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.emit(`pan viewport`),this.notify(`viewport`)),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(J(e)){var n=e;e=this.mutableElements().filter(n)}else he(e)||(e=this.mutableElements());if(e.length!==0){var r=e.boundingBox(),i=this.width(),a=this.height();return t=t===void 0?this._private.zoom:t,{x:(i-t*(r.x1+r.x2))/2,y:(a-t*(r.y1+r.y2))/2}}}},reset:function(){return!this._private.panningEnabled||!this._private.zoomingEnabled||this.viewport({pan:{x:0,y:0},zoom:1}),this},invalidateSize:function(){this._private.sizeCache=null},size:function(){var e=this._private,t=e.container,n=this;return e.sizeCache=e.sizeCache||(t?function(){var e=n.window().getComputedStyle(t),r=function(t){return parseFloat(e.getPropertyValue(t))};return{width:t.clientWidth-r(`padding-left`)-r(`padding-right`),height:t.clientHeight-r(`padding-top`)-r(`padding-bottom`)}}():{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var e=this._private.pan,t=this._private.zoom,n=this.renderedExtent(),r={x1:(n.x1-e.x)/t,x2:(n.x2-e.x)/t,y1:(n.y1-e.y)/t,y2:(n.y2-e.y)/t};return r.w=r.x2-r.x1,r.h=r.y2-r.y1,r},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}},multiClickDebounceTime:function(e){if(e)this._private.multiClickDebounceTime=e;else return this._private.multiClickDebounceTime;return this}};Nd.centre=Nd.center,Nd.autolockNodes=Nd.autolock,Nd.autoungrabifyNodes=Nd.autoungrabify;var Pd={data:Gc.data({field:`data`,bindingEvent:`data`,allowBinding:!0,allowSetting:!0,settingEvent:`data`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeData:Gc.removeData({field:`data`,event:`data`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0}),scratch:Gc.data({field:`scratch`,bindingEvent:`scratch`,allowBinding:!0,allowSetting:!0,settingEvent:`scratch`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeScratch:Gc.removeData({field:`scratch`,event:`scratch`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0})};Pd.attr=Pd.data,Pd.removeAttr=Pd.removeData;var Fd=function(e){var t=this;e=Z({},e);var n=e.container;n&&!me(n)&&me(n[0])&&(n=n[0]);var r=n?n._cyreg:null;r||={},r&&r.cy&&(r.cy.destroy(),r={});var i=r.readies=r.readies||[];n&&(n._cyreg=r),r.cy=t;var a=re!==void 0&&n!==void 0&&!e.headless,o=e;o.layout=Z({name:a?`grid`:`null`},o.layout),o.renderer=Z({name:a?`canvas`:`null`},o.renderer);var s=function(e,t,n){return t===void 0?n===void 0?e:n:t},c=this._private={container:n,ready:!1,options:o,elements:new Yu(this),listeners:[],aniEles:new Yu(this),data:o.data||{},scratch:{},layout:null,renderer:null,destroyed:!1,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:s(!0,o.zoomingEnabled),userZoomingEnabled:s(!0,o.userZoomingEnabled),panningEnabled:s(!0,o.panningEnabled),userPanningEnabled:s(!0,o.userPanningEnabled),boxSelectionEnabled:s(!0,o.boxSelectionEnabled),autolock:s(!1,o.autolock,o.autolockNodes),autoungrabify:s(!1,o.autoungrabify,o.autoungrabifyNodes),autounselectify:s(!1,o.autounselectify),styleEnabled:o.styleEnabled===void 0?a:o.styleEnabled,zoom:X(o.zoom)?o.zoom:1,pan:{x:Y(o.pan)&&X(o.pan.x)?o.pan.x:0,y:Y(o.pan)&&X(o.pan.y)?o.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,multiClickDebounceTime:s(250,o.multiClickDebounceTime)};this.createEmitter(),this.selectionType(o.selectionType),this.zoomRange({min:o.minZoom,max:o.maxZoom});var l=function(e,t){if(e.some(we))return Wa.all(e).then(t);t(e)};c.styleEnabled&&t.setStyle([]);var u=Z({},o,o.renderer);t.initRenderer(u);var d=function(e,n,r){t.notifications(!1);var i=t.mutableElements();i.length>0&&i.remove(),e!=null&&(Y(e)||de(e))&&t.add(e),t.one(`layoutready`,function(e){t.notifications(!0),t.emit(e),t.one(`load`,n),t.emitAndNotify(`load`)}).one(`layoutstop`,function(){t.one(`done`,r),t.emit(`done`)});var a=Z({},t._private.options.layout);a.eles=t.elements(),t.layout(a).run()};l([o.style,o.elements],function(e){var n=e[0],a=e[1];c.styleEnabled&&t.style().append(n),d(a,function(){t.startAnimationLoop(),c.ready=!0,ue(o.ready)&&t.on(`ready`,o.ready);for(var e=0;e0,s=!!e.boundingBox,c=wr(s?e.boundingBox:structuredClone(t.extent())),l;if(he(e.roots))l=e.roots;else if(de(e.roots)){for(var u=[],d=0;d0;){var A=k(),j=T(A,D);if(j)A.outgoers().filter(function(e){return e.isNode()&&n.has(e)}).forEach(O);else if(j===null){vn("Detected double maximal shift for node `"+A.id()+"`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.");break}}}var M=0;if(e.avoidOverlap)for(var N=0;N0&&_[0].length<=3?a/2:0),l=2*Math.PI/_[r].length*i;return r===0&&_[0].length===1&&(o=1),{x:K.x+o*Math.cos(l),y:K.y+o*Math.sin(l)}}else{var u=_[r].length,d=Math.max(u===1?0:s?(c.w-e.padding*2-ee.w)/((e.grid?q:u)-1):(c.w-e.padding*2-ee.w)/((e.grid?q:u)+1),M);return{x:K.x+(i+1-(u+1)/2)*d,y:K.y+(r+1-(B+1)/2)*te}}},re={downward:0,leftward:90,upward:180,rightward:-90};return Object.keys(re).indexOf(e.direction)===-1&&gn(`Invalid direction '${e.direction}' specified for breadthfirst layout. Valid values are: ${Object.keys(re).join(`, `)}`),n.nodes().layoutPositions(this,e,function(t){return sn(ne(t),c,re[e.direction])}),this};var Hd={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,radius:void 0,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function Ud(e){this.options=Z({},Hd,e)}Ud.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,i=t.counterclockwise===void 0?t.clockwise:!t.counterclockwise,a=r.nodes().not(`:parent`);t.sort&&(a=a.sort(t.sort));for(var o=wr(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),s={x:o.x1+o.w/2,y:o.y1+o.h/2},c=(t.sweep===void 0?2*Math.PI-2*Math.PI/a.length:t.sweep)/Math.max(1,a.length-1),l,u=0,d=0;d1&&t.avoidOverlap){u*=1.75;var h=Math.cos(c)-Math.cos(0),g=Math.sin(c)-Math.sin(0),_=Math.sqrt(u*u/(h*h+g*g));l=Math.max(_,l)}return r.nodes().layoutPositions(this,t,function(e,n){var r=t.startAngle+n*c*(i?1:-1),a=l*Math.cos(r),o=l*Math.sin(r);return{x:s.x+a,y:s.y+o}}),this};var Wd={fit:!0,padding:30,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,height:void 0,width:void 0,spacingFactor:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function Gd(e){this.options=Z({},Wd,e)}Gd.prototype.run=function(){for(var e=this.options,t=e,n=t.counterclockwise===void 0?t.clockwise:!t.counterclockwise,r=e.cy,i=t.eles,a=i.nodes().not(`:parent`),o=wr(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()}),s={x:o.x1+o.w/2,y:o.y1+o.h/2},c=[],l=0,u=0;u0&&Math.abs(_[0].value-y.value)>=h&&(_=[],g.push(_)),_.push(y)}var b=l+t.minNodeSpacing;if(!t.avoidOverlap){var x=g.length>0&&g[0].length>1,S=(Math.min(o.w,o.h)/2-b)/(g.length+x?1:0);b=Math.min(b,S)}for(var C=0,w=0;w1&&t.avoidOverlap){var D=Math.cos(E)-Math.cos(0),O=Math.sin(E)-Math.sin(0),k=Math.sqrt(b*b/(D*D+O*O));C=Math.max(k,C)}T.r=C,C+=b}if(t.equidistant){for(var A=0,j=0,M=0;M=e.numIter||(nf(r,e),r.temperature*=e.coolingFactor,r.temperature=e.animationThreshold&&a(),Ut(u)):(hf(r,e),s())};u()}else{for(;l;)l=o(c),c++;hf(r,e),s()}return this},Jd.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.emit(`layoutstop`),this},Jd.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var Yd=function(e,t,n){for(var r=n.eles.edges(),i=n.eles.nodes(),a=wr(n.boundingBox?n.boundingBox:{x1:0,y1:0,w:e.width(),h:e.height()}),o={isCompound:e.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:i.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:r.size(),temperature:n.initialTemp,clientWidth:a.w,clientHeight:a.h,boundingBox:a},s=n.eles.components(),c={},l=0;l0){o.graphSet.push(C);for(var l=0;lr.count?0:r.graph},Zd=function(e,t,n,r){var i=r.graphSet[n];if(-10)var c=r.nodeOverlap*s,l=Math.sqrt(i*i+a*a),u=c*i/l,d=c*a/l;else var f=cf(e,i,a),p=cf(t,-1*i,-1*a),m=p.x-f.x,h=p.y-f.y,g=m*m+h*h,l=Math.sqrt(g),c=(e.nodeRepulsion+t.nodeRepulsion)/g,u=c*m/l,d=c*h/l;e.isLocked||(e.offsetX-=u,e.offsetY-=d),t.isLocked||(t.offsetX+=u,t.offsetY+=d)}},sf=function(e,t,n,r){if(n>0)var i=e.maxX-t.minX;else var i=t.maxX-e.minX;if(r>0)var a=e.maxY-t.minY;else var a=t.maxY-e.minY;return i>=0&&a>=0?Math.sqrt(i*i+a*a):0},cf=function(e,t,n){var r=e.positionX,i=e.positionY,a=e.height||1,o=e.width||1,s=n/t,c=a/o,l={};return t===0&&0n?(l.x=r,l.y=i+a/2,l):0t&&-1*c<=s&&s<=c?(l.x=r-o/2,l.y=i-o*n/2/t,l):0=c)?(l.x=r+a*t/2/n,l.y=i+a/2,l):0>n&&(s<=-1*c||s>=c)?(l.x=r-a*t/2/n,l.y=i-a/2,l):l},lf=function(e,t){for(var n=0;nn){var h=t.gravity*f/m,g=t.gravity*p/m;d.offsetX+=h,d.offsetY+=g}}}}},df=function(e,t){var n=[],r=0,i=-1;for(n.push.apply(n,e.graphSet[0]),i+=e.graphSet[0].length;r<=i;){var a=n[r++],o=e.idToIndex[a],s=e.layoutNodes[o],c=s.children;if(0n)var i={x:n*e/r,y:n*t/r};else var i={x:e,y:t};return i},mf=function(e,t){var n=e.parentId;if(n!=null){var r=t.layoutNodes[t.idToIndex[n]],i=!1;if((r.maxX==null||e.maxX+r.padRight>r.maxX)&&(r.maxX=e.maxX+r.padRight,i=!0),(r.minX==null||e.minX-r.padLeftr.maxY)&&(r.maxY=e.maxY+r.padBottom,i=!0),(r.minY==null||e.minY-r.padToph&&(f+=m+t.componentSpacing,d=0,p=0,m=0)}}},gf={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,condense:!1,rows:void 0,cols:void 0,position:function(e){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function _f(e){this.options=Z({},gf,e)}_f.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,i=r.nodes().not(`:parent`);t.sort&&(i=i.sort(t.sort));var a=wr(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()});if(a.h===0||a.w===0)r.nodes().layoutPositions(this,t,function(e){return{x:a.x1,y:a.y1}});else{var o=i.size(),s=Math.sqrt(o*a.h/a.w),c=Math.round(s),l=Math.round(a.w/a.h*s),u=function(e){if(e==null)return Math.min(c,l);Math.min(c,l)==c?c=e:l=e},d=function(e){if(e==null)return Math.max(c,l);Math.max(c,l)==c?c=e:l=e},f=t.rows,p=t.cols==null?t.columns:t.cols;if(f!=null&&p!=null)c=f,l=p;else if(f!=null&&p==null)c=f,l=Math.ceil(o/c);else if(f==null&&p!=null)l=p,c=Math.ceil(o/l);else if(l*c>o){var m=u(),h=d();(m-1)*h>=o?u(m-1):(h-1)*m>=o&&d(h-1)}else for(;l*c=o?d(_+1):u(g+1)}var v=a.w/l,y=a.h/c;if(t.condense&&(v=0,y=0),t.avoidOverlap)for(var b=0;b=l&&(j=0,A++)},N={},P=0;P(y=Gr(e,t,b[x],b[x+1],b[x+2],b[x+3])))return g(n,y),!0}else if(o.edgeType===`bezier`||o.edgeType===`multibezier`||o.edgeType===`self`||o.edgeType===`compound`){for(var b=o.allpts,x=0;x+5(y=Wr(e,t,b[x],b[x+1],b[x+2],b[x+3],b[x+4],b[x+5])))return g(n,y),!0}for(var h=h||r.source,v=v||r.target,S=i.getArrowWidth(c,d),C=[{name:`source`,x:o.arrowStartX,y:o.arrowStartY,angle:o.srcArrowAngle},{name:`target`,x:o.arrowEndX,y:o.arrowEndY,angle:o.tgtArrowAngle},{name:`mid-source`,x:o.midX,y:o.midY,angle:o.midsrcArrowAngle},{name:`mid-target`,x:o.midX,y:o.midY,angle:o.midtgtArrowAngle}],x=0;x0&&(_(h),_(v))}function y(e,t,n){return kn(e,t,n)}function b(n,r){var i=n._private,a=f,o=r?r+`-`:``;n.boundingBox();var s=i.labelBounds[r||`main`],c=n.pstyle(o+`label`).value;if(!(n.pstyle(`text-events`).strValue!==`yes`||!c)){var l=y(i.rscratch,`labelX`,r),u=y(i.rscratch,`labelY`,r),d=y(i.rscratch,`labelAngle`,r),p=n.pstyle(o+`text-margin-x`).pfValue,m=n.pstyle(o+`text-margin-y`).pfValue,h=s.x1-a-p,_=s.x2+a-p,v=s.y1-a-m,b=s.y2+a-m;if(d){var x=Math.cos(d),S=Math.sin(d),C=function(e,t){return e-=l,t-=u,{x:e*x-t*S+l,y:e*S+t*x+u}},w=C(h,v),T=C(h,b),E=C(_,v),D=C(_,b);if(Kr(e,t,[w.x+p,w.y+m,E.x+p,E.y+m,D.x+p,D.y+m,T.x+p,T.y+m]))return g(n),!0}else if(Nr(s,e,t))return g(n),!0}}for(var x=o.length-1;x>=0;x--){var S=o[x];S.isNode()?_(S)||b(S):v(S)||b(S)||b(S,`source`)||b(S,`target`)}return s},kf.getAllInBox=function(e,t,n,r){var i=this.getCachedZSortedEles().interactive,a=2/this.cy.zoom(),o=[],s=Math.min(e,n),c=Math.max(e,n),l=Math.min(t,r),u=Math.max(t,r);e=s,n=c,t=l,r=u;var d=wr({x1:e,y1:t,x2:n,y2:r}),f=[{x:d.x1,y:d.y1},{x:d.x2,y:d.y1},{x:d.x2,y:d.y2},{x:d.x1,y:d.y2}],p=[[f[0],f[1]],[f[1],f[2]],[f[2],f[3]],[f[3],f[0]]];function m(e,t,n){return kn(e,t,n)}function h(e,t){var n=e._private,r=a,i=``;e.boundingBox();var o=n.labelBounds.main;if(!o)return null;var s=m(n.rscratch,`labelX`,t),c=m(n.rscratch,`labelY`,t),l=m(n.rscratch,`labelAngle`,t),u=e.pstyle(i+`text-margin-x`).pfValue,d=e.pstyle(i+`text-margin-y`).pfValue,f=o.x1-r-u,p=o.x2+r-u,h=o.y1-r-d,g=o.y2+r-d;if(l){var _=Math.cos(l),v=Math.sin(l),y=function(e,t){return e-=s,t-=c,{x:e*_-t*v+s,y:e*v+t*_+c}};return[y(f,h),y(p,h),y(p,g),y(f,g)]}else return[{x:f,y:h},{x:p,y:h},{x:p,y:g},{x:f,y:g}]}function g(e,t,n,r){function i(e,t,n){return(n.y-e.y)*(t.x-e.x)>(t.y-e.y)*(n.x-e.x)}return i(e,n,r)!==i(t,n,r)&&i(e,t,n)!==i(e,t,r)}for(var _=0;_0?-(Math.PI-e.ang):Math.PI+e.ang},Qf=function(e,t,n,r,i){if(e===Yf?Zf(Pf,Nf):Xf(t,e,Nf),Xf(t,n,Pf),Ff=Nf.nx*Pf.ny-Nf.ny*Pf.nx,If=Nf.nx*Pf.nx-Nf.ny*-Pf.ny,zf=Math.asin(Math.max(-1,Math.min(1,Ff))),Math.abs(zf)<1e-6){jf=t.x,Mf=t.y,Vf=Uf=0;return}Lf=1,Rf=!1,If<0?zf<0?zf=Math.PI+zf:(zf=Math.PI-zf,Lf=-1,Rf=!0):zf>0&&(Lf=-1,Rf=!0),Uf=t.radius===void 0?r:t.radius,Bf=zf/2,Wf=Math.min(Nf.len/2,Pf.len/2),i?(Hf=Math.abs(Math.cos(Bf)*Uf/Math.sin(Bf)),Hf>Wf?(Hf=Wf,Vf=Math.abs(Hf*Math.sin(Bf)/Math.cos(Bf))):Vf=Uf):(Hf=Math.min(Wf,Uf),Vf=Math.abs(Hf*Math.sin(Bf)/Math.cos(Bf))),qf=t.x+Pf.nx*Hf,Jf=t.y+Pf.ny*Hf,jf=qf-Pf.ny*Vf*Lf,Mf=Jf+Pf.nx*Vf*Lf,Gf=t.x+Nf.nx*Hf,Kf=t.y+Nf.ny*Hf,Yf=t};function $f(e,t){t.radius===0?e.lineTo(t.cx,t.cy):e.arc(t.cx,t.cy,t.radius,t.startAngle,t.endAngle,t.counterClockwise)}function ep(e,t,n,r){var i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0;return r===0||t.radius===0?{cx:t.x,cy:t.y,radius:0,startX:t.x,startY:t.y,stopX:t.x,stopY:t.y,startAngle:void 0,endAngle:void 0,counterClockwise:void 0}:(Qf(e,t,n,r,i),{cx:jf,cy:Mf,radius:Vf,startX:Gf,startY:Kf,stopX:qf,stopY:Jf,startAngle:Nf.ang+Math.PI/2*Lf,endAngle:Pf.ang-Math.PI/2*Lf,counterClockwise:Rf})}var tp=.01,np=Math.sqrt(2*tp),rp={};rp.findMidptPtsEtc=function(e,t){var n=t.posPts,r=t.intersectionPts,i=t.vectorNormInverse,a,o=e.pstyle(`source-endpoint`),s=e.pstyle(`target-endpoint`),c=o.units!=null&&s.units!=null,l=function(e,t,n,r){var i=r-t,a=n-e,o=Math.sqrt(a*a+i*i);return{x:-i/o,y:a/o}};switch(e.pstyle(`edge-distances`).value){case`node-position`:a=n;break;case`intersection`:a=r;break;case`endpoints`:if(c){var u=G(this.manualEndptToPx(e.source()[0],o),2),d=u[0],f=u[1],p=G(this.manualEndptToPx(e.target()[0],s),2),m=p[0],h=p[1],g={x1:d,y1:f,x2:m,y2:h};i=l(d,f,m,h),a=g}else vn(`Edge ${e.id()} has edge-distances:endpoints specified without manual endpoints specified via source-endpoint and target-endpoint. Falling back on edge-distances:intersection (default).`),a=r;break}return{midptPts:a,vectorNormInverse:i}},rp.findHaystackPoints=function(e){for(var t=0;t0?Math.max(e-t,0):Math.min(e+t,0)},O=D(T,C),k=D(E,w),A=!1;_===l?g=Math.abs(O)>Math.abs(k)?i:r:_===c||_===s?(g=r,A=!0):(_===a||_===o)&&(g=i,A=!0);var j=g===r,M=j?k:O,N=j?E:T,P=gr(N),F=!1;!(A&&(y||x))&&(_===s&&N<0||_===c&&N>0||_===a&&N>0||_===o&&N<0)&&(P*=-1,M=P*Math.abs(M),F=!0);var I=y?(b<0?1+b:b)*M:(b<0?M:0)+b*P,L=function(e){return Math.abs(e)=Math.abs(M)},R=L(I),z=L(Math.abs(M)-Math.abs(I));if((R||z)&&!F)if(j){var B=Math.abs(N)<=f/2,V=Math.abs(T)<=p/2;if(B){var H=(u.x1+u.x2)/2;n.segpts=[H,u.y1,H,u.y2]}else if(V){var U=(u.y1+u.y2)/2;n.segpts=[u.x1,U,u.x2,U]}else n.segpts=[u.x1,u.y2]}else{var W=Math.abs(N)<=d/2,G=Math.abs(E)<=m/2;if(W){var K=(u.y1+u.y2)/2;n.segpts=[u.x1,K,u.x2,K]}else if(G){var ee=(u.x1+u.x2)/2;n.segpts=[ee,u.y1,ee,u.y2]}else n.segpts=[u.x2,u.y1]}else if(j){var te=u.y1+I+(h?f/2*P:0);n.segpts=[u.x1,te,u.x2,te]}else{var q=u.x1+I+(h?d/2*P:0);n.segpts=[q,u.y1,q,u.y2]}if(n.isRound){var ne=e.pstyle(`taxi-radius`).value,re=e.pstyle(`radius-type`).value[0]===`arc-radius`;n.radii=Array(n.segpts.length/2).fill(ne),n.isArcRadius=Array(n.segpts.length/2).fill(re)}},rp.tryToCorrectInvalidPoints=function(e,t){var n=e._private.rscratch;if(n.edgeType===`bezier`){var r=t.srcPos,i=t.tgtPos,a=t.srcW,o=t.srcH,s=t.tgtW,c=t.tgtH,l=t.srcShape,u=t.tgtShape,d=t.srcCornerRadius,f=t.tgtCornerRadius,p=t.srcRs,m=t.tgtRs,h=!X(n.startX)||!X(n.startY),g=!X(n.arrowStartX)||!X(n.arrowStartY),_=!X(n.endX)||!X(n.endY),v=!X(n.arrowEndX)||!X(n.arrowEndY),y=3*(this.getArrowWidth(e.pstyle(`width`).pfValue,e.pstyle(`arrow-scale`).value)*this.arrowShapeWidth),b=_r({x:n.ctrlpts[0],y:n.ctrlpts[1]},{x:n.startX,y:n.startY}),x=bh.poolIndex()){var g=m;m=h,h=g}var _=u.srcPos=m.position(),v=u.tgtPos=h.position(),y=u.srcW=m.outerWidth(),x=u.srcH=m.outerHeight(),S=u.tgtW=h.outerWidth(),C=u.tgtH=h.outerHeight(),w=u.srcShape=n.nodeShapes[t.getNodeShape(m)],T=u.tgtShape=n.nodeShapes[t.getNodeShape(h)],E=u.srcCornerRadius=m.pstyle(`corner-radius`).value===`auto`?`auto`:m.pstyle(`corner-radius`).pfValue,D=u.tgtCornerRadius=h.pstyle(`corner-radius`).value===`auto`?`auto`:h.pstyle(`corner-radius`).pfValue,O=u.tgtRs=h._private.rscratch,k=u.srcRs=m._private.rscratch;u.dirCounts={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0};for(var A=0;A=np||(W=Math.sqrt(Math.max(U*U,tp)+Math.max(H*H,tp)));var G=u.vector={x:U,y:H},K=u.vectorNorm={x:G.x/W,y:G.y/W},ee={x:-K.y,y:K.x};u.nodesOverlap=!X(W)||T.checkPoint(I[0],I[1],0,S,C,v.x,v.y,D,O)||w.checkPoint(R[0],R[1],0,y,x,_.x,_.y,E,k),u.vectorNormInverse=ee,d={nodesOverlap:u.nodesOverlap,dirCounts:u.dirCounts,calculatedIntersection:!0,hasBezier:u.hasBezier,hasUnbundled:u.hasUnbundled,eles:u.eles,srcPos:v,srcRs:O,tgtPos:_,tgtRs:k,srcW:S,srcH:C,tgtW:y,tgtH:x,srcIntn:z,tgtIntn:L,srcShape:T,tgtShape:w,posPts:{x1:V.x2,y1:V.y2,x2:V.x1,y2:V.y1},intersectionPts:{x1:B.x2,y1:B.y2,x2:B.x1,y2:B.y1},vector:{x:-G.x,y:-G.y},vectorNorm:{x:-K.x,y:-K.y},vectorNormInverse:{x:-ee.x,y:-ee.y}}}var te=F?d:u;M.nodesOverlap=te.nodesOverlap,M.srcIntn=te.srcIntn,M.tgtIntn=te.tgtIntn,M.isRound=N.startsWith(`round`),r&&(m.isParent()||m.isChild()||h.isParent()||h.isChild())&&(m.parents().anySame(h)||h.parents().anySame(m)||m.same(h)&&m.isParent())?t.findCompoundLoopPoints(j,te,A,P):m===h?t.findLoopPoints(j,te,A,P):N.endsWith(`segments`)?t.findSegmentsPoints(j,te):N.endsWith(`taxi`)?t.findTaxiPoints(j,te):N===`straight`||!P&&u.eles.length%2==1&&A===Math.floor(u.eles.length/2)?t.findStraightEdgePoints(j):t.findBezierPoints(j,te,A,P,F),t.findEndpoints(j),t.tryToCorrectInvalidPoints(j,te),t.checkForInvalidEdgeWarning(j),t.storeAllpts(j),t.storeEdgeProjections(j),t.calculateArrowAngles(j),t.recalculateEdgeLabelProjections(j),t.calculateLabelAngles(j)}},b=0;b0){var ne=s,re=vr(ne,cr(i)),ie=vr(ne,cr(q)),ae=re;ie2&&vr(ne,{x:q[2],y:q[3]})0){var ge=c,_e=vr(ge,cr(i)),ve=vr(ge,cr(he)),ye=_e;ve<_e&&(i=[he[0],he[1]],ye=ve),he.length>2&&vr(ge,{x:he[2],y:he[3]})=l||v){d={cp:h,segment:_};break}}if(d)break}var y=d.cp,b=d.segment,x=(l-f)/b.length,S=b.t1-b.t0,C=c?b.t0+S*x:b.t1-S*x;C=Cr(0,C,1),t=xr(y.p0,y.p1,y.p2,C),i=dp(y.p0,y.p1,y.p2,C);break;case`straight`:case`segments`:case`haystack`:for(var w=0,T,E,D,O,k=r.allpts.length,A=0;A+3=l));A+=2);var j=(l-E)/T;j=Cr(0,j,1),t=Sr(D,O,j),i=up(D,O);break}o(`labelX`,n,t.x),o(`labelY`,n,t.y),o(`labelAutoAngle`,n,i)}};c(`source`),c(`target`),this.applyLabelDimensions(e)}},cp.applyLabelDimensions=function(e){this.applyPrefixedLabelDimensions(e),e.isEdge()&&(this.applyPrefixedLabelDimensions(e,`source`),this.applyPrefixedLabelDimensions(e,`target`))},cp.applyPrefixedLabelDimensions=function(e,t){var n=e._private,r=this.getLabelText(e,t),i=tn(r,e._private.labelDimsKey);if(kn(n.rscratch,`prefixedLabelDimsKey`,t)!==i){An(n.rscratch,`prefixedLabelDimsKey`,t,i);var a=this.calculateLabelDimensions(e,r),o=e.pstyle(`line-height`).pfValue,s=e.pstyle(`text-wrap`).strValue,c=kn(n.rscratch,`labelWrapCachedLines`,t)||[],l=s===`wrap`?Math.max(c.length,1):1,u=a.height/l,d=u*o,f=a.width,p=a.height+(l-1)*(o-1)*u;An(n.rstyle,`labelWidth`,t,f),An(n.rscratch,`labelWidth`,t,f),An(n.rstyle,`labelHeight`,t,p),An(n.rscratch,`labelHeight`,t,p),An(n.rscratch,`labelLineHeight`,t,d)}},cp.getLabelText=function(e,t){var n=e._private,r=t?t+`-`:``,i=e.pstyle(r+`label`).strValue,a=e.pstyle(`text-transform`).value,o=function(e,r){return r?(An(n.rscratch,e,t,r),r):kn(n.rscratch,e,t)};if(!i)return``;a==`none`||(a==`uppercase`?i=i.toUpperCase():a==`lowercase`&&(i=i.toLowerCase()));var s=e.pstyle(`text-wrap`).value;if(s===`wrap`){var c=o(`labelKey`);if(c!=null&&o(`labelWrapKey`)===c)return o(`labelWrapCachedText`);for(var l=`​`,u=i.split(` +`),d=e.pstyle(`text-max-width`).pfValue,f=e.pstyle(`text-overflow-wrap`).value===`anywhere`,p=[],m=/[\s\u200b]+|$/g,h=0;hd){var v=g.matchAll(m),y=``,b=0,x=z(v),S;try{for(x.s();!(S=x.n()).done;){var C=S.value,w=C[0],T=g.substring(b,C.index);b=C.index+w.length;var E=y.length===0?T:y+T+w;this.calculateLabelDimensions(e,E).width<=d?y+=T+w:(y&&p.push(y),y=T+w)}}catch(e){x.e(e)}finally{x.f()}y.match(/^[\s\u200b]+$/)||p.push(y)}else p.push(g)}o(`labelWrapCachedLines`,p),i=o(`labelWrapCachedText`,p.join(` +`)),o(`labelWrapKey`,c)}else if(s===`ellipsis`){var D=e.pstyle(`text-max-width`).pfValue,O=``,k=`…`,A=!1;if(this.calculateLabelDimensions(e,i).widthD);j++)O+=i[j],j===i.length-1&&(A=!0);return A||(O+=k),O}return i},cp.getLabelJustification=function(e){var t=e.pstyle(`text-justification`).strValue,n=e.pstyle(`text-halign`).strValue;if(t===`auto`)if(e.isNode())switch(n){case`left`:return`right`;case`right`:return`left`;default:return`center`}else return`center`;else return t},cp.calculateLabelDimensions=function(e,t){var n=this.cy.window().document,r=0,i=e.pstyle(`font-style`).strValue,a=e.pstyle(`font-size`).pfValue,o=e.pstyle(`font-family`).strValue,s=e.pstyle(`font-weight`).strValue,c=this.labelCalcCanvas,l=this.labelCalcCanvasContext;if(!c){c=this.labelCalcCanvas=n.createElement(`canvas`),l=this.labelCalcCanvasContext=c.getContext(`2d`);var u=c.style;u.position=`absolute`,u.left=`-9999px`,u.top=`-9999px`,u.zIndex=`-1`,u.visibility=`hidden`,u.pointerEvents=`none`}l.font=`${i} ${s} ${a}px ${o}`;for(var d=0,f=0,p=t.split(` +`),m=0;m1&&arguments[1]!==void 0?arguments[1]:!0;if(t.merge(e),n)for(var r=0;r=e.desktopTapThreshold2}var T=a(t);b&&(e.hoverData.tapholdCancelled=!0);var D=function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];t.length===0?(t.push(v[0]),t.push(v[1])):(t[0]+=v[0],t[1]+=v[1])};n=!0,i(p,[`mousemove`,`vmousemove`,`tapdrag`],t,{x:l[0],y:l[1]});var O=function(e){return{originalEvent:t,type:e,position:{x:l[0],y:l[1]}}},k=function(){e.data.bgActivePosistion=void 0,e.hoverData.selecting||r.emit(O(`boxstart`)),f[4]=1,e.hoverData.selecting=!0,e.redrawHint(`select`,!0),e.redraw()};if(e.hoverData.which===3){if(b){var A=O(`cxtdrag`);g?g.emit(A):r.emit(A),e.hoverData.cxtDragged=!0,(!e.hoverData.cxtOver||p!==e.hoverData.cxtOver)&&(e.hoverData.cxtOver&&e.hoverData.cxtOver.emit(O(`cxtdragout`)),e.hoverData.cxtOver=p,p&&p.emit(O(`cxtdragover`)))}}else if(e.hoverData.dragging){if(n=!0,r.panningEnabled()&&r.userPanningEnabled()){var j;if(e.hoverData.justStartedPan){var M=e.hoverData.mdownPos;j={x:(l[0]-M[0])*s,y:(l[1]-M[1])*s},e.hoverData.justStartedPan=!1}else j={x:v[0]*s,y:v[1]*s};r.panBy(j),r.emit(O(`dragpan`)),e.hoverData.dragged=!0}l=e.projectIntoViewport(t.clientX,t.clientY)}else if(f[4]==1&&(g==null||g.pannable()))b&&(!e.hoverData.dragging&&r.boxSelectionEnabled()&&(T||!r.panningEnabled()||!r.userPanningEnabled())?k():!e.hoverData.selecting&&r.panningEnabled()&&r.userPanningEnabled()&&o(g,e.hoverData.downs)&&(e.hoverData.dragging=!0,e.hoverData.justStartedPan=!0,f[4]=0,e.data.bgActivePosistion=cr(u),e.redrawHint(`select`,!0),e.redraw()),g&&g.pannable()&&g.active()&&g.unactivate());else{if(g&&g.pannable()&&g.active()&&g.unactivate(),(!g||!g.grabbed())&&p!=m&&(m&&i(m,[`mouseout`,`tapdragout`],t,{x:l[0],y:l[1]}),p&&i(p,[`mouseover`,`tapdragover`],t,{x:l[0],y:l[1]}),e.hoverData.last=p),g)if(b){if(r.boxSelectionEnabled()&&T)g&&g.grabbed()&&(_(y),g.emit(O(`freeon`)),y.emit(O(`free`)),e.dragData.didDrag&&(g.emit(O(`dragfreeon`)),y.emit(O(`dragfree`)))),k();else if(g&&g.grabbed()&&e.nodeIsDraggable(g)){var N=!e.dragData.didDrag;N&&e.redrawHint(`eles`,!0),e.dragData.didDrag=!0,e.hoverData.draggingEles||h(y,{inDragLayer:!0});var P={x:0,y:0};if(X(v[0])&&X(v[1])&&(P.x+=v[0],P.y+=v[1],N)){var F=e.hoverData.dragDelta;F&&X(F[0])&&X(F[1])&&(P.x+=F[0],P.y+=F[1])}e.hoverData.draggingEles=!0,y.silentShift(P).emit(O(`position`)).emit(O(`drag`)),e.redrawHint(`drag`,!0),e.redraw()}}else D();n=!0}if(f[2]=l[0],f[3]=l[1],n)return t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),!1}},!1);var O,k,A;e.registerBinding(t,`mouseup`,function(t){if(!(e.hoverData.which===1&&t.which!==1&&e.hoverData.capture)&&e.hoverData.capture){e.hoverData.capture=!1;var r=e.cy,o=e.projectIntoViewport(t.clientX,t.clientY),s=e.selection,c=e.findNearestElement(o[0],o[1],!0,!1),l=e.dragData.possibleDragElements,u=e.hoverData.down,d=a(t);e.data.bgActivePosistion&&(e.redrawHint(`select`,!0),e.redraw()),e.hoverData.tapholdCancelled=!0,e.data.bgActivePosistion=void 0,u&&u.unactivate();var f=function(e){return{originalEvent:t,type:e,position:{x:o[0],y:o[1]}}};if(e.hoverData.which===3){var p=f(`cxttapend`);if(u?u.emit(p):r.emit(p),!e.hoverData.cxtDragged){var m=f(`cxttap`);u?u.emit(m):r.emit(m)}e.hoverData.cxtDragged=!1,e.hoverData.which=null}else if(e.hoverData.which===1){if(i(c,[`mouseup`,`tapend`,`vmouseup`],t,{x:o[0],y:o[1]}),!e.dragData.didDrag&&!e.hoverData.dragged&&!e.hoverData.selecting&&!e.hoverData.isOverThresholdDrag&&(i(u,[`click`,`tap`,`vclick`],t,{x:o[0],y:o[1]}),k=!1,t.timeStamp-A<=r.multiClickDebounceTime()?(O&&clearTimeout(O),k=!0,A=null,i(u,[`dblclick`,`dbltap`,`vdblclick`],t,{x:o[0],y:o[1]})):(O=setTimeout(function(){k||i(u,[`oneclick`,`onetap`,`voneclick`],t,{x:o[0],y:o[1]})},r.multiClickDebounceTime()),A=t.timeStamp)),u==null&&!e.dragData.didDrag&&!e.hoverData.selecting&&!e.hoverData.dragged&&!a(t)&&(r.$(n).unselect([`tapunselect`]),l.length>0&&e.redrawHint(`eles`,!0),e.dragData.possibleDragElements=l=r.collection()),c==u&&!e.dragData.didDrag&&!e.hoverData.selecting&&c!=null&&c._private.selectable&&(e.hoverData.dragging||(r.selectionType()===`additive`||d?c.selected()?c.unselect([`tapunselect`]):c.select([`tapselect`]):d||(r.$(n).unmerge(c).unselect([`tapunselect`]),c.select([`tapselect`]))),e.redrawHint(`eles`,!0)),e.hoverData.selecting){var h=r.collection(e.getAllInBox(s[0],s[1],s[2],s[3]));e.redrawHint(`select`,!0),h.length>0&&e.redrawHint(`eles`,!0),r.emit(f(`boxend`)),r.selectionType()===`additive`||d||r.$(n).unmerge(h).unselect(),h.emit(f(`box`)).stdFilter(function(e){return e.selectable()&&!e.selected()}).select().emit(f(`boxselect`)),e.redraw()}if(e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint(`select`,!0),e.redrawHint(`eles`,!0),e.redraw()),!s[4]){e.redrawHint(`drag`,!0),e.redrawHint(`eles`,!0);var g=u&&u.grabbed();_(l),g&&(u.emit(f(`freeon`)),l.emit(f(`free`)),e.dragData.didDrag&&(u.emit(f(`dragfreeon`)),l.emit(f(`dragfree`))))}}s[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.hoverData.isOverThresholdDrag=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[],e.hoverData.mdownPos=null,e.hoverData.mdownGPos=null,e.hoverData.which=null}},!1);var j=[],M=4,N,P=1e5,F=function(e,t){for(var n=0;n=M){var i=j;if(N=F(i,5),!N){var a=Math.abs(i[0]);N=I(i)&&a>5}if(N)for(var o=0;o5&&(r=gr(r)*5),f=r/-250,N&&(f/=P,f*=3),f*=e.wheelSensitivity,t.deltaMode===1&&(f*=33);var p=s.zoom()*10**f;t.type===`gesturechange`&&(p=e.gestureStartZoom*t.scale),s.zoom({level:p,renderedPosition:{x:d[0],y:d[1]}}),s.emit({type:t.type===`gesturechange`?`pinchzoom`:`scrollzoom`,originalEvent:t,position:{x:u[0],y:u[1]}})}}}};e.registerBinding(e.container,`wheel`,L,!0),e.registerBinding(t,`scroll`,function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout(function(){e.scrollingPage=!1},250)},!0),e.registerBinding(e.container,`gesturestart`,function(t){e.gestureStartZoom=e.cy.zoom(),e.hasTouchStarted||t.preventDefault()},!0),e.registerBinding(e.container,`gesturechange`,function(t){e.hasTouchStarted||L(t)},!0),e.registerBinding(e.container,`mouseout`,function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:`mouseout`,position:{x:n[0],y:n[1]}})},!1),e.registerBinding(e.container,`mouseover`,function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:`mouseover`,position:{x:n[0],y:n[1]}})},!1);var R,z,B,V,H,U,W,G,K,ee,te,q,ne,re=function(e,t,n,r){return Math.sqrt((n-e)*(n-e)+(r-t)*(r-t))},ie=function(e,t,n,r){return(n-e)*(n-e)+(r-t)*(r-t)},ae;e.registerBinding(e.container,`touchstart`,ae=function(t){if(e.hasTouchStarted=!0,E(t)){y(),e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,r=e.touchData.now,a=e.touchData.earlier;if(t.touches[0]){var o=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);r[0]=o[0],r[1]=o[1]}if(t.touches[1]){var o=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);r[2]=o[0],r[3]=o[1]}if(t.touches[2]){var o=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);r[4]=o[0],r[5]=o[1]}var s=function(e){return{originalEvent:t,type:e,position:{x:r[0],y:r[1]}}};if(t.touches[1]){e.touchData.singleTouchMoved=!0,_(e.dragData.touchDragEles);var c=e.findContainerClientCoords();K=c[0],ee=c[1],te=c[2],q=c[3],R=t.touches[0].clientX-K,z=t.touches[0].clientY-ee,B=t.touches[1].clientX-K,V=t.touches[1].clientY-ee,ne=0<=R&&R<=te&&0<=B&&B<=te&&0<=z&&z<=q&&0<=V&&V<=q;var l=n.pan(),u=n.zoom();H=re(R,z,B,V),U=ie(R,z,B,V),W=[(R+B)/2,(z+V)/2],G=[(W[0]-l.x)/u,(W[1]-l.y)/u];var f=200,p=f*f;if(U=1){for(var w=e.touchData.startPosition=[null,null,null,null,null,null],T=0;T=e.touchTapThreshold2}if(n&&e.touchData.cxt){t.preventDefault();var x=t.touches[0].clientX-K,S=t.touches[0].clientY-ee,C=t.touches[1].clientX-K,w=t.touches[1].clientY-ee,T=ie(x,S,C,w),D=T/U,O=150,k=O*O,A=1.5;if(D>=A*A||T>=k){e.touchData.cxt=!1,e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var j=d(`cxttapend`);e.touchData.start?(e.touchData.start.unactivate().emit(j),e.touchData.start=null):a.emit(j)}}if(n&&e.touchData.cxt){var j=d(`cxtdrag`);e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0),e.touchData.start?e.touchData.start.emit(j):a.emit(j),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var M=e.findNearestElement(s[0],s[1],!0,!0);(!e.touchData.cxtOver||M!==e.touchData.cxtOver)&&(e.touchData.cxtOver&&e.touchData.cxtOver.emit(d(`cxtdragout`)),e.touchData.cxtOver=M,M&&M.emit(d(`cxtdragover`)))}else if(n&&t.touches[2]&&a.boxSelectionEnabled())t.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting||a.emit(d(`boxstart`)),e.touchData.selecting=!0,e.touchData.didSelect=!0,r[4]=1,!r||r.length===0||r[0]===void 0?(r[0]=(s[0]+s[2]+s[4])/3,r[1]=(s[1]+s[3]+s[5])/3,r[2]=(s[0]+s[2]+s[4])/3+1,r[3]=(s[1]+s[3]+s[5])/3+1):(r[2]=(s[0]+s[2]+s[4])/3,r[3]=(s[1]+s[3]+s[5])/3),e.redrawHint(`select`,!0),e.redraw();else if(n&&t.touches[1]&&!e.touchData.didSelect&&a.zoomingEnabled()&&a.panningEnabled()&&a.userZoomingEnabled()&&a.userPanningEnabled()){t.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var N=e.dragData.touchDragEles;if(N){e.redrawHint(`drag`,!0);for(var P=0;P0&&!e.hoverData.draggingEles&&!e.swipePanning&&e.data.bgActivePosistion!=null&&(e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0),e.redraw())}},!1);var se;e.registerBinding(t,`touchcancel`,se=function(t){var n=e.touchData.start;e.touchData.capture=!1,n&&n.unactivate()});var ce,le,J,ue;if(e.registerBinding(t,`touchend`,ce=function(t){var r=e.touchData.start;if(e.touchData.capture)t.touches.length===0&&(e.touchData.capture=!1),t.preventDefault();else return;var a=e.selection;e.swipePanning=!1,e.hoverData.draggingEles=!1;var o=e.cy,s=o.zoom(),c=e.touchData.now,l=e.touchData.earlier;if(t.touches[0]){var u=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);c[0]=u[0],c[1]=u[1]}if(t.touches[1]){var u=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);c[2]=u[0],c[3]=u[1]}if(t.touches[2]){var u=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);c[4]=u[0],c[5]=u[1]}var d=function(e){return{originalEvent:t,type:e,position:{x:c[0],y:c[1]}}};r&&r.unactivate();var f;if(e.touchData.cxt){if(f=d(`cxttapend`),r?r.emit(f):o.emit(f),!e.touchData.cxtDragged){var p=d(`cxttap`);r?r.emit(p):o.emit(p)}e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!1,e.touchData.start=null,e.redraw();return}if(!t.touches[2]&&o.boxSelectionEnabled()&&e.touchData.selecting){e.touchData.selecting=!1;var m=o.collection(e.getAllInBox(a[0],a[1],a[2],a[3]));a[0]=void 0,a[1]=void 0,a[2]=void 0,a[3]=void 0,a[4]=0,e.redrawHint(`select`,!0),o.emit(d(`boxend`)),m.emit(d(`box`)).stdFilter(function(e){return e.selectable()&&!e.selected()}).select().emit(d(`boxselect`)),m.nonempty()&&e.redrawHint(`eles`,!0),e.redraw()}if(r?.unactivate(),t.touches[2])e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);else if(!t.touches[1]&&!t.touches[0]&&!t.touches[0]){e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var h=e.dragData.touchDragEles;if(r!=null){var g=r._private.grabbed;_(h),e.redrawHint(`drag`,!0),e.redrawHint(`eles`,!0),g&&(r.emit(d(`freeon`)),h.emit(d(`free`)),e.dragData.didDrag&&(r.emit(d(`dragfreeon`)),h.emit(d(`dragfree`)))),i(r,[`touchend`,`tapend`,`vmouseup`,`tapdragout`],t,{x:c[0],y:c[1]}),r.unactivate(),e.touchData.start=null}else i(e.findNearestElement(c[0],c[1],!0,!0),[`touchend`,`tapend`,`vmouseup`,`tapdragout`],t,{x:c[0],y:c[1]});var v=e.touchData.startPosition[0]-c[0],y=v*v,b=e.touchData.startPosition[1]-c[1],x=(y+b*b)*s*s;e.touchData.singleTouchMoved||(r||o.$(`:selected`).unselect([`tapunselect`]),i(r,[`tap`,`vclick`],t,{x:c[0],y:c[1]}),le=!1,t.timeStamp-ue<=o.multiClickDebounceTime()?(J&&clearTimeout(J),le=!0,ue=null,i(r,[`dbltap`,`vdblclick`],t,{x:c[0],y:c[1]})):(J=setTimeout(function(){le||i(r,[`onetap`,`voneclick`],t,{x:c[0],y:c[1]})},o.multiClickDebounceTime()),ue=t.timeStamp)),r!=null&&!e.dragData.didDrag&&r._private.selectable&&x`u`){var de=[],Y=function(e){return{clientX:e.clientX,clientY:e.clientY,force:1,identifier:e.pointerId,pageX:e.pageX,pageY:e.pageY,radiusX:e.width/2,radiusY:e.height/2,screenX:e.screenX,screenY:e.screenY,target:e.target}},fe=function(e){return{event:e,touch:Y(e)}},pe=function(e){de.push(fe(e))},me=function(e){for(var t=0;t0)return l[0]}return null},p=Object.keys(d),m=0;m0?d:zr(i,a,e,t,n,r,o,s)},checkPoint:function(e,t,n,r,i,a,o,s){s=s===`auto`?li(r,i):s;var c=2*s;if(qr(e,t,this.points,a,o,r,i-c,[0,-1],n)||qr(e,t,this.points,a,o,r-c,i,[0,-1],n))return!0;var l=r/2+2*n,u=i/2+2*n;return!!(Kr(e,t,[a-l,o-u,a-l,o,a+l,o,a+l,o-u])||Qr(e,t,c,c,a+r/2-s,o+i/2-s,n)||Qr(e,t,c,c,a-r/2+s,o+i/2-s,n))}}},bp.registerNodeShapes=function(){var e=this.nodeShapes={},t=this;this.generateEllipse(),this.generatePolygon(`triangle`,oi(3,0)),this.generateRoundPolygon(`round-triangle`,oi(3,0)),this.generatePolygon(`rectangle`,oi(4,0)),e.square=e.rectangle,this.generateRoundRectangle(),this.generateCutRectangle(),this.generateBarrel(),this.generateBottomRoundrectangle();var n=[0,1,1,0,0,-1,-1,0];this.generatePolygon(`diamond`,n),this.generateRoundPolygon(`round-diamond`,n),this.generatePolygon(`pentagon`,oi(5,0)),this.generateRoundPolygon(`round-pentagon`,oi(5,0)),this.generatePolygon(`hexagon`,oi(6,0)),this.generateRoundPolygon(`round-hexagon`,oi(6,0)),this.generatePolygon(`heptagon`,oi(7,0)),this.generateRoundPolygon(`round-heptagon`,oi(7,0)),this.generatePolygon(`octagon`,oi(8,0)),this.generateRoundPolygon(`round-octagon`,oi(8,0));var r=Array(20),i=ci(5,0),a=ci(5,Math.PI/5),o=.5*(3-Math.sqrt(5));o*=1.57;for(var s=0;s=e.deqFastCost*h)break}else if(i){if(p>=e.deqCost*c||p>=e.deqAvgCost*s)break}else if(m>=e.deqNoDrawCost*Tp)break;var g=e.deq(t,d,u);if(g.length>0)for(var _=0;_0&&(e.onDeqd(t,l),!i&&e.shouldRedraw(t,l,d,u)&&r())},a=e.priority||hn;n.beforeRender(i,a(t))}}}},Dp=function(){function e(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:pn;I(this,e),this.idsByKey=new jn,this.keyForId=new jn,this.cachesByLvl=new jn,this.lvls=[],this.getKey=t,this.doesEleInvalidateKey=n}return R(e,[{key:`getIdsFor`,value:function(e){e??gn(`Can not get id list for null key`);var t=this.idsByKey,n=this.idsByKey.get(e);return n||(n=new Pn,t.set(e,n)),n}},{key:`addIdForKey`,value:function(e,t){e!=null&&this.getIdsFor(e).add(t)}},{key:`deleteIdForKey`,value:function(e,t){e!=null&&this.getIdsFor(e).delete(t)}},{key:`getNumberOfIdsForKey`,value:function(e){return e==null?0:this.getIdsFor(e).size}},{key:`updateKeyMappingFor`,value:function(e){var t=e.id(),n=this.keyForId.get(t),r=this.getKey(e);this.deleteIdForKey(n,t),this.addIdForKey(r,t),this.keyForId.set(t,r)}},{key:`deleteKeyMappingFor`,value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteIdForKey(n,t),this.keyForId.delete(t)}},{key:`keyHasChangedFor`,value:function(e){var t=e.id();return this.keyForId.get(t)!==this.getKey(e)}},{key:`isInvalid`,value:function(e){return this.keyHasChangedFor(e)||this.doesEleInvalidateKey(e)}},{key:`getCachesAt`,value:function(e){var t=this.cachesByLvl,n=this.lvls,r=t.get(e);return r||(r=new jn,t.set(e,r),n.push(e)),r}},{key:`getCache`,value:function(e,t){return this.getCachesAt(t).get(e)}},{key:`get`,value:function(e,t){var n=this.getKey(e),r=this.getCache(n,t);return r!=null&&this.updateKeyMappingFor(e),r}},{key:`getForCachedKey`,value:function(e,t){var n=this.keyForId.get(e.id());return this.getCache(n,t)}},{key:`hasCache`,value:function(e,t){return this.getCachesAt(t).has(e)}},{key:`has`,value:function(e,t){var n=this.getKey(e);return this.hasCache(n,t)}},{key:`setCache`,value:function(e,t,n){n.key=e,this.getCachesAt(t).set(e,n)}},{key:`set`,value:function(e,t,n){var r=this.getKey(e);this.setCache(r,t,n),this.updateKeyMappingFor(e)}},{key:`deleteCache`,value:function(e,t){this.getCachesAt(t).delete(e)}},{key:`delete`,value:function(e,t){var n=this.getKey(e);this.deleteCache(n,t)}},{key:`invalidateKey`,value:function(e){var t=this;this.lvls.forEach(function(n){return t.deleteCache(e,n)})}},{key:`invalidate`,value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteKeyMappingFor(e);var r=this.doesEleInvalidateKey(e);return r&&this.invalidateKey(n),r||this.getNumberOfIdsForKey(n)===0}}])}(),Op=25,kp=50,Ap=-4,jp=3,Mp=7.99,Np=8,Pp=1024,Fp=1024,Ip=1024,Lp=.2,Rp=.8,zp=10,Bp=.15,Vp=.1,Hp=.9,Up=.9,Wp=100,Gp=1,Kp={dequeue:`dequeue`,downscale:`downscale`,highQuality:`highQuality`},qp=Tn({getKey:null,doesEleInvalidateKey:pn,drawElement:null,getBoundingBox:null,getRotationPoint:null,getRotationOffset:null,isVisible:fn,allowEdgeTxrCaching:!0,allowParentTxrCaching:!0}),Jp=function(e,t){var n=this;n.renderer=e,n.onDequeues=[];var r=qp(t);Z(n,r),n.lookup=new Dp(r.getKey,r.doesEleInvalidateKey),n.setupDequeueing()},Yp=Jp.prototype;Yp.reasons=Kp,Yp.getTextureQueue=function(e){var t=this;return t.eleImgCaches=t.eleImgCaches||{},t.eleImgCaches[e]=t.eleImgCaches[e]||[]},Yp.getRetiredTextureQueue=function(e){var t=this,n=t.eleImgCaches.retired=t.eleImgCaches.retired||{};return n[e]=n[e]||[]},Yp.getElementQueue=function(){var e=this;return e.eleCacheQueue=e.eleCacheQueue||new Gn(function(e,t){return t.reqs-e.reqs})},Yp.getElementKeyToQueue=function(){var e=this;return e.eleKeyToCacheQueue=e.eleKeyToCacheQueue||{}},Yp.getElement=function(e,t,n,r,i){var a=this,o=this.renderer,s=o.cy.zoom(),c=this.lookup;if(!t||t.w===0||t.h===0||isNaN(t.w)||isNaN(t.h)||!e.visible()||e.removed()||!a.allowEdgeTxrCaching&&e.isEdge()||!a.allowParentTxrCaching&&e.isParent())return null;if(r??=Math.ceil(hr(s*n)),r=Mp||r>jp)return null;var l=2**r,u=t.h*l,d=t.w*l,f=o.eleTextBiggerThanMin(e,l);if(!this.isVisible(e,f))return null;var p=c.get(e,r);if(p&&p.invalidated&&(p.invalidated=!1,p.texture.invalidatedWidth-=p.width),p)return p;var m=u<=Op?Op:u<=kp?kp:Math.ceil(u/kp)*kp;if(u>Ip||d>Fp)return null;var h=a.getTextureQueue(m),g=h[h.length-2],_=function(){return a.recycleTexture(m,d)||a.addTexture(m,d)};g||=h[h.length-1],g||=_(),g.width-g.usedWidthr;D--)T=a.getElement(e,t,n,D,Kp.downscale);E()}else return a.queueElement(e,S.level-1),S;else{var O;if(!y&&!b&&!x)for(var k=r-1;k>=Ap;k--){var A=c.get(e,k);if(A){O=A;break}}if(v(O))return a.queueElement(e,r),O;g.context.translate(g.usedWidth,0),g.context.scale(l,l),this.drawElement(g.context,e,t,f,!1),g.context.scale(1/l,1/l),g.context.translate(-g.usedWidth,0)}return p={x:g.usedWidth,texture:g,level:r,scale:l,width:d,height:u,scaledLabelShown:f},g.usedWidth+=Math.ceil(d+Np),g.eleCaches.push(p),c.set(e,r,p),a.checkTextureFullness(g),p},Yp.invalidateElements=function(e){for(var t=0;t=Lp*e.width&&this.retireTexture(e)},Yp.checkTextureFullness=function(e){var t=this.getTextureQueue(e.height);e.usedWidth/e.width>Rp&&e.fullnessChecks>=zp?En(t,e):e.fullnessChecks++},Yp.retireTexture=function(e){var t=this,n=e.height,r=t.getTextureQueue(n),i=this.lookup;En(r,e),e.retired=!0;for(var a=e.eleCaches,o=0;o=t)return o.retired=!1,o.usedWidth=0,o.invalidatedWidth=0,o.fullnessChecks=0,Dn(o.eleCaches),o.context.setTransform(1,0,0,1,0,0),o.context.clearRect(0,0,o.width,o.height),En(i,o),r.push(o),o}},Yp.queueElement=function(e,t){var n=this,r=n.getElementQueue(),i=n.getElementKeyToQueue(),a=this.getKey(e),o=i[a];if(o)o.level=Math.max(o.level,t),o.eles.merge(e),o.reqs++,r.updateItem(o);else{var s={eles:e.spawn().merge(e),level:t,reqs:1,key:a};r.push(s),i[a]=s}},Yp.dequeue=function(e){for(var t=this,n=t.getElementQueue(),r=t.getElementKeyToQueue(),i=[],a=t.lookup,o=0;o0;o++){var s=n.pop(),c=s.key,l=s.eles[0],u=a.hasCache(l,s.level);if(r[c]=null,!u){i.push(s);var d=t.getBoundingBox(l);t.getElement(l,d,e,s.level,Kp.dequeue)}}return i},Yp.removeFromQueue=function(e){var t=this,n=t.getElementQueue(),r=t.getElementKeyToQueue(),i=this.getKey(e),a=r[i];a!=null&&(a.eles.length===1?(a.reqs=dn,n.updateItem(a),n.pop(),r[i]=null):a.eles.unmerge(e))},Yp.onDequeue=function(e){this.onDequeues.push(e)},Yp.offDequeue=function(e){En(this.onDequeues,e)},Yp.setupDequeueing=Ep.setupDequeueing({deqRedrawThreshold:Wp,deqCost:Bp,deqAvgCost:Vp,deqNoDrawCost:Hp,deqFastCost:Up,deq:function(e,t,n){return e.dequeue(t,n)},onDeqd:function(e,t){for(var n=0;n=$p||n>Qp)return null}r.validateLayersElesOrdering(n,e);var o=r.layersByLevel,s=2**n,c=o[n]=o[n]||[],l,u=r.levelIsComplete(n,e),d,f=function(){var t=function(t){if(r.validateLayersElesOrdering(t,e),r.levelIsComplete(t,e))return d=o[t],!0},i=function(e){if(!d)for(var r=n+e;Zp<=r&&r<=Qp&&!t(r);r+=e);};i(1),i(-1);for(var a=c.length-1;a>=0;a--){var s=c[a];s.invalid&&En(c,s)}};if(!u)f();else return c;var p=function(){if(!l){l=wr();for(var t=0;tlm||a>lm||i*a>cm)return null;var o=r.makeLayer(l,n);if(t!=null){var u=c.indexOf(t)+1;c.splice(u,0,o)}else (e.insert===void 0||e.insert)&&c.unshift(o);return o};if(r.skipping&&!a)return null;for(var h=null,g=e.length/Xp,_=!a,v=0;v=g||!Fr(h.bb,y.boundingBox()))&&(h=m({insert:!0,after:h}),!h))return null;d||_?r.queueLayer(h,y):r.drawEleInLayer(h,y,n,t),h.eles.push(y),x[n]=h}return d||(_?null:c)},fm.getEleLevelForLayerLevel=function(e,t){return e},fm.drawEleInLayer=function(e,t,n,r){var i=this,a=this.renderer,o=e.context,s=t.boundingBox();s.w===0||s.h===0||!t.visible()||(n=i.getEleLevelForLayerLevel(n,r),a.setImgSmoothing(o,!1),a.drawCachedElement(o,t,null,null,n,um),a.setImgSmoothing(o,!0))},fm.levelIsComplete=function(e,t){var n=this.layersByLevel[e];if(!n||n.length===0)return!1;for(var r=0,i=0;i0||a.invalid)return!1;r+=a.eles.length}return r===t.length},fm.validateLayersElesOrdering=function(e,t){var n=this.layersByLevel[e];if(n)for(var r=0;r0){t=!0;break}}return t},fm.invalidateElements=function(e){var t=this;e.length!==0&&(t.lastInvalidationTime=Wt(),!(e.length===0||!t.haveLayers())&&t.updateElementsInLayers(e,function(e,n,r){t.invalidateLayer(e)}))},fm.invalidateLayer=function(e){if(this.lastInvalidationTime=Wt(),!e.invalid){var t=e.level,n=e.eles,r=this.layersByLevel[t];En(r,e),e.elesQueue=[],e.invalid=!0,e.replacement&&(e.replacement.invalid=!0);for(var i=0;i3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,o=this,s=t._private.rscratch;if(!(a&&!t.visible())&&!(s.badLine||s.allpts==null||isNaN(s.allpts[0]))){var c;n&&(c=n,e.translate(-c.x1,-c.y1));var l=a?t.pstyle(`opacity`).value:1,u=a?t.pstyle(`line-opacity`).value:1,d=t.pstyle(`curve-style`).value,f=t.pstyle(`line-style`).value,p=t.pstyle(`width`).pfValue,m=t.pstyle(`line-cap`).value,h=t.pstyle(`line-outline-width`).value,g=t.pstyle(`line-outline-color`).value,_=l*u,v=l*u,y=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:_;d===`straight-triangle`?(o.eleStrokeStyle(e,t,n),o.drawEdgeTrianglePath(t,e,s.allpts)):(e.lineWidth=p,e.lineCap=m,o.eleStrokeStyle(e,t,n),o.drawEdgePath(t,e,s.allpts,f),e.lineCap=`butt`)},b=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:_;if(e.lineWidth=p+h,e.lineCap=m,h>0)o.colorStrokeStyle(e,g[0],g[1],g[2],n);else{e.lineCap=`butt`;return}d===`straight-triangle`?o.drawEdgeTrianglePath(t,e,s.allpts):(o.drawEdgePath(t,e,s.allpts,f),e.lineCap=`butt`)},x=function(){i&&o.drawEdgeOverlay(e,t)},S=function(){i&&o.drawEdgeUnderlay(e,t)},C=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:v;o.drawArrowheads(e,t,n)},w=function(){o.drawElementText(e,t,null,r)};if(e.lineJoin=`round`,t.pstyle(`ghost`).value===`yes`){var T=t.pstyle(`ghost-offset-x`).pfValue,E=t.pstyle(`ghost-offset-y`).pfValue,D=_*t.pstyle(`ghost-opacity`).value;e.translate(T,E),y(D),C(D),e.translate(-T,-E)}else b();S(),y(),C(),x(),w(),n&&e.translate(c.x1,c.y1)}};var Am=function(e){if(![`overlay`,`underlay`].includes(e))throw Error(`Invalid state`);return function(t,n){if(n.visible()){var r=n.pstyle(`${e}-opacity`).value;if(r!==0){var i=this,a=i.usePaths(),o=n._private.rscratch,s=2*n.pstyle(`${e}-padding`).pfValue,c=n.pstyle(`${e}-color`).value;t.lineWidth=s,o.edgeType===`self`&&!a?t.lineCap=`butt`:t.lineCap=`round`,i.colorStrokeStyle(t,c[0],c[1],c[2],r),i.drawEdgePath(n,t,o.allpts,`solid`)}}}};km.drawEdgeOverlay=Am(`overlay`),km.drawEdgeUnderlay=Am(`underlay`),km.drawEdgePath=function(e,t,n,r){var i=e._private.rscratch,a=t,o,s=!1,c=this.usePaths(),l=e.pstyle(`line-dash-pattern`).pfValue,u=e.pstyle(`line-dash-offset`).pfValue;if(c){var d=n.join(`$`);i.pathCacheKey&&i.pathCacheKey===d?(o=t=i.pathCache,s=!0):(o=t=new Path2D,i.pathCacheKey=d,i.pathCache=o)}if(a.setLineDash)switch(r){case`dotted`:a.setLineDash([1,1]);break;case`dashed`:a.setLineDash(l),a.lineDashOffset=u;break;case`solid`:a.setLineDash([]);break}if(!s&&!i.badLine)switch(t.beginPath&&t.beginPath(),t.moveTo(n[0],n[1]),i.edgeType){case`bezier`:case`self`:case`compound`:case`multibezier`:for(var f=2;f+35&&arguments[5]!==void 0?arguments[5]:!0,o=this;if(r==null){if(a&&!o.eleTextBiggerThanMin(t))return}else if(r===!1)return;if(t.isNode()){var s=t.pstyle(`label`);if(!s||!s.value)return;e.textAlign=o.getLabelJustification(t),e.textBaseline=`bottom`}else{var c=t.element()._private.rscratch.badLine,l=t.pstyle(`label`),u=t.pstyle(`source-label`),d=t.pstyle(`target-label`);if(c||(!l||!l.value)&&(!u||!u.value)&&(!d||!d.value))return;e.textAlign=`center`,e.textBaseline=`bottom`}var f=!n,p;n&&(p=n,e.translate(-p.x1,-p.y1)),i==null?(o.drawText(e,t,null,f,a),t.isEdge()&&(o.drawText(e,t,`source`,f,a),o.drawText(e,t,`target`,f,a))):o.drawText(e,t,i,f,a),n&&e.translate(p.x1,p.y1)},Mm.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var n=0;n2&&arguments[2]!==void 0?arguments[2]:!0,r=t.pstyle(`font-style`).strValue,i=t.pstyle(`font-size`).pfValue+`px`,a=t.pstyle(`font-family`).strValue,o=t.pstyle(`font-weight`).strValue,s=n?t.effectiveOpacity()*t.pstyle(`text-opacity`).value:1,c=t.pstyle(`text-outline-opacity`).value*s,l=t.pstyle(`color`).value,u=t.pstyle(`text-outline-color`).value;e.font=r+` `+o+` `+i+` `+a,e.lineJoin=`round`,this.colorFillStyle(e,l[0],l[1],l[2],s),this.colorStrokeStyle(e,u[0],u[1],u[2],c)};function Nm(e,t,n,r,i){var a=Math.min(r,i)/2,o=t+r/2,s=n+i/2;e.beginPath(),e.arc(o,s,a,0,Math.PI*2),e.closePath()}function Pm(e,t,n,r,i){var a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:5,o=Math.min(a,r/2,i/2);e.beginPath(),e.moveTo(t+o,n),e.lineTo(t+r-o,n),e.quadraticCurveTo(t+r,n,t+r,n+o),e.lineTo(t+r,n+i-o),e.quadraticCurveTo(t+r,n+i,t+r-o,n+i),e.lineTo(t+o,n+i),e.quadraticCurveTo(t,n+i,t,n+i-o),e.lineTo(t,n+o),e.quadraticCurveTo(t,n,t+o,n),e.closePath()}Mm.getTextAngle=function(e,t){var n,r=e._private.rscratch,i=t?t+`-`:``,a=e.pstyle(i+`text-rotation`);if(a.strValue===`autorotate`){var o=kn(r,`labelAngle`,t);n=e.isEdge()?o:0}else n=a.strValue===`none`?0:a.pfValue;return n},Mm.drawText=function(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=t._private.rscratch,o=i?t.effectiveOpacity():1;if(!(i&&(o===0||t.pstyle(`text-opacity`).value===0))){n===`main`&&(n=null);var s=kn(a,`labelX`,n),c=kn(a,`labelY`,n),l,u,d=this.getLabelText(t,n);if(d!=null&&d!==``&&!isNaN(s)&&!isNaN(c)){this.setupTextStyle(e,t,i);var f=n?n+`-`:``,p=kn(a,`labelWidth`,n),m=kn(a,`labelHeight`,n),h=t.pstyle(f+`text-margin-x`).pfValue,g=t.pstyle(f+`text-margin-y`).pfValue,_=t.isEdge(),v=t.pstyle(`text-halign`).value,y=t.pstyle(`text-valign`).value;_&&(v=`center`,y=`center`),s+=h,c+=g;var b=r?this.getTextAngle(t,n):0;switch(b!==0&&(l=s,u=c,e.translate(l,u),e.rotate(b),s=0,c=0),y){case`top`:break;case`center`:c+=m/2;break;case`bottom`:c+=m;break}var x=t.pstyle(`text-background-opacity`).value,S=t.pstyle(`text-border-opacity`).value,C=t.pstyle(`text-border-width`).pfValue,w=t.pstyle(`text-background-padding`).pfValue,T=t.pstyle(`text-background-shape`).strValue,E=T===`round-rectangle`||T===`roundrectangle`,D=T===`circle`,O=2;if(x>0||C>0&&S>0){var k=e.fillStyle,A=e.strokeStyle,j=e.lineWidth,M=t.pstyle(`text-background-color`).value,N=t.pstyle(`text-border-color`).value,P=t.pstyle(`text-border-style`).value,F=x>0,I=C>0&&S>0,L=s-w;switch(v){case`left`:L-=p;break;case`center`:L-=p/2;break}var R=c-m-w,z=p+2*w,B=m+2*w;if(F&&(e.fillStyle=`rgba(${M[0]},${M[1]},${M[2]},${x*o})`),I&&(e.strokeStyle=`rgba(${N[0]},${N[1]},${N[2]},${S*o})`,e.lineWidth=C,e.setLineDash))switch(P){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash([4,2]);break;case`double`:e.lineWidth=C/4,e.setLineDash([]);break;default:e.setLineDash([]);break}if(E?(e.beginPath(),Pm(e,L,R,z,B,O)):D?(e.beginPath(),Nm(e,L,R,z,B)):(e.beginPath(),e.rect(L,R,z,B)),F&&e.fill(),I&&e.stroke(),I&&P===`double`){var V=C/2;e.beginPath(),E?Pm(e,L+V,R+V,z-2*V,B-2*V,O):e.rect(L+V,R+V,z-2*V,B-2*V),e.stroke()}e.fillStyle=k,e.strokeStyle=A,e.lineWidth=j,e.setLineDash&&e.setLineDash([])}var H=2*t.pstyle(`text-outline-width`).pfValue;if(H>0&&(e.lineWidth=H),t.pstyle(`text-wrap`).value===`wrap`){var U=kn(a,`labelWrapCachedLines`,n),W=kn(a,`labelLineHeight`,n),G=p/2,K=this.getLabelJustification(t);switch(K===`auto`||(v===`left`?K===`left`?s+=-p:K===`center`&&(s+=-G):v===`center`?K===`left`?s+=-G:K===`right`&&(s+=G):v===`right`&&(K===`center`?s+=G:K===`right`&&(s+=p))),y){case`top`:c-=(U.length-1)*W;break;case`center`:case`bottom`:c-=(U.length-1)*W;break}for(var ee=0;ee0&&e.strokeText(U[ee],s,c),e.fillText(U[ee],s,c),c+=W}else H>0&&e.strokeText(d,s,c),e.fillText(d,s,c);b!==0&&(e.rotate(-b),e.translate(-l,-u))}}};var Fm={};Fm.drawNode=function(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,o=this,s,c,l=t._private,u=l.rscratch,d=t.position();if(!(!X(d.x)||!X(d.y))&&!(a&&!t.visible())){var f=a?t.effectiveOpacity():1,p=o.usePaths(),m,h=!1,g=t.padding();s=t.width()+2*g,c=t.height()+2*g;var _;n&&(_=n,e.translate(-_.x1,-_.y1));for(var v=t.pstyle(`background-image`).value,y=Array(v.length),b=Array(v.length),x=0,S=0;S0&&arguments[0]!==void 0?arguments[0]:D;o.eleFillStyle(e,t,n)},U=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:F;o.colorStrokeStyle(e,O[0],O[1],O[2],t)},W=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:z;o.colorStrokeStyle(e,L[0],L[1],L[2],t)},G=function(e,t,n,r){var i=o.nodePathCache=o.nodePathCache||[],a=nn(n===`polygon`?n+`,`+r.join(`,`):n,``+t,``+e,``+V),s=i[a],c,l=!1;return s==null?(c=new Path2D,i[a]=u.pathCache=c):(c=s,l=!0,u.pathCache=c),{path:c,cacheHit:l}},K=t.pstyle(`shape`).strValue,ee=t.pstyle(`shape-polygon-points`).pfValue;if(p){e.translate(d.x,d.y);var te=G(s,c,K,ee);m=te.path,h=te.cacheHit}var q=function(){if(!h){var n=d;p&&(n={x:0,y:0}),o.nodeShapes[o.getNodeShape(t)].draw(m||e,n.x,n.y,s,c,V,u)}p?e.fill(m):e.fill()},ne=function(){for(var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:f,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,i=l.backgrounding,a=0,s=0;s0&&arguments[0]!==void 0?arguments[0]:!1,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:f;o.hasPie(t)&&(o.drawPie(e,t,r),n&&(p||o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,V,u)))},ie=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:f;o.hasStripe(t)&&(e.save(),p?e.clip(u.pathCache):(o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,V,u),e.clip()),o.drawStripe(e,t,r),e.restore(),n&&(p||o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,V,u)))},ae=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:f,n=(T>0?T:-T)*t,r=T>0?0:255;T!==0&&(o.colorFillStyle(e,r,r,r,n),p?e.fill(m):e.fill())},oe=function(){if(E>0){if(e.lineWidth=E,e.lineCap=j,e.lineJoin=A,e.setLineDash)switch(k){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash(N),e.lineDashOffset=P;break;case`solid`:case`double`:e.setLineDash([]);break}if(M!==`center`){if(e.save(),e.lineWidth*=2,M===`inside`)p?e.clip(m):e.clip();else{var t=new Path2D;t.rect(-s/2-E,-c/2-E,s+2*E,c+2*E),t.addPath(m),e.clip(t,`evenodd`)}p?e.stroke(m):e.stroke(),e.restore()}else p?e.stroke(m):e.stroke();if(k===`double`){e.lineWidth=E/3;var n=e.globalCompositeOperation;e.globalCompositeOperation=`destination-out`,p?e.stroke(m):e.stroke(),e.globalCompositeOperation=n}e.setLineDash&&e.setLineDash([])}},se=function(){if(I>0){if(e.lineWidth=I,e.lineCap=`butt`,e.setLineDash)switch(R){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash([4,2]);break;case`solid`:case`double`:e.setLineDash([]);break}var n=d;p&&(n={x:0,y:0});var r=o.getNodeShape(t),i=E;M===`inside`&&(i=0),M===`outside`&&(i*=2);var a=(s+i+(I+B))/s,l=(c+i+(I+B))/c,u=s*a,f=c*l,m=o.nodeShapes[r].points,h;if(p&&(h=G(u,f,r,m).path),r===`ellipse`)o.drawEllipsePath(h||e,n.x,n.y,u,f);else if([`round-diamond`,`round-heptagon`,`round-hexagon`,`round-octagon`,`round-pentagon`,`round-polygon`,`round-triangle`,`round-tag`].includes(r)){var g=0,_=0,v=0;r===`round-diamond`?g=(i+B+I)*1.4:r===`round-heptagon`?(g=(i+B+I)*1.075,v=-(i/2+B+I)/35):r===`round-hexagon`?g=(i+B+I)*1.12:r===`round-pentagon`?(g=(i+B+I)*1.13,v=-(i/2+B+I)/15):r===`round-tag`?(g=(i+B+I)*1.12,_=(i/2+I+B)*.07):r===`round-triangle`&&(g=(i+B+I)*(Math.PI/2),v=-(i+B/2+I)/Math.PI),g!==0&&(a=(s+g)/s,u=s*a,[`round-hexagon`,`round-tag`].includes(r)||(l=(c+g)/c,f=c*l)),V=V===`auto`?ui(u,f):V;for(var y=u/2,b=f/2,x=V+(i+I+B)/2,S=Array(m.length/2),C=Array(m.length/2),w=0;w0){if(r||=n.position(),i==null||a==null){var f=n.padding();i=n.width()+2*f,a=n.height()+2*f}o.colorFillStyle(t,l[0],l[1],l[2],c),o.nodeShapes[u].draw(t,r.x,r.y,i+s*2,a+s*2,d),t.fill()}}}};Fm.drawNodeOverlay=Im(`overlay`),Fm.drawNodeUnderlay=Im(`underlay`),Fm.hasPie=function(e){return e=e[0],e._private.hasPie},Fm.hasStripe=function(e){return e=e[0],e._private.hasStripe},Fm.drawPie=function(e,t,n,r){t=t[0],r||=t.position();var i=t.cy().style(),a=t.pstyle(`pie-size`),o=t.pstyle(`pie-hole`),s=t.pstyle(`pie-start-angle`).pfValue,c=r.x,l=r.y,u=t.width(),d=t.height(),f=Math.min(u,d)/2,p,m=0;if(this.usePaths()&&(c=0,l=0),a.units===`%`?f*=a.pfValue:a.pfValue!==void 0&&(f=a.pfValue/2),o.units===`%`?p=f*o.pfValue:o.pfValue!==void 0&&(p=o.pfValue/2),!(p>=f))for(var h=1;h<=i.pieBackgroundN;h++){var g=t.pstyle(`pie-`+h+`-background-size`).value,_=t.pstyle(`pie-`+h+`-background-color`).value,v=t.pstyle(`pie-`+h+`-background-opacity`).value*n,y=g/100;y+m>1&&(y=1-m);var b=1.5*Math.PI+2*Math.PI*m;b+=s;var x=2*Math.PI*y,S=b+x;g===0||m>=1||m+y>1||(p===0?(e.beginPath(),e.moveTo(c,l),e.arc(c,l,f,b,S),e.closePath()):(e.beginPath(),e.arc(c,l,f,b,S),e.arc(c,l,p,S,b,!0),e.closePath()),this.colorFillStyle(e,_[0],_[1],_[2],v),e.fill(),m+=y)}},Fm.drawStripe=function(e,t,n,r){t=t[0],r||=t.position();var i=t.cy().style(),a=r.x,o=r.y,s=t.width(),c=t.height(),l=0,u=this.usePaths();e.save();var d=t.pstyle(`stripe-direction`).value,f=t.pstyle(`stripe-size`);switch(d){case`vertical`:break;case`righward`:e.rotate(-Math.PI/2);break}var p=s,m=c;f.units===`%`?(p*=f.pfValue,m*=f.pfValue):f.pfValue!==void 0&&(p=f.pfValue,m=f.pfValue),u&&(a=0,o=0),o-=p/2,a-=m/2;for(var h=1;h<=i.stripeBackgroundN;h++){var g=t.pstyle(`stripe-`+h+`-background-size`).value,_=t.pstyle(`stripe-`+h+`-background-color`).value,v=t.pstyle(`stripe-`+h+`-background-opacity`).value*n,y=g/100;y+l>1&&(y=1-l),!(g===0||l>=1||l+y>1)&&(e.beginPath(),e.rect(a,o+m*l,p,m*y),e.closePath(),this.colorFillStyle(e,_[0],_[1],_[2],v),e.fill(),l+=y)}e.restore()};var Lm={},Rm=100;Lm.getPixelRatio=function(){var e=this.data.contexts[0];if(this.forcedPixelRatio!=null)return this.forcedPixelRatio;var t=this.cy.window(),n=e.backingStorePixelRatio||e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1;return(t.devicePixelRatio||1)/n},Lm.paintCache=function(e){for(var t=this.paintCaches=this.paintCaches||[],n=!0,r,i=0;it.minMbLowQualFrames&&(t.motionBlurPxRatio=t.mbPxRBlurry)),t.clearingMotionBlur&&(t.motionBlurPxRatio=1),t.textureDrawLastFrame&&!d&&(u[t.NODE]=!0,u[t.SELECT_BOX]=!0);var v=n.style(),y=n.zoom(),b=o===void 0?y:o,x=n.pan(),S={x:x.x,y:x.y},C={zoom:y,pan:{x:x.x,y:x.y}},w=t.prevViewport;!(w===void 0||C.zoom!==w.zoom||C.pan.x!==w.pan.x||C.pan.y!==w.pan.y)&&!(h&&!m)&&(t.motionBlurPxRatio=1),s&&(S=s),b*=c,S.x*=c,S.y*=c;var T=t.getCachedZSortedEles();function E(e,n,r,i,a){var o=e.globalCompositeOperation;e.globalCompositeOperation=`destination-out`,t.colorFillStyle(e,255,255,255,t.motionBlurTransparency),e.fillRect(n,r,i,a),e.globalCompositeOperation=o}function D(e,n){var a,c,u,d;!t.clearingMotionBlur&&(e===l.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]||e===l.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG])?(a={x:x.x*p,y:x.y*p},c=y*p,u=t.canvasWidth*p,d=t.canvasHeight*p):(a=S,c=b,u=t.canvasWidth,d=t.canvasHeight),e.setTransform(1,0,0,1,0,0),n===`motionBlur`?E(e,0,0,u,d):!r&&(n===void 0||n)&&e.clearRect(0,0,u,d),i||(e.translate(a.x,a.y),e.scale(c,c)),s&&e.translate(s.x,s.y),o&&e.scale(o,o)}if(d||(t.textureDrawLastFrame=!1),d){if(t.textureDrawLastFrame=!0,!t.textureCache){t.textureCache={},t.textureCache.bb=n.mutableElements().boundingBox(),t.textureCache.texture=t.data.bufferCanvases[t.TEXTURE_BUFFER];var O=t.data.bufferContexts[t.TEXTURE_BUFFER];O.setTransform(1,0,0,1,0,0),O.clearRect(0,0,t.canvasWidth*t.textureMult,t.canvasHeight*t.textureMult),t.render({forcedContext:O,drawOnlyNodeLayer:!0,forcedPxRatio:c*t.textureMult});var C=t.textureCache.viewport={zoom:n.zoom(),pan:n.pan(),width:t.canvasWidth,height:t.canvasHeight};C.mpan={x:(0-C.pan.x)/C.zoom,y:(0-C.pan.y)/C.zoom}}u[t.DRAG]=!1,u[t.NODE]=!1;var k=l.contexts[t.NODE],A=t.textureCache.texture,C=t.textureCache.viewport;k.setTransform(1,0,0,1,0,0),f?E(k,0,0,C.width,C.height):k.clearRect(0,0,C.width,C.height);var j=v.core(`outside-texture-bg-color`).value,M=v.core(`outside-texture-bg-opacity`).value;t.colorFillStyle(k,j[0],j[1],j[2],M),k.fillRect(0,0,C.width,C.height);var y=n.zoom();D(k,!1),k.clearRect(C.mpan.x,C.mpan.y,C.width/C.zoom/c,C.height/C.zoom/c),k.drawImage(A,C.mpan.x,C.mpan.y,C.width/C.zoom/c,C.height/C.zoom/c)}else t.textureOnViewport&&!r&&(t.textureCache=null);var N=n.extent(),P=t.pinching||t.hoverData.dragging||t.swipePanning||t.data.wheelZooming||t.hoverData.draggingEles||t.cy.animated(),F=t.hideEdgesOnViewport&&P,I=[];if(I[t.NODE]=!u[t.NODE]&&f&&!t.clearedForMotionBlur[t.NODE]||t.clearingMotionBlur,I[t.NODE]&&(t.clearedForMotionBlur[t.NODE]=!0),I[t.DRAG]=!u[t.DRAG]&&f&&!t.clearedForMotionBlur[t.DRAG]||t.clearingMotionBlur,I[t.DRAG]&&(t.clearedForMotionBlur[t.DRAG]=!0),u[t.NODE]||i||a||I[t.NODE]){var L=f&&!I[t.NODE]&&p!==1,k=r||(L?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]:l.contexts[t.NODE]);D(k,f&&!L?`motionBlur`:void 0),F?t.drawCachedNodes(k,T.nondrag,c,N):t.drawLayeredElements(k,T.nondrag,c,N),t.debug&&t.drawDebugPoints(k,T.nondrag),!i&&!f&&(u[t.NODE]=!1)}if(!a&&(u[t.DRAG]||i||I[t.DRAG])){var L=f&&!I[t.DRAG]&&p!==1,k=r||(L?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG]:l.contexts[t.DRAG]);D(k,f&&!L?`motionBlur`:void 0),F?t.drawCachedNodes(k,T.drag,c,N):t.drawCachedElements(k,T.drag,c,N),t.debug&&t.drawDebugPoints(k,T.drag),!i&&!f&&(u[t.DRAG]=!1)}if(this.drawSelectionRectangle(e,D),f&&p!==1){var R=l.contexts[t.NODE],z=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE],B=l.contexts[t.DRAG],V=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG],H=function(e,n,r){e.setTransform(1,0,0,1,0,0),r||!_?e.clearRect(0,0,t.canvasWidth,t.canvasHeight):E(e,0,0,t.canvasWidth,t.canvasHeight);var i=p;e.drawImage(n,0,0,t.canvasWidth*i,t.canvasHeight*i,0,0,t.canvasWidth,t.canvasHeight)};(u[t.NODE]||I[t.NODE])&&(H(R,z,I[t.NODE]),u[t.NODE]=!1),(u[t.DRAG]||I[t.DRAG])&&(H(B,V,I[t.DRAG]),u[t.DRAG]=!1)}t.prevViewport=C,t.clearingMotionBlur&&(t.clearingMotionBlur=!1,t.motionBlurCleared=!0,t.motionBlur=!0),f&&(t.motionBlurTimeout=setTimeout(function(){t.motionBlurTimeout=null,t.clearedForMotionBlur[t.NODE]=!1,t.clearedForMotionBlur[t.DRAG]=!1,t.motionBlur=!1,t.clearingMotionBlur=!d,t.mbFrames=0,u[t.NODE]=!0,u[t.DRAG]=!0,t.redraw()},Rm)),r||n.emit(`render`)};var zm;Lm.drawSelectionRectangle=function(e,t){var n=this,r=n.cy,i=n.data,a=r.style(),o=e.drawOnlyNodeLayer,s=e.drawAllLayers,c=i.canvasNeedsRedraw,l=e.forcedContext;if(n.showFps||!o&&c[n.SELECT_BOX]&&!s){var u=l||i.contexts[n.SELECT_BOX];if(t(u),n.selection[4]==1&&(n.hoverData.selecting||n.touchData.selecting)){var d=n.cy.zoom(),f=a.core(`selection-box-border-width`).value/d;u.lineWidth=f,u.fillStyle=`rgba(`+a.core(`selection-box-color`).value[0]+`,`+a.core(`selection-box-color`).value[1]+`,`+a.core(`selection-box-color`).value[2]+`,`+a.core(`selection-box-opacity`).value+`)`,u.fillRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]),f>0&&(u.strokeStyle=`rgba(`+a.core(`selection-box-border-color`).value[0]+`,`+a.core(`selection-box-border-color`).value[1]+`,`+a.core(`selection-box-border-color`).value[2]+`,`+a.core(`selection-box-opacity`).value+`)`,u.strokeRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]))}if(i.bgActivePosistion&&!n.hoverData.selecting){var d=n.cy.zoom(),p=i.bgActivePosistion;u.fillStyle=`rgba(`+a.core(`active-bg-color`).value[0]+`,`+a.core(`active-bg-color`).value[1]+`,`+a.core(`active-bg-color`).value[2]+`,`+a.core(`active-bg-opacity`).value+`)`,u.beginPath(),u.arc(p.x,p.y,a.core(`active-bg-size`).pfValue/d,0,2*Math.PI),u.fill()}var m=n.lastRedrawTime;if(n.showFps&&m){m=Math.round(m);var h=Math.round(1e3/m),g=`1 frame = `+m+` ms = `+h+` fps`;u.setTransform(1,0,0,1,0,0),u.fillStyle=`rgba(255, 0, 0, 0.75)`,u.strokeStyle=`rgba(255, 0, 0, 0.75)`,u.font=`30px Arial`,zm||=u.measureText(g).actualBoundingBoxAscent,u.fillText(g,0,zm),u.strokeRect(0,zm+10,250,20),u.fillRect(0,zm+10,250*Math.min(h/60,1),20)}s||(c[n.SELECT_BOX]=!1)}};function Bm(e,t,n){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS))throw Error(e.getShaderInfoLog(r));return r}function Vm(e,t,n){var r=Bm(e,e.VERTEX_SHADER,t),i=Bm(e,e.FRAGMENT_SHADER,n),a=e.createProgram();if(e.attachShader(a,r),e.attachShader(a,i),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS))throw Error(`Could not initialize shaders`);return a}function Hm(e,t,n){n===void 0&&(n=t);var r=e.makeOffscreenCanvas(t,n),i=r.context=r.getContext(`2d`);return r.clear=function(){return i.clearRect(0,0,r.width,r.height)},r.clear(),r}function Um(e){var t=e.pixelRatio,n=e.cy.zoom(),r=e.cy.pan();return{zoom:n*t,pan:{x:r.x*t,y:r.y*t}}}function Wm(e){var t=e.pixelRatio;return e.cy.zoom()*t}function Gm(e,t,n,r,i){var a=r*n+t.x,o=i*n+t.y;return o=Math.round(e.canvasHeight-o),[a,o]}function Km(e,t){return t.picking?!0:e.pstyle(`background-fill`).value!==`solid`||e.pstyle(`background-image`).strValue!==`none`?!1:e.pstyle(`border-width`).value===0||e.pstyle(`border-opacity`).value===0?!0:e.pstyle(`border-style`).value===`solid`}function qm(e,t){if(e.length!==t.length)return!1;for(var n=0;n>0&255)/255,n[1]=(e>>8&255)/255,n[2]=(e>>16&255)/255,n[3]=(e>>24&255)/255,n}function Xm(e){return e[0]+(e[1]<<8)+(e[2]<<16)+(e[3]<<24)}function Zm(e,t){var n=e.createTexture();return n.buffer=function(t){e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR_MIPMAP_NEAREST),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),e.generateMipmap(e.TEXTURE_2D),e.bindTexture(e.TEXTURE_2D,null)},n.deleteTexture=function(){e.deleteTexture(n)},n}function Qm(e,t){switch(t){case`float`:return[1,e.FLOAT,4];case`vec2`:return[2,e.FLOAT,4];case`vec3`:return[3,e.FLOAT,4];case`vec4`:return[4,e.FLOAT,4];case`int`:return[1,e.INT,4];case`ivec2`:return[2,e.INT,4]}}function $m(e,t,n){switch(t){case e.FLOAT:return new Float32Array(n);case e.INT:return new Int32Array(n)}}function eh(e,t,n,r,i,a){switch(t){case e.FLOAT:return new Float32Array(n.buffer,a*r,i);case e.INT:return new Int32Array(n.buffer,a*r,i)}}function th(e,t,n,r){var i=G(Qm(e,t),2),a=i[0],o=i[1],s=$m(e,o,r),c=e.createBuffer();return e.bindBuffer(e.ARRAY_BUFFER,c),e.bufferData(e.ARRAY_BUFFER,s,e.STATIC_DRAW),o===e.FLOAT?e.vertexAttribPointer(n,a,o,!1,0,0):o===e.INT&&e.vertexAttribIPointer(n,a,o,0,0),e.enableVertexAttribArray(n),e.bindBuffer(e.ARRAY_BUFFER,null),c}function nh(e,t,n,r){var i=G(Qm(e,n),3),a=i[0],o=i[1],s=i[2],c=$m(e,o,t*a),l=a*s,u=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,u),e.bufferData(e.ARRAY_BUFFER,t*l,e.DYNAMIC_DRAW),e.enableVertexAttribArray(r),o===e.FLOAT?e.vertexAttribPointer(r,a,o,!1,l,0):o===e.INT&&e.vertexAttribIPointer(r,a,o,l,0),e.vertexAttribDivisor(r,1),e.bindBuffer(e.ARRAY_BUFFER,null);for(var d=Array(t),f=0;fi&&(a=i/t,o=t*a,s=n*a),{scale:a,texW:o,texH:s}}},{key:`draw`,value:function(e,t,n){var r=this;if(this.locked)throw Error(`can't draw, atlas is locked`);var i=this.texSize,a=this.texRows,o=this.texHeight,s=this.getScale(t),c=s.scale,l=s.texW,u=s.texH,d=function(e,r){if(n&&r){var i=r.context,a=e.x,s=e.row,l=a,u=o*s;i.save(),i.translate(l,u),i.scale(c,c),n(i,t),i.restore()}},f=[null,null],p=function(){d(r.freePointer,r.canvas),f[0]={x:r.freePointer.x,y:r.freePointer.row*o,w:l,h:u},f[1]={x:r.freePointer.x+l,y:r.freePointer.row*o,w:0,h:u},r.freePointer.x+=l,r.freePointer.x==i&&(r.freePointer.x=0,r.freePointer.row++)},m=function(){var e=r.scratch,t=r.canvas;e.clear(),d({x:0,row:0},e);var n=i-r.freePointer.x,a=l-n,s=o,c=r.freePointer.x,p=r.freePointer.row*o,m=n;t.context.drawImage(e,0,0,m,s,c,p,m,s),f[0]={x:c,y:p,w:m,h:u};var h=n,g=(r.freePointer.row+1)*o,_=a;t&&t.context.drawImage(e,h,0,_,s,0,g,_,s),f[1]={x:0,y:g,w:_,h:u},r.freePointer.x=a,r.freePointer.row++},h=function(){r.freePointer.x=0,r.freePointer.row++};if(this.freePointer.x+l<=i)p();else if(this.freePointer.row>=a-1)return!1;else this.freePointer.x===i?(h(),p()):this.enableWrapping?m():(h(),p());return this.keyToLocation.set(e,f),this.needsBuffer=!0,f}},{key:`getOffsets`,value:function(e){return this.keyToLocation.get(e)}},{key:`isEmpty`,value:function(){return this.freePointer.x===0&&this.freePointer.row===0}},{key:`canFit`,value:function(e){if(this.locked)return!1;var t=this.texSize,n=this.texRows,r=this.getScale(e).texW;return this.freePointer.x+r>t?this.freePointer.row1&&arguments[1]!==void 0?arguments[1]:{},r=n.forceRedraw,i=r===void 0?!1:r,a=n.filterEle,o=a===void 0?function(){return!0}:a,s=n.filterType,c=s===void 0?function(){return!0}:s,l=!1,u=!1,d=z(e),f;try{for(d.s();!(f=d.n()).done;){var p=f.value;if(o(p)){var m=z(this.renderTypes.values()),h;try{var g=function(){var e=h.value,n=e.type;if(c(n)){var r=t.collections.get(e.collection),a=e.getKey(p),o=Array.isArray(a)?a:[a];if(i)o.forEach(function(e){return r.markKeyForGC(e)}),u=!0;else{var s=e.getID?e.getID(p):p.id(),d=t._key(n,s),f=t.typeAndIdToKey.get(d);f!==void 0&&!qm(o,f)&&(l=!0,t.typeAndIdToKey.delete(d),f.forEach(function(e){return r.markKeyForGC(e)}))}}};for(m.s();!(h=m.n()).done;)g()}catch(e){m.e(e)}finally{m.f()}}}}catch(e){d.e(e)}finally{d.f()}return u&&(this.gc(),l=!1),l}},{key:`gc`,value:function(){var e=z(this.collections.values()),t;try{for(e.s();!(t=e.n()).done;)t.value.gc()}catch(t){e.e(t)}finally{e.f()}}},{key:`getOrCreateAtlas`,value:function(e,t,n,r){var i=this.renderTypes.get(t),a=this.collections.get(i.collection),o=!1,s=a.draw(r,n,function(t){i.drawClipped?(t.save(),t.beginPath(),t.rect(0,0,n.w,n.h),t.clip(),i.drawElement(t,e,n,!0,!0),t.restore()):i.drawElement(t,e,n,!0,!0),o=!0});if(o){var c=i.getID?i.getID(e):e.id(),l=this._key(t,c);this.typeAndIdToKey.has(l)?this.typeAndIdToKey.get(l).push(r):this.typeAndIdToKey.set(l,[r])}return s}},{key:`getAtlasInfo`,value:function(e,t){var n=this,r=this.renderTypes.get(t),i=r.getKey(e);return(Array.isArray(i)?i:[i]).map(function(i){var a=r.getBoundingBox(e,i),o=n.getOrCreateAtlas(e,t,a,i),s=G(o.getOffsets(i),2),c=s[0];return{atlas:o,tex:c,tex1:c,tex2:s[1],bb:a}})}},{key:`getDebugInfo`,value:function(){var e=[],t=z(this.collections),n;try{for(t.s();!(n=t.n()).done;){var r=G(n.value,2),i=r[0],a=r[1].getCounts(),o=a.keyCount,s=a.atlasCount;e.push({type:i,keyCount:o,atlasCount:s})}}catch(e){t.e(e)}finally{t.f()}return e}}])}(),_h=function(){function e(t){I(this,e),this.globalOptions=t,this.atlasSize=t.webglTexSize,this.maxAtlasesPerBatch=t.webglTexPerBatch,this.batchAtlases=[]}return R(e,[{key:`getMaxAtlasesPerBatch`,value:function(){return this.maxAtlasesPerBatch}},{key:`getAtlasSize`,value:function(){return this.atlasSize}},{key:`getIndexArray`,value:function(){return Array.from({length:this.maxAtlasesPerBatch},function(e,t){return t})}},{key:`startBatch`,value:function(){this.batchAtlases=[]}},{key:`getAtlasCount`,value:function(){return this.batchAtlases.length}},{key:`getAtlases`,value:function(){return this.batchAtlases}},{key:`canAddToCurrentBatch`,value:function(e){return this.batchAtlases.length===this.maxAtlasesPerBatch?this.batchAtlases.includes(e):!0}},{key:`getAtlasIndexForBatch`,value:function(e){var t=this.batchAtlases.indexOf(e);if(t<0){if(this.batchAtlases.length===this.maxAtlasesPerBatch)throw Error(`cannot add more atlases to batch`);this.batchAtlases.push(e),t=this.batchAtlases.length-1}return t}}])}(),vh=` + float circleSD(vec2 p, float r) { + return distance(vec2(0), p) - r; // signed distance + } +`,yh=` + float rectangleSD(vec2 p, vec2 b) { + vec2 d = abs(p)-b; + return distance(vec2(0),max(d,0.0)) + min(max(d.x,d.y),0.0); + } +`,bh=` + float roundRectangleSD(vec2 p, vec2 b, vec4 cr) { + cr.xy = (p.x > 0.0) ? cr.xy : cr.zw; + cr.x = (p.y > 0.0) ? cr.x : cr.y; + vec2 q = abs(p) - b + cr.x; + return min(max(q.x, q.y), 0.0) + distance(vec2(0), max(q, 0.0)) - cr.x; + } +`,xh=` + float ellipseSD(vec2 p, vec2 ab) { + p = abs( p ); // symmetry + + // find root with Newton solver + vec2 q = ab*(p-ab); + float w = (q.x1.0) ? d : -d; + } +`,Sh={SCREEN:{name:`screen`,screen:!0},PICKING:{name:`picking`,picking:!0}},Ch={IGNORE:1,USE_BB:2},wh=0,Th=1,Eh=2,Dh=3,Oh=4,kh=5,Ah=6,jh=7,Mh=function(){function e(t,n,r){I(this,e),this.r=t,this.gl=n,this.maxInstances=r.webglBatchSize,this.atlasSize=r.webglTexSize,this.bgColor=r.bgColor,this.debug=r.webglDebug,this.batchDebugInfo=[],r.enableWrapping=!0,r.createTextureCanvas=Hm,this.atlasManager=new gh(t,r),this.batchManager=new _h(r),this.simpleShapeOptions=new Map,this.program=this._createShaderProgram(Sh.SCREEN),this.pickingProgram=this._createShaderProgram(Sh.PICKING),this.vao=this._createVAO()}return R(e,[{key:`addAtlasCollection`,value:function(e,t){this.atlasManager.addAtlasCollection(e,t)}},{key:`addTextureAtlasRenderType`,value:function(e,t){this.atlasManager.addRenderType(e,t)}},{key:`addSimpleShapeRenderType`,value:function(e,t){this.simpleShapeOptions.set(e,t)}},{key:`invalidate`,value:function(e){var t=(arguments.length>1&&arguments[1]!==void 0?arguments[1]:{}).type,n=this.atlasManager;return t?n.invalidate(e,{filterType:function(e){return e===t},forceRedraw:!0}):n.invalidate(e)}},{key:`gc`,value:function(){this.atlasManager.gc()}},{key:`_createShaderProgram`,value:function(e){var t=this.gl,n=`#version 300 es + precision highp float; + + uniform mat3 uPanZoomMatrix; + uniform int uAtlasSize; + + // instanced + in vec2 aPosition; // a vertex from the unit square + + in mat3 aTransform; // used to transform verticies, eg into a bounding box + in int aVertType; // the type of thing we are rendering + + // the z-index that is output when using picking mode + in vec4 aIndex; + + // For textures + in int aAtlasId; // which shader unit/atlas to use + in vec4 aTex; // x/y/w/h of texture in atlas + + // for edges + in vec4 aPointAPointB; + in vec4 aPointCPointD; + in vec2 aLineWidth; // also used for node border width + + // simple shapes + in vec4 aCornerRadius; // for round-rectangle [top-right, bottom-right, top-left, bottom-left] + in vec4 aColor; // also used for edges + in vec4 aBorderColor; // aLineWidth is used for border width + + // output values passed to the fragment shader + out vec2 vTexCoord; + out vec4 vColor; + out vec2 vPosition; + // flat values are not interpolated + flat out int vAtlasId; + flat out int vVertType; + flat out vec2 vTopRight; + flat out vec2 vBotLeft; + flat out vec4 vCornerRadius; + flat out vec4 vBorderColor; + flat out vec2 vBorderWidth; + flat out vec4 vIndex; + + void main(void) { + int vid = gl_VertexID; + vec2 position = aPosition; // TODO make this a vec3, simplifies some code below + + if(aVertType == ${wh}) { + float texX = aTex.x; // texture coordinates + float texY = aTex.y; + float texW = aTex.z; + float texH = aTex.w; + + if(vid == 1 || vid == 2 || vid == 4) { + texX += texW; + } + if(vid == 2 || vid == 4 || vid == 5) { + texY += texH; + } + + float d = float(uAtlasSize); + vTexCoord = vec2(texX / d, texY / d); // tex coords must be between 0 and 1 + + gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); + } + else if(aVertType == ${Oh} || aVertType == ${jh} + || aVertType == ${kh} || aVertType == ${Ah}) { // simple shapes + + // the bounding box is needed by the fragment shader + vBotLeft = (aTransform * vec3(0, 0, 1)).xy; // flat + vTopRight = (aTransform * vec3(1, 1, 1)).xy; // flat + vPosition = (aTransform * vec3(position, 1)).xy; // will be interpolated + + // calculations are done in the fragment shader, just pass these along + vColor = aColor; + vCornerRadius = aCornerRadius; + vBorderColor = aBorderColor; + vBorderWidth = aLineWidth; + + gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); + } + else if(aVertType == ${Th}) { + vec2 source = aPointAPointB.xy; + vec2 target = aPointAPointB.zw; + + // adjust the geometry so that the line is centered on the edge + position.y = position.y - 0.5; + + // stretch the unit square into a long skinny rectangle + vec2 xBasis = target - source; + vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x)); + vec2 point = source + xBasis * position.x + yBasis * aLineWidth[0] * position.y; + + gl_Position = vec4(uPanZoomMatrix * vec3(point, 1.0), 1.0); + vColor = aColor; + } + else if(aVertType == ${Eh}) { + vec2 pointA = aPointAPointB.xy; + vec2 pointB = aPointAPointB.zw; + vec2 pointC = aPointCPointD.xy; + vec2 pointD = aPointCPointD.zw; + + // adjust the geometry so that the line is centered on the edge + position.y = position.y - 0.5; + + vec2 p0, p1, p2, pos; + if(position.x == 0.0) { // The left side of the unit square + p0 = pointA; + p1 = pointB; + p2 = pointC; + pos = position; + } else { // The right side of the unit square, use same approach but flip the geometry upside down + p0 = pointD; + p1 = pointC; + p2 = pointB; + pos = vec2(0.0, -position.y); + } + + vec2 p01 = p1 - p0; + vec2 p12 = p2 - p1; + vec2 p21 = p1 - p2; + + // Find the normal vector. + vec2 tangent = normalize(normalize(p12) + normalize(p01)); + vec2 normal = vec2(-tangent.y, tangent.x); + + // Find the vector perpendicular to p0 -> p1. + vec2 p01Norm = normalize(vec2(-p01.y, p01.x)); + + // Determine the bend direction. + float sigma = sign(dot(p01 + p21, normal)); + float width = aLineWidth[0]; + + if(sign(pos.y) == -sigma) { + // This is an intersecting vertex. Adjust the position so that there's no overlap. + vec2 point = 0.5 * width * normal * -sigma / dot(normal, p01Norm); + gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0); + } else { + // This is a non-intersecting vertex. Treat it like a mitre join. + vec2 point = 0.5 * width * normal * sigma * dot(normal, p01Norm); + gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0); + } + + vColor = aColor; + } + else if(aVertType == ${Dh} && vid < 3) { + // massage the first triangle into an edge arrow + if(vid == 0) + position = vec2(-0.15, -0.3); + if(vid == 1) + position = vec2( 0.0, 0.0); + if(vid == 2) + position = vec2( 0.15, -0.3); + + gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); + vColor = aColor; + } + else { + gl_Position = vec4(2.0, 0.0, 0.0, 1.0); // discard vertex by putting it outside webgl clip space + } + + vAtlasId = aAtlasId; + vVertType = aVertType; + vIndex = aIndex; + } + `,r=this.batchManager.getIndexArray(),i=Vm(t,n,`#version 300 es + precision highp float; + + // declare texture unit for each texture atlas in the batch + ${r.map(function(e){return`uniform sampler2D uTexture${e};`}).join(` + `)} + + uniform vec4 uBGColor; + uniform float uZoom; + + in vec2 vTexCoord; + in vec4 vColor; + in vec2 vPosition; // model coordinates + + flat in int vAtlasId; + flat in vec4 vIndex; + flat in int vVertType; + flat in vec2 vTopRight; + flat in vec2 vBotLeft; + flat in vec4 vCornerRadius; + flat in vec4 vBorderColor; + flat in vec2 vBorderWidth; + + out vec4 outColor; + + ${vh} + ${yh} + ${bh} + ${xh} + + vec4 blend(vec4 top, vec4 bot) { // blend colors with premultiplied alpha + return vec4( + top.rgb + (bot.rgb * (1.0 - top.a)), + top.a + (bot.a * (1.0 - top.a)) + ); + } + + vec4 distInterp(vec4 cA, vec4 cB, float d) { // interpolate color using Signed Distance + // scale to the zoom level so that borders don't look blurry when zoomed in + // note 1.5 is an aribitrary value chosen because it looks good + return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d))); + } + + void main(void) { + if(vVertType == ${wh}) { + // look up the texel from the texture unit + ${r.map(function(e){return`if(vAtlasId == ${e}) outColor = texture(uTexture${e}, vTexCoord);`}).join(` + else `)} + } + else if(vVertType == ${Dh}) { + // mimics how canvas renderer uses context.globalCompositeOperation = 'destination-out'; + outColor = blend(vColor, uBGColor); + outColor.a = 1.0; // make opaque, masks out line under arrow + } + else if(vVertType == ${Oh} && vBorderWidth == vec2(0.0)) { // simple rectangle with no border + outColor = vColor; // unit square is already transformed to the rectangle, nothing else needs to be done + } + else if(vVertType == ${Oh} || vVertType == ${jh} + || vVertType == ${kh} || vVertType == ${Ah}) { // use SDF + + float outerBorder = vBorderWidth[0]; + float innerBorder = vBorderWidth[1]; + float borderPadding = outerBorder * 2.0; + float w = vTopRight.x - vBotLeft.x - borderPadding; + float h = vTopRight.y - vBotLeft.y - borderPadding; + vec2 b = vec2(w/2.0, h/2.0); // half width, half height + vec2 p = vPosition - vec2(vTopRight.x - b[0] - outerBorder, vTopRight.y - b[1] - outerBorder); // translate to center + + float d; // signed distance + if(vVertType == ${Oh}) { + d = rectangleSD(p, b); + } else if(vVertType == ${jh} && w == h) { + d = circleSD(p, b.x); // faster than ellipse + } else if(vVertType == ${jh}) { + d = ellipseSD(p, b); + } else { + d = roundRectangleSD(p, b, vCornerRadius.wzyx); + } + + // use the distance to interpolate a color to smooth the edges of the shape, doesn't need multisampling + // we must smooth colors inwards, because we can't change pixels outside the shape's bounding box + if(d > 0.0) { + if(d > outerBorder) { + discard; + } else { + outColor = distInterp(vBorderColor, vec4(0), d - outerBorder); + } + } else { + if(d > innerBorder) { + vec4 outerColor = outerBorder == 0.0 ? vec4(0) : vBorderColor; + vec4 innerBorderColor = blend(vBorderColor, vColor); + outColor = distInterp(innerBorderColor, outerColor, d); + } + else { + vec4 outerColor; + if(innerBorder == 0.0 && outerBorder == 0.0) { + outerColor = vec4(0); + } else if(innerBorder == 0.0) { + outerColor = vBorderColor; + } else { + outerColor = blend(vBorderColor, vColor); + } + outColor = distInterp(vColor, outerColor, d - innerBorder); + } + } + } + else { + outColor = vColor; + } + + ${e.picking?`if(outColor.a == 0.0) discard; + else outColor = vIndex;`:``} + } + `);i.aPosition=t.getAttribLocation(i,`aPosition`),i.aIndex=t.getAttribLocation(i,`aIndex`),i.aVertType=t.getAttribLocation(i,`aVertType`),i.aTransform=t.getAttribLocation(i,`aTransform`),i.aAtlasId=t.getAttribLocation(i,`aAtlasId`),i.aTex=t.getAttribLocation(i,`aTex`),i.aPointAPointB=t.getAttribLocation(i,`aPointAPointB`),i.aPointCPointD=t.getAttribLocation(i,`aPointCPointD`),i.aLineWidth=t.getAttribLocation(i,`aLineWidth`),i.aColor=t.getAttribLocation(i,`aColor`),i.aCornerRadius=t.getAttribLocation(i,`aCornerRadius`),i.aBorderColor=t.getAttribLocation(i,`aBorderColor`),i.uPanZoomMatrix=t.getUniformLocation(i,`uPanZoomMatrix`),i.uAtlasSize=t.getUniformLocation(i,`uAtlasSize`),i.uBGColor=t.getUniformLocation(i,`uBGColor`),i.uZoom=t.getUniformLocation(i,`uZoom`),i.uTextures=[];for(var a=0;a1&&arguments[1]!==void 0?arguments[1]:Sh.SCREEN;this.panZoomMatrix=e,this.renderTarget=t,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:`startBatch`,value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:`endFrame`,value:function(){this.endBatch()}},{key:`_isVisible`,value:function(e,t){return e.visible()?t&&t.isVisible?t.isVisible(e):!0:!1}},{key:`drawTexture`,value:function(e,t,n){var r=this.atlasManager,i=this.batchManager,a=r.getRenderTypeOpts(n);if(this._isVisible(e,a)&&!(e.isEdge()&&!this._isValidEdge(e))){if(this.renderTarget.picking&&a.getTexPickingMode){var o=a.getTexPickingMode(e);if(o===Ch.IGNORE)return;if(o==Ch.USE_BB){this.drawPickingRectangle(e,t,n);return}}var s=z(r.getAtlasInfo(e,n)),c;try{for(s.s();!(c=s.n()).done;){var l=c.value,u=l.atlas,d=l.tex1,f=l.tex2;i.canAddToCurrentBatch(u)||this.endBatch();for(var p=i.getAtlasIndexForBatch(u),m=0,h=[[d,!0],[f,!1]];m=this.maxInstances&&this.endBatch()}}}}catch(e){s.e(e)}finally{s.f()}}}},{key:`setTransformMatrix`,value:function(e,t,n,r){var i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=0;if(n.shapeProps&&n.shapeProps.padding&&(a=e.pstyle(n.shapeProps.padding).pfValue),r){var o=r.bb,s=r.tex1,c=r.tex2,l=s.w/(s.w+c.w);i||(l=1-l);var u=this._getAdjustedBB(o,a,i,l);this._applyTransformMatrix(t,u,n,e)}else{var d=n.getBoundingBox(e),f=this._getAdjustedBB(d,a,!0,1);this._applyTransformMatrix(t,f,n,e)}}},{key:`_applyTransformMatrix`,value:function(e,t,n,r){var i,a;sh(e);var o=n.getRotation?n.getRotation(r):0;if(o!==0){var s=n.getRotationPoint(r),c=s.x,l=s.y;lh(e,e,[c,l]),uh(e,e,o);var u=n.getRotationOffset(r);i=u.x+(t.xOffset||0),a=u.y+(t.yOffset||0)}else i=t.x1,a=t.y1;lh(e,e,[i,a]),dh(e,e,[t.w,t.h])}},{key:`_getAdjustedBB`,value:function(e,t,n,r){var i=e.x1,a=e.y1,o=e.w,s=e.h,c=e.yOffset;t&&(i-=t,a-=t,o+=2*t,s+=2*t);var l=0,u=o*r;return n&&r<1?o=u:!n&&r<1&&(l=o-u,i+=l,o=u),{x1:i,y1:a,w:o,h:s,xOffset:l,yOffset:c}}},{key:`drawPickingRectangle`,value:function(e,t,n){var r=this.atlasManager.getRenderTypeOpts(n),i=this.instanceCount;this.vertTypeBuffer.getView(i)[0]=Oh,Ym(t,this.indexBuffer.getView(i)),Jm([0,0,0],1,this.colorBuffer.getView(i));var a=this.transformBuffer.getMatrixView(i);this.setTransformMatrix(e,a,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:`drawNode`,value:function(e,t,n){var r=this.simpleShapeOptions.get(n);if(this._isVisible(e,r)){var i=r.shapeProps,a=this._getVertTypeForShape(e,i.shape);if(a===void 0||r.isSimple&&!r.isSimple(e,this.renderTarget)){this.drawTexture(e,t,n);return}var o=this.instanceCount;if(this.vertTypeBuffer.getView(o)[0]=a,a===kh||a===Ah){var s=r.getBoundingBox(e),c=this._getCornerRadius(e,i.radius,s),l=this.cornerRadiusBuffer.getView(o);l[0]=c,l[1]=c,l[2]=c,l[3]=c,a===Ah&&(l[0]=0,l[2]=0)}Ym(t,this.indexBuffer.getView(o));var u=this.renderTarget.picking?1:e.pstyle(i.opacity).value,d=e.pstyle(i.color).value;Jm(d,u,this.colorBuffer.getView(o));var f=this.lineWidthBuffer.getView(o);if(f[0]=0,f[1]=0,i.border){var p=e.pstyle(`border-width`).value;if(p>0){var m=e.pstyle(`border-color`).value,h=e.pstyle(`border-opacity`).value;Jm(m,h,this.borderColorBuffer.getView(o));var g=e.pstyle(`border-position`).value;if(g===`inside`)f[0]=0,f[1]=-p;else if(g===`outside`)f[0]=p,f[1]=0;else{var _=p/2;f[0]=_,f[1]=-_}}}var v=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(e,v,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:`_getVertTypeForShape`,value:function(e,t){switch(e.pstyle(t).value){case`rectangle`:return Oh;case`ellipse`:return jh;case`roundrectangle`:case`round-rectangle`:return kh;case`bottom-round-rectangle`:return Ah;default:return}}},{key:`_getCornerRadius`,value:function(e,t,n){var r=n.w,i=n.h;if(e.pstyle(t).value===`auto`)return li(r,i);var a=e.pstyle(t).pfValue,o=r/2,s=i/2;return Math.min(a,s,o)}},{key:`drawEdgeArrow`,value:function(e,t,n){if(e.visible()){var r=e._private.rscratch,i,a,o;if(n===`source`?(i=r.arrowStartX,a=r.arrowStartY,o=r.srcArrowAngle):(i=r.arrowEndX,a=r.arrowEndY,o=r.tgtArrowAngle),!(isNaN(i)||i==null||isNaN(a)||a==null||isNaN(o)||o==null)&&e.pstyle(n+`-arrow-shape`).value!==`none`){var s=e.pstyle(n+`-arrow-color`).value,c=e.pstyle(`opacity`).value*e.pstyle(`line-opacity`).value,l=e.pstyle(`width`).pfValue,u=e.pstyle(`arrow-scale`).value,d=this.r.getArrowWidth(l,u),f=this.instanceCount,p=this.transformBuffer.getMatrixView(f);sh(p),lh(p,p,[i,a]),dh(p,p,[d,d]),uh(p,p,o),this.vertTypeBuffer.getView(f)[0]=Dh,Ym(t,this.indexBuffer.getView(f)),Jm(s,c,this.colorBuffer.getView(f)),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}},{key:`drawEdgeLine`,value:function(e,t){if(e.visible()){var n=this._getEdgePoints(e);if(n){var r=e.pstyle(`opacity`).value,i=e.pstyle(`line-opacity`).value,a=e.pstyle(`width`).pfValue,o=e.pstyle(`line-color`).value,s=r*i;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var c=this.instanceCount;this.vertTypeBuffer.getView(c)[0]=Th,Ym(t,this.indexBuffer.getView(c)),Jm(o,s,this.colorBuffer.getView(c));var l=this.lineWidthBuffer.getView(c);l[0]=a;var u=this.pointAPointBBuffer.getView(c);u[0]=n[0],u[1]=n[1],u[2]=n[2],u[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var d=0;d=this.maxInstances&&this.endBatch()}}}}},{key:`_isValidEdge`,value:function(e){var t=e._private.rscratch;return!(t.badLine||t.allpts==null||isNaN(t.allpts[0]))}},{key:`_getEdgePoints`,value:function(e){var t=e._private.rscratch;if(this._isValidEdge(e)){var n=t.allpts;if(n.length==4)return n;var r=this._getNumSegments(e);return this._getCurveSegmentPoints(n,r)}}},{key:`_getNumSegments`,value:function(e){return Math.min(15,this.maxInstances)}},{key:`_getCurveSegmentPoints`,value:function(e,t){if(e.length==4)return e;for(var n=Array((t+1)*2),r=0;r<=t;r++)if(r==0)n[0]=e[0],n[1]=e[1];else if(r==t)n[r*2]=e[e.length-2],n[r*2+1]=e[e.length-1];else{var i=r/t;this._setCurvePoint(e,i,n,r*2)}return n}},{key:`_setCurvePoint`,value:function(e,t,n,r){if(e.length<=2)n[r]=e[0],n[r+1]=e[1];else{for(var i=Array(e.length-2),a=0;a0}},s=function(e){return e.pstyle(`text-events`).strValue===`yes`?Ch.USE_BB:Ch.IGNORE},c=function(e){var t=e.position(),n=t.x,r=t.y,i=e.outerWidth(),a=e.outerHeight();return{w:i,h:a,x1:n-i/2,y1:r-a/2}};n.drawing.addAtlasCollection(`node`,{texRows:e.webglTexRowsNodes}),n.drawing.addAtlasCollection(`label`,{texRows:e.webglTexRows}),n.drawing.addTextureAtlasRenderType(`node-body`,{collection:`node`,getKey:t.getStyleKey,getBoundingBox:t.getElementBox,drawElement:t.drawElement}),n.drawing.addSimpleShapeRenderType(`node-body`,{getBoundingBox:c,isSimple:Km,shapeProps:{shape:`shape`,color:`background-color`,opacity:`background-opacity`,radius:`corner-radius`,border:!0}}),n.drawing.addSimpleShapeRenderType(`node-overlay`,{getBoundingBox:c,isVisible:o(`overlay`),shapeProps:{shape:`overlay-shape`,color:`overlay-color`,opacity:`overlay-opacity`,padding:`overlay-padding`,radius:`overlay-corner-radius`}}),n.drawing.addSimpleShapeRenderType(`node-underlay`,{getBoundingBox:c,isVisible:o(`underlay`),shapeProps:{shape:`underlay-shape`,color:`underlay-color`,opacity:`underlay-opacity`,padding:`underlay-padding`,radius:`underlay-corner-radius`}}),n.drawing.addTextureAtlasRenderType(`label`,{collection:`label`,getTexPickingMode:s,getKey:Ih(t.getLabelKey,null),getBoundingBox:Lh(t.getLabelBox,null),drawClipped:!0,drawElement:t.drawLabel,getRotation:i(null),getRotationPoint:t.getLabelRotationPoint,getRotationOffset:t.getLabelRotationOffset,isVisible:a(`label`)}),n.drawing.addTextureAtlasRenderType(`edge-source-label`,{collection:`label`,getTexPickingMode:s,getKey:Ih(t.getSourceLabelKey,`source`),getBoundingBox:Lh(t.getSourceLabelBox,`source`),drawClipped:!0,drawElement:t.drawSourceLabel,getRotation:i(`source`),getRotationPoint:t.getSourceLabelRotationPoint,getRotationOffset:t.getSourceLabelRotationOffset,isVisible:a(`source-label`)}),n.drawing.addTextureAtlasRenderType(`edge-target-label`,{collection:`label`,getTexPickingMode:s,getKey:Ih(t.getTargetLabelKey,`target`),getBoundingBox:Lh(t.getTargetLabelBox,`target`),drawClipped:!0,drawElement:t.drawTargetLabel,getRotation:i(`target`),getRotationPoint:t.getTargetLabelRotationPoint,getRotationOffset:t.getTargetLabelRotationOffset,isVisible:a(`target-label`)});var l=zt(function(){console.log(`garbage collect flag set`),n.data.gc=!0},1e4);n.onUpdateEleCalcs(function(e,t){var r=!1;t&&t.length>0&&(r|=n.drawing.invalidate(t)),r&&l()}),Rh(n)};function Ph(e){var t=e.cy.container();return Ge(t&&t.style&&t.style.backgroundColor||`white`)}function Fh(e,t){var n=e._private.rscratch;return kn(n,`labelWrapCachedLines`,t)||[]}var Ih=function(e,t){return function(n){var r=e(n),i=Fh(n,t);return i.length>1?i.map(function(e,t){return`${r}_${t}`}):r}},Lh=function(e,t){return function(n,r){var i=e(n);if(typeof r==`string`){var a=r.indexOf(`_`);if(a>0){var o=Number(r.substring(a+1)),s=Fh(n,t),c=i.h/s.length,l=c*o,u=i.y1+l;return{x1:i.x1,w:i.w,y1:u,h:c,yOffset:l}}}return i}};function Rh(e){var t=e.render;e.render=function(n){n||={};var r=e.cy;e.webgl&&(r.zoom()>Mp?(zh(e),t.call(e,n)):(Bh(e),Yh(e,n,Sh.SCREEN)))};var n=e.matchCanvasSize;e.matchCanvasSize=function(t){n.call(e,t),e.pickingFrameBuffer.setFramebufferAttachmentSizes(e.canvasWidth,e.canvasHeight),e.pickingFrameBuffer.needsDraw=!0},e.findNearestElements=function(t,n,r,i){return qh(e,t,n)};var r=e.invalidateCachedZSortedEles;e.invalidateCachedZSortedEles=function(){r.call(e),e.pickingFrameBuffer.needsDraw=!0};var i=e.notify;e.notify=function(t,n){i.call(e,t,n),t===`viewport`||t===`bounds`?e.pickingFrameBuffer.needsDraw=!0:t===`background`&&e.drawing.invalidate(n,{type:`node-body`})}}function zh(e){var t=e.data.contexts[e.WEBGL];t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT)}function Bh(e){var t=function(t){t.save(),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,e.canvasWidth,e.canvasHeight),t.restore()};t(e.data.contexts[e.NODE]),t(e.data.contexts[e.DRAG])}function Vh(e){var t=e.canvasWidth,n=e.canvasHeight,r=Um(e),i=r.pan,a=r.zoom,o=oh();lh(o,o,[i.x,i.y]),dh(o,o,[a,a]);var s=oh();fh(s,t,n);var c=oh();return ch(c,s,o),c}function Hh(e,t){var n=e.canvasWidth,r=e.canvasHeight,i=Um(e),a=i.pan,o=i.zoom;t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,n,r),t.translate(a.x,a.y),t.scale(o,o)}function Uh(e,t){e.drawSelectionRectangle(t,function(t){return Hh(e,t)})}function Wh(e){var t=e.data.contexts[e.NODE];t.save(),Hh(e,t),t.strokeStyle=`rgba(0, 0, 0, 0.3)`,t.beginPath(),t.moveTo(-1e3,0),t.lineTo(1e3,0),t.stroke(),t.beginPath(),t.moveTo(0,-1e3),t.lineTo(0,1e3),t.stroke(),t.restore()}function Gh(e){var t=function(t,n,r){for(var i=t.atlasManager.getAtlasCollection(n),a=e.data.contexts[e.NODE],o=i.atlases,s=0;s=0&&y.add(x)}return y}function qh(e,t,n){var r=Kh(e,t,n),i=e.getCachedZSortedEles(),a,o,s=z(r),c;try{for(s.s();!(c=s.n()).done;){var l=i[c.value];if(!a&&l.isNode()&&(a=l),!o&&l.isEdge()&&(o=l),a&&o)break}}catch(e){s.e(e)}finally{s.f()}return[a,o].filter(Boolean)}function Jh(e,t,n){var r=e.drawing;t+=1,n.isNode()?(r.drawNode(n,t,`node-underlay`),r.drawNode(n,t,`node-body`),r.drawTexture(n,t,`label`),r.drawNode(n,t,`node-overlay`)):(r.drawEdgeLine(n,t),r.drawEdgeArrow(n,t,`source`),r.drawEdgeArrow(n,t,`target`),r.drawTexture(n,t,`label`),r.drawTexture(n,t,`edge-source-label`),r.drawTexture(n,t,`edge-target-label`))}function Yh(e,t,n){var r;e.webglDebug&&(r=performance.now());var i=e.drawing,a=0;if(n.screen&&e.data.canvasNeedsRedraw[e.SELECT_BOX]&&Uh(e,t),e.data.canvasNeedsRedraw[e.NODE]||n.picking){var o=e.data.contexts[e.WEBGL];n.screen?(o.clearColor(0,0,0,0),o.enable(o.BLEND),o.blendFunc(o.ONE,o.ONE_MINUS_SRC_ALPHA)):o.disable(o.BLEND),o.clear(o.COLOR_BUFFER_BIT|o.DEPTH_BUFFER_BIT),o.viewport(0,0,o.canvas.width,o.canvas.height);var s=Vh(e),c=e.getCachedZSortedEles();if(a=c.length,i.startFrame(s,n),n.screen){for(var l=0;l0&&a>0){f.clearRect(0,0,i,a),f.globalCompositeOperation=`source-over`;var p=this.getCachedZSortedEles();if(e.full)f.translate(-n.x1*c,-n.y1*c),f.scale(c,c),this.drawElements(f,p),f.scale(1/c,1/c),f.translate(n.x1*c,n.y1*c);else{var m=t.pan(),h={x:m.x*c,y:m.y*c};c*=t.zoom(),f.translate(h.x,h.y),f.scale(c,c),this.drawElements(f,p),f.scale(1/c,1/c),f.translate(-h.x,-h.y)}e.bg&&(f.globalCompositeOperation=`destination-over`,f.fillStyle=e.bg,f.rect(0,0,i,a),f.fill())}return d};function ig(e,t){for(var n=atob(e),r=new ArrayBuffer(n.length),i=new Uint8Array(r),a=0;a`u`?`undefined`:q(OffscreenCanvas))===`undefined`?(n=this.cy.window().document.createElement(`canvas`),n.width=e,n.height=t):n=new OffscreenCanvas(e,t),n},[hm,Sm,km,jm,Mm,Fm,Lm,Nh,Xh,rg,sg].forEach(function(e){Z(lg,e)});var fg=[{type:`layout`,extensions:wf},{type:`renderer`,extensions:[{name:`null`,impl:Tf},{name:`base`,impl:Cp},{name:`canvas`,impl:cg}]}],pg={},mg={};function hg(e,t,n){var r=n,i=function(n){vn("Can not register `"+t+"` for `"+e+"` since `"+n+"` already exists in the prototype and can not be overridden")};if(e===`core`){if(Fd.prototype[t])return i(t);Fd.prototype[t]=n}else if(e===`collection`){if(Yu.prototype[t])return i(t);Yu.prototype[t]=n}else if(e===`layout`){for(var a=function(e){this.options=e,n.call(this,e),Y(this._private)||(this._private={}),this._private.cy=e.cy,this._private.listeners=[],this.createEmitter()},o=a.prototype=Object.create(n.prototype),s=[],c=0;c{(function(n,r){typeof e==`object`&&typeof t==`object`?t.exports=r():typeof define==`function`&&define.amd?define([],r):typeof e==`object`?e.layoutBase=r():n.layoutBase=r()})(e,function(){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=26)})([(function(e,t,n){function r(){}r.QUALITY=1,r.DEFAULT_CREATE_BENDS_AS_NEEDED=!1,r.DEFAULT_INCREMENTAL=!1,r.DEFAULT_ANIMATION_ON_LAYOUT=!0,r.DEFAULT_ANIMATION_DURING_LAYOUT=!1,r.DEFAULT_ANIMATION_PERIOD=50,r.DEFAULT_UNIFORM_LEAF_NODE_SIZES=!1,r.DEFAULT_GRAPH_MARGIN=15,r.NODE_DIMENSIONS_INCLUDE_LABELS=!1,r.SIMPLE_NODE_SIZE=40,r.SIMPLE_NODE_HALF_SIZE=r.SIMPLE_NODE_SIZE/2,r.EMPTY_COMPOUND_NODE_SIZE=40,r.MIN_EDGE_LENGTH=1,r.WORLD_BOUNDARY=1e6,r.INITIAL_WORLD_BOUNDARY=r.WORLD_BOUNDARY/1e3,r.WORLD_CENTER_X=1200,r.WORLD_CENTER_Y=900,e.exports=r}),(function(e,t,n){var r=n(2),i=n(8),a=n(9);function o(e,t,n){r.call(this,n),this.isOverlapingSourceAndTarget=!1,this.vGraphObject=n,this.bendpoints=[],this.source=e,this.target=t}for(var s in o.prototype=Object.create(r.prototype),r)o[s]=r[s];o.prototype.getSource=function(){return this.source},o.prototype.getTarget=function(){return this.target},o.prototype.isInterGraph=function(){return this.isInterGraph},o.prototype.getLength=function(){return this.length},o.prototype.isOverlapingSourceAndTarget=function(){return this.isOverlapingSourceAndTarget},o.prototype.getBendpoints=function(){return this.bendpoints},o.prototype.getLca=function(){return this.lca},o.prototype.getSourceInLca=function(){return this.sourceInLca},o.prototype.getTargetInLca=function(){return this.targetInLca},o.prototype.getOtherEnd=function(e){if(this.source===e)return this.target;if(this.target===e)return this.source;throw`Node is not incident with this edge`},o.prototype.getOtherEndInGraph=function(e,t){for(var n=this.getOtherEnd(e),r=t.getGraphManager().getRoot();;){if(n.getOwner()==t)return n;if(n.getOwner()==r)break;n=n.getOwner().getParent()}return null},o.prototype.updateLength=function(){var e=[,,,,];this.isOverlapingSourceAndTarget=i.getIntersection(this.target.getRect(),this.source.getRect(),e),this.isOverlapingSourceAndTarget||(this.lengthX=e[0]-e[2],this.lengthY=e[1]-e[3],Math.abs(this.lengthX)<1&&(this.lengthX=a.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=a.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY))},o.prototype.updateLengthSimple=function(){this.lengthX=this.target.getCenterX()-this.source.getCenterX(),this.lengthY=this.target.getCenterY()-this.source.getCenterY(),Math.abs(this.lengthX)<1&&(this.lengthX=a.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=a.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY)},e.exports=o}),(function(e,t,n){function r(e){this.vGraphObject=e}e.exports=r}),(function(e,t,n){var r=n(2),i=n(10),a=n(13),o=n(0),s=n(16),c=n(4);function l(e,t,n,o){n==null&&o==null&&(o=t),r.call(this,o),e.graphManager!=null&&(e=e.graphManager),this.estimatedSize=i.MIN_VALUE,this.inclusionTreeDepth=i.MAX_VALUE,this.vGraphObject=o,this.edges=[],this.graphManager=e,n!=null&&t!=null?this.rect=new a(t.x,t.y,n.width,n.height):this.rect=new a}for(var u in l.prototype=Object.create(r.prototype),r)l[u]=r[u];l.prototype.getEdges=function(){return this.edges},l.prototype.getChild=function(){return this.child},l.prototype.getOwner=function(){return this.owner},l.prototype.getWidth=function(){return this.rect.width},l.prototype.setWidth=function(e){this.rect.width=e},l.prototype.getHeight=function(){return this.rect.height},l.prototype.setHeight=function(e){this.rect.height=e},l.prototype.getCenterX=function(){return this.rect.x+this.rect.width/2},l.prototype.getCenterY=function(){return this.rect.y+this.rect.height/2},l.prototype.getCenter=function(){return new c(this.rect.x+this.rect.width/2,this.rect.y+this.rect.height/2)},l.prototype.getLocation=function(){return new c(this.rect.x,this.rect.y)},l.prototype.getRect=function(){return this.rect},l.prototype.getDiagonal=function(){return Math.sqrt(this.rect.width*this.rect.width+this.rect.height*this.rect.height)},l.prototype.getHalfTheDiagonal=function(){return Math.sqrt(this.rect.height*this.rect.height+this.rect.width*this.rect.width)/2},l.prototype.setRect=function(e,t){this.rect.x=e.x,this.rect.y=e.y,this.rect.width=t.width,this.rect.height=t.height},l.prototype.setCenter=function(e,t){this.rect.x=e-this.rect.width/2,this.rect.y=t-this.rect.height/2},l.prototype.setLocation=function(e,t){this.rect.x=e,this.rect.y=t},l.prototype.moveBy=function(e,t){this.rect.x+=e,this.rect.y+=t},l.prototype.getEdgeListToNode=function(e){var t=[],n=this;return n.edges.forEach(function(r){if(r.target==e){if(r.source!=n)throw`Incorrect edge source!`;t.push(r)}}),t},l.prototype.getEdgesBetween=function(e){var t=[],n=this;return n.edges.forEach(function(r){if(!(r.source==n||r.target==n))throw`Incorrect edge source and/or target`;(r.target==e||r.source==e)&&t.push(r)}),t},l.prototype.getNeighborsList=function(){var e=new Set,t=this;return t.edges.forEach(function(n){if(n.source==t)e.add(n.target);else{if(n.target!=t)throw`Incorrect incidency!`;e.add(n.source)}}),e},l.prototype.withChildren=function(){var e=new Set,t,n;if(e.add(this),this.child!=null)for(var r=this.child.getNodes(),i=0;it&&(this.rect.x-=(this.labelWidth-t)/2,this.setWidth(this.labelWidth)),this.labelHeight>n&&(this.labelPos==`center`?this.rect.y-=(this.labelHeight-n)/2:this.labelPos==`top`&&(this.rect.y-=this.labelHeight-n),this.setHeight(this.labelHeight))}}},l.prototype.getInclusionTreeDepth=function(){if(this.inclusionTreeDepth==i.MAX_VALUE)throw`assert failed`;return this.inclusionTreeDepth},l.prototype.transform=function(e){var t=this.rect.x;t>o.WORLD_BOUNDARY?t=o.WORLD_BOUNDARY:t<-o.WORLD_BOUNDARY&&(t=-o.WORLD_BOUNDARY);var n=this.rect.y;n>o.WORLD_BOUNDARY?n=o.WORLD_BOUNDARY:n<-o.WORLD_BOUNDARY&&(n=-o.WORLD_BOUNDARY);var r=new c(t,n),i=e.inverseTransformPoint(r);this.setLocation(i.x,i.y)},l.prototype.getLeft=function(){return this.rect.x},l.prototype.getRight=function(){return this.rect.x+this.rect.width},l.prototype.getTop=function(){return this.rect.y},l.prototype.getBottom=function(){return this.rect.y+this.rect.height},l.prototype.getParent=function(){return this.owner==null?null:this.owner.getParent()},e.exports=l}),(function(e,t,n){function r(e,t){e==null&&t==null?(this.x=0,this.y=0):(this.x=e,this.y=t)}r.prototype.getX=function(){return this.x},r.prototype.getY=function(){return this.y},r.prototype.setX=function(e){this.x=e},r.prototype.setY=function(e){this.y=e},r.prototype.getDifference=function(e){return new DimensionD(this.x-e.x,this.y-e.y)},r.prototype.getCopy=function(){return new r(this.x,this.y)},r.prototype.translate=function(e){return this.x+=e.width,this.y+=e.height,this},e.exports=r}),(function(e,t,n){var r=n(2),i=n(10),a=n(0),o=n(6),s=n(3),c=n(1),l=n(13),u=n(12),d=n(11);function f(e,t,n){r.call(this,n),this.estimatedSize=i.MIN_VALUE,this.margin=a.DEFAULT_GRAPH_MARGIN,this.edges=[],this.nodes=[],this.isConnected=!1,this.parent=e,t!=null&&t instanceof o?this.graphManager=t:t!=null&&t instanceof Layout&&(this.graphManager=t.graphManager)}for(var p in f.prototype=Object.create(r.prototype),r)f[p]=r[p];f.prototype.getNodes=function(){return this.nodes},f.prototype.getEdges=function(){return this.edges},f.prototype.getGraphManager=function(){return this.graphManager},f.prototype.getParent=function(){return this.parent},f.prototype.getLeft=function(){return this.left},f.prototype.getRight=function(){return this.right},f.prototype.getTop=function(){return this.top},f.prototype.getBottom=function(){return this.bottom},f.prototype.isConnected=function(){return this.isConnected},f.prototype.add=function(e,t,n){if(t==null&&n==null){var r=e;if(this.graphManager==null)throw`Graph has no graph mgr!`;if(this.getNodes().indexOf(r)>-1)throw`Node already in graph!`;return r.owner=this,this.getNodes().push(r),r}else{var i=e;if(!(this.getNodes().indexOf(t)>-1&&this.getNodes().indexOf(n)>-1))throw`Source or target not in graph!`;if(!(t.owner==n.owner&&t.owner==this))throw`Both owners must be this graph!`;return t.owner==n.owner?(i.source=t,i.target=n,i.isInterGraph=!1,this.getEdges().push(i),t.edges.push(i),n!=t&&n.edges.push(i),i):null}},f.prototype.remove=function(e){var t=e;if(e instanceof s){if(t==null)throw`Node is null!`;if(!(t.owner!=null&&t.owner==this))throw`Owner graph is invalid!`;if(this.graphManager==null)throw`Owner graph manager is invalid!`;for(var n=t.edges.slice(),r,i=n.length,a=0;a-1&&u>-1))throw`Source and/or target doesn't know this edge!`;r.source.edges.splice(l,1),r.target!=r.source&&r.target.edges.splice(u,1);var o=r.source.owner.getEdges().indexOf(r);if(o==-1)throw`Not in owner's edge list!`;r.source.owner.getEdges().splice(o,1)}},f.prototype.updateLeftTop=function(){for(var e=i.MAX_VALUE,t=i.MAX_VALUE,n,r,a,o=this.getNodes(),s=o.length,c=0;cn&&(e=n),t>r&&(t=r)}return e==i.MAX_VALUE?null:(a=o[0].getParent().paddingLeft==null?this.margin:o[0].getParent().paddingLeft,this.left=t-a,this.top=e-a,new u(this.left,this.top))},f.prototype.updateBounds=function(e){for(var t=i.MAX_VALUE,n=-i.MAX_VALUE,r=i.MAX_VALUE,a=-i.MAX_VALUE,o,s,c,u,d,f=this.nodes,p=f.length,m=0;mo&&(t=o),nc&&(r=c),ao&&(t=o),nc&&(r=c),a=this.nodes.length){var c=0;n.forEach(function(t){t.owner==e&&c++}),c==this.nodes.length&&(this.isConnected=!0)}},e.exports=f}),(function(e,t,n){var r,i=n(1);function a(e){r=n(5),this.layout=e,this.graphs=[],this.edges=[]}a.prototype.addRoot=function(){var e=this.layout.newGraph(),t=this.layout.newNode(null),n=this.add(e,t);return this.setRootGraph(n),this.rootGraph},a.prototype.add=function(e,t,n,r,i){if(n==null&&r==null&&i==null){if(e==null)throw`Graph is null!`;if(t==null)throw`Parent node is null!`;if(this.graphs.indexOf(e)>-1)throw`Graph already in this graph mgr!`;if(this.graphs.push(e),e.parent!=null)throw`Already has a parent!`;if(t.child!=null)throw`Already has a child!`;return e.parent=t,t.child=e,e}else{i=n,r=t,n=e;var a=r.getOwner(),o=i.getOwner();if(!(a!=null&&a.getGraphManager()==this))throw`Source not in this graph mgr!`;if(!(o!=null&&o.getGraphManager()==this))throw`Target not in this graph mgr!`;if(a==o)return n.isInterGraph=!1,a.add(n,r,i);if(n.isInterGraph=!0,n.source=r,n.target=i,this.edges.indexOf(n)>-1)throw`Edge already in inter-graph edge list!`;if(this.edges.push(n),!(n.source!=null&&n.target!=null))throw`Edge source and/or target is null!`;if(!(n.source.edges.indexOf(n)==-1&&n.target.edges.indexOf(n)==-1))throw`Edge already in source and/or target incidency list!`;return n.source.edges.push(n),n.target.edges.push(n),n}},a.prototype.remove=function(e){if(e instanceof r){var t=e;if(t.getGraphManager()!=this)throw`Graph not in this graph mgr`;if(!(t==this.rootGraph||t.parent!=null&&t.parent.graphManager==this))throw`Invalid parent node!`;var n=[];n=n.concat(t.getEdges());for(var a,o=n.length,s=0;s=t.getRight()?n[0]+=Math.min(t.getX()-e.getX(),e.getRight()-t.getRight()):t.getX()<=e.getX()&&t.getRight()>=e.getRight()&&(n[0]+=Math.min(e.getX()-t.getX(),t.getRight()-e.getRight())),e.getY()<=t.getY()&&e.getBottom()>=t.getBottom()?n[1]+=Math.min(t.getY()-e.getY(),e.getBottom()-t.getBottom()):t.getY()<=e.getY()&&t.getBottom()>=e.getBottom()&&(n[1]+=Math.min(e.getY()-t.getY(),t.getBottom()-e.getBottom()));var a=Math.abs((t.getCenterY()-e.getCenterY())/(t.getCenterX()-e.getCenterX()));t.getCenterY()===e.getCenterY()&&t.getCenterX()===e.getCenterX()&&(a=1);var o=a*n[0],s=n[1]/a;n[0]o)return n[0]=r,n[1]=c,n[2]=a,n[3]=y,!1;if(ia)return n[0]=s,n[1]=i,n[2]=_,n[3]=o,!1;if(ra?(n[0]=u,n[1]=d,C=!0):(n[0]=l,n[1]=c,C=!0):T===D&&(r>a?(n[0]=s,n[1]=c,C=!0):(n[0]=f,n[1]=d,C=!0)),-E===D?a>r?(n[2]=v,n[3]=y,w=!0):(n[2]=_,n[3]=g,w=!0):E===D&&(a>r?(n[2]=h,n[3]=g,w=!0):(n[2]=b,n[3]=y,w=!0)),C&&w)return!1;if(r>a?i>o?(O=this.getCardinalDirection(T,D,4),k=this.getCardinalDirection(E,D,2)):(O=this.getCardinalDirection(-T,D,3),k=this.getCardinalDirection(-E,D,1)):i>o?(O=this.getCardinalDirection(-T,D,1),k=this.getCardinalDirection(-E,D,3)):(O=this.getCardinalDirection(T,D,2),k=this.getCardinalDirection(E,D,4)),!C)switch(O){case 1:j=c,A=r+-m/D,n[0]=A,n[1]=j;break;case 2:A=f,j=i+p*D,n[0]=A,n[1]=j;break;case 3:j=d,A=r+m/D,n[0]=A,n[1]=j;break;case 4:A=u,j=i+-p*D,n[0]=A,n[1]=j;break}if(!w)switch(k){case 1:N=g,M=a+-S/D,n[2]=M,n[3]=N;break;case 2:M=b,N=o+x*D,n[2]=M,n[3]=N;break;case 3:N=y,M=a+S/D,n[2]=M,n[3]=N;break;case 4:M=v,N=o+-x*D,n[2]=M,n[3]=N;break}}return!1},i.getCardinalDirection=function(e,t,n){return e>t?n:1+n%4},i.getIntersection=function(e,t,n,i){if(i==null)return this.getIntersection2(e,t,n);var a=e.x,o=e.y,s=t.x,c=t.y,l=n.x,u=n.y,d=i.x,f=i.y,p=void 0,m=void 0,h=void 0,g=void 0,_=void 0,v=void 0,y=void 0,b=void 0,x=void 0;return h=c-o,_=a-s,y=s*o-a*c,g=f-u,v=l-d,b=d*u-l*f,x=h*v-g*_,x===0?null:(p=(_*b-v*y)/x,m=(g*y-h*b)/x,new r(p,m))},i.angleOfVector=function(e,t,n,r){var i=void 0;return e===n?i=r0?1:e<0?-1:0},r.floor=function(e){return e<0?Math.ceil(e):Math.floor(e)},r.ceil=function(e){return e<0?Math.floor(e):Math.ceil(e)},e.exports=r}),(function(e,t,n){function r(){}r.MAX_VALUE=2147483647,r.MIN_VALUE=-2147483648,e.exports=r}),(function(e,t,n){var r=function(){function e(e,t){for(var n=0;n0&&t;){for(s.push(l[0]);s.length>0&&t;){var u=s[0];s.splice(0,1),o.add(u);for(var d=u.getEdges(),a=0;a-1&&l.splice(h,1)}o=new Set,c=new Map}}return e},f.prototype.createDummyNodesForBendpoints=function(e){for(var t=[],n=e.source,r=this.graphManager.calcLowestCommonAncestor(e.source,e.target),i=0;i0){for(var i=this.edgeToDummyNodes.get(n),a=0;a=0&&t.splice(d,1),s.getNeighborsList().forEach(function(e){if(n.indexOf(e)<0){var t=r.get(e)-1;t==1&&l.push(e),r.set(e,t)}})}n=n.concat(l),(t.length==1||t.length==2)&&(i=!0,a=t[0])}return a},f.prototype.setGraphManager=function(e){this.graphManager=e},e.exports=f}),(function(e,t,n){function r(){}r.seed=1,r.x=0,r.nextDouble=function(){return r.x=Math.sin(r.seed++)*1e4,r.x-Math.floor(r.x)},e.exports=r}),(function(e,t,n){var r=n(4);function i(e,t){this.lworldOrgX=0,this.lworldOrgY=0,this.ldeviceOrgX=0,this.ldeviceOrgY=0,this.lworldExtX=1,this.lworldExtY=1,this.ldeviceExtX=1,this.ldeviceExtY=1}i.prototype.getWorldOrgX=function(){return this.lworldOrgX},i.prototype.setWorldOrgX=function(e){this.lworldOrgX=e},i.prototype.getWorldOrgY=function(){return this.lworldOrgY},i.prototype.setWorldOrgY=function(e){this.lworldOrgY=e},i.prototype.getWorldExtX=function(){return this.lworldExtX},i.prototype.setWorldExtX=function(e){this.lworldExtX=e},i.prototype.getWorldExtY=function(){return this.lworldExtY},i.prototype.setWorldExtY=function(e){this.lworldExtY=e},i.prototype.getDeviceOrgX=function(){return this.ldeviceOrgX},i.prototype.setDeviceOrgX=function(e){this.ldeviceOrgX=e},i.prototype.getDeviceOrgY=function(){return this.ldeviceOrgY},i.prototype.setDeviceOrgY=function(e){this.ldeviceOrgY=e},i.prototype.getDeviceExtX=function(){return this.ldeviceExtX},i.prototype.setDeviceExtX=function(e){this.ldeviceExtX=e},i.prototype.getDeviceExtY=function(){return this.ldeviceExtY},i.prototype.setDeviceExtY=function(e){this.ldeviceExtY=e},i.prototype.transformX=function(e){var t=0,n=this.lworldExtX;return n!=0&&(t=this.ldeviceOrgX+(e-this.lworldOrgX)*this.ldeviceExtX/n),t},i.prototype.transformY=function(e){var t=0,n=this.lworldExtY;return n!=0&&(t=this.ldeviceOrgY+(e-this.lworldOrgY)*this.ldeviceExtY/n),t},i.prototype.inverseTransformX=function(e){var t=0,n=this.ldeviceExtX;return n!=0&&(t=this.lworldOrgX+(e-this.ldeviceOrgX)*this.lworldExtX/n),t},i.prototype.inverseTransformY=function(e){var t=0,n=this.ldeviceExtY;return n!=0&&(t=this.lworldOrgY+(e-this.ldeviceOrgY)*this.lworldExtY/n),t},i.prototype.inverseTransformPoint=function(e){return new r(this.inverseTransformX(e.x),this.inverseTransformY(e.y))},e.exports=i}),(function(e,t,n){function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ta.ADAPTATION_LOWER_NODE_LIMIT&&(this.coolingFactor=Math.max(this.coolingFactor*a.COOLING_ADAPTATION_FACTOR,this.coolingFactor-(e-a.ADAPTATION_LOWER_NODE_LIMIT)/(a.ADAPTATION_UPPER_NODE_LIMIT-a.ADAPTATION_LOWER_NODE_LIMIT)*this.coolingFactor*(1-a.COOLING_ADAPTATION_FACTOR))),this.maxNodeDisplacement=a.MAX_NODE_DISPLACEMENT_INCREMENTAL):(e>a.ADAPTATION_LOWER_NODE_LIMIT?this.coolingFactor=Math.max(a.COOLING_ADAPTATION_FACTOR,1-(e-a.ADAPTATION_LOWER_NODE_LIMIT)/(a.ADAPTATION_UPPER_NODE_LIMIT-a.ADAPTATION_LOWER_NODE_LIMIT)*(1-a.COOLING_ADAPTATION_FACTOR)):this.coolingFactor=1,this.initialCoolingFactor=this.coolingFactor,this.maxNodeDisplacement=a.MAX_NODE_DISPLACEMENT),this.maxIterations=Math.max(this.getAllNodes().length*5,this.maxIterations),this.totalDisplacementThreshold=this.displacementThresholdPerNode*this.getAllNodes().length,this.repulsionRange=this.calcRepulsionRange()},l.prototype.calcSpringForces=function(){for(var e=this.getAllEdges(),t,n=0;n0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n,r,i,o,s=this.getAllNodes(),c;if(this.useFRGridVariant)for(this.totalIterations%a.GRID_CALCULATION_CHECK_PERIOD==1&&e&&this.updateGrid(),c=new Set,n=0;nc||s>c)&&(e.gravitationForceX=-this.gravityConstant*i,e.gravitationForceY=-this.gravityConstant*a)):(c=t.getEstimatedSize()*this.compoundGravityRangeFactor,(o>c||s>c)&&(e.gravitationForceX=-this.gravityConstant*i*this.compoundGravityConstant,e.gravitationForceY=-this.gravityConstant*a*this.compoundGravityConstant))},l.prototype.isConverged=function(){var e,t=!1;return this.totalIterations>this.maxIterations/3&&(t=Math.abs(this.totalDisplacement-this.oldTotalDisplacement)<2),e=this.totalDisplacement=c.length||u>=c[0].length)){for(var d=0;de}}]),e}()}),(function(e,t,n){var r=function(){function e(e,t){for(var n=0;n2&&arguments[2]!==void 0?arguments[2]:1,a=arguments.length>3&&arguments[3]!==void 0?arguments[3]:-1,o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:-1;i(this,e),this.sequence1=t,this.sequence2=n,this.match_score=r,this.mismatch_penalty=a,this.gap_penalty=o,this.iMax=t.length+1,this.jMax=n.length+1,this.grid=Array(this.iMax);for(var s=0;s=0;n--){var r=this.listeners[n];r.event===e&&r.callback===t&&this.listeners.splice(n,1)}},i.emit=function(e,t){for(var n=0;n{(function(n,r){typeof e==`object`&&typeof t==`object`?t.exports=r(wg()):typeof define==`function`&&define.amd?define([`layout-base`],r):typeof e==`object`?e.coseBase=r(wg()):n.coseBase=r(n.layoutBase)})(e,function(e){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=7)})([(function(t,n){t.exports=e}),(function(e,t,n){var r=n(0).FDLayoutConstants;function i(){}for(var a in r)i[a]=r[a];i.DEFAULT_USE_MULTI_LEVEL_SCALING=!1,i.DEFAULT_RADIAL_SEPARATION=r.DEFAULT_EDGE_LENGTH,i.DEFAULT_COMPONENT_SEPERATION=60,i.TILE=!0,i.TILING_PADDING_VERTICAL=10,i.TILING_PADDING_HORIZONTAL=10,i.TREE_REDUCTION_ON_INCREMENTAL=!1,e.exports=i}),(function(e,t,n){var r=n(0).FDLayoutEdge;function i(e,t,n){r.call(this,e,t,n)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).LGraph;function i(e,t,n){r.call(this,e,t,n)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).LGraphManager;function i(e){r.call(this,e)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).FDLayoutNode,i=n(0).IMath;function a(e,t,n,i){r.call(this,e,t,n,i)}for(var o in a.prototype=Object.create(r.prototype),r)a[o]=r[o];a.prototype.move=function(){var e=this.graphManager.getLayout();this.displacementX=e.coolingFactor*(this.springForceX+this.repulsionForceX+this.gravitationForceX)/this.noOfChildren,this.displacementY=e.coolingFactor*(this.springForceY+this.repulsionForceY+this.gravitationForceY)/this.noOfChildren,Math.abs(this.displacementX)>e.coolingFactor*e.maxNodeDisplacement&&(this.displacementX=e.coolingFactor*e.maxNodeDisplacement*i.sign(this.displacementX)),Math.abs(this.displacementY)>e.coolingFactor*e.maxNodeDisplacement&&(this.displacementY=e.coolingFactor*e.maxNodeDisplacement*i.sign(this.displacementY)),this.child==null||this.child.getNodes().length==0?this.moveBy(this.displacementX,this.displacementY):this.propogateDisplacementToChildren(this.displacementX,this.displacementY),e.totalDisplacement+=Math.abs(this.displacementX)+Math.abs(this.displacementY),this.springForceX=0,this.springForceY=0,this.repulsionForceX=0,this.repulsionForceY=0,this.gravitationForceX=0,this.gravitationForceY=0,this.displacementX=0,this.displacementY=0},a.prototype.propogateDisplacementToChildren=function(e,t){for(var n=this.getChild().getNodes(),r,i=0;i0)this.positionNodesRadially(e);else{this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var t=new Set(this.getAllNodes()),n=this.nodesWithGravity.filter(function(e){return t.has(e)});this.graphManager.setAllNodesToApplyGravitation(n),this.positionNodesRandomly()}}else if(c.TREE_REDUCTION_ON_INCREMENTAL){this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var t=new Set(this.getAllNodes()),n=this.nodesWithGravity.filter(function(e){return t.has(e)});this.graphManager.setAllNodesToApplyGravitation(n)}return this.initSpringEmbedder(),this.runSpringEmbedder(),!0},v.prototype.tick=function(){if(this.totalIterations++,this.totalIterations===this.maxIterations&&!this.isTreeGrowing&&!this.isGrowthFinished)if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;if(this.totalIterations%l.CONVERGENCE_CHECK_PERIOD==0&&!this.isTreeGrowing&&!this.isGrowthFinished){if(this.isConverged())if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;this.coolingCycle++,this.layoutQuality==0?this.coolingAdjuster=this.coolingCycle:this.layoutQuality==1&&(this.coolingAdjuster=this.coolingCycle/3),this.coolingFactor=Math.max(this.initialCoolingFactor-this.coolingCycle**+(Math.log(100*(this.initialCoolingFactor-this.finalTemperature))/Math.log(this.maxCoolingCycle))/100*this.coolingAdjuster,this.finalTemperature),this.animationPeriod=Math.ceil(this.initialAnimationPeriod*Math.sqrt(this.coolingFactor))}if(this.isTreeGrowing){if(this.growTreeIterations%10==0)if(this.prunedNodesAll.length>0){this.graphManager.updateBounds(),this.updateGrid(),this.growTree(this.prunedNodesAll),this.graphManager.resetAllNodesToApplyGravitation();var e=new Set(this.getAllNodes()),t=this.nodesWithGravity.filter(function(t){return e.has(t)});this.graphManager.setAllNodesToApplyGravitation(t),this.graphManager.updateBounds(),this.updateGrid(),this.coolingFactor=l.DEFAULT_COOLING_FACTOR_INCREMENTAL}else this.isTreeGrowing=!1,this.isGrowthFinished=!0;this.growTreeIterations++}if(this.isGrowthFinished){if(this.isConverged())return!0;this.afterGrowthIterations%10==0&&(this.graphManager.updateBounds(),this.updateGrid()),this.coolingFactor=l.DEFAULT_COOLING_FACTOR_INCREMENTAL*((100-this.afterGrowthIterations)/100),this.afterGrowthIterations++}var n=!this.isTreeGrowing&&!this.isGrowthFinished,r=this.growTreeIterations%10==1&&this.isTreeGrowing||this.afterGrowthIterations%10==1&&this.isGrowthFinished;return this.totalDisplacement=0,this.graphManager.updateBounds(),this.calcSpringForces(),this.calcRepulsionForces(n,r),this.calcGravitationalForces(),this.moveNodes(),this.animate(),!1},v.prototype.getPositionsData=function(){for(var e=this.graphManager.getAllNodes(),t={},n=0;n1){var s;for(s=0;sr&&(r=Math.floor(o.y)),a=Math.floor(o.x+c.DEFAULT_COMPONENT_SEPERATION)}this.transform(new f(u.WORLD_CENTER_X-o.x/2,u.WORLD_CENTER_Y-o.y/2))},v.radialLayout=function(e,t,n){var r=Math.max(this.maxDiagonalInTree(e),c.DEFAULT_RADIAL_SEPARATION);v.branchRadialLayout(t,null,0,359,0,r);var i=g.calculateBounds(e),a=new _;a.setDeviceOrgX(i.getMinX()),a.setDeviceOrgY(i.getMinY()),a.setWorldOrgX(n.x),a.setWorldOrgY(n.y);for(var o=0;o1;){var _=g[0];g.splice(0,1);var y=u.indexOf(_);y>=0&&u.splice(y,1),p--,d--}m=t==null?0:(u.indexOf(g[0])+1)%p;for(var b=Math.abs(r-n)/d,x=m;f!=d;x=++x%p){var S=u[x].getOtherEnd(e);if(S!=t){var C=(n+f*b)%360,w=(C+b)%360;v.branchRadialLayout(S,e,C,w,i+a,a),f++}}},v.maxDiagonalInTree=function(e){for(var t=m.MIN_VALUE,n=0;nt&&(t=r)}return t},v.prototype.calcRepulsionRange=function(){return 2*(this.level+1)*this.idealEdgeLength},v.prototype.groupZeroDegreeMembers=function(){var e=this,t={};this.memberGroups={},this.idToDummyNode={};for(var n=[],r=this.graphManager.getAllNodes(),i=0;i1){var r=`DummyCompound_`+n;e.memberGroups[r]=t[n];var i=t[n][0].getParent(),a=new o(e.graphManager);a.id=r,a.paddingLeft=i.paddingLeft||0,a.paddingRight=i.paddingRight||0,a.paddingBottom=i.paddingBottom||0,a.paddingTop=i.paddingTop||0,e.idToDummyNode[r]=a;var s=e.getGraphManager().add(e.newGraph(),a),c=i.getChild();c.add(a);for(var l=0;l=0;e--){var t=this.compoundOrder[e],n=t.id,r=t.paddingLeft,i=t.paddingTop;this.adjustLocations(this.tiledMemberPack[n],t.rect.x,t.rect.y,r,i)}},v.prototype.repopulateZeroDegreeMembers=function(){var e=this,t=this.tiledZeroDegreePack;Object.keys(t).forEach(function(n){var r=e.idToDummyNode[n],i=r.paddingLeft,a=r.paddingTop;e.adjustLocations(t[n],r.rect.x,r.rect.y,i,a)})},v.prototype.getToBeTiled=function(e){var t=e.id;if(this.toBeTiled[t]!=null)return this.toBeTiled[t];var n=e.getChild();if(n==null)return this.toBeTiled[t]=!1,!1;for(var r=n.getNodes(),i=0;i0)return this.toBeTiled[t]=!1,!1;if(a.getChild()==null){this.toBeTiled[a.id]=!1;continue}if(!this.getToBeTiled(a))return this.toBeTiled[t]=!1,!1}return this.toBeTiled[t]=!0,!0},v.prototype.getNodeDegree=function(e){e.id;for(var t=e.getEdges(),n=0,r=0;rc&&(c=u.rect.height)}n+=c+e.verticalPadding}},v.prototype.tileCompoundMembers=function(e,t){var n=this;this.tiledMemberPack=[],Object.keys(e).forEach(function(r){var i=t[r];n.tiledMemberPack[r]=n.tileNodes(e[r],i.paddingLeft+i.paddingRight),i.rect.width=n.tiledMemberPack[r].width,i.rect.height=n.tiledMemberPack[r].height})},v.prototype.tileNodes=function(e,t){var n={rows:[],rowWidth:[],rowHeight:[],width:0,height:t,verticalPadding:c.TILING_PADDING_VERTICAL,horizontalPadding:c.TILING_PADDING_HORIZONTAL};e.sort(function(e,t){return e.rect.width*e.rect.height>t.rect.width*t.rect.height?-1:+(e.rect.width*e.rect.height0&&(a+=e.horizontalPadding),e.rowWidth[n]=a,e.width0&&(o+=e.verticalPadding);var s=0;o>e.rowHeight[n]&&(s=e.rowHeight[n],e.rowHeight[n]=o,s=e.rowHeight[n]-s),e.height+=s,e.rows[n].push(t)},v.prototype.getShortestRowIndex=function(e){for(var t=-1,n=Number.MAX_VALUE,r=0;rn&&(t=r,n=e.rowWidth[r]);return t},v.prototype.canAddHorizontal=function(e,t,n){var r=this.getShortestRowIndex(e);if(r<0)return!0;var i=e.rowWidth[r];if(i+e.horizontalPadding+t<=e.width)return!0;var a=0;e.rowHeight[r]0&&(a=n+e.verticalPadding-e.rowHeight[r]);var o=e.width-i>=t+e.horizontalPadding?(e.height+a)/(i+t+e.horizontalPadding):(e.height+a)/e.width;a=n+e.verticalPadding;var s=e.widtha&&t!=n){r.splice(-1,1),e.rows[n].push(i),e.rowWidth[t]=e.rowWidth[t]-a,e.rowWidth[n]=e.rowWidth[n]+a,e.width=e.rowWidth[instance.getLongestRowIndex(e)];for(var o=Number.MIN_VALUE,s=0;so&&(o=r[s].height);t>0&&(o+=e.verticalPadding);var c=e.rowHeight[t]+e.rowHeight[n];e.rowHeight[t]=o,e.rowHeight[n]0)for(var u=i;u<=a;u++)c[0]+=this.grid[u][o-1].length+this.grid[u][o].length-1;if(a0)for(var u=o;u<=s;u++)c[3]+=this.grid[i-1][u].length+this.grid[i][u].length-1;for(var d=m.MAX_VALUE,f,p,h=0;h{(function(n,r){typeof e==`object`&&typeof t==`object`?t.exports=r(Tg()):typeof define==`function`&&define.amd?define([`cose-base`],r):typeof e==`object`?e.cytoscapeCoseBilkent=r(Tg()):n.cytoscapeCoseBilkent=r(n.coseBase)})(e,function(e){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=1)})([(function(t,n){t.exports=e}),(function(e,t,n){var r=n(0).layoutBase.LayoutConstants,i=n(0).layoutBase.FDLayoutConstants,a=n(0).CoSEConstants,o=n(0).CoSELayout,s=n(0).CoSENode,c=n(0).layoutBase.PointD,l=n(0).layoutBase.DimensionD,u={ready:function(){},stop:function(){},quality:`default`,nodeDimensionsIncludeLabels:!1,refresh:30,fit:!0,padding:10,randomize:!0,nodeRepulsion:4500,idealEdgeLength:50,edgeElasticity:.45,nestingFactor:.1,gravity:.25,numIter:2500,tile:!0,animate:`end`,animationDuration:500,tilingPaddingVertical:10,tilingPaddingHorizontal:10,gravityRangeCompound:1.5,gravityCompound:1,gravityRange:3.8,initialEnergyOnIncremental:.5};function d(e,t){var n={};for(var r in e)n[r]=e[r];for(var r in t)n[r]=t[r];return n}function f(e){this.options=d(u,e),p(this.options)}var p=function(e){e.nodeRepulsion!=null&&(a.DEFAULT_REPULSION_STRENGTH=i.DEFAULT_REPULSION_STRENGTH=e.nodeRepulsion),e.idealEdgeLength!=null&&(a.DEFAULT_EDGE_LENGTH=i.DEFAULT_EDGE_LENGTH=e.idealEdgeLength),e.edgeElasticity!=null&&(a.DEFAULT_SPRING_STRENGTH=i.DEFAULT_SPRING_STRENGTH=e.edgeElasticity),e.nestingFactor!=null&&(a.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR=i.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR=e.nestingFactor),e.gravity!=null&&(a.DEFAULT_GRAVITY_STRENGTH=i.DEFAULT_GRAVITY_STRENGTH=e.gravity),e.numIter!=null&&(a.MAX_ITERATIONS=i.MAX_ITERATIONS=e.numIter),e.gravityRange!=null&&(a.DEFAULT_GRAVITY_RANGE_FACTOR=i.DEFAULT_GRAVITY_RANGE_FACTOR=e.gravityRange),e.gravityCompound!=null&&(a.DEFAULT_COMPOUND_GRAVITY_STRENGTH=i.DEFAULT_COMPOUND_GRAVITY_STRENGTH=e.gravityCompound),e.gravityRangeCompound!=null&&(a.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR=i.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR=e.gravityRangeCompound),e.initialEnergyOnIncremental!=null&&(a.DEFAULT_COOLING_FACTOR_INCREMENTAL=i.DEFAULT_COOLING_FACTOR_INCREMENTAL=e.initialEnergyOnIncremental),e.quality==`draft`?r.QUALITY=0:e.quality==`proof`?r.QUALITY=2:r.QUALITY=1,a.NODE_DIMENSIONS_INCLUDE_LABELS=i.NODE_DIMENSIONS_INCLUDE_LABELS=r.NODE_DIMENSIONS_INCLUDE_LABELS=e.nodeDimensionsIncludeLabels,a.DEFAULT_INCREMENTAL=i.DEFAULT_INCREMENTAL=r.DEFAULT_INCREMENTAL=!e.randomize,a.ANIMATE=i.ANIMATE=r.ANIMATE=e.animate,a.TILE=e.tile,a.TILING_PADDING_VERTICAL=typeof e.tilingPaddingVertical==`function`?e.tilingPaddingVertical.call():e.tilingPaddingVertical,a.TILING_PADDING_HORIZONTAL=typeof e.tilingPaddingHorizontal==`function`?e.tilingPaddingHorizontal.call():e.tilingPaddingHorizontal};f.prototype.run=function(){var e,t,n=this.options;this.idToLNode={};var r=this.layout=new o,i=this;i.stopped=!1,this.cy=this.options.cy,this.cy.trigger({type:`layoutstart`,layout:this});var a=r.newGraphManager();this.gm=a;var s=this.options.eles.nodes(),c=this.options.eles.edges();this.root=a.addRoot(),this.processChildrenList(this.root,this.getTopMostNodes(s),r);for(var l=0;l0){var h=n.getGraphManager().add(n.newGraph(),u);this.processChildrenList(h,o,n)}}},f.prototype.stop=function(){return this.stopped=!0,this};var m=function(e){e(`layout`,`cose-bilkent`,f)};typeof cytoscape<`u`&&m(cytoscape),e.exports=m})])})}))(),1),Dg={mapHoverPanel:10,canvasControls:15},$=p(),Og=!1;function kg(){if(!Og){try{Cg.use(Eg.default)}catch{}Og=!0}}var Ag=120,jg=11;function Mg(e){let t=16+7*Math.sqrt(e);return Math.max(16,Math.min(64,Math.round(t)))}var Ng=M.memo(({nodes:e,edges:t,toNodeStatus:n,isEdgeFailing:r,height:i,onSelect:a})=>{let o=(0,M.useRef)(null),s=(0,M.useRef)(null),[l,u]=(0,M.useState)(()=>E()),[d,f]=(0,M.useState)(null);(0,M.useEffect)(()=>k(()=>u(E())),[]);let p=(0,M.useMemo)(()=>{let t=new Map;for(let n of e)t.set(n.id,n);return t},[e]),m=(0,M.useMemo)(()=>{let n=new Map;for(let t of e)n.set(t.id,0);for(let e of t)n.has(e.source)&&n.set(e.source,(n.get(e.source)??0)+1),n.has(e.target)&&n.set(e.target,(n.get(e.target)??0)+1);return n},[e,t]),h=(0,M.useMemo)(()=>{let i=new Set(e.map(e=>e.id)),a=e.map(e=>({group:`nodes`,data:{id:e.id,label:e.id,status:n(e.status),diameter:Mg(m.get(e.id)??0)}})),o=t.filter(e=>i.has(e.source)&&i.has(e.target)).map((e,t)=>({group:`edges`,data:{id:`e${t}-${e.source}-${e.target}`,source:e.source,target:e.target,callCount:e.call_count,failing:r(e.status)}}));return[...a,...o]},[e,t,m,n,r]),g=e.length>Ag,_=(0,M.useMemo)(()=>{let e=e=>{switch(e){case`healthy`:return l.success;case`degraded`:return l.warning;case`failing`:return l.danger;default:return l.fg4}},t=+!g;return[{selector:`node`,style:{width:`data(diameter)`,height:`data(diameter)`,"background-color":t=>e(t.data(`status`)),"border-width":1,"border-color":l.bg1,label:`data(label)`,color:l.fg2,"font-size":11,"font-family":l.fontMono,"text-valign":`bottom`,"text-halign":`center`,"text-margin-y":3,"text-opacity":t,"min-zoomed-font-size":jg,"transition-property":`opacity, text-opacity, background-color`,"transition-duration":0}},{selector:`edge`,style:{"curve-style":`bezier`,"target-arrow-shape":`triangle`,width:`mapData(callCount, 0, 1000, 1, 6)`,"line-color":l.border2,"target-arrow-color":l.border2,"arrow-scale":.8,opacity:.55,"transition-property":`opacity, line-color`,"transition-duration":0}},{selector:`edge[?failing]`,style:{"line-color":l.danger,"target-arrow-color":l.danger,opacity:.85}},{selector:`node.faded`,style:{opacity:.18,"text-opacity":0}},{selector:`edge.faded`,style:{opacity:.06}},{selector:`node.focus`,style:{"border-width":3,"border-color":l.accent,"text-opacity":1,"z-index":10}},{selector:`node.neighbor`,style:{"text-opacity":1,"z-index":5}},{selector:`edge.highlight`,style:{"line-color":l.accent,"target-arrow-color":l.accent,opacity:1,"z-index":5}}]},[l,g]),y=(0,M.useCallback)(e=>{e.batch(()=>{e.elements().removeClass(`faded focus neighbor highlight`)}),f(null)},[]),b=(0,M.useCallback)((e,t,n)=>{let r=e.getElementById(t);if(r.empty())return;let i=r.closedNeighborhood(),a=r.openNeighborhood().nodes();if(e.batch(()=>{e.elements().addClass(`faded`),i.removeClass(`faded`),a.addClass(`neighbor`),r.removeClass(`neighbor`).addClass(`focus`),r.connectedEdges().addClass(`highlight`)}),n){let e=p.get(t),n=r.renderedPosition();e&&f({id:t,node:e,x:n.x,y:n.y})}},[p]);(0,M.useEffect)(()=>{let e=o.current;if(!e)return;kg();let t=Cg({container:e,elements:h,style:_,layout:h.filter(e=>e.group===`nodes`).length<=6?{name:`concentric`,animate:!1,padding:24}:{name:`cose-bilkent`,animate:!1,fit:!0,padding:24,nodeDimensionsIncludeLabels:!1,idealEdgeLength:90,nodeRepulsion:6500,randomize:!0},textureOnViewport:!0,hideEdgesOnViewport:!0,motionBlur:!1,pixelRatio:1,wheelSensitivity:.2,minZoom:.1,maxZoom:4,autoungrabify:!0});s.current=t,t.on(`layoutstop`,()=>t.fit(void 0,24)),t.on(`mouseover`,`node`,e=>{b(t,e.target.id(),!0)}),t.on(`mouseout`,`node`,()=>y(t)),t.on(`pan zoom`,()=>{f(e=>{if(!e)return e;let n=t.getElementById(e.id);if(n.empty())return e;let r=n.renderedPosition();return{...e,x:r.x,y:r.y}})}),t.on(`tap`,`node`,e=>{a(e.target.id())});let n=new ResizeObserver(()=>{t.resize(),t.fit(void 0,24)});return n.observe(e),()=>{n.disconnect(),t.destroy(),s.current=null}},[h,_,b,y,a]);let x=(0,M.useMemo)(()=>{if(!d)return null;let e=o.current?.clientWidth??0,t=o.current?.clientHeight??i,n=d.x+18,r=d.y-96-12;return n+200+12>e&&(n=d.x-200-18),n<12&&(n=12),r<12&&(r=d.y+18),r+96+12>t&&(r=Math.max(12,t-96-12)),{left:n,top:r,w:200}},[d,i]);return(0,$.jsxs)(`div`,{style:{position:`relative`,width:`100%`,height:i},children:[(0,$.jsx)(`div`,{ref:o,style:{position:`absolute`,inset:0},"aria-hidden":`true`}),d&&x&&(0,$.jsx)(`div`,{style:{position:`absolute`,left:x.left,top:x.top,width:x.w,zIndex:Dg.mapHoverPanel,pointerEvents:`none`},children:(0,$.jsxs)(c,{bordered:!0,padding:`sm`,radius:`md`,shadow:`md`,children:[(0,$.jsx)(v,{label:d.id,value:Math.round(d.node.metrics.request_rate_rps),unit:`req/s`}),(0,$.jsx)(v,{label:`Error rate`,value:(d.node.metrics.error_rate*100).toFixed(2),unit:`%`})]})})]})});function Pg(e){return e===`healthy`?`running`:e===`degraded`?`degraded`:e===`failing`?`failed`:`idle`}function Fg(e){return e===`healthy`?`info`:e===`degraded`?`warning`:e===`failing`?`danger`:`subtle`}var Ig=M.memo(({nodes:e,toNodeStatus:t,onSelect:n,selectedId:r})=>(0,$.jsx)(l,{columns:(0,M.useMemo)(()=>[{key:`id`,title:`Service`,render:(e,t)=>(0,$.jsx)(_,{text:t.id})},{key:`status`,title:`Status`,width:130,render:(e,n)=>{let r=t(n.status);return(0,$.jsx)(s,{status:Pg(r),label:(0,$.jsx)(x,{tone:Fg(r),size:`sm`,children:n.status})})}},{key:`rps`,title:`Req rate`,width:110,align:`right`,render:(e,t)=>`${Math.round(t.metrics.request_rate_rps)}/s`},{key:`err`,title:`Error rate`,width:110,align:`right`,render:(e,t)=>`${(t.metrics.error_rate*100).toFixed(2)}%`}],[t]),data:e,rowKey:`id`,density:`compact`,stickyHeader:!0,selection:`single`,selectedKeys:r?[r]:[],onRowClick:e=>n(e.id),empty:`No services match the filter.`}));function Lg(e){return e===`healthy`?`info`:e===`degraded`?`warning`:e===`critical`||e===`failing`?`danger`:`neutral`}var Rg=M.memo(({node:n,edges:r,onClose:a,onSelectService:s})=>{let l=r.filter(e=>e.target===n.id),u=r.filter(e=>e.source===n.id),d=n.metrics.error_rate*100;return(0,$.jsxs)(e,{direction:`vertical`,size:`md`,children:[(0,$.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:(0,$.jsxs)(e,{size:`xs`,align:`center`,children:[(0,$.jsx)(`code`,{children:n.id}),(0,$.jsx)(x,{tone:Lg(n.status),size:`sm`,children:n.status})]}),extra:(0,$.jsx)(i,{icon:(0,$.jsx)(j,{size:13}),"aria-label":`Close`,variant:`ghost`,size:`sm`,onClick:a}),children:(0,$.jsxs)(o,{columns:2,gap:`sm`,children:[(0,$.jsx)(o.Col,{span:1,children:(0,$.jsx)(v,{label:`Req rate (≈)`,value:Math.round(n.metrics.request_rate_rps)})}),(0,$.jsx)(o.Col,{span:1,children:(0,$.jsx)(v,{label:`Error Rate`,value:d.toFixed(2),unit:`%`})}),(0,$.jsx)(o.Col,{span:1,children:(0,$.jsx)(v,{label:`Avg Latency`,value:n.metrics.avg_latency_ms,unit:`ms`})}),(0,$.jsx)(o.Col,{span:1,children:(0,$.jsx)(v,{label:`P99 (est.)`,value:n.metrics.p99_latency_ms,unit:`ms`})})]})}),(0,$.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Health Score`,extra:(0,$.jsx)(x,{tone:`subtle`,size:`sm`,children:n.health_score.toFixed(2)}),children:(0,$.jsx)(g,{value:n.health_score*100,tone:n.health_score<.4?`danger`:n.health_score<.7?`warning`:`neutral`})}),l.length>0&&(0,$.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Upstream`,children:(0,$.jsx)(e,{direction:`vertical`,size:`xs`,children:l.map(n=>(0,$.jsx)(t,{variant:`ghost`,size:`sm`,block:!0,onClick:()=>s(n.source),children:(0,$.jsxs)(e,{justify:`between`,align:`center`,children:[(0,$.jsx)(`code`,{children:n.source}),(0,$.jsxs)(x,{tone:`subtle`,size:`sm`,children:[n.call_count,` calls`]})]})},n.source))})}),u.length>0&&(0,$.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Downstream`,children:(0,$.jsx)(e,{direction:`vertical`,size:`xs`,children:u.map(n=>(0,$.jsx)(t,{variant:`ghost`,size:`sm`,block:!0,onClick:()=>s(n.target),children:(0,$.jsxs)(e,{justify:`between`,align:`center`,children:[(0,$.jsx)(`code`,{children:n.target}),(0,$.jsxs)(x,{tone:`subtle`,size:`sm`,children:[n.call_count,` calls`]})]})},n.target))})}),n.alerts.length>0&&(0,$.jsx)(e,{direction:`vertical`,size:`xs`,children:n.alerts.map((e,t)=>(0,$.jsx)(b,{severity:`danger`,children:e},t))})]})}),zg=M.memo(({items:t})=>(0,$.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,children:(0,$.jsx)(e,{size:`lg`,wrap:!0,children:t.map((e,t)=>(0,$.jsxs)(M.Fragment,{children:[t>0&&(0,$.jsx)(S,{direction:`vertical`}),(0,$.jsx)(v,{...e})]},`${t}-${String(e.label)}`))})}));function Bg(e=800){let[t,n]=(0,M.useState)(()=>typeof window>`u`?e:window.innerHeight);return(0,M.useEffect)(()=>{if(typeof window>`u`)return;let e=()=>n(window.innerHeight);return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),t}function Vg(e){return e===`healthy`||e===`degraded`?e:e===`critical`||e===`failing`?`failing`:`unknown`}function Hg(e){return e===`critical`||e===`failing`}var Ug=M.memo(()=>{let{graph:t,loading:n,error:r}=T(),{dashboard:i,stats:a}=D(),[o,s]=(0,M.useState)(null),[l,f]=(0,M.useState)(``),p=y(m.coarse),[g,_]=(0,M.useState)(null),v=g?g===`list`:p,x=Bg(),S=p?460:Math.max(460,x-320),E=t?.nodes??[],k=t?.edges??[],j=(0,M.useMemo)(()=>{let e=l.trim().toLowerCase();return e?E.filter(t=>t.id.toLowerCase().includes(e)):E},[E,l]),N=i?.active_services??E.length,P=i?.error_rate??0,F=a,I=e=>{if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``&&Number.isFinite(Number(e)))return Number(e)},L=I(F?.TraceCount)??I(F?.traceCount)??i?.total_traces??0,R=I(F?.LogCount)??I(F?.logCount)??i?.total_logs??0,z=I(F?.DBSizeMB)??I(F?.db_size_mb),B=(0,M.useCallback)(e=>{let t=E.find(t=>t.id===e);t&&s(t)},[E]),V=(0,M.useCallback)(()=>s(null),[]);return(0,$.jsxs)(e,{direction:`vertical`,size:`md`,style:{display:`flex`,width:`100%`},children:[(0,$.jsx)(h,{size:`sm`,title:`Service Topology`,subtitle:`Live dependency map · click a node for details`,inlineSubtitle:!0}),(0,$.jsx)(zg,{items:[{label:`Services`,value:N},{label:`Error rate`,value:P.toFixed(2),unit:`%`},{label:`Traces`,value:O(L)},{label:`Logs`,value:O(R)},...z!=null&&Number.isFinite(z)?[{label:`DB`,value:z.toFixed(0),unit:`MB`}]:[]]}),(0,$.jsxs)(c,{bordered:!0,padding:`sm`,radius:`md`,extra:(0,$.jsxs)(e,{size:`sm`,align:`center`,children:[(0,$.jsx)(C,{items:[{key:`graph`,label:`Graph`},{key:`list`,label:`List`}],value:v?`list`:`graph`,onChange:e=>_(e),variant:`segment`,size:`sm`}),(0,$.jsx)(w,{value:l,onChange:e=>f(e),placeholder:`Filter services`,size:`sm`,prefix:(0,$.jsx)(A,{size:12})})]}),children:[n&&(0,$.jsx)(d,{label:`Loading service map`}),r&&(0,$.jsx)(b,{severity:`danger`,title:`Service map failed to load`,children:r}),!n&&!r&&E.length===0&&(0,$.jsx)(b,{severity:`info`,children:`No services discovered yet.`}),!n&&!r&&j.length===0&&E.length>0&&(0,$.jsx)(b,{severity:`info`,children:`No services match the filter.`}),!n&&!r&&j.length>0&&(v?(0,$.jsx)(Ig,{nodes:j,toNodeStatus:Vg,onSelect:B,selectedId:o?.id}):(0,$.jsx)(Ng,{nodes:j,edges:k,toNodeStatus:Vg,isEdgeFailing:Hg,height:S,onSelect:B}))]}),(0,$.jsx)(u,{open:o!==null,onClose:V,placement:`right`,width:p?`92vw`:420,title:o?(0,$.jsx)(`code`,{children:o.id}):void 0,description:`Service detail · upstream, downstream, alerts`,children:o&&(0,$.jsx)(Rg,{node:o,edges:k,onClose:V,onSelectService:B})})]})});export{Ug as default}; \ No newline at end of file diff --git a/internal/ui/dist/assets/cytoscape-cose-bilkent-CEIBo6Gj.js b/internal/ui/dist/assets/cytoscape-cose-bilkent-CEIBo6Gj.js deleted file mode 100644 index 654a4ef..0000000 --- a/internal/ui/dist/assets/cytoscape-cose-bilkent-CEIBo6Gj.js +++ /dev/null @@ -1 +0,0 @@ -import{t as e}from"./index-B9ZFj2IV.js";var t=e(((e,t)=>{(function(n,r){typeof e==`object`&&typeof t==`object`?t.exports=r():typeof define==`function`&&define.amd?define([],r):typeof e==`object`?e.layoutBase=r():n.layoutBase=r()})(e,function(){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=26)})([(function(e,t,n){function r(){}r.QUALITY=1,r.DEFAULT_CREATE_BENDS_AS_NEEDED=!1,r.DEFAULT_INCREMENTAL=!1,r.DEFAULT_ANIMATION_ON_LAYOUT=!0,r.DEFAULT_ANIMATION_DURING_LAYOUT=!1,r.DEFAULT_ANIMATION_PERIOD=50,r.DEFAULT_UNIFORM_LEAF_NODE_SIZES=!1,r.DEFAULT_GRAPH_MARGIN=15,r.NODE_DIMENSIONS_INCLUDE_LABELS=!1,r.SIMPLE_NODE_SIZE=40,r.SIMPLE_NODE_HALF_SIZE=r.SIMPLE_NODE_SIZE/2,r.EMPTY_COMPOUND_NODE_SIZE=40,r.MIN_EDGE_LENGTH=1,r.WORLD_BOUNDARY=1e6,r.INITIAL_WORLD_BOUNDARY=r.WORLD_BOUNDARY/1e3,r.WORLD_CENTER_X=1200,r.WORLD_CENTER_Y=900,e.exports=r}),(function(e,t,n){var r=n(2),i=n(8),a=n(9);function o(e,t,n){r.call(this,n),this.isOverlapingSourceAndTarget=!1,this.vGraphObject=n,this.bendpoints=[],this.source=e,this.target=t}for(var s in o.prototype=Object.create(r.prototype),r)o[s]=r[s];o.prototype.getSource=function(){return this.source},o.prototype.getTarget=function(){return this.target},o.prototype.isInterGraph=function(){return this.isInterGraph},o.prototype.getLength=function(){return this.length},o.prototype.isOverlapingSourceAndTarget=function(){return this.isOverlapingSourceAndTarget},o.prototype.getBendpoints=function(){return this.bendpoints},o.prototype.getLca=function(){return this.lca},o.prototype.getSourceInLca=function(){return this.sourceInLca},o.prototype.getTargetInLca=function(){return this.targetInLca},o.prototype.getOtherEnd=function(e){if(this.source===e)return this.target;if(this.target===e)return this.source;throw`Node is not incident with this edge`},o.prototype.getOtherEndInGraph=function(e,t){for(var n=this.getOtherEnd(e),r=t.getGraphManager().getRoot();;){if(n.getOwner()==t)return n;if(n.getOwner()==r)break;n=n.getOwner().getParent()}return null},o.prototype.updateLength=function(){var e=[,,,,];this.isOverlapingSourceAndTarget=i.getIntersection(this.target.getRect(),this.source.getRect(),e),this.isOverlapingSourceAndTarget||(this.lengthX=e[0]-e[2],this.lengthY=e[1]-e[3],Math.abs(this.lengthX)<1&&(this.lengthX=a.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=a.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY))},o.prototype.updateLengthSimple=function(){this.lengthX=this.target.getCenterX()-this.source.getCenterX(),this.lengthY=this.target.getCenterY()-this.source.getCenterY(),Math.abs(this.lengthX)<1&&(this.lengthX=a.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=a.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY)},e.exports=o}),(function(e,t,n){function r(e){this.vGraphObject=e}e.exports=r}),(function(e,t,n){var r=n(2),i=n(10),a=n(13),o=n(0),s=n(16),c=n(4);function l(e,t,n,o){n==null&&o==null&&(o=t),r.call(this,o),e.graphManager!=null&&(e=e.graphManager),this.estimatedSize=i.MIN_VALUE,this.inclusionTreeDepth=i.MAX_VALUE,this.vGraphObject=o,this.edges=[],this.graphManager=e,n!=null&&t!=null?this.rect=new a(t.x,t.y,n.width,n.height):this.rect=new a}for(var u in l.prototype=Object.create(r.prototype),r)l[u]=r[u];l.prototype.getEdges=function(){return this.edges},l.prototype.getChild=function(){return this.child},l.prototype.getOwner=function(){return this.owner},l.prototype.getWidth=function(){return this.rect.width},l.prototype.setWidth=function(e){this.rect.width=e},l.prototype.getHeight=function(){return this.rect.height},l.prototype.setHeight=function(e){this.rect.height=e},l.prototype.getCenterX=function(){return this.rect.x+this.rect.width/2},l.prototype.getCenterY=function(){return this.rect.y+this.rect.height/2},l.prototype.getCenter=function(){return new c(this.rect.x+this.rect.width/2,this.rect.y+this.rect.height/2)},l.prototype.getLocation=function(){return new c(this.rect.x,this.rect.y)},l.prototype.getRect=function(){return this.rect},l.prototype.getDiagonal=function(){return Math.sqrt(this.rect.width*this.rect.width+this.rect.height*this.rect.height)},l.prototype.getHalfTheDiagonal=function(){return Math.sqrt(this.rect.height*this.rect.height+this.rect.width*this.rect.width)/2},l.prototype.setRect=function(e,t){this.rect.x=e.x,this.rect.y=e.y,this.rect.width=t.width,this.rect.height=t.height},l.prototype.setCenter=function(e,t){this.rect.x=e-this.rect.width/2,this.rect.y=t-this.rect.height/2},l.prototype.setLocation=function(e,t){this.rect.x=e,this.rect.y=t},l.prototype.moveBy=function(e,t){this.rect.x+=e,this.rect.y+=t},l.prototype.getEdgeListToNode=function(e){var t=[],n=this;return n.edges.forEach(function(r){if(r.target==e){if(r.source!=n)throw`Incorrect edge source!`;t.push(r)}}),t},l.prototype.getEdgesBetween=function(e){var t=[],n=this;return n.edges.forEach(function(r){if(!(r.source==n||r.target==n))throw`Incorrect edge source and/or target`;(r.target==e||r.source==e)&&t.push(r)}),t},l.prototype.getNeighborsList=function(){var e=new Set,t=this;return t.edges.forEach(function(n){if(n.source==t)e.add(n.target);else{if(n.target!=t)throw`Incorrect incidency!`;e.add(n.source)}}),e},l.prototype.withChildren=function(){var e=new Set,t,n;if(e.add(this),this.child!=null)for(var r=this.child.getNodes(),i=0;it&&(this.rect.x-=(this.labelWidth-t)/2,this.setWidth(this.labelWidth)),this.labelHeight>n&&(this.labelPos==`center`?this.rect.y-=(this.labelHeight-n)/2:this.labelPos==`top`&&(this.rect.y-=this.labelHeight-n),this.setHeight(this.labelHeight))}}},l.prototype.getInclusionTreeDepth=function(){if(this.inclusionTreeDepth==i.MAX_VALUE)throw`assert failed`;return this.inclusionTreeDepth},l.prototype.transform=function(e){var t=this.rect.x;t>o.WORLD_BOUNDARY?t=o.WORLD_BOUNDARY:t<-o.WORLD_BOUNDARY&&(t=-o.WORLD_BOUNDARY);var n=this.rect.y;n>o.WORLD_BOUNDARY?n=o.WORLD_BOUNDARY:n<-o.WORLD_BOUNDARY&&(n=-o.WORLD_BOUNDARY);var r=new c(t,n),i=e.inverseTransformPoint(r);this.setLocation(i.x,i.y)},l.prototype.getLeft=function(){return this.rect.x},l.prototype.getRight=function(){return this.rect.x+this.rect.width},l.prototype.getTop=function(){return this.rect.y},l.prototype.getBottom=function(){return this.rect.y+this.rect.height},l.prototype.getParent=function(){return this.owner==null?null:this.owner.getParent()},e.exports=l}),(function(e,t,n){function r(e,t){e==null&&t==null?(this.x=0,this.y=0):(this.x=e,this.y=t)}r.prototype.getX=function(){return this.x},r.prototype.getY=function(){return this.y},r.prototype.setX=function(e){this.x=e},r.prototype.setY=function(e){this.y=e},r.prototype.getDifference=function(e){return new DimensionD(this.x-e.x,this.y-e.y)},r.prototype.getCopy=function(){return new r(this.x,this.y)},r.prototype.translate=function(e){return this.x+=e.width,this.y+=e.height,this},e.exports=r}),(function(e,t,n){var r=n(2),i=n(10),a=n(0),o=n(6),s=n(3),c=n(1),l=n(13),u=n(12),d=n(11);function f(e,t,n){r.call(this,n),this.estimatedSize=i.MIN_VALUE,this.margin=a.DEFAULT_GRAPH_MARGIN,this.edges=[],this.nodes=[],this.isConnected=!1,this.parent=e,t!=null&&t instanceof o?this.graphManager=t:t!=null&&t instanceof Layout&&(this.graphManager=t.graphManager)}for(var p in f.prototype=Object.create(r.prototype),r)f[p]=r[p];f.prototype.getNodes=function(){return this.nodes},f.prototype.getEdges=function(){return this.edges},f.prototype.getGraphManager=function(){return this.graphManager},f.prototype.getParent=function(){return this.parent},f.prototype.getLeft=function(){return this.left},f.prototype.getRight=function(){return this.right},f.prototype.getTop=function(){return this.top},f.prototype.getBottom=function(){return this.bottom},f.prototype.isConnected=function(){return this.isConnected},f.prototype.add=function(e,t,n){if(t==null&&n==null){var r=e;if(this.graphManager==null)throw`Graph has no graph mgr!`;if(this.getNodes().indexOf(r)>-1)throw`Node already in graph!`;return r.owner=this,this.getNodes().push(r),r}else{var i=e;if(!(this.getNodes().indexOf(t)>-1&&this.getNodes().indexOf(n)>-1))throw`Source or target not in graph!`;if(!(t.owner==n.owner&&t.owner==this))throw`Both owners must be this graph!`;return t.owner==n.owner?(i.source=t,i.target=n,i.isInterGraph=!1,this.getEdges().push(i),t.edges.push(i),n!=t&&n.edges.push(i),i):null}},f.prototype.remove=function(e){var t=e;if(e instanceof s){if(t==null)throw`Node is null!`;if(!(t.owner!=null&&t.owner==this))throw`Owner graph is invalid!`;if(this.graphManager==null)throw`Owner graph manager is invalid!`;for(var n=t.edges.slice(),r,i=n.length,a=0;a-1&&u>-1))throw`Source and/or target doesn't know this edge!`;r.source.edges.splice(l,1),r.target!=r.source&&r.target.edges.splice(u,1);var o=r.source.owner.getEdges().indexOf(r);if(o==-1)throw`Not in owner's edge list!`;r.source.owner.getEdges().splice(o,1)}},f.prototype.updateLeftTop=function(){for(var e=i.MAX_VALUE,t=i.MAX_VALUE,n,r,a,o=this.getNodes(),s=o.length,c=0;cn&&(e=n),t>r&&(t=r)}return e==i.MAX_VALUE?null:(a=o[0].getParent().paddingLeft==null?this.margin:o[0].getParent().paddingLeft,this.left=t-a,this.top=e-a,new u(this.left,this.top))},f.prototype.updateBounds=function(e){for(var t=i.MAX_VALUE,n=-i.MAX_VALUE,r=i.MAX_VALUE,a=-i.MAX_VALUE,o,s,c,u,d,f=this.nodes,p=f.length,m=0;mo&&(t=o),nc&&(r=c),ao&&(t=o),nc&&(r=c),a=this.nodes.length){var c=0;n.forEach(function(t){t.owner==e&&c++}),c==this.nodes.length&&(this.isConnected=!0)}},e.exports=f}),(function(e,t,n){var r,i=n(1);function a(e){r=n(5),this.layout=e,this.graphs=[],this.edges=[]}a.prototype.addRoot=function(){var e=this.layout.newGraph(),t=this.layout.newNode(null),n=this.add(e,t);return this.setRootGraph(n),this.rootGraph},a.prototype.add=function(e,t,n,r,i){if(n==null&&r==null&&i==null){if(e==null)throw`Graph is null!`;if(t==null)throw`Parent node is null!`;if(this.graphs.indexOf(e)>-1)throw`Graph already in this graph mgr!`;if(this.graphs.push(e),e.parent!=null)throw`Already has a parent!`;if(t.child!=null)throw`Already has a child!`;return e.parent=t,t.child=e,e}else{i=n,r=t,n=e;var a=r.getOwner(),o=i.getOwner();if(!(a!=null&&a.getGraphManager()==this))throw`Source not in this graph mgr!`;if(!(o!=null&&o.getGraphManager()==this))throw`Target not in this graph mgr!`;if(a==o)return n.isInterGraph=!1,a.add(n,r,i);if(n.isInterGraph=!0,n.source=r,n.target=i,this.edges.indexOf(n)>-1)throw`Edge already in inter-graph edge list!`;if(this.edges.push(n),!(n.source!=null&&n.target!=null))throw`Edge source and/or target is null!`;if(!(n.source.edges.indexOf(n)==-1&&n.target.edges.indexOf(n)==-1))throw`Edge already in source and/or target incidency list!`;return n.source.edges.push(n),n.target.edges.push(n),n}},a.prototype.remove=function(e){if(e instanceof r){var t=e;if(t.getGraphManager()!=this)throw`Graph not in this graph mgr`;if(!(t==this.rootGraph||t.parent!=null&&t.parent.graphManager==this))throw`Invalid parent node!`;var n=[];n=n.concat(t.getEdges());for(var a,o=n.length,s=0;s=t.getRight()?n[0]+=Math.min(t.getX()-e.getX(),e.getRight()-t.getRight()):t.getX()<=e.getX()&&t.getRight()>=e.getRight()&&(n[0]+=Math.min(e.getX()-t.getX(),t.getRight()-e.getRight())),e.getY()<=t.getY()&&e.getBottom()>=t.getBottom()?n[1]+=Math.min(t.getY()-e.getY(),e.getBottom()-t.getBottom()):t.getY()<=e.getY()&&t.getBottom()>=e.getBottom()&&(n[1]+=Math.min(e.getY()-t.getY(),t.getBottom()-e.getBottom()));var a=Math.abs((t.getCenterY()-e.getCenterY())/(t.getCenterX()-e.getCenterX()));t.getCenterY()===e.getCenterY()&&t.getCenterX()===e.getCenterX()&&(a=1);var o=a*n[0],s=n[1]/a;n[0]o)return n[0]=r,n[1]=c,n[2]=a,n[3]=y,!1;if(ia)return n[0]=s,n[1]=i,n[2]=_,n[3]=o,!1;if(ra?(n[0]=u,n[1]=d,C=!0):(n[0]=l,n[1]=c,C=!0):T===D&&(r>a?(n[0]=s,n[1]=c,C=!0):(n[0]=f,n[1]=d,C=!0)),-E===D?a>r?(n[2]=v,n[3]=y,w=!0):(n[2]=_,n[3]=g,w=!0):E===D&&(a>r?(n[2]=h,n[3]=g,w=!0):(n[2]=b,n[3]=y,w=!0)),C&&w)return!1;if(r>a?i>o?(O=this.getCardinalDirection(T,D,4),k=this.getCardinalDirection(E,D,2)):(O=this.getCardinalDirection(-T,D,3),k=this.getCardinalDirection(-E,D,1)):i>o?(O=this.getCardinalDirection(-T,D,1),k=this.getCardinalDirection(-E,D,3)):(O=this.getCardinalDirection(T,D,2),k=this.getCardinalDirection(E,D,4)),!C)switch(O){case 1:j=c,A=r+-m/D,n[0]=A,n[1]=j;break;case 2:A=f,j=i+p*D,n[0]=A,n[1]=j;break;case 3:j=d,A=r+m/D,n[0]=A,n[1]=j;break;case 4:A=u,j=i+-p*D,n[0]=A,n[1]=j;break}if(!w)switch(k){case 1:N=g,M=a+-S/D,n[2]=M,n[3]=N;break;case 2:M=b,N=o+x*D,n[2]=M,n[3]=N;break;case 3:N=y,M=a+S/D,n[2]=M,n[3]=N;break;case 4:M=v,N=o+-x*D,n[2]=M,n[3]=N;break}}return!1},i.getCardinalDirection=function(e,t,n){return e>t?n:1+n%4},i.getIntersection=function(e,t,n,i){if(i==null)return this.getIntersection2(e,t,n);var a=e.x,o=e.y,s=t.x,c=t.y,l=n.x,u=n.y,d=i.x,f=i.y,p=void 0,m=void 0,h=void 0,g=void 0,_=void 0,v=void 0,y=void 0,b=void 0,x=void 0;return h=c-o,_=a-s,y=s*o-a*c,g=f-u,v=l-d,b=d*u-l*f,x=h*v-g*_,x===0?null:(p=(_*b-v*y)/x,m=(g*y-h*b)/x,new r(p,m))},i.angleOfVector=function(e,t,n,r){var i=void 0;return e===n?i=r0?1:e<0?-1:0},r.floor=function(e){return e<0?Math.ceil(e):Math.floor(e)},r.ceil=function(e){return e<0?Math.floor(e):Math.ceil(e)},e.exports=r}),(function(e,t,n){function r(){}r.MAX_VALUE=2147483647,r.MIN_VALUE=-2147483648,e.exports=r}),(function(e,t,n){var r=function(){function e(e,t){for(var n=0;n0&&t;){for(s.push(l[0]);s.length>0&&t;){var u=s[0];s.splice(0,1),o.add(u);for(var d=u.getEdges(),a=0;a-1&&l.splice(h,1)}o=new Set,c=new Map}}return e},f.prototype.createDummyNodesForBendpoints=function(e){for(var t=[],n=e.source,r=this.graphManager.calcLowestCommonAncestor(e.source,e.target),i=0;i0){for(var i=this.edgeToDummyNodes.get(n),a=0;a=0&&t.splice(d,1),s.getNeighborsList().forEach(function(e){if(n.indexOf(e)<0){var t=r.get(e)-1;t==1&&l.push(e),r.set(e,t)}})}n=n.concat(l),(t.length==1||t.length==2)&&(i=!0,a=t[0])}return a},f.prototype.setGraphManager=function(e){this.graphManager=e},e.exports=f}),(function(e,t,n){function r(){}r.seed=1,r.x=0,r.nextDouble=function(){return r.x=Math.sin(r.seed++)*1e4,r.x-Math.floor(r.x)},e.exports=r}),(function(e,t,n){var r=n(4);function i(e,t){this.lworldOrgX=0,this.lworldOrgY=0,this.ldeviceOrgX=0,this.ldeviceOrgY=0,this.lworldExtX=1,this.lworldExtY=1,this.ldeviceExtX=1,this.ldeviceExtY=1}i.prototype.getWorldOrgX=function(){return this.lworldOrgX},i.prototype.setWorldOrgX=function(e){this.lworldOrgX=e},i.prototype.getWorldOrgY=function(){return this.lworldOrgY},i.prototype.setWorldOrgY=function(e){this.lworldOrgY=e},i.prototype.getWorldExtX=function(){return this.lworldExtX},i.prototype.setWorldExtX=function(e){this.lworldExtX=e},i.prototype.getWorldExtY=function(){return this.lworldExtY},i.prototype.setWorldExtY=function(e){this.lworldExtY=e},i.prototype.getDeviceOrgX=function(){return this.ldeviceOrgX},i.prototype.setDeviceOrgX=function(e){this.ldeviceOrgX=e},i.prototype.getDeviceOrgY=function(){return this.ldeviceOrgY},i.prototype.setDeviceOrgY=function(e){this.ldeviceOrgY=e},i.prototype.getDeviceExtX=function(){return this.ldeviceExtX},i.prototype.setDeviceExtX=function(e){this.ldeviceExtX=e},i.prototype.getDeviceExtY=function(){return this.ldeviceExtY},i.prototype.setDeviceExtY=function(e){this.ldeviceExtY=e},i.prototype.transformX=function(e){var t=0,n=this.lworldExtX;return n!=0&&(t=this.ldeviceOrgX+(e-this.lworldOrgX)*this.ldeviceExtX/n),t},i.prototype.transformY=function(e){var t=0,n=this.lworldExtY;return n!=0&&(t=this.ldeviceOrgY+(e-this.lworldOrgY)*this.ldeviceExtY/n),t},i.prototype.inverseTransformX=function(e){var t=0,n=this.ldeviceExtX;return n!=0&&(t=this.lworldOrgX+(e-this.ldeviceOrgX)*this.lworldExtX/n),t},i.prototype.inverseTransformY=function(e){var t=0,n=this.ldeviceExtY;return n!=0&&(t=this.lworldOrgY+(e-this.ldeviceOrgY)*this.lworldExtY/n),t},i.prototype.inverseTransformPoint=function(e){return new r(this.inverseTransformX(e.x),this.inverseTransformY(e.y))},e.exports=i}),(function(e,t,n){function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);ta.ADAPTATION_LOWER_NODE_LIMIT&&(this.coolingFactor=Math.max(this.coolingFactor*a.COOLING_ADAPTATION_FACTOR,this.coolingFactor-(e-a.ADAPTATION_LOWER_NODE_LIMIT)/(a.ADAPTATION_UPPER_NODE_LIMIT-a.ADAPTATION_LOWER_NODE_LIMIT)*this.coolingFactor*(1-a.COOLING_ADAPTATION_FACTOR))),this.maxNodeDisplacement=a.MAX_NODE_DISPLACEMENT_INCREMENTAL):(e>a.ADAPTATION_LOWER_NODE_LIMIT?this.coolingFactor=Math.max(a.COOLING_ADAPTATION_FACTOR,1-(e-a.ADAPTATION_LOWER_NODE_LIMIT)/(a.ADAPTATION_UPPER_NODE_LIMIT-a.ADAPTATION_LOWER_NODE_LIMIT)*(1-a.COOLING_ADAPTATION_FACTOR)):this.coolingFactor=1,this.initialCoolingFactor=this.coolingFactor,this.maxNodeDisplacement=a.MAX_NODE_DISPLACEMENT),this.maxIterations=Math.max(this.getAllNodes().length*5,this.maxIterations),this.totalDisplacementThreshold=this.displacementThresholdPerNode*this.getAllNodes().length,this.repulsionRange=this.calcRepulsionRange()},l.prototype.calcSpringForces=function(){for(var e=this.getAllEdges(),t,n=0;n0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,n,r,i,o,s=this.getAllNodes(),c;if(this.useFRGridVariant)for(this.totalIterations%a.GRID_CALCULATION_CHECK_PERIOD==1&&e&&this.updateGrid(),c=new Set,n=0;nc||s>c)&&(e.gravitationForceX=-this.gravityConstant*i,e.gravitationForceY=-this.gravityConstant*a)):(c=t.getEstimatedSize()*this.compoundGravityRangeFactor,(o>c||s>c)&&(e.gravitationForceX=-this.gravityConstant*i*this.compoundGravityConstant,e.gravitationForceY=-this.gravityConstant*a*this.compoundGravityConstant))},l.prototype.isConverged=function(){var e,t=!1;return this.totalIterations>this.maxIterations/3&&(t=Math.abs(this.totalDisplacement-this.oldTotalDisplacement)<2),e=this.totalDisplacement=c.length||u>=c[0].length)){for(var d=0;de}}]),e}()}),(function(e,t,n){var r=function(){function e(e,t){for(var n=0;n2&&arguments[2]!==void 0?arguments[2]:1,a=arguments.length>3&&arguments[3]!==void 0?arguments[3]:-1,o=arguments.length>4&&arguments[4]!==void 0?arguments[4]:-1;i(this,e),this.sequence1=t,this.sequence2=n,this.match_score=r,this.mismatch_penalty=a,this.gap_penalty=o,this.iMax=t.length+1,this.jMax=n.length+1,this.grid=Array(this.iMax);for(var s=0;s=0;n--){var r=this.listeners[n];r.event===e&&r.callback===t&&this.listeners.splice(n,1)}},i.emit=function(e,t){for(var n=0;n{(function(r,i){typeof e==`object`&&typeof n==`object`?n.exports=i(t()):typeof define==`function`&&define.amd?define([`layout-base`],i):typeof e==`object`?e.coseBase=i(t()):r.coseBase=i(r.layoutBase)})(e,function(e){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=7)})([(function(t,n){t.exports=e}),(function(e,t,n){var r=n(0).FDLayoutConstants;function i(){}for(var a in r)i[a]=r[a];i.DEFAULT_USE_MULTI_LEVEL_SCALING=!1,i.DEFAULT_RADIAL_SEPARATION=r.DEFAULT_EDGE_LENGTH,i.DEFAULT_COMPONENT_SEPERATION=60,i.TILE=!0,i.TILING_PADDING_VERTICAL=10,i.TILING_PADDING_HORIZONTAL=10,i.TREE_REDUCTION_ON_INCREMENTAL=!1,e.exports=i}),(function(e,t,n){var r=n(0).FDLayoutEdge;function i(e,t,n){r.call(this,e,t,n)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).LGraph;function i(e,t,n){r.call(this,e,t,n)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).LGraphManager;function i(e){r.call(this,e)}for(var a in i.prototype=Object.create(r.prototype),r)i[a]=r[a];e.exports=i}),(function(e,t,n){var r=n(0).FDLayoutNode,i=n(0).IMath;function a(e,t,n,i){r.call(this,e,t,n,i)}for(var o in a.prototype=Object.create(r.prototype),r)a[o]=r[o];a.prototype.move=function(){var e=this.graphManager.getLayout();this.displacementX=e.coolingFactor*(this.springForceX+this.repulsionForceX+this.gravitationForceX)/this.noOfChildren,this.displacementY=e.coolingFactor*(this.springForceY+this.repulsionForceY+this.gravitationForceY)/this.noOfChildren,Math.abs(this.displacementX)>e.coolingFactor*e.maxNodeDisplacement&&(this.displacementX=e.coolingFactor*e.maxNodeDisplacement*i.sign(this.displacementX)),Math.abs(this.displacementY)>e.coolingFactor*e.maxNodeDisplacement&&(this.displacementY=e.coolingFactor*e.maxNodeDisplacement*i.sign(this.displacementY)),this.child==null||this.child.getNodes().length==0?this.moveBy(this.displacementX,this.displacementY):this.propogateDisplacementToChildren(this.displacementX,this.displacementY),e.totalDisplacement+=Math.abs(this.displacementX)+Math.abs(this.displacementY),this.springForceX=0,this.springForceY=0,this.repulsionForceX=0,this.repulsionForceY=0,this.gravitationForceX=0,this.gravitationForceY=0,this.displacementX=0,this.displacementY=0},a.prototype.propogateDisplacementToChildren=function(e,t){for(var n=this.getChild().getNodes(),r,i=0;i0)this.positionNodesRadially(e);else{this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var t=new Set(this.getAllNodes()),n=this.nodesWithGravity.filter(function(e){return t.has(e)});this.graphManager.setAllNodesToApplyGravitation(n),this.positionNodesRandomly()}}else if(c.TREE_REDUCTION_ON_INCREMENTAL){this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var t=new Set(this.getAllNodes()),n=this.nodesWithGravity.filter(function(e){return t.has(e)});this.graphManager.setAllNodesToApplyGravitation(n)}return this.initSpringEmbedder(),this.runSpringEmbedder(),!0},v.prototype.tick=function(){if(this.totalIterations++,this.totalIterations===this.maxIterations&&!this.isTreeGrowing&&!this.isGrowthFinished)if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;if(this.totalIterations%l.CONVERGENCE_CHECK_PERIOD==0&&!this.isTreeGrowing&&!this.isGrowthFinished){if(this.isConverged())if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;this.coolingCycle++,this.layoutQuality==0?this.coolingAdjuster=this.coolingCycle:this.layoutQuality==1&&(this.coolingAdjuster=this.coolingCycle/3),this.coolingFactor=Math.max(this.initialCoolingFactor-this.coolingCycle**+(Math.log(100*(this.initialCoolingFactor-this.finalTemperature))/Math.log(this.maxCoolingCycle))/100*this.coolingAdjuster,this.finalTemperature),this.animationPeriod=Math.ceil(this.initialAnimationPeriod*Math.sqrt(this.coolingFactor))}if(this.isTreeGrowing){if(this.growTreeIterations%10==0)if(this.prunedNodesAll.length>0){this.graphManager.updateBounds(),this.updateGrid(),this.growTree(this.prunedNodesAll),this.graphManager.resetAllNodesToApplyGravitation();var e=new Set(this.getAllNodes()),t=this.nodesWithGravity.filter(function(t){return e.has(t)});this.graphManager.setAllNodesToApplyGravitation(t),this.graphManager.updateBounds(),this.updateGrid(),this.coolingFactor=l.DEFAULT_COOLING_FACTOR_INCREMENTAL}else this.isTreeGrowing=!1,this.isGrowthFinished=!0;this.growTreeIterations++}if(this.isGrowthFinished){if(this.isConverged())return!0;this.afterGrowthIterations%10==0&&(this.graphManager.updateBounds(),this.updateGrid()),this.coolingFactor=l.DEFAULT_COOLING_FACTOR_INCREMENTAL*((100-this.afterGrowthIterations)/100),this.afterGrowthIterations++}var n=!this.isTreeGrowing&&!this.isGrowthFinished,r=this.growTreeIterations%10==1&&this.isTreeGrowing||this.afterGrowthIterations%10==1&&this.isGrowthFinished;return this.totalDisplacement=0,this.graphManager.updateBounds(),this.calcSpringForces(),this.calcRepulsionForces(n,r),this.calcGravitationalForces(),this.moveNodes(),this.animate(),!1},v.prototype.getPositionsData=function(){for(var e=this.graphManager.getAllNodes(),t={},n=0;n1){var s;for(s=0;sr&&(r=Math.floor(o.y)),a=Math.floor(o.x+c.DEFAULT_COMPONENT_SEPERATION)}this.transform(new f(u.WORLD_CENTER_X-o.x/2,u.WORLD_CENTER_Y-o.y/2))},v.radialLayout=function(e,t,n){var r=Math.max(this.maxDiagonalInTree(e),c.DEFAULT_RADIAL_SEPARATION);v.branchRadialLayout(t,null,0,359,0,r);var i=g.calculateBounds(e),a=new _;a.setDeviceOrgX(i.getMinX()),a.setDeviceOrgY(i.getMinY()),a.setWorldOrgX(n.x),a.setWorldOrgY(n.y);for(var o=0;o1;){var _=g[0];g.splice(0,1);var y=u.indexOf(_);y>=0&&u.splice(y,1),p--,d--}m=t==null?0:(u.indexOf(g[0])+1)%p;for(var b=Math.abs(r-n)/d,x=m;f!=d;x=++x%p){var S=u[x].getOtherEnd(e);if(S!=t){var C=(n+f*b)%360,w=(C+b)%360;v.branchRadialLayout(S,e,C,w,i+a,a),f++}}},v.maxDiagonalInTree=function(e){for(var t=m.MIN_VALUE,n=0;nt&&(t=r)}return t},v.prototype.calcRepulsionRange=function(){return 2*(this.level+1)*this.idealEdgeLength},v.prototype.groupZeroDegreeMembers=function(){var e=this,t={};this.memberGroups={},this.idToDummyNode={};for(var n=[],r=this.graphManager.getAllNodes(),i=0;i1){var r=`DummyCompound_`+n;e.memberGroups[r]=t[n];var i=t[n][0].getParent(),a=new o(e.graphManager);a.id=r,a.paddingLeft=i.paddingLeft||0,a.paddingRight=i.paddingRight||0,a.paddingBottom=i.paddingBottom||0,a.paddingTop=i.paddingTop||0,e.idToDummyNode[r]=a;var s=e.getGraphManager().add(e.newGraph(),a),c=i.getChild();c.add(a);for(var l=0;l=0;e--){var t=this.compoundOrder[e],n=t.id,r=t.paddingLeft,i=t.paddingTop;this.adjustLocations(this.tiledMemberPack[n],t.rect.x,t.rect.y,r,i)}},v.prototype.repopulateZeroDegreeMembers=function(){var e=this,t=this.tiledZeroDegreePack;Object.keys(t).forEach(function(n){var r=e.idToDummyNode[n],i=r.paddingLeft,a=r.paddingTop;e.adjustLocations(t[n],r.rect.x,r.rect.y,i,a)})},v.prototype.getToBeTiled=function(e){var t=e.id;if(this.toBeTiled[t]!=null)return this.toBeTiled[t];var n=e.getChild();if(n==null)return this.toBeTiled[t]=!1,!1;for(var r=n.getNodes(),i=0;i0)return this.toBeTiled[t]=!1,!1;if(a.getChild()==null){this.toBeTiled[a.id]=!1;continue}if(!this.getToBeTiled(a))return this.toBeTiled[t]=!1,!1}return this.toBeTiled[t]=!0,!0},v.prototype.getNodeDegree=function(e){e.id;for(var t=e.getEdges(),n=0,r=0;rc&&(c=u.rect.height)}n+=c+e.verticalPadding}},v.prototype.tileCompoundMembers=function(e,t){var n=this;this.tiledMemberPack=[],Object.keys(e).forEach(function(r){var i=t[r];n.tiledMemberPack[r]=n.tileNodes(e[r],i.paddingLeft+i.paddingRight),i.rect.width=n.tiledMemberPack[r].width,i.rect.height=n.tiledMemberPack[r].height})},v.prototype.tileNodes=function(e,t){var n={rows:[],rowWidth:[],rowHeight:[],width:0,height:t,verticalPadding:c.TILING_PADDING_VERTICAL,horizontalPadding:c.TILING_PADDING_HORIZONTAL};e.sort(function(e,t){return e.rect.width*e.rect.height>t.rect.width*t.rect.height?-1:+(e.rect.width*e.rect.height0&&(a+=e.horizontalPadding),e.rowWidth[n]=a,e.width0&&(o+=e.verticalPadding);var s=0;o>e.rowHeight[n]&&(s=e.rowHeight[n],e.rowHeight[n]=o,s=e.rowHeight[n]-s),e.height+=s,e.rows[n].push(t)},v.prototype.getShortestRowIndex=function(e){for(var t=-1,n=Number.MAX_VALUE,r=0;rn&&(t=r,n=e.rowWidth[r]);return t},v.prototype.canAddHorizontal=function(e,t,n){var r=this.getShortestRowIndex(e);if(r<0)return!0;var i=e.rowWidth[r];if(i+e.horizontalPadding+t<=e.width)return!0;var a=0;e.rowHeight[r]0&&(a=n+e.verticalPadding-e.rowHeight[r]);var o=e.width-i>=t+e.horizontalPadding?(e.height+a)/(i+t+e.horizontalPadding):(e.height+a)/e.width;a=n+e.verticalPadding;var s=e.widtha&&t!=n){r.splice(-1,1),e.rows[n].push(i),e.rowWidth[t]=e.rowWidth[t]-a,e.rowWidth[n]=e.rowWidth[n]+a,e.width=e.rowWidth[instance.getLongestRowIndex(e)];for(var o=Number.MIN_VALUE,s=0;so&&(o=r[s].height);t>0&&(o+=e.verticalPadding);var c=e.rowHeight[t]+e.rowHeight[n];e.rowHeight[t]=o,e.rowHeight[n]0)for(var u=i;u<=a;u++)c[0]+=this.grid[u][o-1].length+this.grid[u][o].length-1;if(a0)for(var u=o;u<=s;u++)c[3]+=this.grid[i-1][u].length+this.grid[i][u].length-1;for(var d=m.MAX_VALUE,f,p,h=0;h{(function(r,i){typeof e==`object`&&typeof t==`object`?t.exports=i(n()):typeof define==`function`&&define.amd?define([`cose-base`],i):typeof e==`object`?e.cytoscapeCoseBilkent=i(n()):r.cytoscapeCoseBilkent=i(r.coseBase)})(e,function(e){return(function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,`a`,t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p=``,n(n.s=1)})([(function(t,n){t.exports=e}),(function(e,t,n){var r=n(0).layoutBase.LayoutConstants,i=n(0).layoutBase.FDLayoutConstants,a=n(0).CoSEConstants,o=n(0).CoSELayout,s=n(0).CoSENode,c=n(0).layoutBase.PointD,l=n(0).layoutBase.DimensionD,u={ready:function(){},stop:function(){},quality:`default`,nodeDimensionsIncludeLabels:!1,refresh:30,fit:!0,padding:10,randomize:!0,nodeRepulsion:4500,idealEdgeLength:50,edgeElasticity:.45,nestingFactor:.1,gravity:.25,numIter:2500,tile:!0,animate:`end`,animationDuration:500,tilingPaddingVertical:10,tilingPaddingHorizontal:10,gravityRangeCompound:1.5,gravityCompound:1,gravityRange:3.8,initialEnergyOnIncremental:.5};function d(e,t){var n={};for(var r in e)n[r]=e[r];for(var r in t)n[r]=t[r];return n}function f(e){this.options=d(u,e),p(this.options)}var p=function(e){e.nodeRepulsion!=null&&(a.DEFAULT_REPULSION_STRENGTH=i.DEFAULT_REPULSION_STRENGTH=e.nodeRepulsion),e.idealEdgeLength!=null&&(a.DEFAULT_EDGE_LENGTH=i.DEFAULT_EDGE_LENGTH=e.idealEdgeLength),e.edgeElasticity!=null&&(a.DEFAULT_SPRING_STRENGTH=i.DEFAULT_SPRING_STRENGTH=e.edgeElasticity),e.nestingFactor!=null&&(a.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR=i.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR=e.nestingFactor),e.gravity!=null&&(a.DEFAULT_GRAVITY_STRENGTH=i.DEFAULT_GRAVITY_STRENGTH=e.gravity),e.numIter!=null&&(a.MAX_ITERATIONS=i.MAX_ITERATIONS=e.numIter),e.gravityRange!=null&&(a.DEFAULT_GRAVITY_RANGE_FACTOR=i.DEFAULT_GRAVITY_RANGE_FACTOR=e.gravityRange),e.gravityCompound!=null&&(a.DEFAULT_COMPOUND_GRAVITY_STRENGTH=i.DEFAULT_COMPOUND_GRAVITY_STRENGTH=e.gravityCompound),e.gravityRangeCompound!=null&&(a.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR=i.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR=e.gravityRangeCompound),e.initialEnergyOnIncremental!=null&&(a.DEFAULT_COOLING_FACTOR_INCREMENTAL=i.DEFAULT_COOLING_FACTOR_INCREMENTAL=e.initialEnergyOnIncremental),e.quality==`draft`?r.QUALITY=0:e.quality==`proof`?r.QUALITY=2:r.QUALITY=1,a.NODE_DIMENSIONS_INCLUDE_LABELS=i.NODE_DIMENSIONS_INCLUDE_LABELS=r.NODE_DIMENSIONS_INCLUDE_LABELS=e.nodeDimensionsIncludeLabels,a.DEFAULT_INCREMENTAL=i.DEFAULT_INCREMENTAL=r.DEFAULT_INCREMENTAL=!e.randomize,a.ANIMATE=i.ANIMATE=r.ANIMATE=e.animate,a.TILE=e.tile,a.TILING_PADDING_VERTICAL=typeof e.tilingPaddingVertical==`function`?e.tilingPaddingVertical.call():e.tilingPaddingVertical,a.TILING_PADDING_HORIZONTAL=typeof e.tilingPaddingHorizontal==`function`?e.tilingPaddingHorizontal.call():e.tilingPaddingHorizontal};f.prototype.run=function(){var e,t,n=this.options;this.idToLNode={};var r=this.layout=new o,i=this;i.stopped=!1,this.cy=this.options.cy,this.cy.trigger({type:`layoutstart`,layout:this});var a=r.newGraphManager();this.gm=a;var s=this.options.eles.nodes(),c=this.options.eles.edges();this.root=a.addRoot(),this.processChildrenList(this.root,this.getTopMostNodes(s),r);for(var l=0;l0){var h=n.getGraphManager().add(n.newGraph(),u);this.processChildrenList(h,o,n)}}},f.prototype.stop=function(){return this.stopped=!0,this};var m=function(e){e(`layout`,`cose-bilkent`,f)};typeof cytoscape<`u`&&m(cytoscape),e.exports=m})])})}));export default r(); \ No newline at end of file diff --git a/internal/ui/dist/assets/cytoscape.esm-Dm6iss-N.js b/internal/ui/dist/assets/cytoscape.esm-Dm6iss-N.js deleted file mode 100644 index 8847b67..0000000 --- a/internal/ui/dist/assets/cytoscape.esm-Dm6iss-N.js +++ /dev/null @@ -1,321 +0,0 @@ -function e(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:i}}throw TypeError(`Invalid attempt to iterate non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var a,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,a=e},f:function(){try{o||n.return==null||n.return()}finally{if(s)throw a}}}}function s(e,t,n){return(t=h(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){if(typeof Symbol<`u`&&e[Symbol.iterator]!=null||e[`@@iterator`]!=null)return Array.from(e)}function l(e,t){var n=e==null?null:typeof Symbol<`u`&&e[Symbol.iterator]||e[`@@iterator`];if(n!=null){var r,i,a,o,s=[],c=!0,l=!1;try{if(a=(n=n.call(e)).next,t===0){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);c=!0);}catch(e){l=!0,i=e}finally{try{if(!c&&n.return!=null&&(o=n.return(),Object(o)!==o))return}finally{if(l)throw i}}return s}}function u(){throw TypeError(`Invalid attempt to destructure non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function d(){throw TypeError(`Invalid attempt to spread non-iterable instance. -In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function f(e,n){return t(e)||l(e,n)||_(e,n)||u()}function p(e){return n(e)||c(e)||_(e)||d()}function m(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return String(e)}function h(e){var t=m(e,`string`);return typeof t==`symbol`?t:t+``}function g(e){"@babel/helpers - typeof";return g=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},g(e)}function _(t,n){if(t){if(typeof t==`string`)return e(t,n);var r={}.toString.call(t).slice(8,-1);return r===`Object`&&t.constructor&&(r=t.constructor.name),r===`Map`||r===`Set`?Array.from(t):r===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?e(t,n):void 0}}var v=typeof window>`u`?null:window,y=v?v.navigator:null;v&&v.document;var b=g(``),x=g({}),S=g(function(){}),C=typeof HTMLElement>`u`?`undefined`:g(HTMLElement),w=function(e){return e&&e.instanceString&&E(e.instanceString)?e.instanceString():null},T=function(e){return e!=null&&g(e)==b},E=function(e){return e!=null&&g(e)===S},D=function(e){return!N(e)&&(Array.isArray?Array.isArray(e):e!=null&&e instanceof Array)},O=function(e){return e!=null&&g(e)===x&&!D(e)&&e.constructor===Object},k=function(e){return e!=null&&g(e)===x},A=function(e){return e!=null&&g(e)===g(1)&&!isNaN(e)},j=function(e){return A(e)&&Math.floor(e)===e},M=function(e){if(C!==`undefined`)return e!=null&&e instanceof HTMLElement},N=function(e){return P(e)||F(e)},P=function(e){return w(e)===`collection`&&e._private.single},F=function(e){return w(e)===`collection`&&!e._private.single},I=function(e){return w(e)===`core`},L=function(e){return w(e)===`stylesheet`},R=function(e){return w(e)===`event`},z=function(e){return e==null?!0:!!(e===``||e.match(/^\s+$/))},B=function(e){return typeof HTMLElement>`u`?!1:e instanceof HTMLElement},V=function(e){return O(e)&&A(e.x1)&&A(e.x2)&&A(e.y1)&&A(e.y2)},H=function(e){return k(e)&&E(e.then)},U=function(){return y&&y.userAgent.match(/msie|trident|edge/i)},W=function(e,t){t||=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return`undefined`;for(var e=[],t=0;tt)},ce=function(e,t){return-1*se(e,t)},X=Object.assign==null?function(e){for(var t=arguments,n=1;n1&&--n,n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var u=RegExp(`^`+re+`$`).exec(e);if(u){if(n=parseInt(u[1]),n<0?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,r=parseFloat(u[2]),r<0||r>100||(r/=100,i=parseFloat(u[3]),i<0||i>100)||(i/=100,a=u[4],a!==void 0&&(a=parseFloat(a),a<0||a>1)))return;if(r===0)o=s=c=Math.round(i*255);else{var d=i<.5?i*(1+r):i+r-i*r,f=2*i-d;o=Math.round(255*l(f,d,n+1/3)),s=Math.round(255*l(f,d,n)),c=Math.round(255*l(f,d,n-1/3))}t=[o,s,c,a]}return t},de=function(e){var t,n=RegExp(`^`+te+`$`).exec(e);if(n){t=[];for(var r=[],i=1;i<=3;i++){var a=n[i];if(a[a.length-1]===`%`&&(r[i]=!0),a=parseFloat(a),r[i]&&(a=a/100*255),a<0||a>255)return;t.push(Math.floor(a))}var o=r[1]||r[2]||r[3],s=r[1]&&r[2]&&r[3];if(o&&!s)return;var c=n[4];if(c!==void 0){if(c=parseFloat(c),c<0||c>1)return;t.push(c)}}return t},fe=function(e){return me[e.toLowerCase()]},pe=function(e){return(D(e)?e:null)||fe(e)||le(e)||de(e)||ue(e)},me={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},he=function(e){for(var t=e.map,n=e.keys,r=n.length,i=0;i=s||t<0||_&&n>=d}function C(){var e=t();if(S(e))return w(e);p=setTimeout(C,x(e))}function w(e){return p=void 0,v&&l?y(e):(l=u=void 0,f)}function T(){p!==void 0&&clearTimeout(p),h=0,l=m=u=p=void 0}function E(){return p===void 0?f:w(t())}function D(){var e=t(),n=S(e);if(l=arguments,u=this,m=e,n){if(p===void 0)return b(m);if(_)return clearTimeout(p),p=setTimeout(C,s),y(m)}return p===void 0&&(p=setTimeout(C,s)),f}return D.cancel=T,D.flush=E,D}return it=o,it}var st=ve(ot()),ct=v?v.performance:null,lt=ct&&ct.now?function(){return ct.now()}:function(){return Date.now()},ut=function(){if(v){if(v.requestAnimationFrame)return function(e){v.requestAnimationFrame(e)};if(v.mozRequestAnimationFrame)return function(e){v.mozRequestAnimationFrame(e)};if(v.webkitRequestAnimationFrame)return function(e){v.webkitRequestAnimationFrame(e)};if(v.msRequestAnimationFrame)return function(e){v.msRequestAnimationFrame(e)}}return function(e){e&&setTimeout(function(){e(lt())},1e3/60)}}(),dt=function(e){return ut(e)},ft=lt,pt=9261,mt=65599,ht=5381,gt=function(e){for(var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:pt,n;n=e.next(),!n.done;)t=t*mt+n.value|0;return t},_t=function(e){return(arguments.length>1&&arguments[1]!==void 0?arguments[1]:pt)*mt+e|0},vt=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ht;return(t<<5)+t+e|0},yt=function(e,t){return e*2097152+t},bt=function(e){return e[0]*2097152+e[1]},xt=function(e,t){return[_t(e[0],t[0]),vt(e[1],t[1])]},St=function(e,t){var n={value:0,done:!1},r=0,i=e.length;return gt({next:function(){return r=0;r--)e[r]===t&&e.splice(r,1)},Jt=function(e){e.splice(0,e.length)},Yt=function(e,t){for(var n=0;n`u`?`undefined`:g(Set))===$t?en:Set,nn=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(e===void 0||t===void 0||!I(e)){Lt(`An element must have a core reference and parameters set`);return}var r=t.group;if(r??=t.data&&t.data.source!=null&&t.data.target!=null?`edges`:`nodes`,r!==`nodes`&&r!==`edges`){Lt("An element must be of type `nodes` or `edges`; you specified `"+r+"`");return}this.length=1,this[0]=this;var i=this._private={cy:e,single:!0,data:t.data||{},position:t.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:r,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!t.selected,selectable:t.selectable===void 0?!0:!!t.selectable,locked:!!t.locked,grabbed:!1,grabbable:t.grabbable===void 0?!0:!!t.grabbable,pannable:t.pannable===void 0?r===`edges`:!!t.pannable,active:!1,classes:new tn,animation:{current:[],queue:[]},rscratch:{},scratch:t.scratch||{},edges:[],children:[],parent:t.parent&&t.parent.isNode()?t.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(i.position.x??(i.position.x=0),i.position.y??(i.position.y=0),t.renderedPosition){var a=t.renderedPosition,o=e.pan(),s=e.zoom();i.position={x:(a.x-o.x)/s,y:(a.y-o.y)/s}}var c=[];D(t.classes)?c=t.classes:T(t.classes)&&(c=t.classes.split(/\s+/));for(var l=0,u=c.length;lt)},l=function(e,t,i,a,o){var s;if(i??=0,o??=n,i<0)throw Error(`lo must be non-negative`);for(a??=e.length;in;0<=n?t++:t--)l.push(t);return l}).apply(this).reverse(),c=[],a=0,o=s.length;ah;0<=h?++f:--f)g.push(a(e,r));return g},m=function(e,t,r,i){var a,o,s;for(i??=n,a=e[r];r>t;){if(s=r-1>>1,o=e[s],i(a,o)<0){e[r]=o,r=s;continue}break}return e[r]=a},h=function(e,t,r){var i,a,o,s,c;for(r??=n,a=e.length,c=t,o=e[t],i=2*t+1;i0;){var x=_.pop(),S=h(x),C=x.id();if(d[C]=S,S!==1/0)for(var w=x.neighborhood().intersect(p),E=0;E0)for(n.unshift(t);u[i];){var a=u[i];n.unshift(a.edge),n.unshift(a.node),r=a.node,i=r.id()}return o.spawn(n)}}}},gn={kruskal:function(e){e||=function(e){return 1};for(var t=this.byGroup(),n=t.nodes,r=t.edges,i=n.length,a=Array(i),o=n,s=function(e){for(var t=0;t0;){if(b(),S++,y===l){for(var C=[],w=i,T=l,E=g[T];C.unshift(w),E!=null&&C.unshift(E),w=h[T],w!=null;)T=w.id(),E=g[T];return{found:!0,distance:u[y],path:this.spawn(C),steps:S}}f[y]=!0;for(var D=v._private.edges,O=0;OE&&(p[w]=E,g[w]=C,_[w]=y),!i){var D=C*l+S;!i&&p[D]>E&&(p[D]=E,g[D]=S,_[D]=y)}}}for(var O=0;O1&&arguments[1]!==void 0?arguments[1]:a,r=v(e),i=[],o=r;;){if(o==null)return t.spawn();var c=_(o),l=c.edge,u=c.pred;if(i.unshift(o[0]),o.same(n)&&i.length>0)break;l!=null&&i.unshift(l),o=u}return s.spawn(i)},x=0;x=0;l--){var u=c[l],d=u[1],f=u[2];(t[d]===o&&t[f]===s||t[d]===s&&t[f]===o)&&c.splice(l,1)}for(var p=0;pr;)t=wn(Math.floor(Math.random()*t.length),e,t),n--;return t},En={kargerStein:function(){var e=this,t=this.byGroup(),n=t.nodes,r=t.edges;r.unmergeBy(function(e){return e.isLoop()});var i=n.length,a=r.length,o=Math.ceil((Math.log(i)/Math.LN2)**2),s=Math.floor(i/Cn);if(i<2){Lt(`At least 2 nodes are required for Karger-Stein algorithm`);return}for(var c=[],l=0;l1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=1/0,i=t;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=-1/0,i=t;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=0,i=0,a=t;a1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;r?e=e.slice(t,n):(n0&&e.splice(0,t));for(var o=0,s=e.length-1;s>=0;s--){var c=e[s];a?isFinite(c)||(e[s]=-1/0,o++):e.splice(s,1)}i&&e.sort(function(e,t){return e-t});var l=e.length,u=Math.floor(l/2);return l%2==0?(e[u-1+o]+e[u+o])/2:e[u+1+o]},Fn=function(e){return Math.PI*e/180},In=function(e,t){return Math.atan2(t,e)-Math.PI/2},Ln=Math.log2||function(e){return Math.log(e)/Math.log(2)},Rn=function(e){return e>0?1:e<0?-1:0},zn=function(e,t){return Math.sqrt(Bn(e,t))},Bn=function(e,t){var n=t.x-e.x,r=t.y-e.y;return n*n+r*r},Vn=function(e){for(var t=e.length,n=0,r=0;r=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(e.w!=null&&e.h!=null&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},qn=function(e){return{x1:e.x1,x2:e.x2,w:e.w,y1:e.y1,y2:e.y2,h:e.h}},Jn=function(e){e.x1=1/0,e.y1=1/0,e.x2=-1/0,e.y2=-1/0,e.w=0,e.h=0},Yn=function(e,t){e.x1=Math.min(e.x1,t.x1),e.x2=Math.max(e.x2,t.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,t.y1),e.y2=Math.max(e.y2,t.y2),e.h=e.y2-e.y1},Xn=function(e,t,n){e.x1=Math.min(e.x1,t),e.x2=Math.max(e.x2,t),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,n),e.y2=Math.max(e.y2,n),e.h=e.y2-e.y1},Zn=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return e.x1-=t,e.x2+=t,e.y1-=t,e.y2+=t,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Qn=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],n,r,i,a;if(t.length===1)n=r=i=a=t[0];else if(t.length===2)n=i=t[0],a=r=t[1];else if(t.length===4){var o=f(t,4);n=o[0],r=o[1],i=o[2],a=o[3]}return e.x1-=a,e.x2+=r,e.y1-=n,e.y2+=i,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},$n=function(e,t){e.x1=t.x1,e.y1=t.y1,e.x2=t.x2,e.y2=t.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1},er=function(e,t){return!(e.x1>t.x2||t.x1>e.x2||e.x2t.y2||t.y1>e.y2)},tr=function(e,t,n){return e.x1<=t&&t<=e.x2&&e.y1<=n&&n<=e.y2},nr=function(e,t){return tr(e,t.x,t.y)},rr=function(e,t){return tr(e,t.x1,t.y1)&&tr(e,t.x2,t.y2)},ir=Math.hypot??function(e,t){return Math.sqrt(e*e+t*t)};function ar(e,t){if(e.length<3)throw Error(`Need at least 3 vertices`);var n=function(e,t){return{x:e.x+t.x,y:e.y+t.y}},r=function(e,t){return{x:e.x-t.x,y:e.y-t.y}},i=function(e,t){return{x:e.x*t,y:e.y*t}},a=function(e,t){return e.x*t.y-e.y*t.x},o=function(e){var t=ir(e.x,e.y);return t===0?{x:0,y:0}:{x:e.x/t,y:e.y/t}},s=function(e){for(var t=0,n=0;n7&&arguments[7]!==void 0?arguments[7]:`auto`,c=s===`auto`?jr(i,a):s,l=i/2,u=a/2;c=Math.min(c,l,u);var d=c!==l,f=c!==u,p;if(d){var m=n-l+c-o,h=r-u-o;if(p=Cr(e,t,n,r,m,h,n+l-c+o,h,!1),p.length>0)return p}if(f){var g=n+l+o;if(p=Cr(e,t,n,r,g,r-u+c-o,g,r+u-c+o,!1),p.length>0)return p}if(d){var _=n-l+c-o,v=r+u+o;if(p=Cr(e,t,n,r,_,v,n+l-c+o,v,!1),p.length>0)return p}if(f){var y=n-l-o;if(p=Cr(e,t,n,r,y,r-u+c-o,y,r+u-c+o,!1),p.length>0)return p}var b,x=n-l+c,S=r-u+c;if(b=xr(e,t,n,r,x,S,c+o),b.length>0&&b[0]<=x&&b[1]<=S)return[b[0],b[1]];var C=n+l-c,w=r-u+c;if(b=xr(e,t,n,r,C,w,c+o),b.length>0&&b[0]>=C&&b[1]<=w)return[b[0],b[1]];var T=n+l-c,E=r+u-c;if(b=xr(e,t,n,r,T,E,c+o),b.length>0&&b[0]>=T&&b[1]>=E)return[b[0],b[1]];var D=n-l+c,O=r+u-c;return b=xr(e,t,n,r,D,O,c+o),b.length>0&&b[0]<=D&&b[1]>=O?[b[0],b[1]]:[]},cr=function(e,t,n,r,i,a,o){var s=o,c=Math.min(n,i),l=Math.max(n,i),u=Math.min(r,a),d=Math.max(r,a);return c-s<=e&&e<=l+s&&u-s<=t&&t<=d+s},lr=function(e,t,n,r,i,a,o,s,c){var l={x1:Math.min(n,o,i)-c,x2:Math.max(n,o,i)+c,y1:Math.min(r,s,a)-c,y2:Math.max(r,s,a)+c};return!(el.x2||tl.y2)},ur=function(e,t,n,r){n-=r;var i=t*t-4*e*n;if(i<0)return[];var a=Math.sqrt(i),o=2*e;return[(-t+a)/o,(-t-a)/o]},dr=function(e,t,n,r,i){e===0&&(e=1e-5),t/=e,n/=e,r/=e;var a,o=(3*n-t*t)/9,s=-(27*r)+t*(9*n-t*t*2),c,l,u,d,f;if(s/=54,a=o*o*o+s*s,i[1]=0,d=t/3,a>0){l=s+Math.sqrt(a),l=l<0?-((-l)**(1/3)):l**(1/3),u=s-Math.sqrt(a),u=u<0?-((-u)**(1/3)):u**(1/3),i[0]=-d+l+u,d+=(l+u)/2,i[4]=i[2]=-d,d=Math.sqrt(3)*(-u+l)/2,i[3]=d,i[5]=-d;return}if(i[5]=i[3]=0,a===0){f=s<0?-((-s)**(1/3)):s**(1/3),i[0]=-d+2*f,i[4]=i[2]=-(f+d);return}o=-o,c=o*o*o,c=Math.acos(s/Math.sqrt(c)),f=2*Math.sqrt(o),i[0]=-d+f*Math.cos(c/3),i[2]=-d+f*Math.cos((c+2*Math.PI)/3),i[4]=-d+f*Math.cos((c+4*Math.PI)/3)},fr=function(e,t,n,r,i,a,o,s){var c=1*n*n-4*n*i+2*n*o+4*i*i-4*i*o+o*o+r*r-4*r*a+2*r*s+4*a*a-4*a*s+s*s,l=9*n*i-3*n*n-3*n*o-6*i*i+3*i*o+9*r*a-3*r*r-3*r*s-6*a*a+3*a*s,u=3*n*n-6*n*i+n*o-n*e+2*i*i+2*i*e-o*e+3*r*r-6*r*a+r*s-r*t+2*a*a+2*a*t-s*t,d=1*n*i-n*n+n*e-i*e+r*a-r*r+r*t-a*t,f=[];dr(c,l,u,d,f);for(var p=1e-7,m=[],h=0;h<6;h+=2)Math.abs(f[h+1])=0&&f[h]<=1&&m.push(f[h]);m.push(1),m.push(0);for(var g=-1,_,v,y,b=0;b=0?yc?(e-i)*(e-i)+(t-a)*(t-a):l-d},mr=function(e,t,n){for(var r,i,a,o,s,c=0,l=0;l=e&&e>=a||r<=e&&e<=a)s=(e-r)/(a-r)*(o-i)+i,s>t&&c++;else continue;return c%2!=0},hr=function(e,t,n,r,i,a,o,s,c){var l=Array(n.length),u;s[0]==null?u=s:(u=Math.atan(s[1]/s[0]),s[0]<0?u+=Math.PI/2:u=-u-Math.PI/2);for(var d=Math.cos(-u),f=Math.sin(-u),p=0;p0?_r(vr(l,-c)):l)},gr=function(e,t,n,r,i,a,o,s){for(var c=Array(n.length*2),l=0;l=0&&h<=1&&_.push(h),g>=0&&g<=1&&_.push(g),_.length===0)return[];var v=_[0]*s[0]+e,y=_[0]*s[1]+t;return _.length>1?_[0]==_[1]?[v,y]:[v,y,_[1]*s[0]+e,_[1]*s[1]+t]:[v,y]},Sr=function(e,t,n){return t<=e&&e<=n||n<=e&&e<=t?e:e<=t&&t<=n||n<=t&&t<=e?t:n},Cr=function(e,t,n,r,i,a,o,s,c){var l=e-i,u=n-e,d=o-i,f=t-a,p=r-t,m=s-a,h=d*f-m*l,g=u*f-p*l,_=m*u-d*p;if(_!==0){var v=h/_,y=g/_,b=.001,x=0-b,S=1+b;return x<=v&&v<=S&&x<=y&&y<=S||c?[e+v*u,t+v*p]:[]}else if(h===0||g===0)return Sr(e,n,o)===o?[o,s]:Sr(e,n,i)===i?[i,a]:Sr(i,o,n)===n?[n,r]:[];else return[]},wr=function(e,t,n,r,i){var a=[],o=r/2,s=i/2,c=t,l=n;a.push({x:c+o*e[0],y:l+s*e[1]});for(var u=1;u0?_r(vr(u,-s)):u}else f=n;for(var m,h,g,_,v=0;v2){for(var p=[l[0],l[1]],m=(p[0]-e)**2+(p[1]-t)**2,h=1;hl&&(l=t)},get:function(e){return c[e]}},d=0;d0?v.edgesTo(_)[0]:_.edgesTo(v)[0];var b=r(y);_=_.id(),l[_]>l[m]+b&&(l[_]=l[m]+b,d.nodes.indexOf(_)<0?d.push(_):d.updateItem(_),c[_]=0,n[_]=[]),l[_]==l[m]+b&&(c[_]=c[_]+c[m],n[_].push(m))}else for(var x=0;x0;){for(var T=t.pop(),E=0;E0&&o.push(n[s]);o.length!==0&&i.push(r.collection(o))}return i},ti=function(e,t){for(var n=0;n5&&arguments[5]!==void 0?arguments[5]:ai,o=r,s,c,l=0;l=2?di(e,t,n,0,ci,li):di(e,t,n,0,si)},squaredEuclidean:function(e,t,n){return di(e,t,n,0,ci)},manhattan:function(e,t,n){return di(e,t,n,0,si)},max:function(e,t,n){return di(e,t,n,-1/0,ui)}};fi[`squared-euclidean`]=fi.squaredEuclidean,fi.squaredeuclidean=fi.squaredEuclidean;function pi(e,t,n,r,i,a){var o=E(e)?e:fi[e]||fi.euclidean;return t===0&&E(e)?o(i,a):o(t,n,r,i,a)}var mi=Kt({k:2,m:2,sensitivityThreshold:1e-4,distance:`euclidean`,maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),hi=function(e){return mi(e)},gi=function(e,t,n,r,i){var a=i===`kMedoids`?function(e){return r[e](n)}:function(e){return n[e]},o=function(e){return r[e](t)},s=n,c=t;return pi(e,r.length,a,o,s,c)},_i=function(e,t,n){for(var r=n.length,i=Array(r),a=Array(r),o=Array(t),s=null,c=0;cn)return!1;return!0},Si=function(e,t,n){for(var r=0;ro&&(o=t[c][l],s=l);i[s].push(e[c])}for(var u=0;u=i.threshold||i.mode===`dendrogram`&&e.length===1)return!1;var p=t[a],m=t[r[a]],h=i.mode===`dendrogram`?{left:p,right:m,key:p.key}:{value:p.value.concat(m.value),key:p.key};e[p.index]=h,e.splice(m.index,1),t[p.key]=h;for(var g=0;gn[m.key][_.key]&&(s=n[m.key][_.key])):i.linkage===`max`?(s=n[p.key][_.key],n[p.key][_.key]0&&r.push(i);return r},Ki=function(e,t,n){for(var r=[],i=0;io&&(a=c,o=t[i*e+c])}a>0&&r.push(a)}for(var l=0;lc&&(s=l,c=u)}n[i]=a[s]}return r=Ki(e,t,n),r},Ji=function(e){for(var t=this.cy(),n=this.nodes(),r=Hi(e),i={},a=0;a=E?(D=E,E=k,O=A):k>D&&(D=k);for(var j=0;j0);S[w%r.minIterations*o+L]=R,I+=R}if(I>0&&(w>=r.minIterations-1||w==r.maxIterations-1)){for(var z=0,B=0;B1||i>1)&&(o=!0),u[t]=[],e.outgoers().forEach(function(e){e.isEdge()&&u[t].push(e.id())})}else d[t]=[void 0,e.target().id()]}):a.forEach(function(e){var t=e.id();e.isNode()?(e.degree(!0)%2&&(s?c?o=!0:c=t:s=t),u[t]=[],e.connectedEdges().forEach(function(e){return u[t].push(e.id())})):d[t]=[e.source().id(),e.target().id()]});var f={found:!1,trail:void 0};if(o)return f;if(c&&s)if(i){if(l&&c!=l)return f;l=c}else if(l&&c!=l&&s!=l)return f;else l||=c;else l||=a[0].id();var p=function(e){for(var t=e,n=[e],r,a,o;u[t].length;)r=u[t].shift(),a=d[r][0],o=d[r][1],t==o?!i&&t!=a&&(u[a]=u[a].filter(function(e){return e!=r}),t=a):(u[o]=u[o].filter(function(e){return e!=r}),t=o),n.unshift(r),n.unshift(t);return n},m=[],h=[];for(h=p(l);h.length!=1;)u[h[0]].length==0?(m.unshift(a.getElementById(h.shift())),m.unshift(a.getElementById(h.shift()))):h=p(h.shift()).concat(h);for(var g in m.unshift(a.getElementById(h.shift())),u)if(u[g].length)return f;return f.found=!0,f.trail=this.spawn(m,!0),f}},Qi=function(){var e=this,t={},n=0,r=0,i=[],a=[],o={},s=function(n,r){for(var o=a.length-1,s=[],c=e.spawn();a[o].x!=n||a[o].y!=r;)s.push(a.pop().edge),o--;s.push(a.pop().edge),s.forEach(function(n){var r=n.connectedNodes().intersection(e);c.merge(n),r.forEach(function(n){var r=n.id(),i=n.connectedEdges().intersection(e);c.merge(n),t[r].cutVertex?c.merge(i.filter(function(e){return e.isLoop()})):c.merge(i)})}),i.push(c)},c=function(l,u,d){l===d&&(r+=1),t[u]={id:n,low:n++,cutVertex:!1};var f=e.getElementById(u).connectedEdges().intersection(e);if(f.size()===0)i.push(e.spawn(e.getElementById(u)));else{var p,m,h,g;f.forEach(function(e){p=e.source().id(),m=e.target().id(),h=p===u?m:p,h!==d&&(g=e.id(),o[g]||(o[g]=!0,a.push({x:u,y:h,edge:e})),h in t?t[u].low=Math.min(t[u].low,t[h].id):(c(l,h,u),t[u].low=Math.min(t[u].low,t[h].low),t[u].id<=t[h].low&&(t[u].cutVertex=!0,s(u,h))))})}};e.forEach(function(e){if(e.isNode()){var n=e.id();n in t||(r=0,c(n,n),t[n].cutVertex=r>1)}});var l=Object.keys(t).filter(function(e){return t[e].cutVertex}).map(function(t){return e.getElementById(t)});return{cut:e.spawn(l),components:i}},$i={hopcroftTarjanBiconnected:Qi,htbc:Qi,htb:Qi,hopcroftTarjanBiconnectedComponents:Qi},ea=function(){var e=this,t={},n=0,r=[],i=[],a=e.spawn(e),o=function(s){if(i.push(s),t[s]={index:n,low:n++,explored:!1},e.getElementById(s).connectedEdges().intersection(e).forEach(function(e){var n=e.target().id();n!==s&&(n in t||o(n),t[n].explored||(t[s].low=Math.min(t[s].low,t[n].low)))}),t[s].index===t[s].low){for(var c=e.spawn();;){var l=i.pop();if(c.merge(e.getElementById(l)),t[l].low=t[s].index,t[l].explored=!0,l===s)break}var u=c.edgesWith(c),d=c.merge(u);r.push(d),a=a.difference(d)}};return e.forEach(function(e){if(e.isNode()){var n=e.id();n in t||o(n)}}),{cut:a,components:r}},ta={tarjanStronglyConnected:ea,tsc:ea,tscc:ea,tarjanStronglyConnectedComponents:ea},na={};[an,hn,gn,vn,bn,Sn,En,Rr,Br,Hr,Wr,ii,ji,Bi,Yi,Zi,$i,ta].forEach(function(e){X(na,e)});var ra=0,ia=1,aa=2,oa=function(e){if(!(this instanceof oa))return new oa(e);this.id=`Thenable/1.0.7`,this.state=ra,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},typeof e==`function`&&e.call(this,this.fulfill.bind(this),this.reject.bind(this))};oa.prototype={fulfill:function(e){return sa(this,ia,`fulfillValue`,e)},reject:function(e){return sa(this,aa,`rejectReason`,e)},then:function(e,t){var n=this,r=new oa;return n.onFulfilled.push(ua(e,r,`fulfill`)),n.onRejected.push(ua(t,r,`reject`)),ca(n),r.proxy}};var sa=function(e,t,n,r){return e.state===ra&&(e.state=t,e[n]=r,ca(e)),e},ca=function(e){e.state===ia?la(e,`onFulfilled`,e.fulfillValue):e.state===aa&&la(e,`onRejected`,e.rejectReason)},la=function(e,t,n){if(e[t].length!==0){var r=e[t];e[t]=[];var i=function(){for(var e=0;e0}},clearQueue:function(){return function(){var e=this,t=e.length===void 0?[e]:e;if(!(this._private.cy||this).styleEnabled())return this;for(var n=0;n-1}return Eo=t,Eo}var ko,Ao;function jo(){if(Ao)return ko;Ao=1;var e=yo();function t(t,n){var r=this.__data__,i=e(r,t);return i<0?(++this.size,r.push([t,n])):r[i][1]=n,this}return ko=t,ko}var Mo,No;function Po(){if(No)return Mo;No=1;var e=po(),t=So(),n=To(),r=Oo(),i=jo();function a(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t-1&&n%1==0&&n0&&this.spawn(r).updateStyle().emit(`class`),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return t!=null&&t._private.classes.has(e)},toggleClass:function(e,t){D(e)||(e=e.match(/\S+/g)||[]);for(var n=this,r=t===void 0,i=[],a=0,o=n.length;a0&&this.spawn(i).updateStyle().emit(`class`),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var n=this;if(t==null)t=250;else if(t===0)return n;return n.addClass(e),setTimeout(function(){n.removeClass(e)},t),n}};hc.className=hc.classNames=hc.classes;var Z={metaChar:`[\\!\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\\`\\{\\|\\}\\~]`,comparatorOp:`=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=`,boolOp:`\\?|\\!|\\^`,string:`"(?:\\\\"|[^"])*"|'(?:\\\\'|[^'])*'`,number:Y,meta:`degree|indegree|outdegree`,separator:`\\s*,\\s*`,descendant:`\\s+`,child:`\\s+>\\s+`,subject:`\\$`,group:`node|edge|\\*`,directedEdge:`\\s+->\\s+`,undirectedEdge:`\\s+<->\\s+`};Z.variable=`(?:[\\w-.]|(?:\\\\`+Z.metaChar+`))+`,Z.className=`(?:[\\w-]|(?:\\\\`+Z.metaChar+`))+`,Z.value=Z.string+`|`+Z.number,Z.id=Z.variable,(function(){var e=Z.comparatorOp.split(`|`),t,n;for(n=0;n=0)&&t!==`=`&&(Z.comparatorOp+=`|\\!`+t)})();var gc=function(){return{checks:[]}},Q={GROUP:0,COLLECTION:1,FILTER:2,DATA_COMPARE:3,DATA_EXIST:4,DATA_BOOL:5,META_COMPARE:6,STATE:7,ID:8,CLASS:9,UNDIRECTED_EDGE:10,DIRECTED_EDGE:11,NODE_SOURCE:12,NODE_TARGET:13,NODE_NEIGHBOR:14,CHILD:15,DESCENDANT:16,PARENT:17,ANCESTOR:18,COMPOUND_SPLIT:19,TRUE:20},_c=[{selector:`:selected`,matches:function(e){return e.selected()}},{selector:`:unselected`,matches:function(e){return!e.selected()}},{selector:`:selectable`,matches:function(e){return e.selectable()}},{selector:`:unselectable`,matches:function(e){return!e.selectable()}},{selector:`:locked`,matches:function(e){return e.locked()}},{selector:`:unlocked`,matches:function(e){return!e.locked()}},{selector:`:visible`,matches:function(e){return e.visible()}},{selector:`:hidden`,matches:function(e){return!e.visible()}},{selector:`:transparent`,matches:function(e){return e.transparent()}},{selector:`:grabbed`,matches:function(e){return e.grabbed()}},{selector:`:free`,matches:function(e){return!e.grabbed()}},{selector:`:removed`,matches:function(e){return e.removed()}},{selector:`:inside`,matches:function(e){return!e.removed()}},{selector:`:grabbable`,matches:function(e){return e.grabbable()}},{selector:`:ungrabbable`,matches:function(e){return!e.grabbable()}},{selector:`:animated`,matches:function(e){return e.animated()}},{selector:`:unanimated`,matches:function(e){return!e.animated()}},{selector:`:parent`,matches:function(e){return e.isParent()}},{selector:`:childless`,matches:function(e){return e.isChildless()}},{selector:`:child`,matches:function(e){return e.isChild()}},{selector:`:orphan`,matches:function(e){return e.isOrphan()}},{selector:`:nonorphan`,matches:function(e){return e.isChild()}},{selector:`:compound`,matches:function(e){return e.isNode()?e.isParent():e.source().isParent()||e.target().isParent()}},{selector:`:loop`,matches:function(e){return e.isLoop()}},{selector:`:simple`,matches:function(e){return e.isSimple()}},{selector:`:active`,matches:function(e){return e.active()}},{selector:`:inactive`,matches:function(e){return!e.active()}},{selector:`:backgrounding`,matches:function(e){return e.backgrounding()}},{selector:`:nonbackgrounding`,matches:function(e){return!e.backgrounding()}}].sort(function(e,t){return ce(e.selector,t.selector)}),vc=function(){for(var e={},t,n=0;n<_c.length;n++)t=_c[n],e[t.selector]=t.matches;return e}(),yc=function(e,t){return vc[e](t)},bc=`(`+_c.map(function(e){return e.selector}).join(`|`)+`)`,xc=function(e){return e.replace(RegExp(`\\\\(`+Z.metaChar+`)`,`g`),function(e,t){return t})},Sc=function(e,t,n){e[e.length-1]=n},Cc=[{name:`group`,query:!0,regex:`(`+Z.group+`)`,populate:function(e,t,n){var r=f(n,1)[0];t.checks.push({type:Q.GROUP,value:r===`*`?r:r+`s`})}},{name:`state`,query:!0,regex:bc,populate:function(e,t,n){var r=f(n,1)[0];t.checks.push({type:Q.STATE,value:r})}},{name:`id`,query:!0,regex:`\\#(`+Z.id+`)`,populate:function(e,t,n){var r=f(n,1)[0];t.checks.push({type:Q.ID,value:xc(r)})}},{name:`className`,query:!0,regex:`\\.(`+Z.className+`)`,populate:function(e,t,n){var r=f(n,1)[0];t.checks.push({type:Q.CLASS,value:xc(r)})}},{name:`dataExists`,query:!0,regex:`\\[\\s*(`+Z.variable+`)\\s*\\]`,populate:function(e,t,n){var r=f(n,1)[0];t.checks.push({type:Q.DATA_EXIST,field:xc(r)})}},{name:`dataCompare`,query:!0,regex:`\\[\\s*(`+Z.variable+`)\\s*(`+Z.comparatorOp+`)\\s*(`+Z.value+`)\\s*\\]`,populate:function(e,t,n){var r=f(n,3),i=r[0],a=r[1],o=r[2];o=RegExp(`^`+Z.string+`$`).exec(o)==null?parseFloat(o):o.substring(1,o.length-1),t.checks.push({type:Q.DATA_COMPARE,field:xc(i),operator:a,value:o})}},{name:`dataBool`,query:!0,regex:`\\[\\s*(`+Z.boolOp+`)\\s*(`+Z.variable+`)\\s*\\]`,populate:function(e,t,n){var r=f(n,2),i=r[0],a=r[1];t.checks.push({type:Q.DATA_BOOL,field:xc(a),operator:i})}},{name:`metaCompare`,query:!0,regex:`\\[\\[\\s*(`+Z.meta+`)\\s*(`+Z.comparatorOp+`)\\s*(`+Z.number+`)\\s*\\]\\]`,populate:function(e,t,n){var r=f(n,3),i=r[0],a=r[1],o=r[2];t.checks.push({type:Q.META_COMPARE,field:xc(i),operator:a,value:parseFloat(o)})}},{name:`nextQuery`,separator:!0,regex:Z.separator,populate:function(e,t){var n=e.currentSubject,r=e.edgeCount,i=e.compoundCount,a=e[e.length-1];return n!=null&&(a.subject=n,e.currentSubject=null),a.edgeCount=r,a.compoundCount=i,e.edgeCount=0,e.compoundCount=0,e[e.length++]=gc()}},{name:`directedEdge`,separator:!0,regex:Z.directedEdge,populate:function(e,t){if(e.currentSubject==null){var n=gc(),r=t,i=gc();return n.checks.push({type:Q.DIRECTED_EDGE,source:r,target:i}),Sc(e,t,n),e.edgeCount++,i}else{var a=gc(),o=t,s=gc();return a.checks.push({type:Q.NODE_SOURCE,source:o,target:s}),Sc(e,t,a),e.edgeCount++,s}}},{name:`undirectedEdge`,separator:!0,regex:Z.undirectedEdge,populate:function(e,t){if(e.currentSubject==null){var n=gc(),r=t,i=gc();return n.checks.push({type:Q.UNDIRECTED_EDGE,nodes:[r,i]}),Sc(e,t,n),e.edgeCount++,i}else{var a=gc(),o=t,s=gc();return a.checks.push({type:Q.NODE_NEIGHBOR,node:o,neighbor:s}),Sc(e,t,a),s}}},{name:`child`,separator:!0,regex:Z.child,populate:function(e,t){if(e.currentSubject==null){var n=gc(),r=gc(),i=e[e.length-1];return n.checks.push({type:Q.CHILD,parent:i,child:r}),Sc(e,t,n),e.compoundCount++,r}else if(e.currentSubject===t){var a=gc(),o=e[e.length-1],s=gc(),c=gc(),l=gc(),u=gc();return a.checks.push({type:Q.COMPOUND_SPLIT,left:o,right:s,subject:c}),c.checks=t.checks,t.checks=[{type:Q.TRUE}],u.checks.push({type:Q.TRUE}),s.checks.push({type:Q.PARENT,parent:u,child:l}),Sc(e,o,a),e.currentSubject=c,e.compoundCount++,l}else{var d=gc(),f=gc(),p=[{type:Q.PARENT,parent:d,child:f}];return d.checks=t.checks,t.checks=p,e.compoundCount++,f}}},{name:`descendant`,separator:!0,regex:Z.descendant,populate:function(e,t){if(e.currentSubject==null){var n=gc(),r=gc(),i=e[e.length-1];return n.checks.push({type:Q.DESCENDANT,ancestor:i,descendant:r}),Sc(e,t,n),e.compoundCount++,r}else if(e.currentSubject===t){var a=gc(),o=e[e.length-1],s=gc(),c=gc(),l=gc(),u=gc();return a.checks.push({type:Q.COMPOUND_SPLIT,left:o,right:s,subject:c}),c.checks=t.checks,t.checks=[{type:Q.TRUE}],u.checks.push({type:Q.TRUE}),s.checks.push({type:Q.ANCESTOR,ancestor:u,descendant:l}),Sc(e,o,a),e.currentSubject=c,e.compoundCount++,l}else{var d=gc(),f=gc(),p=[{type:Q.ANCESTOR,ancestor:d,descendant:f}];return d.checks=t.checks,t.checks=p,e.compoundCount++,f}}},{name:`subject`,modifier:!0,regex:Z.subject,populate:function(e,t){if(e.currentSubject!=null&&e.currentSubject!==t)return zt("Redefinition of subject in selector `"+e.toString()+"`"),!1;e.currentSubject=t;var n=e[e.length-1].checks[0],r=n==null?null:n.type;r===Q.DIRECTED_EDGE?n.type=Q.NODE_TARGET:r===Q.UNDIRECTED_EDGE&&(n.type=Q.NODE_NEIGHBOR,n.node=n.nodes[1],n.neighbor=n.nodes[0],n.nodes=null)}}];Cc.forEach(function(e){return e.regexObj=RegExp(`^`+e.regex)});var wc=function(e){for(var t,n,r,i=0;i0&&l.edgeCount>0)return zt("The selector `"+e+"` is invalid because it uses both a compound selector and an edge selector"),!1;if(l.edgeCount>1)return zt("The selector `"+e+"` is invalid because it uses multiple edge selectors"),!1;l.edgeCount===1&&zt("The selector `"+e+"` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.")}return!0},toString:function(){if(this.toStringCache!=null)return this.toStringCache;for(var e=function(e){return e??``},t=function(t){return T(t)?`"`+t+`"`:e(t)},n=function(e){return` `+e+` `},r=function(r,a){var o=r.type,s=r.value;switch(o){case Q.GROUP:var c=e(s);return c.substring(0,c.length-1);case Q.DATA_COMPARE:var l=r.field,u=r.operator;return`[`+l+n(e(u))+t(s)+`]`;case Q.DATA_BOOL:var d=r.operator,f=r.field;return`[`+e(d)+f+`]`;case Q.DATA_EXIST:return`[`+r.field+`]`;case Q.META_COMPARE:var p=r.operator;return`[[`+r.field+n(e(p))+t(s)+`]]`;case Q.STATE:return s;case Q.ID:return`#`+s;case Q.CLASS:return`.`+s;case Q.PARENT:case Q.CHILD:return i(r.parent,a)+n(`>`)+i(r.child,a);case Q.ANCESTOR:case Q.DESCENDANT:return i(r.ancestor,a)+` `+i(r.descendant,a);case Q.COMPOUND_SPLIT:var m=i(r.left,a),h=i(r.subject,a),g=i(r.right,a);return m+(m.length>0?` `:``)+h+g;case Q.TRUE:return``}},i=function(e,t){return e.checks.reduce(function(n,i,a){return n+(t===e&&a===0?`$`:``)+r(i,t)},``)},a=``,o=0;o1&&o=0&&(t=t.replace(`!`,``),u=!0),t.indexOf(`@`)>=0&&(t=t.replace(`@`,``),l=!0),(i||o||l)&&(s=!i&&!a?``:``+e,c=``+n),l&&(e=s=s.toLowerCase(),n=c=c.toLowerCase()),t){case`*=`:r=s.indexOf(c)>=0;break;case`$=`:r=s.indexOf(c,s.length-c.length)>=0;break;case`^=`:r=s.indexOf(c)===0;break;case`=`:r=e===n;break;case`>`:d=!0,r=e>n;break;case`>=`:d=!0,r=e>=n;break;case`<`:d=!0,r=e0;){var l=i.shift();t(l),a.add(l.id()),o&&r(i,a,l)}return e}function Vc(e,t,n){if(n.isParent())for(var r=n._private.children,i=0;i1&&arguments[1]!==void 0?arguments[1]:!0;return Bc(this,e,t,Vc)};function Hc(e,t,n){if(n.isChild()){var r=n._private.parent;t.has(r.id())||e.push(r)}}zc.forEachUp=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return Bc(this,e,t,Hc)};function Uc(e,t,n){Hc(e,t,n),Vc(e,t,n)}zc.forEachUpAndDown=function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return Bc(this,e,t,Uc)},zc.ancestors=zc.parents;var Wc=Gc={data:pc.data({field:`data`,bindingEvent:`data`,allowBinding:!0,allowSetting:!0,settingEvent:`data`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:pc.removeData({field:`data`,event:`data`,triggerFnName:`trigger`,triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:pc.data({field:`scratch`,bindingEvent:`scratch`,allowBinding:!0,allowSetting:!0,settingEvent:`scratch`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeScratch:pc.removeData({field:`scratch`,event:`scratch`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0}),rscratch:pc.data({field:`rscratch`,allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:pc.removeData({field:`rscratch`,triggerEvent:!1}),id:function(){var e=this[0];if(e)return e._private.data.id}},Gc;Wc.attr=Wc.data,Wc.removeAttr=Wc.removeData;var Kc=Gc,qc={};function Jc(e){return function(t){var n=this;if(t===void 0&&(t=!0),n.length!==0)if(n.isNode()&&!n.removed()){for(var r=0,i=n[0],a=i._private.edges,o=0;ot}),minIndegree:Yc(`indegree`,function(e,t){return et}),minOutdegree:Yc(`outdegree`,function(e,t){return et})}),X(qc,{totalDegree:function(e){for(var t=0,n=this.nodes(),r=0;r0,d=u;u&&(l=l[0]);var f=d?l.position():{x:0,y:0};t===void 0?i!==void 0&&c.position({x:i.x+f.x,y:i.y+f.y}):c.position(e,t+f[e])}else{var p=n.position(),m=o?n.parent():null,h=m&&m.length>0,g=h;h&&(m=m[0]);var _=g?m.position():{x:0,y:0};return i={x:p.x-_.x,y:p.y-_.y},e===void 0?i:i[e]}else if(!a)return;return this}},Xc.modelPosition=Xc.point=Xc.position,Xc.modelPositions=Xc.points=Xc.positions,Xc.renderedPoint=Xc.renderedPosition,Xc.relativePoint=Xc.relativePosition;var el=Zc,tl=nl={},nl;nl.renderedBoundingBox=function(e){var t=this.boundingBox(e),n=this.cy(),r=n.zoom(),i=n.pan(),a=t.x1*r+i.x,o=t.x2*r+i.x,s=t.y1*r+i.y,c=t.y2*r+i.y;return{x1:a,x2:o,y1:s,y2:c,w:o-a,h:c-s}},nl.dirtyCompoundBoundsCache=function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,t=this.cy();return!t.styleEnabled()||!t.hasCompoundNodes()||this.forEachUp(function(t){if(t.isParent()){var n=t._private;n.compoundBoundsClean=!1,n.bbCache=null,e||t.emitAndNotify(`bounds`)}}),this},nl.updateCompoundBounds=function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes()||!e&&t.batching())return this;function n(e){if(!e.isParent())return;var t=e._private,n=e.children(),r=e.pstyle(`compound-sizing-wrt-labels`).value===`include`,i={width:{val:e.pstyle(`min-width`).pfValue,left:e.pstyle(`min-width-bias-left`),right:e.pstyle(`min-width-bias-right`)},height:{val:e.pstyle(`min-height`).pfValue,top:e.pstyle(`min-height-bias-top`),bottom:e.pstyle(`min-height-bias-bottom`)}},a=n.boundingBox({includeLabels:r,includeOverlays:!1,useCache:!1}),o=t.position;(a.w===0||a.h===0)&&(a={w:e.pstyle(`width`).pfValue,h:e.pstyle(`height`).pfValue},a.x1=o.x-a.w/2,a.x2=o.x+a.w/2,a.y1=o.y-a.h/2,a.y2=o.y+a.h/2);function s(e,t,n){var r=0,i=0,a=t+n;return e>0&&a>0&&(r=t/a*e,i=n/a*e),{biasDiff:r,biasComplementDiff:i}}function c(e,t,n,r){if(n.units===`%`)switch(r){case`width`:return e>0?n.pfValue*e:0;case`height`:return t>0?n.pfValue*t:0;case`average`:return e>0&&t>0?n.pfValue*(e+t)/2:0;case`min`:return e>0&&t>0?e>t?n.pfValue*t:n.pfValue*e:0;case`max`:return e>0&&t>0?e>t?n.pfValue*e:n.pfValue*t:0;default:return 0}else if(n.units===`px`)return n.pfValue;else return 0}var l=i.width.left.value;i.width.left.units===`px`&&i.width.val>0&&(l=l*100/i.width.val);var u=i.width.right.value;i.width.right.units===`px`&&i.width.val>0&&(u=u*100/i.width.val);var d=i.height.top.value;i.height.top.units===`px`&&i.height.val>0&&(d=d*100/i.height.val);var f=i.height.bottom.value;i.height.bottom.units===`px`&&i.height.val>0&&(f=f*100/i.height.val);var p=s(i.width.val-a.w,l,u),m=p.biasDiff,h=p.biasComplementDiff,g=s(i.height.val-a.h,d,f),_=g.biasDiff,v=g.biasComplementDiff;t.autoPadding=c(a.w,a.h,e.pstyle(`padding`),e.pstyle(`padding-relative-to`).value),t.autoWidth=Math.max(a.w,i.width.val),o.x=(-m+a.x1+a.x2+h)/2,t.autoHeight=Math.max(a.h,i.height.val),o.y=(-_+a.y1+a.y2+v)/2}for(var r=0;re.x2?r:e.x2,e.y1=ne.y2?i:e.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1)},al=function(e,t){return t==null?e:il(e,t.x1,t.y1,t.x2,t.y2)},ol=function(e,t,n){return Xt(e,t,n)},sl=function(e,t,n){if(!t.cy().headless()){var r=t._private,i=r.rstyle,a=i.arrowWidth/2,o=t.pstyle(n+`-arrow-shape`).value,s,c;if(o!==`none`){n===`source`?(s=i.srcX,c=i.srcY):n===`target`?(s=i.tgtX,c=i.tgtY):(s=i.midX,c=i.midY);var l=r.arrowBounds=r.arrowBounds||{},u=l[n]=l[n]||{};u.x1=s-a,u.y1=c-a,u.x2=s+a,u.y2=c+a,u.w=u.x2-u.x1,u.h=u.y2-u.y1,Zn(u,1),il(e,u.x1,u.y1,u.x2,u.y2)}}},cl=function(e,t,n){if(!t.cy().headless()){var r=n?n+`-`:``,i=t._private,a=i.rstyle;if(t.pstyle(r+`label`).strValue){var o=t.pstyle(`text-halign`),s=t.pstyle(`text-valign`),c=ol(a,`labelWidth`,n),l=ol(a,`labelHeight`,n),u=ol(a,`labelX`,n),d=ol(a,`labelY`,n),f=t.pstyle(r+`text-margin-x`).pfValue,p=t.pstyle(r+`text-margin-y`).pfValue,m=t.isEdge(),h=t.pstyle(r+`text-rotation`),g=t.pstyle(`text-outline-width`).pfValue,_=t.pstyle(`text-border-width`).pfValue/2,v=t.pstyle(`text-background-padding`).pfValue,y=2,b=l,x=c,S=x/2,C=b/2,w,T,E,D;if(m)w=u-S,T=u+S,E=d-C,D=d+C;else{switch(o.value){case`left`:w=u-x,T=u;break;case`center`:w=u-S,T=u+S;break;case`right`:w=u,T=u+x;break}switch(s.value){case`top`:E=d-b,D=d;break;case`center`:E=d-C,D=d+C;break;case`bottom`:E=d,D=d+b;break}}var O=f-Math.max(g,_)-v-y,k=f+Math.max(g,_)+v+y,A=p-Math.max(g,_)-v-y,j=p+Math.max(g,_)+v+y;w+=O,T+=k,E+=A,D+=j;var M=n||`main`,N=i.labelBounds,P=N[M]=N[M]||{};P.x1=w,P.y1=E,P.x2=T,P.y2=D,P.w=T-w,P.h=D-E,P.leftPad=O,P.rightPad=k,P.topPad=A,P.botPad=j;var F=m&&h.strValue===`autorotate`,I=h.pfValue!=null&&h.pfValue!==0;if(F||I){var L=F?ol(i.rstyle,`labelAngle`,n):h.pfValue,R=Math.cos(L),z=Math.sin(L),B=(w+T)/2,V=(E+D)/2;if(!m){switch(o.value){case`left`:B=T;break;case`right`:B=w;break}switch(s.value){case`top`:V=D;break;case`bottom`:V=E;break}}var H=function(e,t){return e-=B,t-=V,{x:e*R-t*z+B,y:e*z+t*R+V}},U=H(w,E),W=H(w,D),G=H(T,E),K=H(T,D);w=Math.min(U.x,W.x,G.x,K.x),T=Math.max(U.x,W.x,G.x,K.x),E=Math.min(U.y,W.y,G.y,K.y),D=Math.max(U.y,W.y,G.y,K.y)}var q=M+`Rot`,J=N[q]=N[q]||{};J.x1=w,J.y1=E,J.x2=T,J.y2=D,J.w=T-w,J.h=D-E,il(e,w,E,T,D),il(i.labelBounds.all,w,E,T,D)}return e}},ll=function(e,t){if(!t.cy().headless()){var n=t.pstyle(`outline-opacity`).value,r=t.pstyle(`outline-width`).value+t.pstyle(`outline-offset`).value;ul(e,t,n,r,`outside`,r/2)}},ul=function(e,t,n,r,i,a){if(!(n===0||r<=0||i===`inside`)){var o=t.cy().renderer(),s=o.nodeShapes[o.getNodeShape(t)];if(s){var c=t.position(),l=c.x,u=c.y,d=t.width(),f=t.height();s.hasMiterBounds?(i===`center`&&(r/=2),al(e,s.miterBounds(l,u,d,f,r))):a!=null&&a>0&&Qn(e,[a,a,a,a])}}},dl=function(e,t){if(!t.cy().headless()){var n=t.pstyle(`border-opacity`).value,r=t.pstyle(`border-width`).pfValue,i=t.pstyle(`border-position`).value;ul(e,t,n,r,i)}},fl=function(e,t){var n=e._private.cy,r=n.styleEnabled(),i=n.headless(),a=Kn(),o=e._private,s=e.isNode(),c=e.isEdge(),l,u,d,f,p,m,h=o.rstyle,g=s&&r?e.pstyle(`bounds-expansion`).pfValue:[0],_=function(e){return e.pstyle(`display`).value!==`none`},v=!r||_(e)&&(!c||_(e.source())&&_(e.target()));if(v){var y=0,b=0;r&&t.includeOverlays&&(y=e.pstyle(`overlay-opacity`).value,y!==0&&(b=e.pstyle(`overlay-padding`).value));var x=0,S=0;r&&t.includeUnderlays&&(x=e.pstyle(`underlay-opacity`).value,x!==0&&(S=e.pstyle(`underlay-padding`).value));var C=Math.max(b,S),w=0,T=0;if(r&&(w=e.pstyle(`width`).pfValue,T=w/2),s&&t.includeNodes){var E=e.position();p=E.x,m=E.y;var D=e.outerWidth()/2,O=e.outerHeight()/2;l=p-D,u=p+D,d=m-O,f=m+O,il(a,l,d,u,f),r&&ll(a,e),r&&t.includeOutlines&&!i&&ll(a,e),r&&dl(a,e)}else if(c&&t.includeEdges)if(r&&!i){var k=e.pstyle(`curve-style`).strValue;if(l=Math.min(h.srcX,h.midX,h.tgtX),u=Math.max(h.srcX,h.midX,h.tgtX),d=Math.min(h.srcY,h.midY,h.tgtY),f=Math.max(h.srcY,h.midY,h.tgtY),l-=T,u+=T,d-=T,f+=T,il(a,l,d,u,f),k===`haystack`){var A=h.haystackPts;if(A&&A.length===2){if(l=A[0].x,d=A[0].y,u=A[1].x,f=A[1].y,l>u){var j=l;l=u,u=j}if(d>f){var M=d;d=f,f=M}il(a,l-T,d-T,u+T,f+T)}}else if(k===`bezier`||k===`unbundled-bezier`||ee(k,`segments`)||ee(k,`taxi`)){var N;switch(k){case`bezier`:case`unbundled-bezier`:N=h.bezierPts;break;case`segments`:case`taxi`:case`round-segments`:case`round-taxi`:N=h.linePts;break}if(N!=null)for(var P=0;Pu){var R=l;l=u,u=R}if(d>f){var z=d;d=f,f=z}l-=T,u+=T,d-=T,f+=T,il(a,l,d,u,f)}if(r&&t.includeEdges&&c&&(sl(a,e,`mid-source`),sl(a,e,`mid-target`),sl(a,e,`source`),sl(a,e,`target`)),r&&e.pstyle(`ghost`).value===`yes`){var B=e.pstyle(`ghost-offset-x`).pfValue,V=e.pstyle(`ghost-offset-y`).pfValue;il(a,a.x1+B,a.y1+V,a.x2+B,a.y2+V)}var H=o.bodyBounds=o.bodyBounds||{};$n(H,a),Qn(H,g),Zn(H,1),r&&(l=a.x1,u=a.x2,d=a.y1,f=a.y2,il(a,l-C,d-C,u+C,f+C));var U=o.overlayBounds=o.overlayBounds||{};$n(U,a),Qn(U,g),Zn(U,1);var W=o.labelBounds=o.labelBounds||{};W.all==null?W.all=Kn():Jn(W.all),r&&t.includeLabels&&(t.includeMainLabels&&cl(a,e,null),c&&(t.includeSourceLabels&&cl(a,e,`source`),t.includeTargetLabels&&cl(a,e,`target`)))}return a.x1=rl(a.x1),a.y1=rl(a.y1),a.x2=rl(a.x2),a.y2=rl(a.y2),a.w=rl(a.x2-a.x1),a.h=rl(a.y2-a.y1),a.w>0&&a.h>0&&v&&(Qn(a,g),Zn(a,1)),a},pl=function(e){var t=0,n=function(e){return+!!e<0&&arguments[0]!==void 0?arguments[0]:Ll,t=arguments.length>1?arguments[1]:void 0,n=0;n=0;s--)o(s);return this},zl.removeAllListeners=function(){return this.removeListener(`*`)},zl.emit=zl.trigger=function(e,t,n){var r=this.listeners,i=r.length;return this.emitting++,D(t)||(t=[t]),Hl(this,function(e,a){n!=null&&(r=[{event:a.event,type:a.type,namespace:a.namespace,callback:n}],i=r.length);for(var o=function(){var n=r[s];if(n.type===a.type&&(!n.namespace||n.namespace===a.namespace||n.namespace===Pl)&&e.eventMatches(e.context,n,a)){var i=[a];t!=null&&Yt(i,t),e.beforeEmit(e.context,n,a),n.conf&&n.conf.one&&(e.listeners=e.listeners.filter(function(e){return e!==n}));var o=e.callbackContext(e.context,n,a),c=n.callback.apply(o,i);e.afterEmit(e.context,n,a),c===!1&&(a.stopPropagation(),a.preventDefault())}},s=0;s1&&!r){var i=this.length-1,a=this[i],o=a._private.data.id;this[i]=void 0,this[e]=a,n.set(o,{ele:a,index:e})}return this.length--,this},unmergeOne:function(e){e=e[0];var t=this._private,n=e._private.data.id,r=t.map.get(n);if(!r)return this;var i=r.index;return this.unmergeAt(i),this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(e&&T(e)){var n=e;e=t.mutableElements().filter(n)}for(var r=0;r=0;t--){var n=this[t];e(n)&&this.unmergeAt(t)}return this},map:function(e,t){for(var n=[],r=this,i=0;in&&(n=s,r=o)}return{value:n,ele:r}},min:function(e,t){for(var n=1/0,r,i=this,a=0;a=0&&i`u`?`undefined`:g(Symbol))!=e&&g(Symbol.iterator)!=e&&(Xl[Symbol.iterator]=function(){var e=this,t={value:void 0,done:!1},n=0,r=this.length;return s({next:function(){return n1&&arguments[1]!==void 0?arguments[1]:!0,n=this[0],r=n.cy();if(r.styleEnabled()&&n)return n._private.styleDirty&&(n._private.styleDirty=!1,r.style().apply(n)),n._private.style[e]??(t?r.style().getDefaultProperty(e):null)},numericStyle:function(e){var t=this[0];if(t.cy().styleEnabled()&&t){var n=t.pstyle(e);return n.pfValue===void 0?n.value:n.pfValue}},numericStyleUnits:function(e){var t=this[0];if(t.cy().styleEnabled()&&t)return t.pstyle(e).units},renderedStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=this[0];if(n)return t.style().getRenderedStyle(n,e)},style:function(e,t){var n=this.cy();if(!n.styleEnabled())return this;var r=!1,i=n.style();if(O(e)){var a=e;i.applyBypass(this,a,r),this.emitAndNotify(`style`)}else if(T(e))if(t===void 0){var o=this[0];return o?i.getStylePropertyValue(o,e):void 0}else i.applyBypass(this,e,t,r),this.emitAndNotify(`style`);else if(e===void 0){var s=this[0];return s?i.getRawStyle(s):void 0}return this},removeStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=!1,r=t.style(),i=this;if(e===void 0)for(var a=0;a0&&t.push(u[0]),t.push(s[0])}return this.spawn(t,!0).filter(e)},`neighborhood`),closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),lu.neighbourhood=lu.neighborhood,lu.closedNeighbourhood=lu.closedNeighborhood,lu.openNeighbourhood=lu.openNeighborhood,X(lu,{source:Rc(function(e){var t=this[0],n;return t&&(n=t._private.source||t.cy().collection()),n&&e?n.filter(e):n},`source`),target:Rc(function(e){var t=this[0],n;return t&&(n=t._private.target||t.cy().collection()),n&&e?n.filter(e):n},`target`),sources:pu({attr:`source`}),targets:pu({attr:`target`})});function pu(e){return function(t){for(var n=[],r=0;r0);return a},component:function(){var e=this[0];return e.cy().mutableElements().components(e)[0]}}),lu.componentsOf=lu.components;var gu=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!1;if(e===void 0){Lt(`A collection must have a reference to the core`);return}var i=new Qt,a=!1;if(!t)t=[];else if(t.length>0&&O(t[0])&&!P(t[0])){a=!0;for(var o=[],s=new tn,c=0,l=t.length;c0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,n=this,r=n.cy(),i=r._private,a=[],o=[],s,c=0,l=n.length;c0){for(var I=s.length===n.length?n:new gu(r,s),L=0;L0&&arguments[0]!==void 0?arguments[0]:!0,t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,n=this,r=[],i={},a=n._private.cy;function o(e){for(var t=e._private.edges,n=0;n0&&(e?E.emitAndNotify(`remove`):t&&E.emit(`remove`));for(var D=0;D0?i=c:r=c;while(Math.abs(a)>o&&++l=a?v(t,u):d===0?u:b(t,r,r+l)}var S=!1;function C(){S=!0,(e!==t||n!==r)&&y()}var w=function(i){return S||C(),e===t&&n===r?i:i===0?0:i===1?1:g(x(i),t,r)};w.getControlPoints=function(){return[{x:e,y:t},{x:n,y:r}]};var T=`generateBezier(`+[e,t,n,r]+`)`;return w.toString=function(){return T},w}var bu=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,n,r){var i={x:t.x+r.dx*n,v:t.v+r.dv*n,tension:t.tension,friction:t.friction};return{dx:i.v,dv:e(i)}}function n(n,r){var i={dx:n.v,dv:e(n)},a=t(n,r*.5,i),o=t(n,r*.5,a),s=t(n,r,o),c=1/6*(i.dx+2*(a.dx+o.dx)+s.dx),l=1/6*(i.dv+2*(a.dv+o.dv)+s.dv);return n.x+=c*r,n.v+=l*r,n}return function e(t,r,i){var a={x:-1,v:0,tension:null,friction:null},o=[0],s=0,c=1/1e4,l=16/1e3,u,d,f;for(t=parseFloat(t)||500,r=parseFloat(r)||20,i||=null,a.tension=t,a.friction=r,u=i!==null,u?(s=e(t,r),d=s/i*l):d=l;f=n(f||a,d),o.push(1+f.x),s+=16,Math.abs(f.x)>c&&Math.abs(f.v)>c;);return u?function(e){return o[e*(o.length-1)|0]}:s}}(),xu=function(e,t,n,r){var i=yu(e,t,n,r);return function(e,t,n){return e+(t-e)*i(n)}},Su={linear:function(e,t,n){return e+(t-e)*n},ease:xu(.25,.1,.25,1),"ease-in":xu(.42,0,1,1),"ease-out":xu(0,0,.58,1),"ease-in-out":xu(.42,0,.58,1),"ease-in-sine":xu(.47,0,.745,.715),"ease-out-sine":xu(.39,.575,.565,1),"ease-in-out-sine":xu(.445,.05,.55,.95),"ease-in-quad":xu(.55,.085,.68,.53),"ease-out-quad":xu(.25,.46,.45,.94),"ease-in-out-quad":xu(.455,.03,.515,.955),"ease-in-cubic":xu(.55,.055,.675,.19),"ease-out-cubic":xu(.215,.61,.355,1),"ease-in-out-cubic":xu(.645,.045,.355,1),"ease-in-quart":xu(.895,.03,.685,.22),"ease-out-quart":xu(.165,.84,.44,1),"ease-in-out-quart":xu(.77,0,.175,1),"ease-in-quint":xu(.755,.05,.855,.06),"ease-out-quint":xu(.23,1,.32,1),"ease-in-out-quint":xu(.86,0,.07,1),"ease-in-expo":xu(.95,.05,.795,.035),"ease-out-expo":xu(.19,1,.22,1),"ease-in-out-expo":xu(1,0,0,1),"ease-in-circ":xu(.6,.04,.98,.335),"ease-out-circ":xu(.075,.82,.165,1),"ease-in-out-circ":xu(.785,.135,.15,.86),spring:function(e,t,n){if(n===0)return Su.linear;var r=bu(e,t,n);return function(e,t,n){return e+(t-e)*r(n)}},"cubic-bezier":xu};function Cu(e,t,n,r,i){if(r===1||t===n)return n;var a=i(t,n,r);return e==null?a:((e.roundValue||e.color)&&(a=Math.round(a)),e.min!==void 0&&(a=Math.max(a,e.min)),e.max!==void 0&&(a=Math.min(a,e.max)),a)}function wu(e,t){return e.pfValue!=null||e.value!=null?e.pfValue!=null&&(t==null||t.type.units!==`%`)?e.pfValue:e.value:e}function Tu(e,t,n,r,i){var a=i==null?null:i.type;n<0?n=0:n>1&&(n=1);var o=wu(e,i),s=wu(t,i);if(A(o)&&A(s))return Cu(a,o,s,n,r);if(D(o)&&D(s)){for(var c=[],l=0;l0?(d===`spring`&&f.push(o.duration),o.easingImpl=Su[d].apply(null,f)):o.easingImpl=Su[d]}var p=o.easingImpl,m=o.duration===0?1:(n-c)/o.duration;if(o.applying&&(m=o.progress),m<0?m=0:m>1&&(m=1),o.delay==null){var h=o.startPosition,g=o.position;if(g&&i&&!e.locked()){var _={};Du(h.x,g.x)&&(_.x=Tu(h.x,g.x,m,p)),Du(h.y,g.y)&&(_.y=Tu(h.y,g.y,m,p)),e.position(_)}var v=o.startPan,y=o.pan,b=a.pan,x=y!=null&&r;x&&(Du(v.x,y.x)&&(b.x=Tu(v.x,y.x,m,p)),Du(v.y,y.y)&&(b.y=Tu(v.y,y.y,m,p)),e.emit(`pan`));var S=o.startZoom,C=o.zoom,w=C!=null&&r;w&&(Du(S,C)&&(a.zoom=Gn(a.minZoom,Tu(S,C,m,p),a.maxZoom)),e.emit(`zoom`)),(x||w)&&e.emit(`viewport`);var E=o.style;if(E&&E.length>0&&i){for(var D=0;D=0;t--){var n=e[t];n()}e.splice(0,e.length)},u=a.length-1;u>=0;u--){var d=a[u],f=d._private;if(f.stopped){a.splice(u,1),f.hooked=!1,f.playing=!1,f.started=!1,l(f.frames);continue}!f.playing&&!f.applying||(f.playing&&f.applying&&(f.applying=!1),f.started||Ou(t,d,e),Eu(t,d,e,n),f.applying&&=!1,l(f.frames),f.step!=null&&f.step(e),d.completed()&&(a.splice(u,1),f.hooked=!1,f.playing=!1,f.started=!1,l(f.completes)),s=!0)}return!n&&a.length===0&&o.length===0&&r.push(t),s}for(var a=!1,o=0;o0?t.notify(`draw`,n):t.notify(`draw`)),n.unmerge(r),t.emit(`step`)}var Au={animate:pc.animate(),animation:pc.animation(),animated:pc.animated(),clearQueue:pc.clearQueue(),delay:pc.delay(),delayAnimation:pc.delayAnimation(),stop:pc.stop(),addToAnimationPool:function(e){var t=this;t.styleEnabled()&&t._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){var e=this;if(e._private.animationsRunning=!0,!e.styleEnabled())return;function t(){e._private.animationsRunning&&dt(function(n){ku(n,e),t()})}var n=e.renderer();n&&n.beforeRender?n.beforeRender(function(t,n){ku(n,e)},n.beforeRenderPriorities.animations):t()}},ju={qualifierCompare:function(e,t){return e==null||t==null?e==null&&t==null:e.sameText(t)},eventMatches:function(e,t,n){var r=t.qualifier;return r==null?!0:e!==n.target&&P(n.target)&&r.matches(n.target)},addEventFields:function(e,t){t.cy=e,t.target=e},callbackContext:function(e,t,n){return t.qualifier==null?e:n.target}},Mu=function(e){return T(e)?new Fc(e):e},Nu={createEmitter:function(){var e=this._private;return e.emitter||=new Rl(ju,this),this},emitter:function(){return this._private.emitter},on:function(e,t,n){return this.emitter().on(e,Mu(t),n),this},removeListener:function(e,t,n){return this.emitter().removeListener(e,Mu(t),n),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},one:function(e,t,n){return this.emitter().one(e,Mu(t),n),this},once:function(e,t,n){return this.emitter().one(e,Mu(t),n),this},emit:function(e,t){return this.emitter().emit(e,t),this},emitAndNotify:function(e,t){return this.emit(e),this.notify(e,t),this}};pc.eventAliasesOn(Nu);var Pu={png:function(e){var t=this._private.renderer;return e||={},t.png(e)},jpg:function(e){var t=this._private.renderer;return e||={},e.bg=e.bg||`#fff`,t.jpg(e)}};Pu.jpeg=Pu.jpg;var Fu={layout:function(e){var t=this;if(e==null){Lt(`Layout options must be specified to make a layout`);return}if(e.name==null){Lt("A `name` must be specified to make a layout");return}var n=e.name,r=t.extension(`layout`,n);if(r==null){Lt("No such layout `"+n+"` found. Did you forget to import it and `cytoscape.use()` it?");return}return new r(X({},e,{cy:t,eles:T(e.eles)?t.$(e.eles):e.eles==null?t.$():e.eles}))}};Fu.createLayout=Fu.makeLayout=Fu.layout;var Iu={notify:function(e,t){var n=this._private;if(this.batching()){n.batchNotifications=n.batchNotifications||{};var r=n.batchNotifications[e]=n.batchNotifications[e]||this.collection();t!=null&&r.merge(t);return}if(n.notificationsEnabled){var i=this.renderer();this.destroyed()||!i||i.notify(e,t)}},notifications:function(e){var t=this._private;return e===void 0?t.notificationsEnabled:(t.notificationsEnabled=!!e,this)},noNotifications:function(e){this.notifications(!1),e(),this.notifications(!0)},batching:function(){return this._private.batchCount>0},startBatch:function(){var e=this._private;return e.batchCount??=0,e.batchCount===0&&(e.batchStyleEles=this.collection(),e.batchNotifications={}),e.batchCount++,this},endBatch:function(){var e=this._private;if(e.batchCount===0)return this;if(e.batchCount--,e.batchCount===0){e.batchStyleEles.updateStyle();var t=this.renderer();Object.keys(e.batchNotifications).forEach(function(n){var r=e.batchNotifications[n];r.empty()?t.notify(n):t.notify(n,r)})}return this},batch:function(e){return this.startBatch(),e(),this.endBatch(),this},batchData:function(e){var t=this;return this.batch(function(){for(var n=Object.keys(e),r=0;r0;)t.removeChild(t.childNodes[0]);e._private.renderer=null,e.mutableElements().forEach(function(e){var t=e._private;t.rscratch={},t.rstyle={},t.animation.current=[],t.animation.queue=[]})},onRender:function(e){return this.on(`render`,e)},offRender:function(e){return this.off(`render`,e)}};Ru.invalidateDimensions=Ru.resize;var zu={collection:function(e,t){return T(e)?this.$(e):N(e)?e.collection():D(e)?(t||={},new gu(this,e,t.unique,t.removed)):new gu(this)},nodes:function(e){var t=this.$(function(e){return e.isNode()});return e?t.filter(e):t},edges:function(e){var t=this.$(function(e){return e.isEdge()});return e?t.filter(e):t},$:function(e){var t=this._private.elements;return e?t.filter(e):t.spawnSelf()},mutableElements:function(){return this._private.elements}};zu.elements=zu.filter=zu.$;var Bu={},Vu=`t`,Hu=`f`;Bu.apply=function(e){for(var t=this,n=t._private.cy.collection(),r=0;r0;if(f||d&&p){var m=void 0;f&&p||f?m=l.properties:p&&(m=l.mappedProperties);for(var h=0;h1&&(b=1),s.color){var S=r.valueMin[0],C=r.valueMax[0],w=r.valueMin[1],T=r.valueMax[1],E=r.valueMin[2],D=r.valueMax[2],O=r.valueMin[3]==null?1:r.valueMin[3],k=r.valueMax[3]==null?1:r.valueMax[3],j=[Math.round(S+(C-S)*b),Math.round(w+(T-w)*b),Math.round(E+(D-E)*b),Math.round(O+(k-O)*b)];a={bypass:r.bypass,name:r.name,value:j,strValue:`rgb(`+j[0]+`, `+j[1]+`, `+j[2]+`)`}}else if(s.number){var M=r.valueMin+(r.valueMax-r.valueMin)*b;a=this.parse(r.name,M,r.bypass,f)}else return!1;if(!a)return h(),!1;a.mapping=r,r=a;break;case o.data:for(var N=r.field.split(`.`),P=d.data,F=0;F0&&a>0){for(var s={},c=!1,l=0;l0?e.delayAnimation(o).play().promise().then(t):t()}).then(function(){return e.animation({style:s,duration:a,easing:e.pstyle(`transition-timing-function`).value,queue:!1}).play().promise()}).then(function(){n.removeBypasses(e,i),e.emitAndNotify(`style`),r.transitioning=!1})}else r.transitioning&&=(this.removeBypasses(e,i),e.emitAndNotify(`style`),!1)},Bu.checkTrigger=function(e,t,n,r,i,a){var o=this.properties[t],s=i(o);e.removed()||s!=null&&s(n,r,e)&&a(o)},Bu.checkZOrderTrigger=function(e,t,n,r){var i=this;this.checkTrigger(e,t,n,r,function(e){return e.triggersZOrder},function(){i._private.cy.notify(`zorder`,e)})},Bu.checkBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBounds},function(t){e.dirtyCompoundBoundsCache(),e.dirtyBoundingBoxCache()})},Bu.checkConnectedEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBoundsOfConnectedEdges},function(t){e.connectedEdges().forEach(function(e){e.dirtyBoundingBoxCache()})})},Bu.checkParallelEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,function(e){return e.triggersBoundsOfParallelEdges},function(t){e.parallelEdges().forEach(function(e){e.dirtyBoundingBoxCache()})})},Bu.checkTriggers=function(e,t,n,r){e.dirtyStyleCache(),this.checkZOrderTrigger(e,t,n,r),this.checkBoundsTrigger(e,t,n,r),this.checkConnectedEdgesBoundsTrigger(e,t,n,r),this.checkParallelEdgesBoundsTrigger(e,t,n,r)};var Uu={};Uu.applyBypass=function(e,t,n,r){var i=this,a=[],o=!0;if(t===`*`||t===`**`){if(n!==void 0)for(var s=0;si.length?r.substr(i.length):``}function c(){a=a.length>o.length?a.substr(o.length):``}for(;!r.match(/^\s*$/);){var l=r.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!l){zt(`Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: `+r);break}i=l[0];var u=l[1];if(u!==`core`&&new Fc(u).invalid){zt(`Skipping parsing of block: Invalid selector found in string stylesheet: `+u),s();continue}var d=l[2],f=!1;a=d;for(var p=[];!a.match(/^\s*$/);){var m=a.match(/^\s*(.+?)\s*:\s*(.+?)(?:\s*;|\s*$)/);if(!m){zt(`Skipping parsing of block: Invalid formatting of style property and value definitions found in:`+d),f=!0;break}o=m[0];var h=m[1],g=m[2];if(!t.properties[h]){zt(`Skipping property: Invalid property name in: `+o),c();continue}if(!n.parse(h,g)){zt(`Skipping property: Invalid property definition in: `+o),c();continue}p.push({name:h,val:g}),c()}if(f){s();break}n.selector(u);for(var _=0;_=7&&t[0]===`d`&&(u=new RegExp(s.data.regex).exec(t))){if(n)return!1;var f=s.data;return{name:e,value:u,strValue:``+t,mapped:f,field:u[1],bypass:n}}else if(t.length>=10&&t[0]===`m`&&(d=new RegExp(s.mapData.regex).exec(t))){if(n||l.multiple)return!1;var p=s.mapData;if(!(l.color||l.number))return!1;var m=this.parse(e,d[4]);if(!m||m.mapped)return!1;var h=this.parse(e,d[5]);if(!h||h.mapped)return!1;if(m.pfValue===h.pfValue||m.strValue===h.strValue)return zt("`"+e+`: `+t+"` is not a valid mapper because the output range is zero; converting to `"+e+`: `+m.strValue+"`"),this.parse(e,m.strValue);if(l.color){var g=m.value,_=h.value;if(g[0]===_[0]&&g[1]===_[1]&&g[2]===_[2]&&(g[3]===_[3]||(g[3]==null||g[3]===1)&&(_[3]==null||_[3]===1)))return!1}return{name:e,value:d,strValue:``+t,mapped:p,field:d[1],fieldMin:parseFloat(d[2]),fieldMax:parseFloat(d[3]),valueMin:m.value,valueMax:h.value,bypass:n}}}if(l.multiple&&r!==`multiple`){var v=c?t.split(/\s+/):D(t)?t:[t];if(l.evenMultiple&&v.length%2!=0)return null;for(var y=[],b=[],x=[],S=``,C=!1,w=0;w0?` `:``)+O.strValue}return l.validate&&!l.validate(y,b)?null:l.singleEnum&&C?y.length===1&&T(y[0])?{name:e,value:y[0],strValue:y[0],bypass:n}:null:{name:e,value:y,pfValue:x,strValue:S,bypass:n,units:b}}var k=function(){for(var r=0;rl.max||l.strictMax&&t===l.max))return null;var F={name:e,value:t,strValue:``+t+(A||``),units:A,bypass:n};return l.unitless||A!==`px`&&A!==`em`?F.pfValue=t:F.pfValue=A===`px`||!A?t:this.getEmSizeInPixels()*t,(A===`ms`||A===`s`)&&(F.pfValue=A===`ms`?t:1e3*t),(A===`deg`||A===`rad`)&&(F.pfValue=A===`rad`?t:Fn(t)),A===`%`&&(F.pfValue=t/100),F}else if(l.propList){var I=[],L=``+t;if(L!==`none`){for(var R=L.split(/\s*,\s*|\s+/),z=0;z0&&o>0&&!isNaN(n.w)&&!isNaN(n.h)&&n.w>0&&n.h>0){s=Math.min((a-2*t)/n.w,(o-2*t)/n.h),s=s>this._private.maxZoom?this._private.maxZoom:s,s=s=n.minZoom&&(n.maxZoom=t),this},minZoom:function(e){return e===void 0?this._private.minZoom:this.zoomRange({min:e})},maxZoom:function(e){return e===void 0?this._private.maxZoom:this.zoomRange({max:e})},getZoomedViewport:function(e){var t=this._private,n=t.pan,r=t.zoom,i,a,o=!1;if(t.zoomingEnabled||(o=!0),A(e)?a=e:O(e)&&(a=e.level,e.position==null?e.renderedPosition!=null&&(i=e.renderedPosition):i=On(e.position,r,n),i!=null&&!t.panningEnabled&&(o=!0)),a=a>t.maxZoom?t.maxZoom:a,a=at.maxZoom||!t.zoomingEnabled?a=!0:(t.zoom=s,i.push(`zoom`))}if(r&&(!a||!e.cancelOnFailedZoom)&&t.panningEnabled){var c=e.pan;A(c.x)&&(t.pan.x=c.x,o=!1),A(c.y)&&(t.pan.y=c.y,o=!1),o||i.push(`pan`)}return i.length>0&&(i.push(`viewport`),this.emit(i.join(` `)),this.notify(`viewport`)),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.emit(`pan viewport`),this.notify(`viewport`)),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(T(e)){var n=e;e=this.mutableElements().filter(n)}else N(e)||(e=this.mutableElements());if(e.length!==0){var r=e.boundingBox(),i=this.width(),a=this.height();return t=t===void 0?this._private.zoom:t,{x:(i-t*(r.x1+r.x2))/2,y:(a-t*(r.y1+r.y2))/2}}}},reset:function(){return!this._private.panningEnabled||!this._private.zoomingEnabled||this.viewport({pan:{x:0,y:0},zoom:1}),this},invalidateSize:function(){this._private.sizeCache=null},size:function(){var e=this._private,t=e.container,n=this;return e.sizeCache=e.sizeCache||(t?function(){var e=n.window().getComputedStyle(t),r=function(t){return parseFloat(e.getPropertyValue(t))};return{width:t.clientWidth-r(`padding-left`)-r(`padding-right`),height:t.clientHeight-r(`padding-top`)-r(`padding-bottom`)}}():{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var e=this._private.pan,t=this._private.zoom,n=this.renderedExtent(),r={x1:(n.x1-e.x)/t,x2:(n.x2-e.x)/t,y1:(n.y1-e.y)/t,y2:(n.y2-e.y)/t};return r.w=r.x2-r.x1,r.h=r.y2-r.y1,r},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}},multiClickDebounceTime:function(e){if(e)this._private.multiClickDebounceTime=e;else return this._private.multiClickDebounceTime;return this}};ed.centre=ed.center,ed.autolockNodes=ed.autolock,ed.autoungrabifyNodes=ed.autoungrabify;var td={data:pc.data({field:`data`,bindingEvent:`data`,allowBinding:!0,allowSetting:!0,settingEvent:`data`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeData:pc.removeData({field:`data`,event:`data`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0}),scratch:pc.data({field:`scratch`,bindingEvent:`scratch`,allowBinding:!0,allowSetting:!0,settingEvent:`scratch`,settingTriggersEvent:!0,triggerFnName:`trigger`,allowGetting:!0,updateStyle:!0}),removeScratch:pc.removeData({field:`scratch`,event:`scratch`,triggerFnName:`trigger`,triggerEvent:!0,updateStyle:!0})};td.attr=td.data,td.removeAttr=td.removeData;var nd=function(e){var t=this;e=X({},e);var n=e.container;n&&!M(n)&&M(n[0])&&(n=n[0]);var r=n?n._cyreg:null;r||={},r&&r.cy&&(r.cy.destroy(),r={});var i=r.readies=r.readies||[];n&&(n._cyreg=r),r.cy=t;var a=v!==void 0&&n!==void 0&&!e.headless,o=e;o.layout=X({name:a?`grid`:`null`},o.layout),o.renderer=X({name:a?`canvas`:`null`},o.renderer);var s=function(e,t,n){return t===void 0?n===void 0?e:n:t},c=this._private={container:n,ready:!1,options:o,elements:new gu(this),listeners:[],aniEles:new gu(this),data:o.data||{},scratch:{},layout:null,renderer:null,destroyed:!1,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:s(!0,o.zoomingEnabled),userZoomingEnabled:s(!0,o.userZoomingEnabled),panningEnabled:s(!0,o.panningEnabled),userPanningEnabled:s(!0,o.userPanningEnabled),boxSelectionEnabled:s(!0,o.boxSelectionEnabled),autolock:s(!1,o.autolock,o.autolockNodes),autoungrabify:s(!1,o.autoungrabify,o.autoungrabifyNodes),autounselectify:s(!1,o.autounselectify),styleEnabled:o.styleEnabled===void 0?a:o.styleEnabled,zoom:A(o.zoom)?o.zoom:1,pan:{x:O(o.pan)&&A(o.pan.x)?o.pan.x:0,y:O(o.pan)&&A(o.pan.y)?o.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,multiClickDebounceTime:s(250,o.multiClickDebounceTime)};this.createEmitter(),this.selectionType(o.selectionType),this.zoomRange({min:o.minZoom,max:o.maxZoom});var l=function(e,t){if(e.some(H))return fa.all(e).then(t);t(e)};c.styleEnabled&&t.setStyle([]);var u=X({},o,o.renderer);t.initRenderer(u);var d=function(e,n,r){t.notifications(!1);var i=t.mutableElements();i.length>0&&i.remove(),e!=null&&(O(e)||D(e))&&t.add(e),t.one(`layoutready`,function(e){t.notifications(!0),t.emit(e),t.one(`load`,n),t.emitAndNotify(`load`)}).one(`layoutstop`,function(){t.one(`done`,r),t.emit(`done`)});var a=X({},t._private.options.layout);a.eles=t.elements(),t.layout(a).run()};l([o.style,o.elements],function(e){var n=e[0],a=e[1];c.styleEnabled&&t.style().append(n),d(a,function(){t.startAnimationLoop(),c.ready=!0,E(o.ready)&&t.on(`ready`,o.ready);for(var e=0;e0,s=!!e.boundingBox,c=Kn(s?e.boundingBox:structuredClone(t.extent())),l;if(N(e.roots))l=e.roots;else if(D(e.roots)){for(var u=[],d=0;d0;){var M=j(),P=E(M,k);if(P)M.outgoers().filter(function(e){return e.isNode()&&n.has(e)}).forEach(A);else if(P===null){zt("Detected double maximal shift for node `"+M.id()+"`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.");break}}}var F=0;if(e.avoidOverlap)for(var I=0;I0&&_[0].length<=3?a/2:0),l=2*Math.PI/_[r].length*i;return r===0&&_[0].length===1&&(o=1),{x:ee.x+o*Math.cos(l),y:ee.y+o*Math.sin(l)}}else{var u=_[r].length,d=Math.max(u===1?0:s?(c.w-e.padding*2-Y.w)/((e.grid?ne:u)-1):(c.w-e.padding*2-Y.w)/((e.grid?ne:u)+1),F);return{x:ee.x+(i+1-(u+1)/2)*d,y:ee.y+(r+1-(U+1)/2)*te}}},ie={downward:0,leftward:90,upward:180,rightward:-90};return Object.keys(ie).indexOf(e.direction)===-1&&Lt(`Invalid direction '${e.direction}' specified for breadthfirst layout. Valid values are: ${Object.keys(ie).join(`, `)}`),n.nodes().layoutPositions(this,e,function(t){return Ot(re(t),c,ie[e.direction])}),this};var ld={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,radius:void 0,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function ud(e){this.options=X({},ld,e)}ud.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,i=t.counterclockwise===void 0?t.clockwise:!t.counterclockwise,a=r.nodes().not(`:parent`);t.sort&&(a=a.sort(t.sort));for(var o=Kn(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),s={x:o.x1+o.w/2,y:o.y1+o.h/2},c=(t.sweep===void 0?2*Math.PI-2*Math.PI/a.length:t.sweep)/Math.max(1,a.length-1),l,u=0,d=0;d1&&t.avoidOverlap){u*=1.75;var h=Math.cos(c)-Math.cos(0),g=Math.sin(c)-Math.sin(0),_=Math.sqrt(u*u/(h*h+g*g));l=Math.max(_,l)}return r.nodes().layoutPositions(this,t,function(e,n){var r=t.startAngle+n*c*(i?1:-1),a=l*Math.cos(r),o=l*Math.sin(r);return{x:s.x+a,y:s.y+o}}),this};var dd={fit:!0,padding:30,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,height:void 0,width:void 0,spacingFactor:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function fd(e){this.options=X({},dd,e)}fd.prototype.run=function(){for(var e=this.options,t=e,n=t.counterclockwise===void 0?t.clockwise:!t.counterclockwise,r=e.cy,i=t.eles,a=i.nodes().not(`:parent`),o=Kn(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()}),s={x:o.x1+o.w/2,y:o.y1+o.h/2},c=[],l=0,u=0;u0&&Math.abs(_[0].value-y.value)>=h&&(_=[],g.push(_)),_.push(y)}var b=l+t.minNodeSpacing;if(!t.avoidOverlap){var x=g.length>0&&g[0].length>1,S=(Math.min(o.w,o.h)/2-b)/(g.length+x?1:0);b=Math.min(b,S)}for(var C=0,w=0;w1&&t.avoidOverlap){var D=Math.cos(E)-Math.cos(0),O=Math.sin(E)-Math.sin(0),k=Math.sqrt(b*b/(D*D+O*O));C=Math.max(k,C)}T.r=C,C+=b}if(t.equidistant){for(var A=0,j=0,M=0;M=e.numIter||(Cd(r,e),r.temperature*=e.coolingFactor,r.temperature=e.animationThreshold&&a(),dt(u)):(Fd(r,e),s())};u()}else{for(;l;)l=o(c),c++;Fd(r,e),s()}return this},hd.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.emit(`layoutstop`),this},hd.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var gd=function(e,t,n){for(var r=n.eles.edges(),i=n.eles.nodes(),a=Kn(n.boundingBox?n.boundingBox:{x1:0,y1:0,w:e.width(),h:e.height()}),o={isCompound:e.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:i.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:r.size(),temperature:n.initialTemp,clientWidth:a.w,clientHeight:a.h,boundingBox:a},s=n.eles.components(),c={},l=0;l0){o.graphSet.push(C);for(var l=0;lr.count?0:r.graph},vd=function(e,t,n,r){var i=r.graphSet[n];if(-10)var c=r.nodeOverlap*s,l=Math.sqrt(i*i+a*a),u=c*i/l,d=c*a/l;else var f=Od(e,i,a),p=Od(t,-1*i,-1*a),m=p.x-f.x,h=p.y-f.y,g=m*m+h*h,l=Math.sqrt(g),c=(e.nodeRepulsion+t.nodeRepulsion)/g,u=c*m/l,d=c*h/l;e.isLocked||(e.offsetX-=u,e.offsetY-=d),t.isLocked||(t.offsetX+=u,t.offsetY+=d)}},Dd=function(e,t,n,r){if(n>0)var i=e.maxX-t.minX;else var i=t.maxX-e.minX;if(r>0)var a=e.maxY-t.minY;else var a=t.maxY-e.minY;return i>=0&&a>=0?Math.sqrt(i*i+a*a):0},Od=function(e,t,n){var r=e.positionX,i=e.positionY,a=e.height||1,o=e.width||1,s=n/t,c=a/o,l={};return t===0&&0n?(l.x=r,l.y=i+a/2,l):0t&&-1*c<=s&&s<=c?(l.x=r-o/2,l.y=i-o*n/2/t,l):0=c)?(l.x=r+a*t/2/n,l.y=i+a/2,l):0>n&&(s<=-1*c||s>=c)?(l.x=r-a*t/2/n,l.y=i-a/2,l):l},kd=function(e,t){for(var n=0;nn){var h=t.gravity*f/m,g=t.gravity*p/m;d.offsetX+=h,d.offsetY+=g}}}}},jd=function(e,t){var n=[],r=0,i=-1;for(n.push.apply(n,e.graphSet[0]),i+=e.graphSet[0].length;r<=i;){var a=n[r++],o=e.idToIndex[a],s=e.layoutNodes[o],c=s.children;if(0n)var i={x:n*e/r,y:n*t/r};else var i={x:e,y:t};return i},Pd=function(e,t){var n=e.parentId;if(n!=null){var r=t.layoutNodes[t.idToIndex[n]],i=!1;if((r.maxX==null||e.maxX+r.padRight>r.maxX)&&(r.maxX=e.maxX+r.padRight,i=!0),(r.minX==null||e.minX-r.padLeftr.maxY)&&(r.maxY=e.maxY+r.padBottom,i=!0),(r.minY==null||e.minY-r.padToph&&(f+=m+t.componentSpacing,d=0,p=0,m=0)}}},Id={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,condense:!1,rows:void 0,cols:void 0,position:function(e){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function Ld(e){this.options=X({},Id,e)}Ld.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,i=r.nodes().not(`:parent`);t.sort&&(i=i.sort(t.sort));var a=Kn(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()});if(a.h===0||a.w===0)r.nodes().layoutPositions(this,t,function(e){return{x:a.x1,y:a.y1}});else{var o=i.size(),s=Math.sqrt(o*a.h/a.w),c=Math.round(s),l=Math.round(a.w/a.h*s),u=function(e){if(e==null)return Math.min(c,l);Math.min(c,l)==c?c=e:l=e},d=function(e){if(e==null)return Math.max(c,l);Math.max(c,l)==c?c=e:l=e},f=t.rows,p=t.cols==null?t.columns:t.cols;if(f!=null&&p!=null)c=f,l=p;else if(f!=null&&p==null)c=f,l=Math.ceil(o/c);else if(f==null&&p!=null)l=p,c=Math.ceil(o/l);else if(l*c>o){var m=u(),h=d();(m-1)*h>=o?u(m-1):(h-1)*m>=o&&d(h-1)}else for(;l*c=o?d(_+1):u(g+1)}var v=a.w/l,y=a.h/c;if(t.condense&&(v=0,y=0),t.avoidOverlap)for(var b=0;b=l&&(j=0,A++)},N={},P=0;P(y=pr(e,t,b[x],b[x+1],b[x+2],b[x+3])))return g(n,y),!0}else if(o.edgeType===`bezier`||o.edgeType===`multibezier`||o.edgeType===`self`||o.edgeType===`compound`){for(var b=o.allpts,x=0;x+5(y=fr(e,t,b[x],b[x+1],b[x+2],b[x+3],b[x+4],b[x+5])))return g(n,y),!0}for(var h=h||r.source,v=v||r.target,S=i.getArrowWidth(c,d),C=[{name:`source`,x:o.arrowStartX,y:o.arrowStartY,angle:o.srcArrowAngle},{name:`target`,x:o.arrowEndX,y:o.arrowEndY,angle:o.tgtArrowAngle},{name:`mid-source`,x:o.midX,y:o.midY,angle:o.midsrcArrowAngle},{name:`mid-target`,x:o.midX,y:o.midY,angle:o.midtgtArrowAngle}],x=0;x0&&(_(h),_(v))}function y(e,t,n){return Xt(e,t,n)}function b(n,r){var i=n._private,a=f,o=r?r+`-`:``;n.boundingBox();var s=i.labelBounds[r||`main`],c=n.pstyle(o+`label`).value;if(!(n.pstyle(`text-events`).strValue!==`yes`||!c)){var l=y(i.rscratch,`labelX`,r),u=y(i.rscratch,`labelY`,r),d=y(i.rscratch,`labelAngle`,r),p=n.pstyle(o+`text-margin-x`).pfValue,m=n.pstyle(o+`text-margin-y`).pfValue,h=s.x1-a-p,_=s.x2+a-p,v=s.y1-a-m,b=s.y2+a-m;if(d){var x=Math.cos(d),S=Math.sin(d),C=function(e,t){return e-=l,t-=u,{x:e*x-t*S+l,y:e*S+t*x+u}},w=C(h,v),T=C(h,b),E=C(_,v),D=C(_,b);if(mr(e,t,[w.x+p,w.y+m,E.x+p,E.y+m,D.x+p,D.y+m,T.x+p,T.y+m]))return g(n),!0}else if(tr(s,e,t))return g(n),!0}}for(var x=o.length-1;x>=0;x--){var S=o[x];S.isNode()?_(S)||b(S):v(S)||b(S)||b(S,`source`)||b(S,`target`)}return s},Yd.getAllInBox=function(e,t,n,r){var i=this.getCachedZSortedEles().interactive,a=2/this.cy.zoom(),o=[],s=Math.min(e,n),c=Math.max(e,n),l=Math.min(t,r),u=Math.max(t,r);e=s,n=c,t=l,r=u;var d=Kn({x1:e,y1:t,x2:n,y2:r}),p=[{x:d.x1,y:d.y1},{x:d.x2,y:d.y1},{x:d.x2,y:d.y2},{x:d.x1,y:d.y2}],m=[[p[0],p[1]],[p[1],p[2]],[p[2],p[3]],[p[3],p[0]]];function h(e,t,n){return Xt(e,t,n)}function g(e,t){var n=e._private,r=a,i=``;e.boundingBox();var o=n.labelBounds.main;if(!o)return null;var s=h(n.rscratch,`labelX`,t),c=h(n.rscratch,`labelY`,t),l=h(n.rscratch,`labelAngle`,t),u=e.pstyle(i+`text-margin-x`).pfValue,d=e.pstyle(i+`text-margin-y`).pfValue,f=o.x1-r-u,p=o.x2+r-u,m=o.y1-r-d,g=o.y2+r-d;if(l){var _=Math.cos(l),v=Math.sin(l),y=function(e,t){return e-=s,t-=c,{x:e*_-t*v+s,y:e*v+t*_+c}};return[y(f,m),y(p,m),y(p,g),y(f,g)]}else return[{x:f,y:m},{x:p,y:m},{x:p,y:g},{x:f,y:g}]}function _(e,t,n,r){function i(e,t,n){return(n.y-e.y)*(t.x-e.x)>(t.y-e.y)*(n.x-e.x)}return i(e,n,r)!==i(t,n,r)&&i(e,t,n)!==i(e,t,r)}for(var v=0;v0?-(Math.PI-e.ang):Math.PI+e.ang},yf=function(e,t,n,r,i){if(e===gf?vf(ef,$d):_f(t,e,$d),_f(t,n,ef),tf=$d.nx*ef.ny-$d.ny*ef.nx,nf=$d.nx*ef.nx-$d.ny*-ef.ny,of=Math.asin(Math.max(-1,Math.min(1,tf))),Math.abs(of)<1e-6){Zd=t.x,Qd=t.y,cf=uf=0;return}rf=1,af=!1,nf<0?of<0?of=Math.PI+of:(of=Math.PI-of,rf=-1,af=!0):of>0&&(rf=-1,af=!0),uf=t.radius===void 0?r:t.radius,sf=of/2,df=Math.min($d.len/2,ef.len/2),i?(lf=Math.abs(Math.cos(sf)*uf/Math.sin(sf)),lf>df?(lf=df,cf=Math.abs(lf*Math.sin(sf)/Math.cos(sf))):cf=uf):(lf=Math.min(df,uf),cf=Math.abs(lf*Math.sin(sf)/Math.cos(sf))),mf=t.x+ef.nx*lf,hf=t.y+ef.ny*lf,Zd=mf-ef.ny*cf*rf,Qd=hf+ef.nx*cf*rf,ff=t.x+$d.nx*lf,pf=t.y+$d.ny*lf,gf=t};function bf(e,t){t.radius===0?e.lineTo(t.cx,t.cy):e.arc(t.cx,t.cy,t.radius,t.startAngle,t.endAngle,t.counterClockwise)}function xf(e,t,n,r){var i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0;return r===0||t.radius===0?{cx:t.x,cy:t.y,radius:0,startX:t.x,startY:t.y,stopX:t.x,stopY:t.y,startAngle:void 0,endAngle:void 0,counterClockwise:void 0}:(yf(e,t,n,r,i),{cx:Zd,cy:Qd,radius:cf,startX:ff,startY:pf,stopX:mf,stopY:hf,startAngle:$d.ang+Math.PI/2*rf,endAngle:ef.ang-Math.PI/2*rf,counterClockwise:af})}var Sf=.01,Cf=Math.sqrt(2*Sf),wf={};wf.findMidptPtsEtc=function(e,t){var n=t.posPts,r=t.intersectionPts,i=t.vectorNormInverse,a,o=e.pstyle(`source-endpoint`),s=e.pstyle(`target-endpoint`),c=o.units!=null&&s.units!=null,l=function(e,t,n,r){var i=r-t,a=n-e,o=Math.sqrt(a*a+i*i);return{x:-i/o,y:a/o}};switch(e.pstyle(`edge-distances`).value){case`node-position`:a=n;break;case`intersection`:a=r;break;case`endpoints`:if(c){var u=f(this.manualEndptToPx(e.source()[0],o),2),d=u[0],p=u[1],m=f(this.manualEndptToPx(e.target()[0],s),2),h=m[0],g=m[1],_={x1:d,y1:p,x2:h,y2:g};i=l(d,p,h,g),a=_}else zt(`Edge ${e.id()} has edge-distances:endpoints specified without manual endpoints specified via source-endpoint and target-endpoint. Falling back on edge-distances:intersection (default).`),a=r;break}return{midptPts:a,vectorNormInverse:i}},wf.findHaystackPoints=function(e){for(var t=0;t0?Math.max(e-t,0):Math.min(e+t,0)},O=D(T,C),k=D(E,w),A=!1;_===l?g=Math.abs(O)>Math.abs(k)?i:r:_===c||_===s?(g=r,A=!0):(_===a||_===o)&&(g=i,A=!0);var j=g===r,M=j?k:O,N=j?E:T,P=Rn(N),F=!1;!(A&&(y||x))&&(_===s&&N<0||_===c&&N>0||_===a&&N>0||_===o&&N<0)&&(P*=-1,M=P*Math.abs(M),F=!0);var I=y?(b<0?1+b:b)*M:(b<0?M:0)+b*P,L=function(e){return Math.abs(e)=Math.abs(M)},R=L(I),z=L(Math.abs(M)-Math.abs(I));if((R||z)&&!F)if(j){var B=Math.abs(N)<=f/2,V=Math.abs(T)<=p/2;if(B){var H=(u.x1+u.x2)/2;n.segpts=[H,u.y1,H,u.y2]}else if(V){var U=(u.y1+u.y2)/2;n.segpts=[u.x1,U,u.x2,U]}else n.segpts=[u.x1,u.y2]}else{var W=Math.abs(N)<=d/2,G=Math.abs(E)<=m/2;if(W){var K=(u.y1+u.y2)/2;n.segpts=[u.x1,K,u.x2,K]}else if(G){var q=(u.x1+u.x2)/2;n.segpts=[q,u.y1,q,u.y2]}else n.segpts=[u.x2,u.y1]}else if(j){var J=u.y1+I+(h?f/2*P:0);n.segpts=[u.x1,J,u.x2,J]}else{var ee=u.x1+I+(h?d/2*P:0);n.segpts=[ee,u.y1,ee,u.y2]}if(n.isRound){var Y=e.pstyle(`taxi-radius`).value,te=e.pstyle(`radius-type`).value[0]===`arc-radius`;n.radii=Array(n.segpts.length/2).fill(Y),n.isArcRadius=Array(n.segpts.length/2).fill(te)}},wf.tryToCorrectInvalidPoints=function(e,t){var n=e._private.rscratch;if(n.edgeType===`bezier`){var r=t.srcPos,i=t.tgtPos,a=t.srcW,o=t.srcH,s=t.tgtW,c=t.tgtH,l=t.srcShape,u=t.tgtShape,d=t.srcCornerRadius,f=t.tgtCornerRadius,p=t.srcRs,m=t.tgtRs,h=!A(n.startX)||!A(n.startY),g=!A(n.arrowStartX)||!A(n.arrowStartY),_=!A(n.endX)||!A(n.endY),v=!A(n.arrowEndX)||!A(n.arrowEndY),y=3*(this.getArrowWidth(e.pstyle(`width`).pfValue,e.pstyle(`arrow-scale`).value)*this.arrowShapeWidth),b=zn({x:n.ctrlpts[0],y:n.ctrlpts[1]},{x:n.startX,y:n.startY}),x=bh.poolIndex()){var g=m;m=h,h=g}var _=u.srcPos=m.position(),v=u.tgtPos=h.position(),y=u.srcW=m.outerWidth(),b=u.srcH=m.outerHeight(),S=u.tgtW=h.outerWidth(),C=u.tgtH=h.outerHeight(),w=u.srcShape=n.nodeShapes[t.getNodeShape(m)],T=u.tgtShape=n.nodeShapes[t.getNodeShape(h)],E=u.srcCornerRadius=m.pstyle(`corner-radius`).value===`auto`?`auto`:m.pstyle(`corner-radius`).pfValue,D=u.tgtCornerRadius=h.pstyle(`corner-radius`).value===`auto`?`auto`:h.pstyle(`corner-radius`).pfValue,O=u.tgtRs=h._private.rscratch,k=u.srcRs=m._private.rscratch;u.dirCounts={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0};for(var j=0;j=Cf||(G=Math.sqrt(Math.max(W*W,Sf)+Math.max(U*U,Sf)));var K=u.vector={x:W,y:U},q=u.vectorNorm={x:K.x/G,y:K.y/G},J={x:-q.y,y:q.x};u.nodesOverlap=!A(G)||T.checkPoint(L[0],L[1],0,S,C,v.x,v.y,D,O)||w.checkPoint(z[0],z[1],0,y,b,_.x,_.y,E,k),u.vectorNormInverse=J,d={nodesOverlap:u.nodesOverlap,dirCounts:u.dirCounts,calculatedIntersection:!0,hasBezier:u.hasBezier,hasUnbundled:u.hasUnbundled,eles:u.eles,srcPos:v,srcRs:O,tgtPos:_,tgtRs:k,srcW:S,srcH:C,tgtW:y,tgtH:b,srcIntn:B,tgtIntn:R,srcShape:T,tgtShape:w,posPts:{x1:H.x2,y1:H.y2,x2:H.x1,y2:H.y1},intersectionPts:{x1:V.x2,y1:V.y2,x2:V.x1,y2:V.y1},vector:{x:-K.x,y:-K.y},vectorNorm:{x:-q.x,y:-q.y},vectorNormInverse:{x:-J.x,y:-J.y}}}var Y=I?d:u;N.nodesOverlap=Y.nodesOverlap,N.srcIntn=Y.srcIntn,N.tgtIntn=Y.tgtIntn,N.isRound=P.startsWith(`round`),r&&(m.isParent()||m.isChild()||h.isParent()||h.isChild())&&(m.parents().anySame(h)||h.parents().anySame(m)||m.same(h)&&m.isParent())?t.findCompoundLoopPoints(M,Y,j,F):m===h?t.findLoopPoints(M,Y,j,F):P.endsWith(`segments`)?t.findSegmentsPoints(M,Y):P.endsWith(`taxi`)?t.findTaxiPoints(M,Y):P===`straight`||!F&&u.eles.length%2==1&&j===Math.floor(u.eles.length/2)?t.findStraightEdgePoints(M):t.findBezierPoints(M,Y,j,F,I),t.findEndpoints(M),t.tryToCorrectInvalidPoints(M,Y),t.checkForInvalidEdgeWarning(M),t.storeAllpts(M),t.storeEdgeProjections(M),t.calculateArrowAngles(M),t.recalculateEdgeLabelProjections(M),t.calculateLabelAngles(M)}},x=0;x0){var ne=s,re=Bn(ne,An(i)),ie=Bn(ne,An(te)),ae=re;ie2&&Bn(ne,{x:te[2],y:te[3]})0){var _e=c,ve=Bn(_e,An(i)),ye=Bn(_e,An(ge)),be=ve;ye2&&Bn(_e,{x:ge[2],y:ge[3]})=l||v){d={cp:h,segment:_};break}}if(d)break}var y=d.cp,b=d.segment,x=(l-f)/b.length,S=b.t1-b.t0,C=c?b.t0+S*x:b.t1-S*x;C=Gn(0,C,1),t=Un(y.p0,y.p1,y.p2,C),i=Mf(y.p0,y.p1,y.p2,C);break;case`straight`:case`segments`:case`haystack`:for(var w=0,T,E,D,O,k=r.allpts.length,A=0;A+3=l));A+=2);var j=(l-E)/T;j=Gn(0,j,1),t=Wn(D,O,j),i=jf(D,O);break}o(`labelX`,n,t.x),o(`labelY`,n,t.y),o(`labelAutoAngle`,n,i)}};c(`source`),c(`target`),this.applyLabelDimensions(e)}},kf.applyLabelDimensions=function(e){this.applyPrefixedLabelDimensions(e),e.isEdge()&&(this.applyPrefixedLabelDimensions(e,`source`),this.applyPrefixedLabelDimensions(e,`target`))},kf.applyPrefixedLabelDimensions=function(e,t){var n=e._private,r=this.getLabelText(e,t),i=Ct(r,e._private.labelDimsKey);if(Xt(n.rscratch,`prefixedLabelDimsKey`,t)!==i){Zt(n.rscratch,`prefixedLabelDimsKey`,t,i);var a=this.calculateLabelDimensions(e,r),o=e.pstyle(`line-height`).pfValue,s=e.pstyle(`text-wrap`).strValue,c=Xt(n.rscratch,`labelWrapCachedLines`,t)||[],l=s===`wrap`?Math.max(c.length,1):1,u=a.height/l,d=u*o,f=a.width,p=a.height+(l-1)*(o-1)*u;Zt(n.rstyle,`labelWidth`,t,f),Zt(n.rscratch,`labelWidth`,t,f),Zt(n.rstyle,`labelHeight`,t,p),Zt(n.rscratch,`labelHeight`,t,p),Zt(n.rscratch,`labelLineHeight`,t,d)}},kf.getLabelText=function(e,t){var n=e._private,r=t?t+`-`:``,i=e.pstyle(r+`label`).strValue,a=e.pstyle(`text-transform`).value,s=function(e,r){return r?(Zt(n.rscratch,e,t,r),r):Xt(n.rscratch,e,t)};if(!i)return``;a==`none`||(a==`uppercase`?i=i.toUpperCase():a==`lowercase`&&(i=i.toLowerCase()));var c=e.pstyle(`text-wrap`).value;if(c===`wrap`){var l=s(`labelKey`);if(l!=null&&s(`labelWrapKey`)===l)return s(`labelWrapCachedText`);for(var u=`​`,d=i.split(` -`),f=e.pstyle(`text-max-width`).pfValue,p=e.pstyle(`text-overflow-wrap`).value===`anywhere`,m=[],h=/[\s\u200b]+|$/g,g=0;gf){var y=_.matchAll(h),b=``,x=0,S=o(y),C;try{for(S.s();!(C=S.n()).done;){var w=C.value,T=w[0],E=_.substring(x,w.index);x=w.index+T.length;var D=b.length===0?E:b+E+T;this.calculateLabelDimensions(e,D).width<=f?b+=E+T:(b&&m.push(b),b=E+T)}}catch(e){S.e(e)}finally{S.f()}b.match(/^[\s\u200b]+$/)||m.push(b)}else m.push(_)}s(`labelWrapCachedLines`,m),i=s(`labelWrapCachedText`,m.join(` -`)),s(`labelWrapKey`,l)}else if(c===`ellipsis`){var O=e.pstyle(`text-max-width`).pfValue,k=``,A=`…`,j=!1;if(this.calculateLabelDimensions(e,i).widthO);M++)k+=i[M],M===i.length-1&&(j=!0);return j||(k+=A),k}return i},kf.getLabelJustification=function(e){var t=e.pstyle(`text-justification`).strValue,n=e.pstyle(`text-halign`).strValue;if(t===`auto`)if(e.isNode())switch(n){case`left`:return`right`;case`right`:return`left`;default:return`center`}else return`center`;else return t},kf.calculateLabelDimensions=function(e,t){var n=this.cy.window().document,r=0,i=e.pstyle(`font-style`).strValue,a=e.pstyle(`font-size`).pfValue,o=e.pstyle(`font-family`).strValue,s=e.pstyle(`font-weight`).strValue,c=this.labelCalcCanvas,l=this.labelCalcCanvasContext;if(!c){c=this.labelCalcCanvas=n.createElement(`canvas`),l=this.labelCalcCanvasContext=c.getContext(`2d`);var u=c.style;u.position=`absolute`,u.left=`-9999px`,u.top=`-9999px`,u.zIndex=`-1`,u.visibility=`hidden`,u.pointerEvents=`none`}l.font=`${i} ${s} ${a}px ${o}`;for(var d=0,f=0,p=t.split(` -`),m=0;m1&&arguments[1]!==void 0?arguments[1]:!0;if(t.merge(e),n)for(var r=0;r=e.desktopTapThreshold2}var T=a(t);b&&(e.hoverData.tapholdCancelled=!0);var D=function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];t.length===0?(t.push(v[0]),t.push(v[1])):(t[0]+=v[0],t[1]+=v[1])};n=!0,i(p,[`mousemove`,`vmousemove`,`tapdrag`],t,{x:l[0],y:l[1]});var O=function(e){return{originalEvent:t,type:e,position:{x:l[0],y:l[1]}}},k=function(){e.data.bgActivePosistion=void 0,e.hoverData.selecting||r.emit(O(`boxstart`)),f[4]=1,e.hoverData.selecting=!0,e.redrawHint(`select`,!0),e.redraw()};if(e.hoverData.which===3){if(b){var j=O(`cxtdrag`);g?g.emit(j):r.emit(j),e.hoverData.cxtDragged=!0,(!e.hoverData.cxtOver||p!==e.hoverData.cxtOver)&&(e.hoverData.cxtOver&&e.hoverData.cxtOver.emit(O(`cxtdragout`)),e.hoverData.cxtOver=p,p&&p.emit(O(`cxtdragover`)))}}else if(e.hoverData.dragging){if(n=!0,r.panningEnabled()&&r.userPanningEnabled()){var M;if(e.hoverData.justStartedPan){var N=e.hoverData.mdownPos;M={x:(l[0]-N[0])*s,y:(l[1]-N[1])*s},e.hoverData.justStartedPan=!1}else M={x:v[0]*s,y:v[1]*s};r.panBy(M),r.emit(O(`dragpan`)),e.hoverData.dragged=!0}l=e.projectIntoViewport(t.clientX,t.clientY)}else if(f[4]==1&&(g==null||g.pannable()))b&&(!e.hoverData.dragging&&r.boxSelectionEnabled()&&(T||!r.panningEnabled()||!r.userPanningEnabled())?k():!e.hoverData.selecting&&r.panningEnabled()&&r.userPanningEnabled()&&o(g,e.hoverData.downs)&&(e.hoverData.dragging=!0,e.hoverData.justStartedPan=!0,f[4]=0,e.data.bgActivePosistion=An(u),e.redrawHint(`select`,!0),e.redraw()),g&&g.pannable()&&g.active()&&g.unactivate());else{if(g&&g.pannable()&&g.active()&&g.unactivate(),(!g||!g.grabbed())&&p!=m&&(m&&i(m,[`mouseout`,`tapdragout`],t,{x:l[0],y:l[1]}),p&&i(p,[`mouseover`,`tapdragover`],t,{x:l[0],y:l[1]}),e.hoverData.last=p),g)if(b){if(r.boxSelectionEnabled()&&T)g&&g.grabbed()&&(_(y),g.emit(O(`freeon`)),y.emit(O(`free`)),e.dragData.didDrag&&(g.emit(O(`dragfreeon`)),y.emit(O(`dragfree`)))),k();else if(g&&g.grabbed()&&e.nodeIsDraggable(g)){var P=!e.dragData.didDrag;P&&e.redrawHint(`eles`,!0),e.dragData.didDrag=!0,e.hoverData.draggingEles||h(y,{inDragLayer:!0});var F={x:0,y:0};if(A(v[0])&&A(v[1])&&(F.x+=v[0],F.y+=v[1],P)){var I=e.hoverData.dragDelta;I&&A(I[0])&&A(I[1])&&(F.x+=I[0],F.y+=I[1])}e.hoverData.draggingEles=!0,y.silentShift(F).emit(O(`position`)).emit(O(`drag`)),e.redrawHint(`drag`,!0),e.redraw()}}else D();n=!0}if(f[2]=l[0],f[3]=l[1],n)return t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),!1}},!1);var O,k,j;e.registerBinding(t,`mouseup`,function(t){if(!(e.hoverData.which===1&&t.which!==1&&e.hoverData.capture)&&e.hoverData.capture){e.hoverData.capture=!1;var r=e.cy,o=e.projectIntoViewport(t.clientX,t.clientY),s=e.selection,c=e.findNearestElement(o[0],o[1],!0,!1),l=e.dragData.possibleDragElements,u=e.hoverData.down,d=a(t);e.data.bgActivePosistion&&(e.redrawHint(`select`,!0),e.redraw()),e.hoverData.tapholdCancelled=!0,e.data.bgActivePosistion=void 0,u&&u.unactivate();var f=function(e){return{originalEvent:t,type:e,position:{x:o[0],y:o[1]}}};if(e.hoverData.which===3){var p=f(`cxttapend`);if(u?u.emit(p):r.emit(p),!e.hoverData.cxtDragged){var m=f(`cxttap`);u?u.emit(m):r.emit(m)}e.hoverData.cxtDragged=!1,e.hoverData.which=null}else if(e.hoverData.which===1){if(i(c,[`mouseup`,`tapend`,`vmouseup`],t,{x:o[0],y:o[1]}),!e.dragData.didDrag&&!e.hoverData.dragged&&!e.hoverData.selecting&&!e.hoverData.isOverThresholdDrag&&(i(u,[`click`,`tap`,`vclick`],t,{x:o[0],y:o[1]}),k=!1,t.timeStamp-j<=r.multiClickDebounceTime()?(O&&clearTimeout(O),k=!0,j=null,i(u,[`dblclick`,`dbltap`,`vdblclick`],t,{x:o[0],y:o[1]})):(O=setTimeout(function(){k||i(u,[`oneclick`,`onetap`,`voneclick`],t,{x:o[0],y:o[1]})},r.multiClickDebounceTime()),j=t.timeStamp)),u==null&&!e.dragData.didDrag&&!e.hoverData.selecting&&!e.hoverData.dragged&&!a(t)&&(r.$(n).unselect([`tapunselect`]),l.length>0&&e.redrawHint(`eles`,!0),e.dragData.possibleDragElements=l=r.collection()),c==u&&!e.dragData.didDrag&&!e.hoverData.selecting&&c!=null&&c._private.selectable&&(e.hoverData.dragging||(r.selectionType()===`additive`||d?c.selected()?c.unselect([`tapunselect`]):c.select([`tapselect`]):d||(r.$(n).unmerge(c).unselect([`tapunselect`]),c.select([`tapselect`]))),e.redrawHint(`eles`,!0)),e.hoverData.selecting){var h=r.collection(e.getAllInBox(s[0],s[1],s[2],s[3]));e.redrawHint(`select`,!0),h.length>0&&e.redrawHint(`eles`,!0),r.emit(f(`boxend`)),r.selectionType()===`additive`||d||r.$(n).unmerge(h).unselect(),h.emit(f(`box`)).stdFilter(function(e){return e.selectable()&&!e.selected()}).select().emit(f(`boxselect`)),e.redraw()}if(e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint(`select`,!0),e.redrawHint(`eles`,!0),e.redraw()),!s[4]){e.redrawHint(`drag`,!0),e.redrawHint(`eles`,!0);var g=u&&u.grabbed();_(l),g&&(u.emit(f(`freeon`)),l.emit(f(`free`)),e.dragData.didDrag&&(u.emit(f(`dragfreeon`)),l.emit(f(`dragfree`))))}}s[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.hoverData.isOverThresholdDrag=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[],e.hoverData.mdownPos=null,e.hoverData.mdownGPos=null,e.hoverData.which=null}},!1);var M=[],N=4,P,F=1e5,I=function(e,t){for(var n=0;n=N){var i=M;if(P=I(i,5),!P){var a=Math.abs(i[0]);P=L(i)&&a>5}if(P)for(var o=0;o5&&(r=Rn(r)*5),f=r/-250,P&&(f/=F,f*=3),f*=e.wheelSensitivity,t.deltaMode===1&&(f*=33);var p=s.zoom()*10**f;t.type===`gesturechange`&&(p=e.gestureStartZoom*t.scale),s.zoom({level:p,renderedPosition:{x:d[0],y:d[1]}}),s.emit({type:t.type===`gesturechange`?`pinchzoom`:`scrollzoom`,originalEvent:t,position:{x:u[0],y:u[1]}})}}}};e.registerBinding(e.container,`wheel`,R,!0),e.registerBinding(t,`scroll`,function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout(function(){e.scrollingPage=!1},250)},!0),e.registerBinding(e.container,`gesturestart`,function(t){e.gestureStartZoom=e.cy.zoom(),e.hasTouchStarted||t.preventDefault()},!0),e.registerBinding(e.container,`gesturechange`,function(t){e.hasTouchStarted||R(t)},!0),e.registerBinding(e.container,`mouseout`,function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:`mouseout`,position:{x:n[0],y:n[1]}})},!1),e.registerBinding(e.container,`mouseover`,function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:`mouseover`,position:{x:n[0],y:n[1]}})},!1);var z,B,V,H,U,W,G,K,q,J,ee,Y,te,ne=function(e,t,n,r){return Math.sqrt((n-e)*(n-e)+(r-t)*(r-t))},re=function(e,t,n,r){return(n-e)*(n-e)+(r-t)*(r-t)},ie;e.registerBinding(e.container,`touchstart`,ie=function(t){if(e.hasTouchStarted=!0,E(t)){y(),e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,r=e.touchData.now,a=e.touchData.earlier;if(t.touches[0]){var o=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);r[0]=o[0],r[1]=o[1]}if(t.touches[1]){var o=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);r[2]=o[0],r[3]=o[1]}if(t.touches[2]){var o=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);r[4]=o[0],r[5]=o[1]}var s=function(e){return{originalEvent:t,type:e,position:{x:r[0],y:r[1]}}};if(t.touches[1]){e.touchData.singleTouchMoved=!0,_(e.dragData.touchDragEles);var c=e.findContainerClientCoords();q=c[0],J=c[1],ee=c[2],Y=c[3],z=t.touches[0].clientX-q,B=t.touches[0].clientY-J,V=t.touches[1].clientX-q,H=t.touches[1].clientY-J,te=0<=z&&z<=ee&&0<=V&&V<=ee&&0<=B&&B<=Y&&0<=H&&H<=Y;var l=n.pan(),u=n.zoom();U=ne(z,B,V,H),W=re(z,B,V,H),G=[(z+V)/2,(B+H)/2],K=[(G[0]-l.x)/u,(G[1]-l.y)/u];var f=200,p=f*f;if(W=1){for(var w=e.touchData.startPosition=[null,null,null,null,null,null],T=0;T=e.touchTapThreshold2}if(n&&e.touchData.cxt){t.preventDefault();var x=t.touches[0].clientX-q,S=t.touches[0].clientY-J,C=t.touches[1].clientX-q,w=t.touches[1].clientY-J,T=re(x,S,C,w),D=T/W,O=150,k=O*O,j=1.5;if(D>=j*j||T>=k){e.touchData.cxt=!1,e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var M=d(`cxttapend`);e.touchData.start?(e.touchData.start.unactivate().emit(M),e.touchData.start=null):a.emit(M)}}if(n&&e.touchData.cxt){var M=d(`cxtdrag`);e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0),e.touchData.start?e.touchData.start.emit(M):a.emit(M),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var N=e.findNearestElement(s[0],s[1],!0,!0);(!e.touchData.cxtOver||N!==e.touchData.cxtOver)&&(e.touchData.cxtOver&&e.touchData.cxtOver.emit(d(`cxtdragout`)),e.touchData.cxtOver=N,N&&N.emit(d(`cxtdragover`)))}else if(n&&t.touches[2]&&a.boxSelectionEnabled())t.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting||a.emit(d(`boxstart`)),e.touchData.selecting=!0,e.touchData.didSelect=!0,r[4]=1,!r||r.length===0||r[0]===void 0?(r[0]=(s[0]+s[2]+s[4])/3,r[1]=(s[1]+s[3]+s[5])/3,r[2]=(s[0]+s[2]+s[4])/3+1,r[3]=(s[1]+s[3]+s[5])/3+1):(r[2]=(s[0]+s[2]+s[4])/3,r[3]=(s[1]+s[3]+s[5])/3),e.redrawHint(`select`,!0),e.redraw();else if(n&&t.touches[1]&&!e.touchData.didSelect&&a.zoomingEnabled()&&a.panningEnabled()&&a.userZoomingEnabled()&&a.userPanningEnabled()){t.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var P=e.dragData.touchDragEles;if(P){e.redrawHint(`drag`,!0);for(var F=0;F0&&!e.hoverData.draggingEles&&!e.swipePanning&&e.data.bgActivePosistion!=null&&(e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0),e.redraw())}},!1);var oe;e.registerBinding(t,`touchcancel`,oe=function(t){var n=e.touchData.start;e.touchData.capture=!1,n&&n.unactivate()});var se,ce,X,le;if(e.registerBinding(t,`touchend`,se=function(t){var r=e.touchData.start;if(e.touchData.capture)t.touches.length===0&&(e.touchData.capture=!1),t.preventDefault();else return;var a=e.selection;e.swipePanning=!1,e.hoverData.draggingEles=!1;var o=e.cy,s=o.zoom(),c=e.touchData.now,l=e.touchData.earlier;if(t.touches[0]){var u=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);c[0]=u[0],c[1]=u[1]}if(t.touches[1]){var u=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);c[2]=u[0],c[3]=u[1]}if(t.touches[2]){var u=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);c[4]=u[0],c[5]=u[1]}var d=function(e){return{originalEvent:t,type:e,position:{x:c[0],y:c[1]}}};r&&r.unactivate();var f;if(e.touchData.cxt){if(f=d(`cxttapend`),r?r.emit(f):o.emit(f),!e.touchData.cxtDragged){var p=d(`cxttap`);r?r.emit(p):o.emit(p)}e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!1,e.touchData.start=null,e.redraw();return}if(!t.touches[2]&&o.boxSelectionEnabled()&&e.touchData.selecting){e.touchData.selecting=!1;var m=o.collection(e.getAllInBox(a[0],a[1],a[2],a[3]));a[0]=void 0,a[1]=void 0,a[2]=void 0,a[3]=void 0,a[4]=0,e.redrawHint(`select`,!0),o.emit(d(`boxend`)),m.emit(d(`box`)).stdFilter(function(e){return e.selectable()&&!e.selected()}).select().emit(d(`boxselect`)),m.nonempty()&&e.redrawHint(`eles`,!0),e.redraw()}if(r?.unactivate(),t.touches[2])e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);else if(!t.touches[1]&&!t.touches[0]&&!t.touches[0]){e.data.bgActivePosistion=void 0,e.redrawHint(`select`,!0);var h=e.dragData.touchDragEles;if(r!=null){var g=r._private.grabbed;_(h),e.redrawHint(`drag`,!0),e.redrawHint(`eles`,!0),g&&(r.emit(d(`freeon`)),h.emit(d(`free`)),e.dragData.didDrag&&(r.emit(d(`dragfreeon`)),h.emit(d(`dragfree`)))),i(r,[`touchend`,`tapend`,`vmouseup`,`tapdragout`],t,{x:c[0],y:c[1]}),r.unactivate(),e.touchData.start=null}else i(e.findNearestElement(c[0],c[1],!0,!0),[`touchend`,`tapend`,`vmouseup`,`tapdragout`],t,{x:c[0],y:c[1]});var v=e.touchData.startPosition[0]-c[0],y=v*v,b=e.touchData.startPosition[1]-c[1],x=(y+b*b)*s*s;e.touchData.singleTouchMoved||(r||o.$(`:selected`).unselect([`tapunselect`]),i(r,[`tap`,`vclick`],t,{x:c[0],y:c[1]}),ce=!1,t.timeStamp-le<=o.multiClickDebounceTime()?(X&&clearTimeout(X),ce=!0,le=null,i(r,[`dbltap`,`vdblclick`],t,{x:c[0],y:c[1]})):(X=setTimeout(function(){ce||i(r,[`onetap`,`voneclick`],t,{x:c[0],y:c[1]})},o.multiClickDebounceTime()),le=t.timeStamp)),r!=null&&!e.dragData.didDrag&&r._private.selectable&&x`u`){var ue=[],de=function(e){return{clientX:e.clientX,clientY:e.clientY,force:1,identifier:e.pointerId,pageX:e.pageX,pageY:e.pageY,radiusX:e.width/2,radiusY:e.height/2,screenX:e.screenX,screenY:e.screenY,target:e.target}},fe=function(e){return{event:e,touch:de(e)}},pe=function(e){ue.push(fe(e))},me=function(e){for(var t=0;t0)return l[0]}return null},p=Object.keys(d),m=0;m0?d:sr(i,a,e,t,n,r,o,s)},checkPoint:function(e,t,n,r,i,a,o,s){s=s===`auto`?jr(r,i):s;var c=2*s;if(hr(e,t,this.points,a,o,r,i-c,[0,-1],n)||hr(e,t,this.points,a,o,r-c,i,[0,-1],n))return!0;var l=r/2+2*n,u=i/2+2*n;return!!(mr(e,t,[a-l,o-u,a-l,o,a+l,o,a+l,o-u])||br(e,t,c,c,a+r/2-s,o+i/2-s,n)||br(e,t,c,c,a-r/2+s,o+i/2-s,n))}}},Vf.registerNodeShapes=function(){var e=this.nodeShapes={},t=this;this.generateEllipse(),this.generatePolygon(`triangle`,Or(3,0)),this.generateRoundPolygon(`round-triangle`,Or(3,0)),this.generatePolygon(`rectangle`,Or(4,0)),e.square=e.rectangle,this.generateRoundRectangle(),this.generateCutRectangle(),this.generateBarrel(),this.generateBottomRoundrectangle();var n=[0,1,1,0,0,-1,-1,0];this.generatePolygon(`diamond`,n),this.generateRoundPolygon(`round-diamond`,n),this.generatePolygon(`pentagon`,Or(5,0)),this.generateRoundPolygon(`round-pentagon`,Or(5,0)),this.generatePolygon(`hexagon`,Or(6,0)),this.generateRoundPolygon(`round-hexagon`,Or(6,0)),this.generatePolygon(`heptagon`,Or(7,0)),this.generateRoundPolygon(`round-heptagon`,Or(7,0)),this.generatePolygon(`octagon`,Or(8,0)),this.generateRoundPolygon(`round-octagon`,Or(8,0));var r=Array(20),i=Ar(5,0),a=Ar(5,Math.PI/5),o=.5*(3-Math.sqrt(5));o*=1.57;for(var s=0;s=e.deqFastCost*h)break}else if(i){if(p>=e.deqCost*c||p>=e.deqAvgCost*s)break}else if(m>=e.deqNoDrawCost*Kf)break;var g=e.deq(t,d,u);if(g.length>0)for(var _=0;_0&&(e.onDeqd(t,l),!i&&e.shouldRedraw(t,l,d,u)&&r())},a=e.priority||It;n.beforeRender(i,a(t))}}}},Jf=function(){function e(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Pt;r(this,e),this.idsByKey=new Qt,this.keyForId=new Qt,this.cachesByLvl=new Qt,this.lvls=[],this.getKey=t,this.doesEleInvalidateKey=n}return a(e,[{key:`getIdsFor`,value:function(e){e??Lt(`Can not get id list for null key`);var t=this.idsByKey,n=this.idsByKey.get(e);return n||(n=new tn,t.set(e,n)),n}},{key:`addIdForKey`,value:function(e,t){e!=null&&this.getIdsFor(e).add(t)}},{key:`deleteIdForKey`,value:function(e,t){e!=null&&this.getIdsFor(e).delete(t)}},{key:`getNumberOfIdsForKey`,value:function(e){return e==null?0:this.getIdsFor(e).size}},{key:`updateKeyMappingFor`,value:function(e){var t=e.id(),n=this.keyForId.get(t),r=this.getKey(e);this.deleteIdForKey(n,t),this.addIdForKey(r,t),this.keyForId.set(t,r)}},{key:`deleteKeyMappingFor`,value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteIdForKey(n,t),this.keyForId.delete(t)}},{key:`keyHasChangedFor`,value:function(e){var t=e.id();return this.keyForId.get(t)!==this.getKey(e)}},{key:`isInvalid`,value:function(e){return this.keyHasChangedFor(e)||this.doesEleInvalidateKey(e)}},{key:`getCachesAt`,value:function(e){var t=this.cachesByLvl,n=this.lvls,r=t.get(e);return r||(r=new Qt,t.set(e,r),n.push(e)),r}},{key:`getCache`,value:function(e,t){return this.getCachesAt(t).get(e)}},{key:`get`,value:function(e,t){var n=this.getKey(e),r=this.getCache(n,t);return r!=null&&this.updateKeyMappingFor(e),r}},{key:`getForCachedKey`,value:function(e,t){var n=this.keyForId.get(e.id());return this.getCache(n,t)}},{key:`hasCache`,value:function(e,t){return this.getCachesAt(t).has(e)}},{key:`has`,value:function(e,t){var n=this.getKey(e);return this.hasCache(n,t)}},{key:`setCache`,value:function(e,t,n){n.key=e,this.getCachesAt(t).set(e,n)}},{key:`set`,value:function(e,t,n){var r=this.getKey(e);this.setCache(r,t,n),this.updateKeyMappingFor(e)}},{key:`deleteCache`,value:function(e,t){this.getCachesAt(t).delete(e)}},{key:`delete`,value:function(e,t){var n=this.getKey(e);this.deleteCache(n,t)}},{key:`invalidateKey`,value:function(e){var t=this;this.lvls.forEach(function(n){return t.deleteCache(e,n)})}},{key:`invalidate`,value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteKeyMappingFor(e);var r=this.doesEleInvalidateKey(e);return r&&this.invalidateKey(n),r||this.getNumberOfIdsForKey(n)===0}}])}(),Yf=25,Xf=50,Zf=-4,Qf=3,$f=7.99,ep=8,tp=1024,np=1024,rp=1024,ip=.2,ap=.8,op=10,sp=.15,cp=.1,lp=.9,up=.9,dp=100,fp=1,pp={dequeue:`dequeue`,downscale:`downscale`,highQuality:`highQuality`},mp=Kt({getKey:null,doesEleInvalidateKey:Pt,drawElement:null,getBoundingBox:null,getRotationPoint:null,getRotationOffset:null,isVisible:Nt,allowEdgeTxrCaching:!0,allowParentTxrCaching:!0}),hp=function(e,t){var n=this;n.renderer=e,n.onDequeues=[];var r=mp(t);X(n,r),n.lookup=new Jf(r.getKey,r.doesEleInvalidateKey),n.setupDequeueing()},gp=hp.prototype;gp.reasons=pp,gp.getTextureQueue=function(e){var t=this;return t.eleImgCaches=t.eleImgCaches||{},t.eleImgCaches[e]=t.eleImgCaches[e]||[]},gp.getRetiredTextureQueue=function(e){var t=this,n=t.eleImgCaches.retired=t.eleImgCaches.retired||{};return n[e]=n[e]||[]},gp.getElementQueue=function(){var e=this;return e.eleCacheQueue=e.eleCacheQueue||new pn(function(e,t){return t.reqs-e.reqs})},gp.getElementKeyToQueue=function(){var e=this;return e.eleKeyToCacheQueue=e.eleKeyToCacheQueue||{}},gp.getElement=function(e,t,n,r,i){var a=this,o=this.renderer,s=o.cy.zoom(),c=this.lookup;if(!t||t.w===0||t.h===0||isNaN(t.w)||isNaN(t.h)||!e.visible()||e.removed()||!a.allowEdgeTxrCaching&&e.isEdge()||!a.allowParentTxrCaching&&e.isParent())return null;if(r??=Math.ceil(Ln(s*n)),r=$f||r>Qf)return null;var l=2**r,u=t.h*l,d=t.w*l,f=o.eleTextBiggerThanMin(e,l);if(!this.isVisible(e,f))return null;var p=c.get(e,r);if(p&&p.invalidated&&(p.invalidated=!1,p.texture.invalidatedWidth-=p.width),p)return p;var m=u<=Yf?Yf:u<=Xf?Xf:Math.ceil(u/Xf)*Xf;if(u>rp||d>np)return null;var h=a.getTextureQueue(m),g=h[h.length-2],_=function(){return a.recycleTexture(m,d)||a.addTexture(m,d)};g||=h[h.length-1],g||=_(),g.width-g.usedWidthr;D--)T=a.getElement(e,t,n,D,pp.downscale);E()}else return a.queueElement(e,S.level-1),S;else{var O;if(!y&&!b&&!x)for(var k=r-1;k>=Zf;k--){var A=c.get(e,k);if(A){O=A;break}}if(v(O))return a.queueElement(e,r),O;g.context.translate(g.usedWidth,0),g.context.scale(l,l),this.drawElement(g.context,e,t,f,!1),g.context.scale(1/l,1/l),g.context.translate(-g.usedWidth,0)}return p={x:g.usedWidth,texture:g,level:r,scale:l,width:d,height:u,scaledLabelShown:f},g.usedWidth+=Math.ceil(d+ep),g.eleCaches.push(p),c.set(e,r,p),a.checkTextureFullness(g),p},gp.invalidateElements=function(e){for(var t=0;t=ip*e.width&&this.retireTexture(e)},gp.checkTextureFullness=function(e){var t=this.getTextureQueue(e.height);e.usedWidth/e.width>ap&&e.fullnessChecks>=op?qt(t,e):e.fullnessChecks++},gp.retireTexture=function(e){var t=this,n=e.height,r=t.getTextureQueue(n),i=this.lookup;qt(r,e),e.retired=!0;for(var a=e.eleCaches,o=0;o=t)return o.retired=!1,o.usedWidth=0,o.invalidatedWidth=0,o.fullnessChecks=0,Jt(o.eleCaches),o.context.setTransform(1,0,0,1,0,0),o.context.clearRect(0,0,o.width,o.height),qt(i,o),r.push(o),o}},gp.queueElement=function(e,t){var n=this,r=n.getElementQueue(),i=n.getElementKeyToQueue(),a=this.getKey(e),o=i[a];if(o)o.level=Math.max(o.level,t),o.eles.merge(e),o.reqs++,r.updateItem(o);else{var s={eles:e.spawn().merge(e),level:t,reqs:1,key:a};r.push(s),i[a]=s}},gp.dequeue=function(e){for(var t=this,n=t.getElementQueue(),r=t.getElementKeyToQueue(),i=[],a=t.lookup,o=0;o0;o++){var s=n.pop(),c=s.key,l=s.eles[0],u=a.hasCache(l,s.level);if(r[c]=null,!u){i.push(s);var d=t.getBoundingBox(l);t.getElement(l,d,e,s.level,pp.dequeue)}}return i},gp.removeFromQueue=function(e){var t=this,n=t.getElementQueue(),r=t.getElementKeyToQueue(),i=this.getKey(e),a=r[i];a!=null&&(a.eles.length===1?(a.reqs=Mt,n.updateItem(a),n.pop(),r[i]=null):a.eles.unmerge(e))},gp.onDequeue=function(e){this.onDequeues.push(e)},gp.offDequeue=function(e){qt(this.onDequeues,e)},gp.setupDequeueing=qf.setupDequeueing({deqRedrawThreshold:dp,deqCost:sp,deqAvgCost:cp,deqNoDrawCost:lp,deqFastCost:up,deq:function(e,t,n){return e.dequeue(t,n)},onDeqd:function(e,t){for(var n=0;n=bp||n>yp)return null}r.validateLayersElesOrdering(n,e);var o=r.layersByLevel,s=2**n,c=o[n]=o[n]||[],l,u=r.levelIsComplete(n,e),d,f=function(){var t=function(t){if(r.validateLayersElesOrdering(t,e),r.levelIsComplete(t,e))return d=o[t],!0},i=function(e){if(!d)for(var r=n+e;vp<=r&&r<=yp&&!t(r);r+=e);};i(1),i(-1);for(var a=c.length-1;a>=0;a--){var s=c[a];s.invalid&&qt(c,s)}};if(!u)f();else return c;var p=function(){if(!l){l=Kn();for(var t=0;tAp||a>Ap||i*a>kp)return null;var o=r.makeLayer(l,n);if(t!=null){var u=c.indexOf(t)+1;c.splice(u,0,o)}else (e.insert===void 0||e.insert)&&c.unshift(o);return o};if(r.skipping&&!a)return null;for(var h=null,g=e.length/_p,_=!a,v=0;v=g||!rr(h.bb,y.boundingBox()))&&(h=m({insert:!0,after:h}),!h))return null;d||_?r.queueLayer(h,y):r.drawEleInLayer(h,y,n,t),h.eles.push(y),x[n]=h}return d||(_?null:c)},Np.getEleLevelForLayerLevel=function(e,t){return e},Np.drawEleInLayer=function(e,t,n,r){var i=this,a=this.renderer,o=e.context,s=t.boundingBox();s.w===0||s.h===0||!t.visible()||(n=i.getEleLevelForLayerLevel(n,r),a.setImgSmoothing(o,!1),a.drawCachedElement(o,t,null,null,n,jp),a.setImgSmoothing(o,!0))},Np.levelIsComplete=function(e,t){var n=this.layersByLevel[e];if(!n||n.length===0)return!1;for(var r=0,i=0;i0||a.invalid)return!1;r+=a.eles.length}return r===t.length},Np.validateLayersElesOrdering=function(e,t){var n=this.layersByLevel[e];if(n)for(var r=0;r0){t=!0;break}}return t},Np.invalidateElements=function(e){var t=this;e.length!==0&&(t.lastInvalidationTime=ft(),!(e.length===0||!t.haveLayers())&&t.updateElementsInLayers(e,function(e,n,r){t.invalidateLayer(e)}))},Np.invalidateLayer=function(e){if(this.lastInvalidationTime=ft(),!e.invalid){var t=e.level,n=e.eles,r=this.layersByLevel[t];qt(r,e),e.elesQueue=[],e.invalid=!0,e.replacement&&(e.replacement.invalid=!0);for(var i=0;i3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,o=this,s=t._private.rscratch;if(!(a&&!t.visible())&&!(s.badLine||s.allpts==null||isNaN(s.allpts[0]))){var c;n&&(c=n,e.translate(-c.x1,-c.y1));var l=a?t.pstyle(`opacity`).value:1,u=a?t.pstyle(`line-opacity`).value:1,d=t.pstyle(`curve-style`).value,f=t.pstyle(`line-style`).value,p=t.pstyle(`width`).pfValue,m=t.pstyle(`line-cap`).value,h=t.pstyle(`line-outline-width`).value,g=t.pstyle(`line-outline-color`).value,_=l*u,v=l*u,y=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:_;d===`straight-triangle`?(o.eleStrokeStyle(e,t,n),o.drawEdgeTrianglePath(t,e,s.allpts)):(e.lineWidth=p,e.lineCap=m,o.eleStrokeStyle(e,t,n),o.drawEdgePath(t,e,s.allpts,f),e.lineCap=`butt`)},b=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:_;if(e.lineWidth=p+h,e.lineCap=m,h>0)o.colorStrokeStyle(e,g[0],g[1],g[2],n);else{e.lineCap=`butt`;return}d===`straight-triangle`?o.drawEdgeTrianglePath(t,e,s.allpts):(o.drawEdgePath(t,e,s.allpts,f),e.lineCap=`butt`)},x=function(){i&&o.drawEdgeOverlay(e,t)},S=function(){i&&o.drawEdgeUnderlay(e,t)},C=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:v;o.drawArrowheads(e,t,n)},w=function(){o.drawElementText(e,t,null,r)};if(e.lineJoin=`round`,t.pstyle(`ghost`).value===`yes`){var T=t.pstyle(`ghost-offset-x`).pfValue,E=t.pstyle(`ghost-offset-y`).pfValue,D=_*t.pstyle(`ghost-opacity`).value;e.translate(T,E),y(D),C(D),e.translate(-T,-E)}else b();S(),y(),C(),x(),w(),n&&e.translate(c.x1,c.y1)}};var Zp=function(e){if(![`overlay`,`underlay`].includes(e))throw Error(`Invalid state`);return function(t,n){if(n.visible()){var r=n.pstyle(`${e}-opacity`).value;if(r!==0){var i=this,a=i.usePaths(),o=n._private.rscratch,s=2*n.pstyle(`${e}-padding`).pfValue,c=n.pstyle(`${e}-color`).value;t.lineWidth=s,o.edgeType===`self`&&!a?t.lineCap=`butt`:t.lineCap=`round`,i.colorStrokeStyle(t,c[0],c[1],c[2],r),i.drawEdgePath(n,t,o.allpts,`solid`)}}}};Xp.drawEdgeOverlay=Zp(`overlay`),Xp.drawEdgeUnderlay=Zp(`underlay`),Xp.drawEdgePath=function(e,t,n,r){var i=e._private.rscratch,a=t,s,c=!1,l=this.usePaths(),u=e.pstyle(`line-dash-pattern`).pfValue,d=e.pstyle(`line-dash-offset`).pfValue;if(l){var f=n.join(`$`);i.pathCacheKey&&i.pathCacheKey===f?(s=t=i.pathCache,c=!0):(s=t=new Path2D,i.pathCacheKey=f,i.pathCache=s)}if(a.setLineDash)switch(r){case`dotted`:a.setLineDash([1,1]);break;case`dashed`:a.setLineDash(u),a.lineDashOffset=d;break;case`solid`:a.setLineDash([]);break}if(!c&&!i.badLine)switch(t.beginPath&&t.beginPath(),t.moveTo(n[0],n[1]),i.edgeType){case`bezier`:case`self`:case`compound`:case`multibezier`:for(var p=2;p+35&&arguments[5]!==void 0?arguments[5]:!0,o=this;if(r==null){if(a&&!o.eleTextBiggerThanMin(t))return}else if(r===!1)return;if(t.isNode()){var s=t.pstyle(`label`);if(!s||!s.value)return;e.textAlign=o.getLabelJustification(t),e.textBaseline=`bottom`}else{var c=t.element()._private.rscratch.badLine,l=t.pstyle(`label`),u=t.pstyle(`source-label`),d=t.pstyle(`target-label`);if(c||(!l||!l.value)&&(!u||!u.value)&&(!d||!d.value))return;e.textAlign=`center`,e.textBaseline=`bottom`}var f=!n,p;n&&(p=n,e.translate(-p.x1,-p.y1)),i==null?(o.drawText(e,t,null,f,a),t.isEdge()&&(o.drawText(e,t,`source`,f,a),o.drawText(e,t,`target`,f,a))):o.drawText(e,t,i,f,a),n&&e.translate(p.x1,p.y1)},$p.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var n=0;n2&&arguments[2]!==void 0?arguments[2]:!0,r=t.pstyle(`font-style`).strValue,i=t.pstyle(`font-size`).pfValue+`px`,a=t.pstyle(`font-family`).strValue,o=t.pstyle(`font-weight`).strValue,s=n?t.effectiveOpacity()*t.pstyle(`text-opacity`).value:1,c=t.pstyle(`text-outline-opacity`).value*s,l=t.pstyle(`color`).value,u=t.pstyle(`text-outline-color`).value;e.font=r+` `+o+` `+i+` `+a,e.lineJoin=`round`,this.colorFillStyle(e,l[0],l[1],l[2],s),this.colorStrokeStyle(e,u[0],u[1],u[2],c)};function em(e,t,n,r,i){var a=Math.min(r,i)/2,o=t+r/2,s=n+i/2;e.beginPath(),e.arc(o,s,a,0,Math.PI*2),e.closePath()}function tm(e,t,n,r,i){var a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:5,o=Math.min(a,r/2,i/2);e.beginPath(),e.moveTo(t+o,n),e.lineTo(t+r-o,n),e.quadraticCurveTo(t+r,n,t+r,n+o),e.lineTo(t+r,n+i-o),e.quadraticCurveTo(t+r,n+i,t+r-o,n+i),e.lineTo(t+o,n+i),e.quadraticCurveTo(t,n+i,t,n+i-o),e.lineTo(t,n+o),e.quadraticCurveTo(t,n,t+o,n),e.closePath()}$p.getTextAngle=function(e,t){var n,r=e._private.rscratch,i=t?t+`-`:``,a=e.pstyle(i+`text-rotation`);if(a.strValue===`autorotate`){var o=Xt(r,`labelAngle`,t);n=e.isEdge()?o:0}else n=a.strValue===`none`?0:a.pfValue;return n},$p.drawText=function(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=t._private.rscratch,o=i?t.effectiveOpacity():1;if(!(i&&(o===0||t.pstyle(`text-opacity`).value===0))){n===`main`&&(n=null);var s=Xt(a,`labelX`,n),c=Xt(a,`labelY`,n),l,u,d=this.getLabelText(t,n);if(d!=null&&d!==``&&!isNaN(s)&&!isNaN(c)){this.setupTextStyle(e,t,i);var f=n?n+`-`:``,p=Xt(a,`labelWidth`,n),m=Xt(a,`labelHeight`,n),h=t.pstyle(f+`text-margin-x`).pfValue,g=t.pstyle(f+`text-margin-y`).pfValue,_=t.isEdge(),v=t.pstyle(`text-halign`).value,y=t.pstyle(`text-valign`).value;_&&(v=`center`,y=`center`),s+=h,c+=g;var b=r?this.getTextAngle(t,n):0;switch(b!==0&&(l=s,u=c,e.translate(l,u),e.rotate(b),s=0,c=0),y){case`top`:break;case`center`:c+=m/2;break;case`bottom`:c+=m;break}var x=t.pstyle(`text-background-opacity`).value,S=t.pstyle(`text-border-opacity`).value,C=t.pstyle(`text-border-width`).pfValue,w=t.pstyle(`text-background-padding`).pfValue,T=t.pstyle(`text-background-shape`).strValue,E=T===`round-rectangle`||T===`roundrectangle`,D=T===`circle`,O=2;if(x>0||C>0&&S>0){var k=e.fillStyle,A=e.strokeStyle,j=e.lineWidth,M=t.pstyle(`text-background-color`).value,N=t.pstyle(`text-border-color`).value,P=t.pstyle(`text-border-style`).value,F=x>0,I=C>0&&S>0,L=s-w;switch(v){case`left`:L-=p;break;case`center`:L-=p/2;break}var R=c-m-w,z=p+2*w,B=m+2*w;if(F&&(e.fillStyle=`rgba(${M[0]},${M[1]},${M[2]},${x*o})`),I&&(e.strokeStyle=`rgba(${N[0]},${N[1]},${N[2]},${S*o})`,e.lineWidth=C,e.setLineDash))switch(P){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash([4,2]);break;case`double`:e.lineWidth=C/4,e.setLineDash([]);break;default:e.setLineDash([]);break}if(E?(e.beginPath(),tm(e,L,R,z,B,O)):D?(e.beginPath(),em(e,L,R,z,B)):(e.beginPath(),e.rect(L,R,z,B)),F&&e.fill(),I&&e.stroke(),I&&P===`double`){var V=C/2;e.beginPath(),E?tm(e,L+V,R+V,z-2*V,B-2*V,O):e.rect(L+V,R+V,z-2*V,B-2*V),e.stroke()}e.fillStyle=k,e.strokeStyle=A,e.lineWidth=j,e.setLineDash&&e.setLineDash([])}var H=2*t.pstyle(`text-outline-width`).pfValue;if(H>0&&(e.lineWidth=H),t.pstyle(`text-wrap`).value===`wrap`){var U=Xt(a,`labelWrapCachedLines`,n),W=Xt(a,`labelLineHeight`,n),G=p/2,K=this.getLabelJustification(t);switch(K===`auto`||(v===`left`?K===`left`?s+=-p:K===`center`&&(s+=-G):v===`center`?K===`left`?s+=-G:K===`right`&&(s+=G):v===`right`&&(K===`center`?s+=G:K===`right`&&(s+=p))),y){case`top`:c-=(U.length-1)*W;break;case`center`:case`bottom`:c-=(U.length-1)*W;break}for(var q=0;q0&&e.strokeText(U[q],s,c),e.fillText(U[q],s,c),c+=W}else H>0&&e.strokeText(d,s,c),e.fillText(d,s,c);b!==0&&(e.rotate(-b),e.translate(-l,-u))}}};var nm={};nm.drawNode=function(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,o=this,s,c,l=t._private,u=l.rscratch,d=t.position();if(!(!A(d.x)||!A(d.y))&&!(a&&!t.visible())){var f=a?t.effectiveOpacity():1,p=o.usePaths(),m,h=!1,g=t.padding();s=t.width()+2*g,c=t.height()+2*g;var _;n&&(_=n,e.translate(-_.x1,-_.y1));for(var v=t.pstyle(`background-image`).value,y=Array(v.length),b=Array(v.length),x=0,S=0;S0&&arguments[0]!==void 0?arguments[0]:D;o.eleFillStyle(e,t,n)},W=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:I;o.colorStrokeStyle(e,O[0],O[1],O[2],t)},G=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:B;o.colorStrokeStyle(e,R[0],R[1],R[2],t)},K=function(e,t,n,r){var i=o.nodePathCache=o.nodePathCache||[],a=wt(n===`polygon`?n+`,`+r.join(`,`):n,``+t,``+e,``+H),s=i[a],c,l=!1;return s==null?(c=new Path2D,i[a]=u.pathCache=c):(c=s,l=!0,u.pathCache=c),{path:c,cacheHit:l}},q=t.pstyle(`shape`).strValue,J=t.pstyle(`shape-polygon-points`).pfValue;if(p){e.translate(d.x,d.y);var ee=K(s,c,q,J);m=ee.path,h=ee.cacheHit}var Y=function(){if(!h){var n=d;p&&(n={x:0,y:0}),o.nodeShapes[o.getNodeShape(t)].draw(m||e,n.x,n.y,s,c,H,u)}p?e.fill(m):e.fill()},te=function(){for(var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:f,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,i=l.backgrounding,a=0,s=0;s0&&arguments[0]!==void 0?arguments[0]:!1,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:f;o.hasPie(t)&&(o.drawPie(e,t,r),n&&(p||o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,H,u)))},re=function(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:f;o.hasStripe(t)&&(e.save(),p?e.clip(u.pathCache):(o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,H,u),e.clip()),o.drawStripe(e,t,r),e.restore(),n&&(p||o.nodeShapes[o.getNodeShape(t)].draw(e,d.x,d.y,s,c,H,u)))},ie=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:f,n=(T>0?T:-T)*t,r=T>0?0:255;T!==0&&(o.colorFillStyle(e,r,r,r,n),p?e.fill(m):e.fill())},ae=function(){if(E>0){if(e.lineWidth=E,e.lineCap=M,e.lineJoin=j,e.setLineDash)switch(k){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash(P),e.lineDashOffset=F;break;case`solid`:case`double`:e.setLineDash([]);break}if(N!==`center`){if(e.save(),e.lineWidth*=2,N===`inside`)p?e.clip(m):e.clip();else{var t=new Path2D;t.rect(-s/2-E,-c/2-E,s+2*E,c+2*E),t.addPath(m),e.clip(t,`evenodd`)}p?e.stroke(m):e.stroke(),e.restore()}else p?e.stroke(m):e.stroke();if(k===`double`){e.lineWidth=E/3;var n=e.globalCompositeOperation;e.globalCompositeOperation=`destination-out`,p?e.stroke(m):e.stroke(),e.globalCompositeOperation=n}e.setLineDash&&e.setLineDash([])}},oe=function(){if(L>0){if(e.lineWidth=L,e.lineCap=`butt`,e.setLineDash)switch(z){case`dotted`:e.setLineDash([1,1]);break;case`dashed`:e.setLineDash([4,2]);break;case`solid`:case`double`:e.setLineDash([]);break}var n=d;p&&(n={x:0,y:0});var r=o.getNodeShape(t),i=E;N===`inside`&&(i=0),N===`outside`&&(i*=2);var a=(s+i+(L+V))/s,l=(c+i+(L+V))/c,u=s*a,f=c*l,m=o.nodeShapes[r].points,h;if(p&&(h=K(u,f,r,m).path),r===`ellipse`)o.drawEllipsePath(h||e,n.x,n.y,u,f);else if([`round-diamond`,`round-heptagon`,`round-hexagon`,`round-octagon`,`round-pentagon`,`round-polygon`,`round-triangle`,`round-tag`].includes(r)){var g=0,_=0,v=0;r===`round-diamond`?g=(i+V+L)*1.4:r===`round-heptagon`?(g=(i+V+L)*1.075,v=-(i/2+V+L)/35):r===`round-hexagon`?g=(i+V+L)*1.12:r===`round-pentagon`?(g=(i+V+L)*1.13,v=-(i/2+V+L)/15):r===`round-tag`?(g=(i+V+L)*1.12,_=(i/2+L+V)*.07):r===`round-triangle`&&(g=(i+V+L)*(Math.PI/2),v=-(i+V/2+L)/Math.PI),g!==0&&(a=(s+g)/s,u=s*a,[`round-hexagon`,`round-tag`].includes(r)||(l=(c+g)/c,f=c*l)),H=H===`auto`?Mr(u,f):H;for(var y=u/2,b=f/2,x=H+(i+L+V)/2,S=Array(m.length/2),C=Array(m.length/2),w=0;w0){if(r||=n.position(),i==null||a==null){var f=n.padding();i=n.width()+2*f,a=n.height()+2*f}o.colorFillStyle(t,l[0],l[1],l[2],c),o.nodeShapes[u].draw(t,r.x,r.y,i+s*2,a+s*2,d),t.fill()}}}};nm.drawNodeOverlay=rm(`overlay`),nm.drawNodeUnderlay=rm(`underlay`),nm.hasPie=function(e){return e=e[0],e._private.hasPie},nm.hasStripe=function(e){return e=e[0],e._private.hasStripe},nm.drawPie=function(e,t,n,r){t=t[0],r||=t.position();var i=t.cy().style(),a=t.pstyle(`pie-size`),o=t.pstyle(`pie-hole`),s=t.pstyle(`pie-start-angle`).pfValue,c=r.x,l=r.y,u=t.width(),d=t.height(),f=Math.min(u,d)/2,p,m=0;if(this.usePaths()&&(c=0,l=0),a.units===`%`?f*=a.pfValue:a.pfValue!==void 0&&(f=a.pfValue/2),o.units===`%`?p=f*o.pfValue:o.pfValue!==void 0&&(p=o.pfValue/2),!(p>=f))for(var h=1;h<=i.pieBackgroundN;h++){var g=t.pstyle(`pie-`+h+`-background-size`).value,_=t.pstyle(`pie-`+h+`-background-color`).value,v=t.pstyle(`pie-`+h+`-background-opacity`).value*n,y=g/100;y+m>1&&(y=1-m);var b=1.5*Math.PI+2*Math.PI*m;b+=s;var x=2*Math.PI*y,S=b+x;g===0||m>=1||m+y>1||(p===0?(e.beginPath(),e.moveTo(c,l),e.arc(c,l,f,b,S),e.closePath()):(e.beginPath(),e.arc(c,l,f,b,S),e.arc(c,l,p,S,b,!0),e.closePath()),this.colorFillStyle(e,_[0],_[1],_[2],v),e.fill(),m+=y)}},nm.drawStripe=function(e,t,n,r){t=t[0],r||=t.position();var i=t.cy().style(),a=r.x,o=r.y,s=t.width(),c=t.height(),l=0,u=this.usePaths();e.save();var d=t.pstyle(`stripe-direction`).value,f=t.pstyle(`stripe-size`);switch(d){case`vertical`:break;case`righward`:e.rotate(-Math.PI/2);break}var p=s,m=c;f.units===`%`?(p*=f.pfValue,m*=f.pfValue):f.pfValue!==void 0&&(p=f.pfValue,m=f.pfValue),u&&(a=0,o=0),o-=p/2,a-=m/2;for(var h=1;h<=i.stripeBackgroundN;h++){var g=t.pstyle(`stripe-`+h+`-background-size`).value,_=t.pstyle(`stripe-`+h+`-background-color`).value,v=t.pstyle(`stripe-`+h+`-background-opacity`).value*n,y=g/100;y+l>1&&(y=1-l),!(g===0||l>=1||l+y>1)&&(e.beginPath(),e.rect(a,o+m*l,p,m*y),e.closePath(),this.colorFillStyle(e,_[0],_[1],_[2],v),e.fill(),l+=y)}e.restore()};var im={},am=100;im.getPixelRatio=function(){var e=this.data.contexts[0];if(this.forcedPixelRatio!=null)return this.forcedPixelRatio;var t=this.cy.window(),n=e.backingStorePixelRatio||e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1;return(t.devicePixelRatio||1)/n},im.paintCache=function(e){for(var t=this.paintCaches=this.paintCaches||[],n=!0,r,i=0;it.minMbLowQualFrames&&(t.motionBlurPxRatio=t.mbPxRBlurry)),t.clearingMotionBlur&&(t.motionBlurPxRatio=1),t.textureDrawLastFrame&&!d&&(u[t.NODE]=!0,u[t.SELECT_BOX]=!0);var v=n.style(),y=n.zoom(),b=o===void 0?y:o,x=n.pan(),S={x:x.x,y:x.y},C={zoom:y,pan:{x:x.x,y:x.y}},w=t.prevViewport;!(w===void 0||C.zoom!==w.zoom||C.pan.x!==w.pan.x||C.pan.y!==w.pan.y)&&!(h&&!m)&&(t.motionBlurPxRatio=1),s&&(S=s),b*=c,S.x*=c,S.y*=c;var T=t.getCachedZSortedEles();function E(e,n,r,i,a){var o=e.globalCompositeOperation;e.globalCompositeOperation=`destination-out`,t.colorFillStyle(e,255,255,255,t.motionBlurTransparency),e.fillRect(n,r,i,a),e.globalCompositeOperation=o}function D(e,n){var a,c,u,d;!t.clearingMotionBlur&&(e===l.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]||e===l.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG])?(a={x:x.x*p,y:x.y*p},c=y*p,u=t.canvasWidth*p,d=t.canvasHeight*p):(a=S,c=b,u=t.canvasWidth,d=t.canvasHeight),e.setTransform(1,0,0,1,0,0),n===`motionBlur`?E(e,0,0,u,d):!r&&(n===void 0||n)&&e.clearRect(0,0,u,d),i||(e.translate(a.x,a.y),e.scale(c,c)),s&&e.translate(s.x,s.y),o&&e.scale(o,o)}if(d||(t.textureDrawLastFrame=!1),d){if(t.textureDrawLastFrame=!0,!t.textureCache){t.textureCache={},t.textureCache.bb=n.mutableElements().boundingBox(),t.textureCache.texture=t.data.bufferCanvases[t.TEXTURE_BUFFER];var O=t.data.bufferContexts[t.TEXTURE_BUFFER];O.setTransform(1,0,0,1,0,0),O.clearRect(0,0,t.canvasWidth*t.textureMult,t.canvasHeight*t.textureMult),t.render({forcedContext:O,drawOnlyNodeLayer:!0,forcedPxRatio:c*t.textureMult});var C=t.textureCache.viewport={zoom:n.zoom(),pan:n.pan(),width:t.canvasWidth,height:t.canvasHeight};C.mpan={x:(0-C.pan.x)/C.zoom,y:(0-C.pan.y)/C.zoom}}u[t.DRAG]=!1,u[t.NODE]=!1;var k=l.contexts[t.NODE],A=t.textureCache.texture,C=t.textureCache.viewport;k.setTransform(1,0,0,1,0,0),f?E(k,0,0,C.width,C.height):k.clearRect(0,0,C.width,C.height);var j=v.core(`outside-texture-bg-color`).value,M=v.core(`outside-texture-bg-opacity`).value;t.colorFillStyle(k,j[0],j[1],j[2],M),k.fillRect(0,0,C.width,C.height);var y=n.zoom();D(k,!1),k.clearRect(C.mpan.x,C.mpan.y,C.width/C.zoom/c,C.height/C.zoom/c),k.drawImage(A,C.mpan.x,C.mpan.y,C.width/C.zoom/c,C.height/C.zoom/c)}else t.textureOnViewport&&!r&&(t.textureCache=null);var N=n.extent(),P=t.pinching||t.hoverData.dragging||t.swipePanning||t.data.wheelZooming||t.hoverData.draggingEles||t.cy.animated(),F=t.hideEdgesOnViewport&&P,I=[];if(I[t.NODE]=!u[t.NODE]&&f&&!t.clearedForMotionBlur[t.NODE]||t.clearingMotionBlur,I[t.NODE]&&(t.clearedForMotionBlur[t.NODE]=!0),I[t.DRAG]=!u[t.DRAG]&&f&&!t.clearedForMotionBlur[t.DRAG]||t.clearingMotionBlur,I[t.DRAG]&&(t.clearedForMotionBlur[t.DRAG]=!0),u[t.NODE]||i||a||I[t.NODE]){var L=f&&!I[t.NODE]&&p!==1,k=r||(L?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]:l.contexts[t.NODE]);D(k,f&&!L?`motionBlur`:void 0),F?t.drawCachedNodes(k,T.nondrag,c,N):t.drawLayeredElements(k,T.nondrag,c,N),t.debug&&t.drawDebugPoints(k,T.nondrag),!i&&!f&&(u[t.NODE]=!1)}if(!a&&(u[t.DRAG]||i||I[t.DRAG])){var L=f&&!I[t.DRAG]&&p!==1,k=r||(L?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG]:l.contexts[t.DRAG]);D(k,f&&!L?`motionBlur`:void 0),F?t.drawCachedNodes(k,T.drag,c,N):t.drawCachedElements(k,T.drag,c,N),t.debug&&t.drawDebugPoints(k,T.drag),!i&&!f&&(u[t.DRAG]=!1)}if(this.drawSelectionRectangle(e,D),f&&p!==1){var R=l.contexts[t.NODE],z=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE],B=l.contexts[t.DRAG],V=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG],H=function(e,n,r){e.setTransform(1,0,0,1,0,0),r||!_?e.clearRect(0,0,t.canvasWidth,t.canvasHeight):E(e,0,0,t.canvasWidth,t.canvasHeight);var i=p;e.drawImage(n,0,0,t.canvasWidth*i,t.canvasHeight*i,0,0,t.canvasWidth,t.canvasHeight)};(u[t.NODE]||I[t.NODE])&&(H(R,z,I[t.NODE]),u[t.NODE]=!1),(u[t.DRAG]||I[t.DRAG])&&(H(B,V,I[t.DRAG]),u[t.DRAG]=!1)}t.prevViewport=C,t.clearingMotionBlur&&(t.clearingMotionBlur=!1,t.motionBlurCleared=!0,t.motionBlur=!0),f&&(t.motionBlurTimeout=setTimeout(function(){t.motionBlurTimeout=null,t.clearedForMotionBlur[t.NODE]=!1,t.clearedForMotionBlur[t.DRAG]=!1,t.motionBlur=!1,t.clearingMotionBlur=!d,t.mbFrames=0,u[t.NODE]=!0,u[t.DRAG]=!0,t.redraw()},am)),r||n.emit(`render`)};var om;im.drawSelectionRectangle=function(e,t){var n=this,r=n.cy,i=n.data,a=r.style(),o=e.drawOnlyNodeLayer,s=e.drawAllLayers,c=i.canvasNeedsRedraw,l=e.forcedContext;if(n.showFps||!o&&c[n.SELECT_BOX]&&!s){var u=l||i.contexts[n.SELECT_BOX];if(t(u),n.selection[4]==1&&(n.hoverData.selecting||n.touchData.selecting)){var d=n.cy.zoom(),f=a.core(`selection-box-border-width`).value/d;u.lineWidth=f,u.fillStyle=`rgba(`+a.core(`selection-box-color`).value[0]+`,`+a.core(`selection-box-color`).value[1]+`,`+a.core(`selection-box-color`).value[2]+`,`+a.core(`selection-box-opacity`).value+`)`,u.fillRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]),f>0&&(u.strokeStyle=`rgba(`+a.core(`selection-box-border-color`).value[0]+`,`+a.core(`selection-box-border-color`).value[1]+`,`+a.core(`selection-box-border-color`).value[2]+`,`+a.core(`selection-box-opacity`).value+`)`,u.strokeRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]))}if(i.bgActivePosistion&&!n.hoverData.selecting){var d=n.cy.zoom(),p=i.bgActivePosistion;u.fillStyle=`rgba(`+a.core(`active-bg-color`).value[0]+`,`+a.core(`active-bg-color`).value[1]+`,`+a.core(`active-bg-color`).value[2]+`,`+a.core(`active-bg-opacity`).value+`)`,u.beginPath(),u.arc(p.x,p.y,a.core(`active-bg-size`).pfValue/d,0,2*Math.PI),u.fill()}var m=n.lastRedrawTime;if(n.showFps&&m){m=Math.round(m);var h=Math.round(1e3/m),g=`1 frame = `+m+` ms = `+h+` fps`;u.setTransform(1,0,0,1,0,0),u.fillStyle=`rgba(255, 0, 0, 0.75)`,u.strokeStyle=`rgba(255, 0, 0, 0.75)`,u.font=`30px Arial`,om||=u.measureText(g).actualBoundingBoxAscent,u.fillText(g,0,om),u.strokeRect(0,om+10,250,20),u.fillRect(0,om+10,250*Math.min(h/60,1),20)}s||(c[n.SELECT_BOX]=!1)}};function sm(e,t,n){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS))throw Error(e.getShaderInfoLog(r));return r}function cm(e,t,n){var r=sm(e,e.VERTEX_SHADER,t),i=sm(e,e.FRAGMENT_SHADER,n),a=e.createProgram();if(e.attachShader(a,r),e.attachShader(a,i),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS))throw Error(`Could not initialize shaders`);return a}function lm(e,t,n){n===void 0&&(n=t);var r=e.makeOffscreenCanvas(t,n),i=r.context=r.getContext(`2d`);return r.clear=function(){return i.clearRect(0,0,r.width,r.height)},r.clear(),r}function um(e){var t=e.pixelRatio,n=e.cy.zoom(),r=e.cy.pan();return{zoom:n*t,pan:{x:r.x*t,y:r.y*t}}}function dm(e){var t=e.pixelRatio;return e.cy.zoom()*t}function fm(e,t,n,r,i){var a=r*n+t.x,o=i*n+t.y;return o=Math.round(e.canvasHeight-o),[a,o]}function pm(e,t){return t.picking?!0:e.pstyle(`background-fill`).value!==`solid`||e.pstyle(`background-image`).strValue!==`none`?!1:e.pstyle(`border-width`).value===0||e.pstyle(`border-opacity`).value===0?!0:e.pstyle(`border-style`).value===`solid`}function mm(e,t){if(e.length!==t.length)return!1;for(var n=0;n>0&255)/255,n[1]=(e>>8&255)/255,n[2]=(e>>16&255)/255,n[3]=(e>>24&255)/255,n}function _m(e){return e[0]+(e[1]<<8)+(e[2]<<16)+(e[3]<<24)}function vm(e,t){var n=e.createTexture();return n.buffer=function(t){e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR_MIPMAP_NEAREST),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,t),e.generateMipmap(e.TEXTURE_2D),e.bindTexture(e.TEXTURE_2D,null)},n.deleteTexture=function(){e.deleteTexture(n)},n}function ym(e,t){switch(t){case`float`:return[1,e.FLOAT,4];case`vec2`:return[2,e.FLOAT,4];case`vec3`:return[3,e.FLOAT,4];case`vec4`:return[4,e.FLOAT,4];case`int`:return[1,e.INT,4];case`ivec2`:return[2,e.INT,4]}}function bm(e,t,n){switch(t){case e.FLOAT:return new Float32Array(n);case e.INT:return new Int32Array(n)}}function xm(e,t,n,r,i,a){switch(t){case e.FLOAT:return new Float32Array(n.buffer,a*r,i);case e.INT:return new Int32Array(n.buffer,a*r,i)}}function Sm(e,t,n,r){var i=f(ym(e,t),2),a=i[0],o=i[1],s=bm(e,o,r),c=e.createBuffer();return e.bindBuffer(e.ARRAY_BUFFER,c),e.bufferData(e.ARRAY_BUFFER,s,e.STATIC_DRAW),o===e.FLOAT?e.vertexAttribPointer(n,a,o,!1,0,0):o===e.INT&&e.vertexAttribIPointer(n,a,o,0,0),e.enableVertexAttribArray(n),e.bindBuffer(e.ARRAY_BUFFER,null),c}function Cm(e,t,n,r){var i=f(ym(e,n),3),a=i[0],o=i[1],s=i[2],c=bm(e,o,t*a),l=a*s,u=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,u),e.bufferData(e.ARRAY_BUFFER,t*l,e.DYNAMIC_DRAW),e.enableVertexAttribArray(r),o===e.FLOAT?e.vertexAttribPointer(r,a,o,!1,l,0):o===e.INT&&e.vertexAttribIPointer(r,a,o,l,0),e.vertexAttribDivisor(r,1),e.bindBuffer(e.ARRAY_BUFFER,null);for(var d=Array(t),p=0;pi&&(a=i/t,o=t*a,s=n*a),{scale:a,texW:o,texH:s}}},{key:`draw`,value:function(e,t,n){var r=this;if(this.locked)throw Error(`can't draw, atlas is locked`);var i=this.texSize,a=this.texRows,o=this.texHeight,s=this.getScale(t),c=s.scale,l=s.texW,u=s.texH,d=function(e,r){if(n&&r){var i=r.context,a=e.x,s=e.row,l=a,u=o*s;i.save(),i.translate(l,u),i.scale(c,c),n(i,t),i.restore()}},f=[null,null],p=function(){d(r.freePointer,r.canvas),f[0]={x:r.freePointer.x,y:r.freePointer.row*o,w:l,h:u},f[1]={x:r.freePointer.x+l,y:r.freePointer.row*o,w:0,h:u},r.freePointer.x+=l,r.freePointer.x==i&&(r.freePointer.x=0,r.freePointer.row++)},m=function(){var e=r.scratch,t=r.canvas;e.clear(),d({x:0,row:0},e);var n=i-r.freePointer.x,a=l-n,s=o,c=r.freePointer.x,p=r.freePointer.row*o,m=n;t.context.drawImage(e,0,0,m,s,c,p,m,s),f[0]={x:c,y:p,w:m,h:u};var h=n,g=(r.freePointer.row+1)*o,_=a;t&&t.context.drawImage(e,h,0,_,s,0,g,_,s),f[1]={x:0,y:g,w:_,h:u},r.freePointer.x=a,r.freePointer.row++},h=function(){r.freePointer.x=0,r.freePointer.row++};if(this.freePointer.x+l<=i)p();else if(this.freePointer.row>=a-1)return!1;else this.freePointer.x===i?(h(),p()):this.enableWrapping?m():(h(),p());return this.keyToLocation.set(e,f),this.needsBuffer=!0,f}},{key:`getOffsets`,value:function(e){return this.keyToLocation.get(e)}},{key:`isEmpty`,value:function(){return this.freePointer.x===0&&this.freePointer.row===0}},{key:`canFit`,value:function(e){if(this.locked)return!1;var t=this.texSize,n=this.texRows,r=this.getScale(e).texW;return this.freePointer.x+r>t?this.freePointer.row1&&arguments[1]!==void 0?arguments[1]:{},r=n.forceRedraw,i=r===void 0?!1:r,a=n.filterEle,s=a===void 0?function(){return!0}:a,c=n.filterType,l=c===void 0?function(){return!0}:c,u=!1,d=!1,f=o(e),p;try{for(f.s();!(p=f.n()).done;){var m=p.value;if(s(m)){var h=o(this.renderTypes.values()),g;try{var _=function(){var e=g.value,n=e.type;if(l(n)){var r=t.collections.get(e.collection),a=e.getKey(m),o=Array.isArray(a)?a:[a];if(i)o.forEach(function(e){return r.markKeyForGC(e)}),d=!0;else{var s=e.getID?e.getID(m):m.id(),c=t._key(n,s),f=t.typeAndIdToKey.get(c);f!==void 0&&!mm(o,f)&&(u=!0,t.typeAndIdToKey.delete(c),f.forEach(function(e){return r.markKeyForGC(e)}))}}};for(h.s();!(g=h.n()).done;)_()}catch(e){h.e(e)}finally{h.f()}}}}catch(e){f.e(e)}finally{f.f()}return d&&(this.gc(),u=!1),u}},{key:`gc`,value:function(){var e=o(this.collections.values()),t;try{for(e.s();!(t=e.n()).done;)t.value.gc()}catch(t){e.e(t)}finally{e.f()}}},{key:`getOrCreateAtlas`,value:function(e,t,n,r){var i=this.renderTypes.get(t),a=this.collections.get(i.collection),o=!1,s=a.draw(r,n,function(t){i.drawClipped?(t.save(),t.beginPath(),t.rect(0,0,n.w,n.h),t.clip(),i.drawElement(t,e,n,!0,!0),t.restore()):i.drawElement(t,e,n,!0,!0),o=!0});if(o){var c=i.getID?i.getID(e):e.id(),l=this._key(t,c);this.typeAndIdToKey.has(l)?this.typeAndIdToKey.get(l).push(r):this.typeAndIdToKey.set(l,[r])}return s}},{key:`getAtlasInfo`,value:function(e,t){var n=this,r=this.renderTypes.get(t),i=r.getKey(e);return(Array.isArray(i)?i:[i]).map(function(i){var a=r.getBoundingBox(e,i),o=n.getOrCreateAtlas(e,t,a,i),s=f(o.getOffsets(i),2),c=s[0];return{atlas:o,tex:c,tex1:c,tex2:s[1],bb:a}})}},{key:`getDebugInfo`,value:function(){var e=[],t=o(this.collections),n;try{for(t.s();!(n=t.n()).done;){var r=f(n.value,2),i=r[0],a=r[1].getCounts(),s=a.keyCount,c=a.atlasCount;e.push({type:i,keyCount:s,atlasCount:c})}}catch(e){t.e(e)}finally{t.f()}return e}}])}(),Rm=function(){function e(t){r(this,e),this.globalOptions=t,this.atlasSize=t.webglTexSize,this.maxAtlasesPerBatch=t.webglTexPerBatch,this.batchAtlases=[]}return a(e,[{key:`getMaxAtlasesPerBatch`,value:function(){return this.maxAtlasesPerBatch}},{key:`getAtlasSize`,value:function(){return this.atlasSize}},{key:`getIndexArray`,value:function(){return Array.from({length:this.maxAtlasesPerBatch},function(e,t){return t})}},{key:`startBatch`,value:function(){this.batchAtlases=[]}},{key:`getAtlasCount`,value:function(){return this.batchAtlases.length}},{key:`getAtlases`,value:function(){return this.batchAtlases}},{key:`canAddToCurrentBatch`,value:function(e){return this.batchAtlases.length===this.maxAtlasesPerBatch?this.batchAtlases.includes(e):!0}},{key:`getAtlasIndexForBatch`,value:function(e){var t=this.batchAtlases.indexOf(e);if(t<0){if(this.batchAtlases.length===this.maxAtlasesPerBatch)throw Error(`cannot add more atlases to batch`);this.batchAtlases.push(e),t=this.batchAtlases.length-1}return t}}])}(),zm=` - float circleSD(vec2 p, float r) { - return distance(vec2(0), p) - r; // signed distance - } -`,Bm=` - float rectangleSD(vec2 p, vec2 b) { - vec2 d = abs(p)-b; - return distance(vec2(0),max(d,0.0)) + min(max(d.x,d.y),0.0); - } -`,Vm=` - float roundRectangleSD(vec2 p, vec2 b, vec4 cr) { - cr.xy = (p.x > 0.0) ? cr.xy : cr.zw; - cr.x = (p.y > 0.0) ? cr.x : cr.y; - vec2 q = abs(p) - b + cr.x; - return min(max(q.x, q.y), 0.0) + distance(vec2(0), max(q, 0.0)) - cr.x; - } -`,Hm=` - float ellipseSD(vec2 p, vec2 ab) { - p = abs( p ); // symmetry - - // find root with Newton solver - vec2 q = ab*(p-ab); - float w = (q.x1.0) ? d : -d; - } -`,Um={SCREEN:{name:`screen`,screen:!0},PICKING:{name:`picking`,picking:!0}},Wm={IGNORE:1,USE_BB:2},Gm=0,Km=1,qm=2,Jm=3,Ym=4,Xm=5,Zm=6,Qm=7,$m=function(){function e(t,n,i){r(this,e),this.r=t,this.gl=n,this.maxInstances=i.webglBatchSize,this.atlasSize=i.webglTexSize,this.bgColor=i.bgColor,this.debug=i.webglDebug,this.batchDebugInfo=[],i.enableWrapping=!0,i.createTextureCanvas=lm,this.atlasManager=new Lm(t,i),this.batchManager=new Rm(i),this.simpleShapeOptions=new Map,this.program=this._createShaderProgram(Um.SCREEN),this.pickingProgram=this._createShaderProgram(Um.PICKING),this.vao=this._createVAO()}return a(e,[{key:`addAtlasCollection`,value:function(e,t){this.atlasManager.addAtlasCollection(e,t)}},{key:`addTextureAtlasRenderType`,value:function(e,t){this.atlasManager.addRenderType(e,t)}},{key:`addSimpleShapeRenderType`,value:function(e,t){this.simpleShapeOptions.set(e,t)}},{key:`invalidate`,value:function(e){var t=(arguments.length>1&&arguments[1]!==void 0?arguments[1]:{}).type,n=this.atlasManager;return t?n.invalidate(e,{filterType:function(e){return e===t},forceRedraw:!0}):n.invalidate(e)}},{key:`gc`,value:function(){this.atlasManager.gc()}},{key:`_createShaderProgram`,value:function(e){var t=this.gl,n=`#version 300 es - precision highp float; - - uniform mat3 uPanZoomMatrix; - uniform int uAtlasSize; - - // instanced - in vec2 aPosition; // a vertex from the unit square - - in mat3 aTransform; // used to transform verticies, eg into a bounding box - in int aVertType; // the type of thing we are rendering - - // the z-index that is output when using picking mode - in vec4 aIndex; - - // For textures - in int aAtlasId; // which shader unit/atlas to use - in vec4 aTex; // x/y/w/h of texture in atlas - - // for edges - in vec4 aPointAPointB; - in vec4 aPointCPointD; - in vec2 aLineWidth; // also used for node border width - - // simple shapes - in vec4 aCornerRadius; // for round-rectangle [top-right, bottom-right, top-left, bottom-left] - in vec4 aColor; // also used for edges - in vec4 aBorderColor; // aLineWidth is used for border width - - // output values passed to the fragment shader - out vec2 vTexCoord; - out vec4 vColor; - out vec2 vPosition; - // flat values are not interpolated - flat out int vAtlasId; - flat out int vVertType; - flat out vec2 vTopRight; - flat out vec2 vBotLeft; - flat out vec4 vCornerRadius; - flat out vec4 vBorderColor; - flat out vec2 vBorderWidth; - flat out vec4 vIndex; - - void main(void) { - int vid = gl_VertexID; - vec2 position = aPosition; // TODO make this a vec3, simplifies some code below - - if(aVertType == ${Gm}) { - float texX = aTex.x; // texture coordinates - float texY = aTex.y; - float texW = aTex.z; - float texH = aTex.w; - - if(vid == 1 || vid == 2 || vid == 4) { - texX += texW; - } - if(vid == 2 || vid == 4 || vid == 5) { - texY += texH; - } - - float d = float(uAtlasSize); - vTexCoord = vec2(texX / d, texY / d); // tex coords must be between 0 and 1 - - gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); - } - else if(aVertType == ${Ym} || aVertType == ${Qm} - || aVertType == ${Xm} || aVertType == ${Zm}) { // simple shapes - - // the bounding box is needed by the fragment shader - vBotLeft = (aTransform * vec3(0, 0, 1)).xy; // flat - vTopRight = (aTransform * vec3(1, 1, 1)).xy; // flat - vPosition = (aTransform * vec3(position, 1)).xy; // will be interpolated - - // calculations are done in the fragment shader, just pass these along - vColor = aColor; - vCornerRadius = aCornerRadius; - vBorderColor = aBorderColor; - vBorderWidth = aLineWidth; - - gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); - } - else if(aVertType == ${Km}) { - vec2 source = aPointAPointB.xy; - vec2 target = aPointAPointB.zw; - - // adjust the geometry so that the line is centered on the edge - position.y = position.y - 0.5; - - // stretch the unit square into a long skinny rectangle - vec2 xBasis = target - source; - vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x)); - vec2 point = source + xBasis * position.x + yBasis * aLineWidth[0] * position.y; - - gl_Position = vec4(uPanZoomMatrix * vec3(point, 1.0), 1.0); - vColor = aColor; - } - else if(aVertType == ${qm}) { - vec2 pointA = aPointAPointB.xy; - vec2 pointB = aPointAPointB.zw; - vec2 pointC = aPointCPointD.xy; - vec2 pointD = aPointCPointD.zw; - - // adjust the geometry so that the line is centered on the edge - position.y = position.y - 0.5; - - vec2 p0, p1, p2, pos; - if(position.x == 0.0) { // The left side of the unit square - p0 = pointA; - p1 = pointB; - p2 = pointC; - pos = position; - } else { // The right side of the unit square, use same approach but flip the geometry upside down - p0 = pointD; - p1 = pointC; - p2 = pointB; - pos = vec2(0.0, -position.y); - } - - vec2 p01 = p1 - p0; - vec2 p12 = p2 - p1; - vec2 p21 = p1 - p2; - - // Find the normal vector. - vec2 tangent = normalize(normalize(p12) + normalize(p01)); - vec2 normal = vec2(-tangent.y, tangent.x); - - // Find the vector perpendicular to p0 -> p1. - vec2 p01Norm = normalize(vec2(-p01.y, p01.x)); - - // Determine the bend direction. - float sigma = sign(dot(p01 + p21, normal)); - float width = aLineWidth[0]; - - if(sign(pos.y) == -sigma) { - // This is an intersecting vertex. Adjust the position so that there's no overlap. - vec2 point = 0.5 * width * normal * -sigma / dot(normal, p01Norm); - gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0); - } else { - // This is a non-intersecting vertex. Treat it like a mitre join. - vec2 point = 0.5 * width * normal * sigma * dot(normal, p01Norm); - gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0); - } - - vColor = aColor; - } - else if(aVertType == ${Jm} && vid < 3) { - // massage the first triangle into an edge arrow - if(vid == 0) - position = vec2(-0.15, -0.3); - if(vid == 1) - position = vec2( 0.0, 0.0); - if(vid == 2) - position = vec2( 0.15, -0.3); - - gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0); - vColor = aColor; - } - else { - gl_Position = vec4(2.0, 0.0, 0.0, 1.0); // discard vertex by putting it outside webgl clip space - } - - vAtlasId = aAtlasId; - vVertType = aVertType; - vIndex = aIndex; - } - `,r=this.batchManager.getIndexArray(),i=cm(t,n,`#version 300 es - precision highp float; - - // declare texture unit for each texture atlas in the batch - ${r.map(function(e){return`uniform sampler2D uTexture${e};`}).join(` - `)} - - uniform vec4 uBGColor; - uniform float uZoom; - - in vec2 vTexCoord; - in vec4 vColor; - in vec2 vPosition; // model coordinates - - flat in int vAtlasId; - flat in vec4 vIndex; - flat in int vVertType; - flat in vec2 vTopRight; - flat in vec2 vBotLeft; - flat in vec4 vCornerRadius; - flat in vec4 vBorderColor; - flat in vec2 vBorderWidth; - - out vec4 outColor; - - ${zm} - ${Bm} - ${Vm} - ${Hm} - - vec4 blend(vec4 top, vec4 bot) { // blend colors with premultiplied alpha - return vec4( - top.rgb + (bot.rgb * (1.0 - top.a)), - top.a + (bot.a * (1.0 - top.a)) - ); - } - - vec4 distInterp(vec4 cA, vec4 cB, float d) { // interpolate color using Signed Distance - // scale to the zoom level so that borders don't look blurry when zoomed in - // note 1.5 is an aribitrary value chosen because it looks good - return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d))); - } - - void main(void) { - if(vVertType == ${Gm}) { - // look up the texel from the texture unit - ${r.map(function(e){return`if(vAtlasId == ${e}) outColor = texture(uTexture${e}, vTexCoord);`}).join(` - else `)} - } - else if(vVertType == ${Jm}) { - // mimics how canvas renderer uses context.globalCompositeOperation = 'destination-out'; - outColor = blend(vColor, uBGColor); - outColor.a = 1.0; // make opaque, masks out line under arrow - } - else if(vVertType == ${Ym} && vBorderWidth == vec2(0.0)) { // simple rectangle with no border - outColor = vColor; // unit square is already transformed to the rectangle, nothing else needs to be done - } - else if(vVertType == ${Ym} || vVertType == ${Qm} - || vVertType == ${Xm} || vVertType == ${Zm}) { // use SDF - - float outerBorder = vBorderWidth[0]; - float innerBorder = vBorderWidth[1]; - float borderPadding = outerBorder * 2.0; - float w = vTopRight.x - vBotLeft.x - borderPadding; - float h = vTopRight.y - vBotLeft.y - borderPadding; - vec2 b = vec2(w/2.0, h/2.0); // half width, half height - vec2 p = vPosition - vec2(vTopRight.x - b[0] - outerBorder, vTopRight.y - b[1] - outerBorder); // translate to center - - float d; // signed distance - if(vVertType == ${Ym}) { - d = rectangleSD(p, b); - } else if(vVertType == ${Qm} && w == h) { - d = circleSD(p, b.x); // faster than ellipse - } else if(vVertType == ${Qm}) { - d = ellipseSD(p, b); - } else { - d = roundRectangleSD(p, b, vCornerRadius.wzyx); - } - - // use the distance to interpolate a color to smooth the edges of the shape, doesn't need multisampling - // we must smooth colors inwards, because we can't change pixels outside the shape's bounding box - if(d > 0.0) { - if(d > outerBorder) { - discard; - } else { - outColor = distInterp(vBorderColor, vec4(0), d - outerBorder); - } - } else { - if(d > innerBorder) { - vec4 outerColor = outerBorder == 0.0 ? vec4(0) : vBorderColor; - vec4 innerBorderColor = blend(vBorderColor, vColor); - outColor = distInterp(innerBorderColor, outerColor, d); - } - else { - vec4 outerColor; - if(innerBorder == 0.0 && outerBorder == 0.0) { - outerColor = vec4(0); - } else if(innerBorder == 0.0) { - outerColor = vBorderColor; - } else { - outerColor = blend(vBorderColor, vColor); - } - outColor = distInterp(vColor, outerColor, d - innerBorder); - } - } - } - else { - outColor = vColor; - } - - ${e.picking?`if(outColor.a == 0.0) discard; - else outColor = vIndex;`:``} - } - `);i.aPosition=t.getAttribLocation(i,`aPosition`),i.aIndex=t.getAttribLocation(i,`aIndex`),i.aVertType=t.getAttribLocation(i,`aVertType`),i.aTransform=t.getAttribLocation(i,`aTransform`),i.aAtlasId=t.getAttribLocation(i,`aAtlasId`),i.aTex=t.getAttribLocation(i,`aTex`),i.aPointAPointB=t.getAttribLocation(i,`aPointAPointB`),i.aPointCPointD=t.getAttribLocation(i,`aPointCPointD`),i.aLineWidth=t.getAttribLocation(i,`aLineWidth`),i.aColor=t.getAttribLocation(i,`aColor`),i.aCornerRadius=t.getAttribLocation(i,`aCornerRadius`),i.aBorderColor=t.getAttribLocation(i,`aBorderColor`),i.uPanZoomMatrix=t.getUniformLocation(i,`uPanZoomMatrix`),i.uAtlasSize=t.getUniformLocation(i,`uAtlasSize`),i.uBGColor=t.getUniformLocation(i,`uBGColor`),i.uZoom=t.getUniformLocation(i,`uZoom`),i.uTextures=[];for(var a=0;a1&&arguments[1]!==void 0?arguments[1]:Um.SCREEN;this.panZoomMatrix=e,this.renderTarget=t,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:`startBatch`,value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:`endFrame`,value:function(){this.endBatch()}},{key:`_isVisible`,value:function(e,t){return e.visible()?t&&t.isVisible?t.isVisible(e):!0:!1}},{key:`drawTexture`,value:function(e,t,n){var r=this.atlasManager,i=this.batchManager,a=r.getRenderTypeOpts(n);if(this._isVisible(e,a)&&!(e.isEdge()&&!this._isValidEdge(e))){if(this.renderTarget.picking&&a.getTexPickingMode){var s=a.getTexPickingMode(e);if(s===Wm.IGNORE)return;if(s==Wm.USE_BB){this.drawPickingRectangle(e,t,n);return}}var c=o(r.getAtlasInfo(e,n)),l;try{for(c.s();!(l=c.n()).done;){var u=l.value,d=u.atlas,p=u.tex1,m=u.tex2;i.canAddToCurrentBatch(d)||this.endBatch();for(var h=i.getAtlasIndexForBatch(d),g=0,_=[[p,!0],[m,!1]];g<_.length;g++){var v=f(_[g],2),y=v[0],b=v[1];if(y.w!=0){var x=this.instanceCount;this.vertTypeBuffer.getView(x)[0]=Gm,gm(t,this.indexBuffer.getView(x));var S=this.atlasIdBuffer.getView(x);S[0]=h;var C=this.texBuffer.getView(x);C[0]=y.x,C[1]=y.y,C[2]=y.w,C[3]=y.h;var w=this.transformBuffer.getMatrixView(x);this.setTransformMatrix(e,w,a,u,b),this.instanceCount++,b||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(e){c.e(e)}finally{c.f()}}}},{key:`setTransformMatrix`,value:function(e,t,n,r){var i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,a=0;if(n.shapeProps&&n.shapeProps.padding&&(a=e.pstyle(n.shapeProps.padding).pfValue),r){var o=r.bb,s=r.tex1,c=r.tex2,l=s.w/(s.w+c.w);i||(l=1-l);var u=this._getAdjustedBB(o,a,i,l);this._applyTransformMatrix(t,u,n,e)}else{var d=n.getBoundingBox(e),f=this._getAdjustedBB(d,a,!0,1);this._applyTransformMatrix(t,f,n,e)}}},{key:`_applyTransformMatrix`,value:function(e,t,n,r){var i,a;Om(e);var o=n.getRotation?n.getRotation(r):0;if(o!==0){var s=n.getRotationPoint(r),c=s.x,l=s.y;Am(e,e,[c,l]),jm(e,e,o);var u=n.getRotationOffset(r);i=u.x+(t.xOffset||0),a=u.y+(t.yOffset||0)}else i=t.x1,a=t.y1;Am(e,e,[i,a]),Mm(e,e,[t.w,t.h])}},{key:`_getAdjustedBB`,value:function(e,t,n,r){var i=e.x1,a=e.y1,o=e.w,s=e.h,c=e.yOffset;t&&(i-=t,a-=t,o+=2*t,s+=2*t);var l=0,u=o*r;return n&&r<1?o=u:!n&&r<1&&(l=o-u,i+=l,o=u),{x1:i,y1:a,w:o,h:s,xOffset:l,yOffset:c}}},{key:`drawPickingRectangle`,value:function(e,t,n){var r=this.atlasManager.getRenderTypeOpts(n),i=this.instanceCount;this.vertTypeBuffer.getView(i)[0]=Ym,gm(t,this.indexBuffer.getView(i)),hm([0,0,0],1,this.colorBuffer.getView(i));var a=this.transformBuffer.getMatrixView(i);this.setTransformMatrix(e,a,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:`drawNode`,value:function(e,t,n){var r=this.simpleShapeOptions.get(n);if(this._isVisible(e,r)){var i=r.shapeProps,a=this._getVertTypeForShape(e,i.shape);if(a===void 0||r.isSimple&&!r.isSimple(e,this.renderTarget)){this.drawTexture(e,t,n);return}var o=this.instanceCount;if(this.vertTypeBuffer.getView(o)[0]=a,a===Xm||a===Zm){var s=r.getBoundingBox(e),c=this._getCornerRadius(e,i.radius,s),l=this.cornerRadiusBuffer.getView(o);l[0]=c,l[1]=c,l[2]=c,l[3]=c,a===Zm&&(l[0]=0,l[2]=0)}gm(t,this.indexBuffer.getView(o));var u=this.renderTarget.picking?1:e.pstyle(i.opacity).value,d=e.pstyle(i.color).value;hm(d,u,this.colorBuffer.getView(o));var f=this.lineWidthBuffer.getView(o);if(f[0]=0,f[1]=0,i.border){var p=e.pstyle(`border-width`).value;if(p>0){var m=e.pstyle(`border-color`).value,h=e.pstyle(`border-opacity`).value;hm(m,h,this.borderColorBuffer.getView(o));var g=e.pstyle(`border-position`).value;if(g===`inside`)f[0]=0,f[1]=-p;else if(g===`outside`)f[0]=p,f[1]=0;else{var _=p/2;f[0]=_,f[1]=-_}}}var v=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(e,v,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}},{key:`_getVertTypeForShape`,value:function(e,t){switch(e.pstyle(t).value){case`rectangle`:return Ym;case`ellipse`:return Qm;case`roundrectangle`:case`round-rectangle`:return Xm;case`bottom-round-rectangle`:return Zm;default:return}}},{key:`_getCornerRadius`,value:function(e,t,n){var r=n.w,i=n.h;if(e.pstyle(t).value===`auto`)return jr(r,i);var a=e.pstyle(t).pfValue,o=r/2,s=i/2;return Math.min(a,s,o)}},{key:`drawEdgeArrow`,value:function(e,t,n){if(e.visible()){var r=e._private.rscratch,i,a,o;if(n===`source`?(i=r.arrowStartX,a=r.arrowStartY,o=r.srcArrowAngle):(i=r.arrowEndX,a=r.arrowEndY,o=r.tgtArrowAngle),!(isNaN(i)||i==null||isNaN(a)||a==null||isNaN(o)||o==null)&&e.pstyle(n+`-arrow-shape`).value!==`none`){var s=e.pstyle(n+`-arrow-color`).value,c=e.pstyle(`opacity`).value*e.pstyle(`line-opacity`).value,l=e.pstyle(`width`).pfValue,u=e.pstyle(`arrow-scale`).value,d=this.r.getArrowWidth(l,u),f=this.instanceCount,p=this.transformBuffer.getMatrixView(f);Om(p),Am(p,p,[i,a]),Mm(p,p,[d,d]),jm(p,p,o),this.vertTypeBuffer.getView(f)[0]=Jm,gm(t,this.indexBuffer.getView(f)),hm(s,c,this.colorBuffer.getView(f)),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}},{key:`drawEdgeLine`,value:function(e,t){if(e.visible()){var n=this._getEdgePoints(e);if(n){var r=e.pstyle(`opacity`).value,i=e.pstyle(`line-opacity`).value,a=e.pstyle(`width`).pfValue,o=e.pstyle(`line-color`).value,s=r*i;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),n.length==4){var c=this.instanceCount;this.vertTypeBuffer.getView(c)[0]=Km,gm(t,this.indexBuffer.getView(c)),hm(o,s,this.colorBuffer.getView(c));var l=this.lineWidthBuffer.getView(c);l[0]=a;var u=this.pointAPointBBuffer.getView(c);u[0]=n[0],u[1]=n[1],u[2]=n[2],u[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var d=0;d=this.maxInstances&&this.endBatch()}}}}},{key:`_isValidEdge`,value:function(e){var t=e._private.rscratch;return!(t.badLine||t.allpts==null||isNaN(t.allpts[0]))}},{key:`_getEdgePoints`,value:function(e){var t=e._private.rscratch;if(this._isValidEdge(e)){var n=t.allpts;if(n.length==4)return n;var r=this._getNumSegments(e);return this._getCurveSegmentPoints(n,r)}}},{key:`_getNumSegments`,value:function(e){return Math.min(15,this.maxInstances)}},{key:`_getCurveSegmentPoints`,value:function(e,t){if(e.length==4)return e;for(var n=Array((t+1)*2),r=0;r<=t;r++)if(r==0)n[0]=e[0],n[1]=e[1];else if(r==t)n[r*2]=e[e.length-2],n[r*2+1]=e[e.length-1];else{var i=r/t;this._setCurvePoint(e,i,n,r*2)}return n}},{key:`_setCurvePoint`,value:function(e,t,n,r){if(e.length<=2)n[r]=e[0],n[r+1]=e[1];else{for(var i=Array(e.length-2),a=0;a0}},s=function(e){return e.pstyle(`text-events`).strValue===`yes`?Wm.USE_BB:Wm.IGNORE},c=function(e){var t=e.position(),n=t.x,r=t.y,i=e.outerWidth(),a=e.outerHeight();return{w:i,h:a,x1:n-i/2,y1:r-a/2}};n.drawing.addAtlasCollection(`node`,{texRows:e.webglTexRowsNodes}),n.drawing.addAtlasCollection(`label`,{texRows:e.webglTexRows}),n.drawing.addTextureAtlasRenderType(`node-body`,{collection:`node`,getKey:t.getStyleKey,getBoundingBox:t.getElementBox,drawElement:t.drawElement}),n.drawing.addSimpleShapeRenderType(`node-body`,{getBoundingBox:c,isSimple:pm,shapeProps:{shape:`shape`,color:`background-color`,opacity:`background-opacity`,radius:`corner-radius`,border:!0}}),n.drawing.addSimpleShapeRenderType(`node-overlay`,{getBoundingBox:c,isVisible:o(`overlay`),shapeProps:{shape:`overlay-shape`,color:`overlay-color`,opacity:`overlay-opacity`,padding:`overlay-padding`,radius:`overlay-corner-radius`}}),n.drawing.addSimpleShapeRenderType(`node-underlay`,{getBoundingBox:c,isVisible:o(`underlay`),shapeProps:{shape:`underlay-shape`,color:`underlay-color`,opacity:`underlay-opacity`,padding:`underlay-padding`,radius:`underlay-corner-radius`}}),n.drawing.addTextureAtlasRenderType(`label`,{collection:`label`,getTexPickingMode:s,getKey:rh(t.getLabelKey,null),getBoundingBox:ih(t.getLabelBox,null),drawClipped:!0,drawElement:t.drawLabel,getRotation:i(null),getRotationPoint:t.getLabelRotationPoint,getRotationOffset:t.getLabelRotationOffset,isVisible:a(`label`)}),n.drawing.addTextureAtlasRenderType(`edge-source-label`,{collection:`label`,getTexPickingMode:s,getKey:rh(t.getSourceLabelKey,`source`),getBoundingBox:ih(t.getSourceLabelBox,`source`),drawClipped:!0,drawElement:t.drawSourceLabel,getRotation:i(`source`),getRotationPoint:t.getSourceLabelRotationPoint,getRotationOffset:t.getSourceLabelRotationOffset,isVisible:a(`source-label`)}),n.drawing.addTextureAtlasRenderType(`edge-target-label`,{collection:`label`,getTexPickingMode:s,getKey:rh(t.getTargetLabelKey,`target`),getBoundingBox:ih(t.getTargetLabelBox,`target`),drawClipped:!0,drawElement:t.drawTargetLabel,getRotation:i(`target`),getRotationPoint:t.getTargetLabelRotationPoint,getRotationOffset:t.getTargetLabelRotationOffset,isVisible:a(`target-label`)});var l=st(function(){console.log(`garbage collect flag set`),n.data.gc=!0},1e4);n.onUpdateEleCalcs(function(e,t){var r=!1;t&&t.length>0&&(r|=n.drawing.invalidate(t)),r&&l()}),ah(n)};function th(e){var t=e.cy.container();return pe(t&&t.style&&t.style.backgroundColor||`white`)}function nh(e,t){var n=e._private.rscratch;return Xt(n,`labelWrapCachedLines`,t)||[]}var rh=function(e,t){return function(n){var r=e(n),i=nh(n,t);return i.length>1?i.map(function(e,t){return`${r}_${t}`}):r}},ih=function(e,t){return function(n,r){var i=e(n);if(typeof r==`string`){var a=r.indexOf(`_`);if(a>0){var o=Number(r.substring(a+1)),s=nh(n,t),c=i.h/s.length,l=c*o,u=i.y1+l;return{x1:i.x1,w:i.w,y1:u,h:c,yOffset:l}}}return i}};function ah(e){var t=e.render;e.render=function(n){n||={};var r=e.cy;e.webgl&&(r.zoom()>$f?(oh(e),t.call(e,n)):(sh(e),gh(e,n,Um.SCREEN)))};var n=e.matchCanvasSize;e.matchCanvasSize=function(t){n.call(e,t),e.pickingFrameBuffer.setFramebufferAttachmentSizes(e.canvasWidth,e.canvasHeight),e.pickingFrameBuffer.needsDraw=!0},e.findNearestElements=function(t,n,r,i){return mh(e,t,n)};var r=e.invalidateCachedZSortedEles;e.invalidateCachedZSortedEles=function(){r.call(e),e.pickingFrameBuffer.needsDraw=!0};var i=e.notify;e.notify=function(t,n){i.call(e,t,n),t===`viewport`||t===`bounds`?e.pickingFrameBuffer.needsDraw=!0:t===`background`&&e.drawing.invalidate(n,{type:`node-body`})}}function oh(e){var t=e.data.contexts[e.WEBGL];t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT)}function sh(e){var t=function(t){t.save(),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,e.canvasWidth,e.canvasHeight),t.restore()};t(e.data.contexts[e.NODE]),t(e.data.contexts[e.DRAG])}function ch(e){var t=e.canvasWidth,n=e.canvasHeight,r=um(e),i=r.pan,a=r.zoom,o=Dm();Am(o,o,[i.x,i.y]),Mm(o,o,[a,a]);var s=Dm();Nm(s,t,n);var c=Dm();return km(c,s,o),c}function lh(e,t){var n=e.canvasWidth,r=e.canvasHeight,i=um(e),a=i.pan,o=i.zoom;t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,n,r),t.translate(a.x,a.y),t.scale(o,o)}function uh(e,t){e.drawSelectionRectangle(t,function(t){return lh(e,t)})}function dh(e){var t=e.data.contexts[e.NODE];t.save(),lh(e,t),t.strokeStyle=`rgba(0, 0, 0, 0.3)`,t.beginPath(),t.moveTo(-1e3,0),t.lineTo(1e3,0),t.stroke(),t.beginPath(),t.moveTo(0,-1e3),t.lineTo(0,1e3),t.stroke(),t.restore()}function fh(e){var t=function(t,n,r){for(var i=t.atlasManager.getAtlasCollection(n),a=e.data.contexts[e.NODE],o=i.atlases,s=0;s=0&&b.add(S)}return b}function mh(e,t,n){var r=ph(e,t,n),i=e.getCachedZSortedEles(),a,s,c=o(r),l;try{for(c.s();!(l=c.n()).done;){var u=i[l.value];if(!a&&u.isNode()&&(a=u),!s&&u.isEdge()&&(s=u),a&&s)break}}catch(e){c.e(e)}finally{c.f()}return[a,s].filter(Boolean)}function hh(e,t,n){var r=e.drawing;t+=1,n.isNode()?(r.drawNode(n,t,`node-underlay`),r.drawNode(n,t,`node-body`),r.drawTexture(n,t,`label`),r.drawNode(n,t,`node-overlay`)):(r.drawEdgeLine(n,t),r.drawEdgeArrow(n,t,`source`),r.drawEdgeArrow(n,t,`target`),r.drawTexture(n,t,`label`),r.drawTexture(n,t,`edge-source-label`),r.drawTexture(n,t,`edge-target-label`))}function gh(e,t,n){var r;e.webglDebug&&(r=performance.now());var i=e.drawing,a=0;if(n.screen&&e.data.canvasNeedsRedraw[e.SELECT_BOX]&&uh(e,t),e.data.canvasNeedsRedraw[e.NODE]||n.picking){var s=e.data.contexts[e.WEBGL];n.screen?(s.clearColor(0,0,0,0),s.enable(s.BLEND),s.blendFunc(s.ONE,s.ONE_MINUS_SRC_ALPHA)):s.disable(s.BLEND),s.clear(s.COLOR_BUFFER_BIT|s.DEPTH_BUFFER_BIT),s.viewport(0,0,s.canvas.width,s.canvas.height);var c=ch(e),l=e.getCachedZSortedEles();if(a=l.length,i.startFrame(c,n),n.screen){for(var u=0;u0&&a>0){f.clearRect(0,0,i,a),f.globalCompositeOperation=`source-over`;var p=this.getCachedZSortedEles();if(e.full)f.translate(-n.x1*c,-n.y1*c),f.scale(c,c),this.drawElements(f,p),f.scale(1/c,1/c),f.translate(n.x1*c,n.y1*c);else{var m=t.pan(),h={x:m.x*c,y:m.y*c};c*=t.zoom(),f.translate(h.x,h.y),f.scale(c,c),this.drawElements(f,p),f.scale(1/c,1/c),f.translate(-h.x,-h.y)}e.bg&&(f.globalCompositeOperation=`destination-over`,f.fillStyle=e.bg,f.rect(0,0,i,a),f.fill())}return d};function Th(e,t){for(var n=atob(e),r=new ArrayBuffer(n.length),i=new Uint8Array(r),a=0;a`u`?`undefined`:g(OffscreenCanvas))===`undefined`?(n=this.cy.window().document.createElement(`canvas`),n.width=e,n.height=t):n=new OffscreenCanvas(e,t),n},[Ip,Up,Xp,Qp,$p,nm,im,eh,_h,wh,Oh].forEach(function(e){X($,e)});var Mh=[{type:`layout`,extensions:Wd},{type:`renderer`,extensions:[{name:`null`,impl:Gd},{name:`base`,impl:Wf},{name:`canvas`,impl:kh}]}],Nh={},Ph={};function Fh(e,t,n){var r=n,i=function(n){zt("Can not register `"+t+"` for `"+e+"` since `"+n+"` already exists in the prototype and can not be overridden")};if(e===`core`){if(nd.prototype[t])return i(t);nd.prototype[t]=n}else if(e===`collection`){if(gu.prototype[t])return i(t);gu.prototype[t]=n}else if(e===`layout`){for(var a=function(e){this.options=e,n.call(this,e),O(this._private)||(this._private={}),this._private.cy=e.cy,this._private.listeners=[],this.createEmitter()},o=a.prototype=Object.create(n.prototype),s=[],c=0;c()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},ee=Object.prototype.hasOwnProperty;function te(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function ne(e,t){return te(e.type,t,e.props)}function re(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function ie(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ae=/\/+/g;function oe(e,t){return typeof e==`object`&&e&&e.key!=null?ie(``+e.key):t.toString(36)}function se(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ce(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ce(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+oe(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(ae,`$&/`)+`/`),ce(o,r,i,``,function(e){return e})):o!=null&&(re(o)&&(o=ne(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ae,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=l()})),d=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,re());else{var t=n(l);t!==null&&oe(x,t.startTime-e)}}var S=!1,C=-1,w=5,ee=-1;function te(){return g?!0:!(e.unstable_now()-eet&&te());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&oe(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?re():S=!1}}}var re;if(typeof y==`function`)re=function(){y(ne)};else if(typeof MessageChannel<`u`){var ie=new MessageChannel,ae=ie.port2;ie.port1.onmessage=ne,re=function(){ae.postMessage(null)}}else re=function(){_(ne,0)};function oe(t,n){C=_(function(){t(e.unstable_now())},n)}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(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,oe(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,re()))),r},e.unstable_shouldYield=te,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),f=o(((e,t)=>{t.exports=d()})),p=o((e=>{var t=u();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=p()})),h=o((e=>{var t=f(),n=u(),r=m();function i(e){var t=`https://react.dev/errors/`+e;if(1fe||(e.current=de[fe],de[fe]=null,fe--)}function k(e,t){fe++,de[fe]=e.current,e.current=t}var me=pe(null),he=pe(null),ge=pe(null),_e=pe(null);function ve(e,t){switch(k(ge,t),k(he,e),k(me,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}O(me),k(me,e)}function ye(){O(me),O(he),O(ge)}function be(e){e.memoizedState!==null&&k(_e,e);var t=me.current,n=Hd(t,e.type);t!==n&&(k(he,e),k(me,n))}function xe(e){he.current===e&&(O(me),O(he)),_e.current===e&&(O(_e),Qf._currentValue=ue)}var Se,Ce;function we(e){if(Se===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Se=t&&t[1]||``,Ce=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Te=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?we(n):``}function De(e,t){switch(e.tag){case 26:case 27:case 5:return we(e.type);case 16:return we(`Lazy`);case 13:return e.child!==t&&t!==null?we(`Suspense Fallback`):we(`Suspense`);case 19:return we(`SuspenseList`);case 0:case 15:return Ee(e.type,!1);case 11:return Ee(e.type.render,!1);case 1:return Ee(e.type,!0);case 31:return we(`Activity`);default:return``}}function Oe(e){try{var t=``,n=null;do t+=De(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var ke=Object.prototype.hasOwnProperty,Ae=t.unstable_scheduleCallback,je=t.unstable_cancelCallback,Me=t.unstable_shouldYield,Ne=t.unstable_requestPaint,Pe=t.unstable_now,Fe=t.unstable_getCurrentPriorityLevel,Ie=t.unstable_ImmediatePriority,Le=t.unstable_UserBlockingPriority,Re=t.unstable_NormalPriority,ze=t.unstable_LowPriority,Be=t.unstable_IdlePriority,Ve=t.log,He=t.unstable_setDisableYieldValue,Ue=null,We=null;function A(e){if(typeof Ve==`function`&&He(e),We&&typeof We.setStrictMode==`function`)try{We.setStrictMode(Ue,e)}catch{}}var j=Math.clz32?Math.clz32:qe,Ge=Math.log,Ke=Math.LN2;function qe(e){return e>>>=0,e===0?32:31-(Ge(e)/Ke|0)|0}var Je=256,Ye=262144,Xe=4194304;function Ze(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Qe(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=Ze(n))):i=Ze(o):i=Ze(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=Ze(n))):i=Ze(o)):i=Ze(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function $e(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function et(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function tt(){var e=Xe;return Xe<<=1,!(Xe&62914560)&&(Xe=4194304),e}function nt(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function rt(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function it(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),_n=!1;if(gn)try{var vn={};Object.defineProperty(vn,`passive`,{get:function(){_n=!0}}),window.addEventListener(`test`,vn,vn),window.removeEventListener(`test`,vn,vn)}catch{_n=!1}var yn=null,bn=null,xn=null;function Sn(){if(xn)return xn;var e,t=bn,n=t.length,r,i=`value`in yn?yn.value:yn.textContent,a=i.length;for(e=0;e=er),rr=` `,ir=!1;function ar(e,t){switch(e){case`keyup`:return Qn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function or(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var sr=!1;function cr(e,t){switch(e){case`compositionend`:return or(t);case`keypress`:return t.which===32?(ir=!0,rr):null;case`textInput`:return e=t.data,e===rr&&ir?null:e;default:return null}}function lr(e,t){if(sr)return e===`compositionend`||!$n&&ar(e,t)?(e=Sn(),xn=bn=yn=null,sr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=jr(n)}}function Nr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Nr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Pr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Ut(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Ut(e.document)}return t}function Fr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Ir=gn&&`documentMode`in document&&11>=document.documentMode,Lr=null,Rr=null,zr=null,Br=!1;function Vr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Br||Lr==null||Lr!==Ut(r)||(r=Lr,`selectionStart`in r&&Fr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),zr&&Ar(zr,r)||(zr=r,r=Ed(Rr,`onSelect`),0>=o,i-=o,Ni=1<<32-j(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),N&&Fi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),N&&Fi(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return N&&Fi(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),N&&Fi(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case _:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===re&&Na(l)===r.type){n(e,r.sibling),c=a(r,o.props),Ba(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=bi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=yi(o.type,o.key,o.props,null,e.mode,c),Ba(c,o),c.return=e,e=c)}return s(e);case v:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=Ci(o,e.mode,c),c.return=e,e=c}return s(e);case re:return o=Na(o),b(e,r,o,c)}if(le(o))return h(e,r,o,c);if(se(o)){if(l=se(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,za(o),c);if(o.$$typeof===C)return b(e,r,ca(e,o),c);Va(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=xi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Ra=0;var i=b(e,t,n,r);return La=null,i}catch(t){if(t===Da||t===ka)throw t;var a=hi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ua=Ha(!0),Wa=Ha(!1),Ga=!1;function Ka(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function qa(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ja(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ya(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,G&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=fi(e),di(e,null,n),t}return ci(e,r,t,n),fi(e)}function Xa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ot(e,n)}}function Za(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Qa=!1;function $a(){if(Qa){var e=va;if(e!==null)throw e}}function eo(e,t,n,r){Qa=!1;var i=e.updateQueue;Ga=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(J&f)===f:(r&f)===f){f!==0&&f===_a&&(Qa=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:Ga=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Gl|=o,e.lanes=o,e.memoizedState=d}}function to(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function no(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=E.T,s={};E.T=s,Ls(e,!1,t,n);try{var c=i(),l=E.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Is(e,t,xa(c,r),pu(e)):Is(e,t,r,pu(e))}catch(n){Is(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{D.p=a,o!==null&&s.types!==null&&(o.types=s.types),E.T=o}}function Es(){}function Ds(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=Os(e).queue;Ts(e,a,t,ue,n===null?Es:function(){return ks(e),n(r)})}function Os(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:ue,baseState:ue,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ro,lastRenderedState:ue},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ro,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ks(e){var t=Os(e);t.next===null&&(t=e.alternate.memoizedState),Is(e,t.next.queue,{},pu())}function As(){return sa(Qf)}function js(){return B().memoizedState}function Ms(){return B().memoizedState}function Ns(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Ja(n);var r=Ya(t,e,n);r!==null&&(hu(r,t,n),Xa(r,t,n)),t={cache:pa()},e.payload=t;return}t=t.return}}function Ps(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Rs(e)?zs(t,n):(n=li(e,t,n,r),n!==null&&(hu(n,e,r),Bs(n,t,r)))}function Fs(e,t,n){Is(e,t,n,pu())}function Is(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Rs(e))zs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,kr(s,o))return ci(e,t,i,0),K===null&&si(),!1}catch{}if(n=li(e,t,i,r),n!==null)return hu(n,e,r),Bs(n,t,r),!0}return!1}function Ls(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Rs(e)){if(t)throw Error(i(479))}else t=li(e,n,r,2),t!==null&&hu(t,e,2)}function Rs(e){var t=e.alternate;return e===I||t!==null&&t===I}function zs(e,t){yo=vo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Bs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ot(e,n)}}var Vs={readContext:sa,use:Io,useCallback:z,useContext:z,useEffect:z,useImperativeHandle:z,useLayoutEffect:z,useInsertionEffect:z,useMemo:z,useReducer:z,useRef:z,useState:z,useDebugValue:z,useDeferredValue:z,useTransition:z,useSyncExternalStore:z,useId:z,useHostTransitionStatus:z,useFormState:z,useActionState:z,useOptimistic:z,useMemoCache:z,useCacheRefresh:z};Vs.useEffectEvent=z;var Hs={readContext:sa,use:Io,useCallback:function(e,t){return No().memoizedState=[e,t===void 0?null:t],e},useContext:sa,useEffect:fs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),us(4194308,4,vs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return us(4194308,4,e,t)},useInsertionEffect:function(e,t){us(4,2,e,t)},useMemo:function(e,t){var n=No();t=t===void 0?null:t;var r=e();if(bo){A(!0);try{e()}finally{A(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=No();if(n!==void 0){var i=n(t);if(bo){A(!0);try{n(t)}finally{A(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ps.bind(null,I,e),[r.memoizedState,e]},useRef:function(e){var t=No();return e={current:e},t.memoizedState=e},useState:function(e){e=Jo(e);var t=e.queue,n=Fs.bind(null,I,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:bs,useDeferredValue:function(e,t){return Cs(No(),e,t)},useTransition:function(){var e=Jo(!1);return e=Ts.bind(null,I,e.queue,!0,!1),No().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=I,a=No();if(N){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),K===null)throw Error(i(349));J&127||Uo(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,fs(Go.bind(null,r,o,e),[e]),r.flags|=2048,cs(9,{destroy:void 0},Wo.bind(null,r,o,n,t),null),n},useId:function(){var e=No(),t=K.identifierPrefix;if(N){var n=Pi,r=Ni;n=(r&~(1<<32-j(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=xo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[pt]=t,o[mt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Pd(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Fc(t)}}return H(t),Ic(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Fc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ge.current,qi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Bi,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[pt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Wi(t,!0)}else e=Bd(e).createTextNode(r),e[pt]=t,t.stateNode=e}return H(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=qi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[pt]=t}else Ji(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;H(t),e=!1}else n=Yi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(ho(t),t):(ho(t),null);if(t.flags&128)throw Error(i(558))}return H(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=qi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[pt]=t}else Ji(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;H(t),a=!1}else a=Yi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(ho(t),t):(ho(t),null)}return ho(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Rc(t,t.updateQueue),H(t),null);case 4:return ye(),e===null&&Sd(t.stateNode.containerInfo),H(t),null;case 10:return ta(t.type),H(t),null;case 19:if(O(F),r=t.memoizedState,r===null)return H(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)zc(r,!1);else{if(X!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=go(e),o!==null){for(t.flags|=128,zc(r,!1),e=o.updateQueue,t.updateQueue=e,Rc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)vi(n,e),n=n.sibling;return k(F,F.current&1|2),N&&Fi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Pe()>tu&&(t.flags|=128,a=!0,zc(r,!1),t.lanes=4194304)}else{if(!a)if(e=go(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,Rc(t,e),zc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!N)return H(t),null}else 2*Pe()-r.renderingStartTime>tu&&n!==536870912&&(t.flags|=128,a=!0,zc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(H(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Pe(),e.sibling=null,n=F.current,k(F,a?n&1|2:n&1),N&&Fi(t,r.treeForkCount),e);case 22:case 23:return ho(t),so(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(H(t),t.subtreeFlags&6&&(t.flags|=8192)):H(t),n=t.updateQueue,n!==null&&Rc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&O(Ca),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ta(P),H(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Vc(e,t){switch(Ri(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ta(P),ye(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return xe(t),null;case 31:if(t.memoizedState!==null){if(ho(t),t.alternate===null)throw Error(i(340));Ji()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(ho(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ji()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return O(F),null;case 4:return ye(),null;case 10:return ta(t.type),null;case 22:case 23:return ho(t),so(),e!==null&&O(Ca),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ta(P),null;case 25:return null;default:return null}}function Hc(e,t){switch(Ri(t),t.tag){case 3:ta(P),ye();break;case 26:case 27:case 5:xe(t);break;case 4:ye();break;case 31:t.memoizedState!==null&&ho(t);break;case 13:ho(t);break;case 19:O(F);break;case 10:ta(t.type);break;case 22:case 23:ho(t),so(),e!==null&&O(Ca);break;case 24:ta(P)}}function Uc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Wc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function Gc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{no(t,n)}catch(t){Z(e,e.return,t)}}}function Kc(e,t,n){n.props=Ys(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function qc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Jc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}function Yc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Xc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[mt]=t}catch(t){Z(e,e.return,t)}}function Zc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function Qc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Zc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function $c(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=sn));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for($c(e,t,n),e=e.sibling;e!==null;)$c(e,t,n),e=e.sibling}function el(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(el(e,t,n),e=e.sibling;e!==null;)el(e,t,n),e=e.sibling}function tl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[pt]=e,t[mt]=n}catch(t){Z(e,e.return,t)}}var nl=!1,U=!1,rl=!1,il=typeof WeakSet==`function`?WeakSet:Set,al=null;function ol(e,t){if(e=e.containerInfo,Rd=sp,e=Pr(e),Fr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,al=t;al!==null;)if(t=al,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,al=e;else for(;al!==null;){switch(t=al,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(o,r,n),o[pt]=e,Et(o),r=o;break a;case`link`:var s=Vf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=Mr(s,h),v=Mr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,E.T=null,n=lu,lu=null;var o=au,s=su;if(iu=0,ou=au=null,su=0,G&6)throw Error(i(331));var c=G;if(G|=4,Fl(o.current),Dl(o,o.current,s,n),G=c,id(0,!1),We&&typeof We.onPostCommitFiberRoot==`function`)try{We.onPostCommitFiberRoot(Ue,o)}catch{}return!0}finally{D.p=a,E.T=r,Vu(e,t)}}function Wu(e,t,n){t=Ti(n,t),t=tc(e.stateNode,t,2),e=Ya(e,t,2),e!==null&&(rt(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(ru===null||!ru.has(r))){e=Ti(n,e),n=nc(2),r=Ya(t,n,2),r!==null&&(rc(n,r,t,e),rt(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new zl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Ul=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,K===e&&(J&n)===n&&(X===4||X===3&&(J&62914560)===J&&300>Pe()-$l?!(G&2)&&Su(e,0):ql|=n,Yl===J&&(Yl=0)),rd(e)}function qu(e,t){t===0&&(t=tt()),e=ui(e,t),e!==null&&(rt(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return Ae(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-j(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=J,a=Qe(r,r===K?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||$e(r,a)||(n=!0,ld(r,a));r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Pe(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}iu!==0&&iu!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Gt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),Et(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Gt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Gt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Gt(n.imageSizes)+`"]`)):i+=`[href="`+Gt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),Et(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Gt(r)+`"][href="`+Gt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=h({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),Et(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=Tt(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);Et(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=Tt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),Et(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=Tt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),Et(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var a=(a=ge.current)?gf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=Tt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var o=Tt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(jf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Nf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=Tt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Af(e){return`href="`+Gt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),Et(t),e.head.appendChild(t))}function Pf(e){return`[src="`+Gt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Gt(n.href)+`"]`);if(r)return t.instance=r,Et(r),r;var a=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),Et(r),Pd(r,`style`,a),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Af(n.href);var o=e.querySelector(jf(a));if(o)return t.state.loading|=4,t.instance=o,Et(o),o;r=Mf(n),(a=mf.get(a))&&Rf(r,a),o=(e.ownerDocument||e).createElement(`link`),Et(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Pd(o,`link`,r),t.state.loading|=4,Lf(o,n.precedence,e),t.instance=o;case`script`:return o=Pf(n.src),(a=e.querySelector(Ff(o)))?(t.instance=a,Et(a),a):(r=n,(a=mf.get(o))&&(r=h({},n),zf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),Et(a),Pd(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,Et(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),Et(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()})),_=o((e=>{var t=Symbol.for(`react.transitional.element`);function n(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.jsx=n,e.jsxs=n})),v=o(((e,t)=>{t.exports=_()}));function y(...e){let t=``;for(let n of e)n&&(t+=t?` `+n:n);return t}var b=0;function x(e=`rcs`){return b+=1,`${e}-${b}`}var S=v(),C=c(u(),1),w=C.forwardRef(function(e,t){let{variant:n=`secondary`,size:r=`md`,shape:i=`rect`,loading:a=!1,disabled:o=!1,block:s=!1,iconLeft:c,iconRight:l,type:u=`button`,children:d,onClick:f,className:p,style:m,id:h,"data-testid":g,"aria-label":_,"aria-labelledby":v,"aria-describedby":b}=e;return(0,S.jsxs)(`button`,{ref:t,id:h,"data-testid":g,type:u,className:y(`rcs-button`,`rcs-button--${n}`,`rcs-button--${r}`,i!==`rect`&&`rcs-button--${i}`,s&&`rcs-button--block`,p),style:m,disabled:o||a,"aria-disabled":o||a||void 0,"aria-busy":a||void 0,"aria-label":_,"aria-labelledby":v,"aria-describedby":b,onClick:f,children:[a?(0,S.jsx)(`span`,{className:`rcs-button-spinner`,"aria-hidden":!0}):c,d,l]})}),ee=C.forwardRef(function(e,t){let{icon:n,round:r=!1,"aria-label":i,...a}=e;return(0,S.jsx)(w,{ref:t,...a,shape:r?`circle`:`square`,"aria-label":i,children:n})}),te=C.forwardRef(function(e,t){let{value:n,defaultValue:r,placeholder:i,size:a=`md`,status:o=`default`,disabled:s=!1,readOnly:c=!1,invalid:l=!1,prefix:u,suffix:d,clearable:f=!1,type:p=`text`,autoFocus:m=!1,onChange:h,onFocus:g,onBlur:_,onKeyDown:v,className:b,style:x,id:w,"data-testid":ee,"aria-label":te,"aria-labelledby":ne,"aria-describedby":re}=e,ie=n!==void 0,[ae,oe]=C.useState(r??``),se=ie?n:ae,ce=C.useRef(null);C.useImperativeHandle(t,()=>ce.current);let T=l?`error`:o;return(0,S.jsxs)(`span`,{className:y(`rcs-input-wrap`,`rcs-input-wrap--${a}`,b),style:x,"data-status":T,"data-disabled":s||void 0,children:[u&&(0,S.jsx)(`span`,{className:`rcs-input-affix rcs-input-affix--left`,children:u}),(0,S.jsx)(`input`,{ref:ce,id:w,"data-testid":ee,className:`rcs-input`,type:p,value:se,placeholder:i,disabled:s,readOnly:c,autoFocus:m,"aria-invalid":T===`error`||void 0,"aria-label":te,"aria-labelledby":ne,"aria-describedby":re,onChange:e=>{ie||oe(e.target.value),h?.(e.target.value,e)},onFocus:g,onBlur:_,onKeyDown:v}),f&&se&&!s&&!c&&(0,S.jsx)(`button`,{type:`button`,className:`rcs-input-clear`,"aria-label":`Clear`,onClick:e=>{let t=ce.current;ie||oe(``),t&&((Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,`value`)?.set)?.call(t,``),t.dispatchEvent(new Event(`input`,{bubbles:!0}))),h?.(``,e)},children:`×`}),d&&(0,S.jsx)(`span`,{className:`rcs-input-affix rcs-input-affix--right`,children:d})]})});C.forwardRef(function(e,t){let{value:n,defaultValue:r,placeholder:i,rows:a=4,autoResize:o=!1,maxLength:s,showCount:c=!1,size:l=`md`,status:u=`default`,disabled:d=!1,readOnly:f=!1,invalid:p=!1,onChange:m,onFocus:h,onBlur:g,onKeyDown:_,autoFocus:v,className:b,style:x,id:w,"data-testid":ee,"aria-label":te,"aria-labelledby":ne,"aria-describedby":re}=e,ie=n!==void 0,[ae,oe]=C.useState(r??``),se=ie?n:ae,ce=C.useRef(null);C.useImperativeHandle(t,()=>ce.current),C.useLayoutEffect(()=>{if(!o)return;let e=ce.current;e&&(e.style.height=`auto`,e.style.height=e.scrollHeight+`px`)},[se,o]);let T=p?`error`:u;return(0,S.jsxs)(`span`,{style:{display:`block`,width:`100%`,...x},children:[(0,S.jsx)(`textarea`,{ref:ce,id:w,"data-testid":ee,className:y(`rcs-textarea`,`rcs-textarea--${l}`,b),rows:a,value:se,placeholder:i,maxLength:s,disabled:d,readOnly:f,autoFocus:v,"aria-invalid":T===`error`||void 0,"aria-label":te,"aria-labelledby":ne,"aria-describedby":re,"data-status":T,onChange:e=>{ie||oe(e.target.value),m?.(e.target.value,e)},onFocus:h,onBlur:g,onKeyDown:_}),c&&(0,S.jsxs)(`span`,{className:`rcs-textarea-count`,children:[se.length,s?` / ${s}`:``]})]})});function ne(e){let{tone:t=`neutral`,size:n=`md`,icon:r,closable:i=!1,onClose:a,children:o,className:s,style:c,id:l}=e;return(0,S.jsxs)(`span`,{id:l,className:y(`rcs-badge`,`rcs-badge--${t}`,n!==`md`&&`rcs-badge--${n}`,s),style:c,children:[r&&(0,S.jsx)(`span`,{"aria-hidden":!0,children:r}),o,i&&(0,S.jsx)(`button`,{type:`button`,className:`rcs-badge-x`,"aria-label":`Remove`,onClick:a,children:`×`})]})}var re={xs:4,sm:8,md:12,lg:16,xl:24};function ie(e){return e===void 0?12:typeof e==`number`?e:re[e]}var ae={none:`0`,sm:`4px`,md:`6px`,lg:`8px`,pill:`9999px`,circle:`50%`};function oe(e){return e===void 0?`var(--radius-md)`:typeof e==`number`?`${e}px`:ae[e]}var se={none:`none`,sm:`var(--shadow-sm)`,md:`var(--shadow-md)`,lg:`var(--shadow-lg)`,overlay:`var(--shadow-lg)`};function ce(e){let{title:t,subtitle:n,extra:r,footer:i,bordered:a=!0,hoverable:o=!1,padding:s,radius:c,shadow:l=`none`,children:u,className:d,style:f,id:p}=e,m={borderRadius:oe(c),boxShadow:se[l],border:a?void 0:`0`,...f};return(0,S.jsxs)(`div`,{id:p,className:y(`rcs-card`,d),style:m,"data-hoverable":o||void 0,children:[(t||r)&&(0,S.jsxs)(`div`,{className:`rcs-card-header`,children:[(0,S.jsxs)(`div`,{children:[t&&(0,S.jsx)(`div`,{className:`rcs-card-title`,children:t}),n&&(0,S.jsx)(`div`,{className:`rcs-card-subtitle`,children:n})]}),r&&(0,S.jsx)(`div`,{className:`rcs-card-extra`,children:r})]}),(0,S.jsx)(`div`,{className:`rcs-card-body`,style:s===void 0?void 0:{padding:ie(s)},children:u}),i&&(0,S.jsx)(`div`,{className:`rcs-card-footer`,children:i})]})}function T(e){let{direction:t=`horizontal`,size:n=`sm`,align:r,justify:i,wrap:a=!1,split:o,children:s,className:c,style:l,id:u}=e,d=ie(n),f=C.Children.toArray(s);return(0,S.jsx)(`div`,{id:u,className:y(`rcs-space`,t===`vertical`&&`rcs-space--vertical`,a&&`rcs-space--wrap`,c),style:{gap:d,alignItems:r,justifyContent:i,flexDirection:t===`vertical`?`column`:`row`,...l},children:f.map((e,t)=>(0,S.jsxs)(C.Fragment,{children:[e,o&&te.key===m),g=(e,t)=>{t||(d||p(e),o?.(e))};return(0,S.jsxs)(`div`,{id:u,"data-scrollable":s||void 0,className:y(`rcs-tabs`,`rcs-tabs--${i}`,`rcs-tabs--${a}`,c),style:l,children:[(0,S.jsx)(`div`,{className:`rcs-tabs-nav`,"data-scrollable":s||void 0,role:`tablist`,children:t.map(e=>(0,S.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":e.key===m,disabled:e.disabled,"data-active":e.key===m||void 0,className:`rcs-tabs-tab`,onClick:()=>g(e.key,e.disabled),children:[e.icon&&(0,S.jsx)(`span`,{"aria-hidden":!0,children:e.icon}),(0,S.jsx)(`span`,{children:e.label}),e.badge&&(0,S.jsx)(`span`,{style:{marginLeft:4},children:e.badge})]},e.key))}),h?.content&&(0,S.jsx)(`div`,{className:`rcs-tabs-content`,role:`tabpanel`,children:h.content})]})}function fe(e){let{items:t,separator:n=`/`,maxItems:r,className:i,style:a,id:o}=e,s=t;return r&&t.length>r&&(s=[t[0],{label:`…`},...t.slice(t.length-(r-2))]),(0,S.jsx)(`nav`,{id:o,"aria-label":`Breadcrumb`,className:y(`rcs-breadcrumb`,i),style:a,children:s.map((e,t)=>{let r=t===s.length-1,i=e.href?(0,S.jsxs)(`a`,{href:e.href,onClick:e.onClick,children:[e.icon&&(0,S.jsx)(`span`,{"aria-hidden":!0,style:{marginRight:4},children:e.icon}),e.label]}):e.onClick?(0,S.jsx)(`button`,{type:`button`,onClick:e.onClick,style:{background:`none`,border:0,padding:0,color:`inherit`,cursor:`pointer`,font:`inherit`},children:e.label}):(0,S.jsx)(`span`,{children:e.label});return(0,S.jsxs)(C.Fragment,{children:[(0,S.jsx)(`span`,{className:r?`rcs-breadcrumb-item--last`:void 0,children:i}),!r&&(0,S.jsx)(`span`,{className:`rcs-breadcrumb-sep`,"aria-hidden":!0,children:n})]},t)})})}var pe={info:`ⓘ`,success:`✓`,warning:`⚠`,danger:`✕`};function O(e){let{severity:t,title:n,children:r,closable:i=!1,icon:a,action:o,onClose:s,className:c,style:l,id:u}=e;return(0,S.jsxs)(`div`,{id:u,role:`alert`,className:y(`rcs-alert`,`rcs-alert--${t}`,c),style:l,children:[a!==!1&&(0,S.jsx)(`span`,{className:`rcs-alert-icon`,"aria-hidden":!0,children:a??pe[t]}),(0,S.jsxs)(`div`,{className:`rcs-alert-body`,children:[n&&(0,S.jsx)(`div`,{className:`rcs-alert-title`,children:n}),r&&(0,S.jsx)(`div`,{className:`rcs-alert-content`,children:r}),o&&(0,S.jsx)(`div`,{className:`rcs-alert-action`,children:o})]}),i&&(0,S.jsx)(`button`,{type:`button`,className:`rcs-alert-close`,"aria-label":`Dismiss`,onClick:s,children:`×`})]})}function k(e,t){C.useEffect(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t])}function me(e){let{open:t,title:n,description:r,placement:i=`right`,width:a=360,closeOnEsc:o=!0,closeOnBackdrop:s=!0,footer:c,children:l,onClose:u,className:d,style:f,id:p}=e;if(k(t&&o,u),!t)return null;let m=typeof a==`number`?`${a}px`:a,h={...f};return i===`left`||i===`right`?h.width=m:h.height=m,(0,S.jsx)(`div`,{className:`rcs-modal-backdrop`,role:`dialog`,"aria-modal":`true`,style:{alignItems:i===`top`?`flex-start`:i===`bottom`?`flex-end`:`stretch`,justifyItems:i===`left`?`flex-start`:i===`right`?`flex-end`:`stretch`,padding:0},onClick:e=>{s&&e.target===e.currentTarget&&u()},children:(0,S.jsxs)(`div`,{id:p,className:y(`rcs-drawer`,`rcs-drawer--${i}`,d),style:h,children:[(n||r)&&(0,S.jsxs)(`div`,{className:`rcs-modal-header`,children:[n&&(0,S.jsx)(`h2`,{className:`rcs-modal-title`,children:n}),r&&(0,S.jsx)(`div`,{className:`rcs-modal-desc`,children:r})]}),(0,S.jsx)(`div`,{className:`rcs-modal-body`,style:{flex:1,overflow:`auto`},children:l}),c&&(0,S.jsx)(`div`,{className:`rcs-modal-footer`,children:c})]})})}function he(e){let{value:t,indeterminate:n=!1,variant:r=`linear`,size:i=`md`,tone:a=`neutral`,showValue:o=!1,className:s,style:c,id:l}=e,u=Math.max(0,Math.min(100,t));if(r===`circular`){let e=i===`lg`?24:i===`sm`?14:18,t=i===`lg`?3:2,n=2*Math.PI*e,r=u/100*n;return(0,S.jsx)(`span`,{id:l,className:y(`rcs-progress`,s),style:c,role:`progressbar`,"aria-valuenow":u,children:(0,S.jsxs)(`svg`,{width:e*2+t*2,height:e*2+t*2,children:[(0,S.jsx)(`circle`,{cx:e+t,cy:e+t,r:e,stroke:`var(--bg-3)`,strokeWidth:t,fill:`none`}),(0,S.jsx)(`circle`,{cx:e+t,cy:e+t,r:e,stroke:a===`danger`?`var(--danger)`:a===`warning`?`var(--warning)`:`var(--bg-inverse)`,strokeWidth:t,fill:`none`,strokeDasharray:`${r} ${n}`,strokeLinecap:`round`,transform:`rotate(-90 ${e+t} ${e+t})`,style:{transition:`stroke-dasharray 0.3s var(--ease-out-quart)`}})]})})}return(0,S.jsxs)(`div`,{id:l,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n?void 0:u,className:y(`rcs-progress`,`rcs-progress--${i}`,s),style:c,"data-tone":a,"data-indeterminate":n||void 0,children:[(0,S.jsx)(`div`,{className:`rcs-progress-track`,children:(0,S.jsx)(`div`,{className:`rcs-progress-fill`,style:{width:`${u}%`}})}),o&&(0,S.jsxs)(`div`,{className:`rcs-progress-value`,children:[Math.round(u),`%`]})]})}function ge(e){let{size:t=`md`,tone:n=`neutral`,label:r,className:i,style:a,id:o}=e;return(0,S.jsxs)(`span`,{id:o,className:y(`rcs-spin`,`rcs-spin--${t}`,i),style:a,"data-tone":n,role:`status`,children:[(0,S.jsx)(`span`,{className:`rcs-spin-glyph`,"aria-hidden":!0}),r&&(0,S.jsx)(`span`,{children:r})]})}var _e=[],ve=new Set;function ye(){for(let e of ve)e([..._e])}var be={show(e){let t=e.id??x(`toast`),n={...e,id:t};_e.push(n),ye();let r=e.duration??4e3;return r>0&&window.setTimeout(()=>be.dismiss(t),r),t},dismiss(e){let t=_e.findIndex(t=>t.id===e);t>=0&&(_e.splice(t,1)[0].onDismiss?.(),ye())},async promise(e,t){let n=be.show({severity:`info`,title:t.loading,duration:0});try{let r=await e;return be.dismiss(n),be.show({severity:`success`,title:t.success}),r}catch(e){throw be.dismiss(n),be.show({severity:`danger`,title:t.error}),e}}};function xe(){let[e,t]=C.useState([]);return C.useEffect(()=>(ve.add(t),()=>{ve.delete(t)}),[]),(0,S.jsx)(`div`,{className:`rcs-toast-region`,"aria-live":`polite`,"aria-atomic":`false`,children:e.map(e=>(0,S.jsxs)(`div`,{className:y(`rcs-toast`,`rcs-toast--${e.severity??`info`}`),role:`status`,children:[(0,S.jsx)(`span`,{className:`rcs-toast-icon`,"aria-hidden":!0,children:pe[e.severity??`info`]}),(0,S.jsxs)(`div`,{style:{flex:1},children:[(0,S.jsx)(`div`,{className:`rcs-toast-title`,children:e.title}),e.description&&(0,S.jsx)(`div`,{className:`rcs-toast-desc`,children:e.description})]}),e.action&&(0,S.jsx)(`button`,{className:`rcs-toast-action`,onClick:()=>{e.action.onClick(),be.dismiss(e.id)},children:e.action.label}),(0,S.jsx)(`button`,{className:`rcs-input-clear`,"aria-label":`Dismiss`,onClick:()=>be.dismiss(e.id),children:`×`})]},e.id))})}function Se(e){let{label:t,value:n,unit:r,delta:i,sparkline:a,className:o,style:s,id:c}=e;return(0,S.jsxs)(`div`,{id:c,className:y(`rcs-stat`,o),style:s,children:[(0,S.jsx)(`div`,{className:`rcs-stat-label`,children:t}),(0,S.jsxs)(`div`,{className:`rcs-stat-value`,children:[(0,S.jsx)(`span`,{children:n}),r&&(0,S.jsx)(`span`,{className:`rcs-stat-unit`,children:r})]}),i&&(0,S.jsxs)(`span`,{className:`rcs-stat-delta`,"data-tone":i.tone??`neutral`,children:[i.direction===`up`?`↑`:`↓`,i.value,`%`]}),a&&a.length>1&&(0,S.jsx)(Ce,{data:a})]})}function Ce({data:e}){let t=Math.min(...e),n=Math.max(...e)-t||1;return(0,S.jsx)(`svg`,{viewBox:`0 0 80 24`,className:`rcs-stat-spark`,preserveAspectRatio:`none`,children:(0,S.jsx)(`polyline`,{points:e.map((r,i)=>`${i/(e.length-1)*80},${24-(r-t)/n*24}`).join(` `),fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`})})}function we(e){let{title:t,subtitle:n,breadcrumbs:r,tabs:i,actions:a,badge:o,avatar:s,back:c,size:l=`md`,inlineSubtitle:u,backInline:d,className:f,style:p,id:m}=e,h=c&&!d,g=c&&d;return(0,S.jsxs)(`div`,{id:m,className:y(`rcs-page-header`,`rcs-page-header--${l}`,f),"data-inline-subtitle":u||void 0,"data-back-inline":d||void 0,style:p,children:[h&&(0,S.jsxs)(`button`,{type:`button`,className:`rcs-page-header-back`,onClick:c.onClick,children:[`← `,c.label??`Back`]}),r&&r.length>0&&(0,S.jsx)(`div`,{style:{marginBottom:8},children:(0,S.jsx)(fe,{items:r})}),(0,S.jsxs)(`div`,{className:`rcs-page-header-row`,children:[(0,S.jsxs)(`div`,{className:`rcs-page-header-title`,children:[g&&(0,S.jsx)(`button`,{type:`button`,"aria-label":c.label??`Back`,className:`rcs-page-header-back-inline`,onClick:c.onClick,children:`←`}),s,(0,S.jsxs)(`div`,{className:`rcs-page-header-title-text`,children:[(0,S.jsxs)(`h1`,{children:[t,o&&(0,S.jsx)(`span`,{style:{marginLeft:8},children:o})]}),n&&(0,S.jsx)(`div`,{className:`rcs-page-header-subtitle`,children:n})]})]}),a&&(0,S.jsx)(`div`,{className:`rcs-page-header-actions`,children:a})]}),i&&i.length>0&&(0,S.jsx)(`div`,{className:`rcs-page-header-tabs`,children:(0,S.jsx)(de,{items:i,variant:`line`})})]})}function Te(e){let{header:t,sidebar:n,footer:r,sidebarWidth:i=240,sidebarCollapsible:a,children:o,className:s,style:c,id:l}=e;return(0,S.jsxs)(`div`,{id:l,className:y(`rcs-app-shell`,s),style:{"--rcs-sidebar-w":`${i}px`,...c},children:[t&&(0,S.jsx)(`header`,{className:`rcs-app-shell-header`,children:t}),(0,S.jsxs)(`div`,{className:`rcs-app-shell-body`,"data-has-sidebar":!!n||void 0,children:[n&&(0,S.jsx)(`aside`,{className:`rcs-app-shell-sidebar`,children:n}),(0,S.jsx)(`main`,{className:`rcs-app-shell-main`,children:o})]}),r&&(0,S.jsx)(`footer`,{className:`rcs-app-shell-footer`,children:r})]})}var Ee=C.createContext(null),De={"signal-red":`#E60000`,"signal-red-700":`#9E0000`,"signal-red-900":`#520000`,"cod-gray":`#1C1C1C`,"cod-gray-700":`#2B2B2B`,"cod-gray-500":`#5A5A5A`,"cod-gray-300":`#A6A6A6`,"cod-gray-100":`#F5F5F5`,"cod-gray-050":`#FAFAFA`,white:`#FFFFFF`};function Oe(e){let{mode:t,accent:n,fontFamily:r,children:i}=e,[a,o]=C.useState(t??`light`),s=t??a;C.useEffect(()=>{typeof document>`u`||document.documentElement.setAttribute(`data-theme`,s)},[s]),C.useEffect(()=>{typeof document>`u`||!n||document.documentElement.style.setProperty(`--accent`,De[n])},[n]),C.useEffect(()=>{typeof document>`u`||!r||(r.sans&&document.documentElement.style.setProperty(`--font-sans`,r.sans),r.mono&&document.documentElement.style.setProperty(`--font-mono`,r.mono))},[r]);let c=C.useMemo(()=>({mode:s,setMode:e=>o(e),toggle:()=>o(e=>e===`light`?`dark`:`light`)}),[s]);return(0,S.jsx)(Ee.Provider,{value:c,children:i})}var ke=g(),Ae=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),je=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),Me={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},Ne=(0,C.forwardRef)(({color:e=`currentColor`,size:t=24,strokeWidth:n=2,absoluteStrokeWidth:r,className:i=``,children:a,iconNode:o,...s},c)=>(0,C.createElement)(`svg`,{ref:c,...Me,width:t,height:t,stroke:e,strokeWidth:r?Number(n)*24/Number(t):n,className:je(`lucide`,i),...s},[...o.map(([e,t])=>(0,C.createElement)(e,t)),...Array.isArray(a)?a:[a]])),Pe=(e,t)=>{let n=(0,C.forwardRef)(({className:n,...r},i)=>(0,C.createElement)(Ne,{ref:i,iconNode:t,className:je(`lucide-${Ae(e)}`,n),...r}));return n.displayName=`${e}`,n},Fe=Pe(`Check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]),Ie=Pe(`Copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),Le=Pe(`Moon`,[[`path`,{d:`M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z`,key:`a7tn18`}]]),Re=Pe(`Search`,[[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}],[`path`,{d:`m21 21-4.3-4.3`,key:`1qie3q`}]]),ze=Pe(`Sun`,[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]),Be=Pe(`X`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),Ve=`oc-theme`;function He(){let[e,t]=(0,C.useState)(()=>localStorage.getItem(Ve)??`dark`);return(0,C.useEffect)(()=>{document.documentElement.setAttribute(`data-theme`,e),localStorage.setItem(Ve,e)},[e]),{theme:e,toggle:()=>t(e=>e===`dark`?`light`:`dark`)}}function Ue(e){let[t,n]=(0,C.useState)(()=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(e).matches);return(0,C.useEffect)(()=>{if(typeof window>`u`||typeof window.matchMedia!=`function`)return;let t=window.matchMedia(e),r=()=>n(t.matches);return r(),t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}function We({wsConnected:e}){let{theme:t,toggle:n}=He(),r=Ue(`(max-width: 760px)`),[i,a]=(0,C.useState)(!1),o=typeof window<`u`?`${window.location.origin}/mcp`:`/mcp`,s=async()=>{typeof navigator>`u`||!navigator.clipboard||(await navigator.clipboard.writeText(o),a(!0),window.setTimeout(()=>a(!1),1500))},c=(0,S.jsx)(ee,{icon:t===`dark`?(0,S.jsx)(ze,{size:15}):(0,S.jsx)(Le,{size:15}),"aria-label":`Toggle theme`,variant:`ghost`,size:`sm`,shape:`circle`,onClick:n}),l=(0,S.jsx)(ne,{tone:e?`info`:`danger`,size:`sm`,children:e?`live`:`offline`}),u=(0,S.jsx)(w,{variant:`primary`,size:`sm`,iconLeft:i?(0,S.jsx)(Fe,{size:12}):(0,S.jsx)(Ie,{size:12}),onClick:s,children:i?`Copied`:`Copy MCP URL`});return r?(0,S.jsxs)(T,{justify:`between`,align:`center`,style:{display:`flex`,width:`100%`,padding:`0.5rem 0.75rem`},children:[(0,S.jsx)(`strong`,{children:`OtelContext`}),(0,S.jsxs)(T,{size:`xs`,align:`center`,children:[u,l,c]})]}):(0,S.jsxs)(T,{justify:`between`,align:`center`,style:{display:`flex`,width:`100%`,padding:`0.5rem 1rem`,gap:`0.75rem`},children:[(0,S.jsx)(T,{size:`md`,align:`center`,children:(0,S.jsx)(`strong`,{children:`OtelContext`})}),(0,S.jsx)(`div`,{style:{flex:1,minWidth:0,maxWidth:640},children:(0,S.jsx)(te,{value:o,readOnly:!0,type:`url`,size:`sm`,"aria-label":`MCP endpoint URL`})}),(0,S.jsxs)(T,{size:`sm`,align:`center`,children:[u,l,c]})]})}var A={fg1:`#1C1C1C`,fg2:`#3D3D3D`,fg3:`#5A5A5A`,fg4:`#A6A6A6`,bg1:`#FFFFFF`,bg2:`#FAFAFA`,bg3:`#F5F5F5`,border1:`#E5E5E5`,border2:`#D4D4D4`,accent:`#E60000`,accentSoft:`rgba(230,0,0,0.08)`,success:`#1F9E5C`,warning:`#D98E2B`,danger:`#E60000`,info:`#2D73D9`,series:[`#E60000`,`#1C1C1C`,`#5A5A5A`,`#2D73D9`,`#1F9E5C`,`#D98E2B`,`#9E0000`,`#A6A6A6`],fontSans:`Inter, system-ui, sans-serif`,fontMono:`'JetBrains Mono', monospace`,mode:`light`};function j(e,t){return typeof window>`u`?t:getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function Ge(){if(typeof window>`u`)return A;let e=document.documentElement.getAttribute(`data-theme`)??`light`,t=j(`--fg-1`,A.fg1),n=j(`--fg-2`,A.fg2),r=j(`--fg-3`,A.fg3),i=j(`--fg-4`,A.fg4),a=j(`--bg-1`,A.bg1),o=j(`--bg-2`,A.bg2),s=j(`--bg-3`,A.bg3),c=j(`--border-1`,A.border1),l=j(`--border-2`,A.border2),u=j(`--accent`,A.accent);return{fg1:t,fg2:n,fg3:r,fg4:i,bg1:a,bg2:o,bg3:s,border1:c,border2:l,accent:u,accentSoft:j(`--accent-soft`,A.accentSoft),success:j(`--success`,A.success),warning:j(`--warning`,A.warning),danger:j(`--danger`,A.danger),info:j(`--info`,A.info),series:e===`dark`?[u,`#F5F5F5`,`#A6A6A6`,`#5BA0F2`,`#3FBE83`,`#E5A65A`,`#FF6464`,`#7A7A7A`]:[u,`#1C1C1C`,`#5A5A5A`,`#2D73D9`,`#1F9E5C`,`#D98E2B`,`#9E0000`,`#A6A6A6`],fontSans:j(`--font-sans`,A.fontSans),fontMono:j(`--font-mono`,A.fontMono),mode:e}}function Ke(e){if(typeof window>`u`)return()=>{};let t=new MutationObserver(e);return t.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),()=>t.disconnect()}var qe=`modulepreload`,Je=function(e){return`/`+e},Ye={},Xe=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=Je(t,n),t in Ye)return;Ye[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:qe,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},Ze=null;function Qe(){if(typeof window>`u`)return{webgl2:!1,webgpu:!1,devicePixelRatio:1,maxTextureSize:0};if(Ze)return{...Ze,devicePixelRatio:window.devicePixelRatio||1,maxTextureSize:0};let e=!1,t=0;try{let n=document.createElement(`canvas`).getContext(`webgl2`);n&&(e=!0,t=n.getParameter(n.MAX_TEXTURE_SIZE))}catch{}let n=`gpu`in navigator&&typeof navigator.gpu==`object`;return Ze={webgl2:e,webgpu:n},{webgl2:e,webgpu:n,devicePixelRatio:window.devicePixelRatio||1,maxTextureSize:t}}function $e(e,t,n=5e4){let r=Qe();return e===`canvas`?`canvas`:e===`webgl`?r.webgl2?`webgl`:`canvas`:e===`webgpu`?r.webgpu?`webgpu`:r.webgl2?`webgl`:`canvas`:r.webgpu&&t>n?`webgpu`:r.webgl2&&t>n?`webgl`:`canvas`}var et=null;async function tt(){if(et)return et;try{let e=await Xe(()=>import(`./design-system-IOKLDoaG.js`),[]),t=await Xe(()=>import(`./design-system-DFjB0sSn.js`),[]);return et={Deck:e.Deck,SolidPolygonLayer:t.SolidPolygonLayer,ScatterplotLayer:t.ScatterplotLayer,LineLayer:t.LineLayer,ArcLayer:t.ArcLayer,PolygonLayer:t.PolygonLayer},et}catch(e){return console.warn(`[@ossrandom/design-system] WebGL renderer requested but @deck.gl/core not installed. Falling back to canvas. Run: pnpm add @deck.gl/core @deck.gl/layers`,e),null}}function nt(e,t=255){if(!e)return[0,0,0,t];if(e.startsWith(`rgb`)){let n=/rgba?\(([^)]+)\)/.exec(e);if(!n)return[0,0,0,t];let[r=0,i=0,a=0,o=1]=n[1].split(`,`).map(e=>parseFloat(e.trim()));return[r,i,a,Math.round(o*255)]}let n=e.replace(`#`,``);return n.length===3?[parseInt(n[0]+n[0],16),parseInt(n[1]+n[1],16),parseInt(n[2]+n[2],16),t]:n.length>=6?[parseInt(n.slice(0,2),16),parseInt(n.slice(2,4),16),parseInt(n.slice(4,6),16),n.length===8?parseInt(n.slice(6,8),16):t]:[0,0,0,t]}var rt=null;async function it(){if(rt)return rt.ctor;try{let e=await Xe(()=>import(`./cytoscape.esm-Dm6iss-N.js`),[]),t=e.default??e;try{let e=await Xe(()=>import(`./cytoscape-cose-bilkent-CEIBo6Gj.js`).then(e=>c(e.default,1)),[]);t.use(e.default??e)}catch{}return rt={ctor:t},t}catch(e){return console.warn(`[@ossrandom/design-system] cytoscape not installed:`,e),null}}function at(e,t){return t<=0?3:3+Math.sqrt(e)/Math.sqrt(t)*11}function ot(e,t){let n=new Map;for(let t of e)n.set(t.id,0);for(let e of t)n.set(e.source,(n.get(e.source)??0)+1),n.set(e.target,(n.get(e.target)??0)+1);let r=0;for(let e of n.values())e>r&&(r=e);return{degrees:n,max:r}}async function st(e,t,n,r){let{degrees:i}=ot(e,t);if(e.every(e=>e.x!==void 0&&e.y!==void 0))return e.map(e=>({...e,x:e.x,y:e.y,degree:i.get(e.id)??0}));try{let a=await Xe(()=>import(`./design-system-BNhP-Tae.js`),[]),o=e.map(e=>({...e,x:n/2+(Math.random()-.5)*100,y:r/2+(Math.random()-.5)*100,degree:i.get(e.id)??0})),s=a.forceSimulation(o).force(`link`,a.forceLink(t.map(e=>({source:e.source,target:e.target}))).id(e=>e.id).distance(60)).force(`charge`,a.forceManyBody().strength(-300)).force(`center`,a.forceCenter(n/2,r/2)).force(`collide`,a.forceCollide(14)).stop();for(let e=0;e<200;e++)s.tick();return o}catch{let t=Math.ceil(Math.sqrt(e.length)),a=n/t,o=r/Math.ceil(e.length/t);return e.map((e,n)=>({...e,x:n%t*a+a/2,y:Math.floor(n/t)*o+o/2,degree:i.get(e.id)??0}))}}function ct(e){let{nodes:t,edges:n,height:r=480,layout:i=`cose-bilkent`,engine:a=`auto`,onNodeClick:o,onEdgeClick:s,className:c,style:l,id:u}=e,d=C.useRef(null),f=C.useRef(null),p=C.useRef(null),[m,h]=C.useState(0),[g,_]=C.useState(`canvas`);return C.useEffect(()=>{_($e(a,t.length+n.length,500))},[a,t.length,n.length]),C.useEffect(()=>{if(!d.current)return;let e=new ResizeObserver(e=>{let t=Math.floor(e[0].contentRect.width);t>0&&t!==m&&h(t)});return e.observe(d.current),()=>e.disconnect()},[m]),C.useEffect(()=>{if(g!==`canvas`||!d.current)return;let e=!1,r=d.current;return it().then(a=>{if(!a||e){a||(r.innerHTML=`
Service map (canvas) requires cytoscape. Run: pnpm add cytoscape cytoscape-cose-bilkent
`);return}let c=Ge(),{degrees:l,max:u}=ot(t,n),d=a({container:r,elements:[...t.map(e=>{let t=l.get(e.id)??0,n=at(t,u);return{data:{id:e.id,label:e.label,status:e.status,kind:e.kind,degree:t,diameter:Math.round(n*2)}}}),...n.map(e=>({data:{id:`${e.source}->${e.target}`,source:e.source,target:e.target,label:e.label,status:e.status}}))],style:lt(c),layout:{name:i,animate:!1,fit:!0,padding:24,nodeRepulsion:6e3,idealEdgeLength:80},wheelSensitivity:.2,minZoom:.2,maxZoom:3});o&&d.on(`tap`,`node`,e=>o(e.target.data())),s&&d.on(`tap`,`edge`,e=>s(e.target.data()));let p=e=>{let t=e.isNode?.()??!0;if(d.elements().addClass(`rcs-dim`),t){let t=e.connectedEdges?.(),n=e.connectedNodes?.();n?.removeClass(`rcs-dim`),t?.removeClass(`rcs-dim`),d.$(`#${ut(e.id())}`).removeClass(`rcs-dim`),d.$(`#${ut(e.id())}`).addClass(`rcs-focus`),t?.addClass(`rcs-focus-edge`),n?.addClass(`rcs-neighbor`)}else{let t=e.connectedNodes?.();t?.removeClass(`rcs-dim`),t?.addClass(`rcs-neighbor`)}},m=()=>{d.elements().removeClass(`rcs-dim rcs-focus rcs-focus-edge rcs-neighbor`)};d.on(`mouseover`,`node`,e=>p(e.target)),d.on(`mouseover`,`edge`,e=>p(e.target)),d.on(`mouseout`,`node`,()=>m()),d.on(`mouseout`,`edge`,()=>m()),d.on(`tap`,`node`,e=>p(e.target)),d.on(`tap`,`edge`,e=>p(e.target));let h=d.container();h&&h.addEventListener(`pointerleave`,m),f.current=d}),()=>{e=!0,f.current?.destroy(),f.current=null,r.innerHTML=``}},[g,t,n,i,o,s]),C.useEffect(()=>{if(g===`canvas`||m===0||!d.current)return;let e=!1,i=d.current;return(async()=>{let a=await tt();if(!a||e){_(`canvas`);return}let c=await st(t,n,m,r);if(e)return;let l=new Map(c.map((e,t)=>[e.id,t])),u=Ge(),d=c.reduce((e,t)=>Math.max(e,t.degree),0),f=g===`webgpu`?`webgpu`:`webgl`,h=a.ScatterplotLayer,v=a.ArcLayer,y=new Map,b=new Map;for(let e of c)y.set(e.id,new Set),b.set(e.id,new Set);for(let e of n){let t=`${e.source}->${e.target}`;y.get(e.source)?.add(e.target),y.get(e.target)?.add(e.source),b.get(e.source)?.add(t),b.get(e.target)?.add(t)}let x=null,S=e=>!x||e===x?!0:y.get(x)?.has(e)??!1,C=e=>x?e.source===x||e.target===x:!0,w=(e,t)=>[e[0],e[1],e[2],t],ee=()=>[new v({id:`service-edges`,data:n.map(e=>({...e,sourcePos:c[l.get(e.source)??0],targetPos:c[l.get(e.target)??0]})),getSourcePosition:e=>[e.sourcePos.x,e.sourcePos.y,0],getTargetPosition:e=>[e.targetPos.x,e.targetPos.y,0],getSourceColor:e=>{let t=C(e);return w(nt(t&&x?u.accent:e.status===`failing`?u.danger:u.border2),t?255:60)},getTargetColor:e=>{let t=C(e);return w(nt(t&&x?u.accent:e.status===`failing`?u.danger:u.fg4),t?255:60)},getWidth:e=>C(e)&&x||e.status===`failing`?2:1,getHeight:.3,pickable:!!s,updateTriggers:{getSourceColor:[x],getTargetColor:[x],getWidth:[x]}}),new h({id:`service-nodes`,data:c,getPosition:e=>[e.x,e.y,0],getFillColor:e=>{let t=S(e.id);return w(nt(e.status===`failing`?u.danger:e.status===`degraded`?u.warning:e.status===`healthy`?u.success:u.fg3),t?230:60)},getLineColor:e=>x===e.id?nt(u.accent):nt(u.bg1),getRadius:e=>at(e.degree,d),radiusUnits:`pixels`,stroked:!0,getLineWidth:e=>x===e.id?2:1,lineWidthUnits:`pixels`,pickable:!0,updateTriggers:{getFillColor:[x],getLineColor:[x],getLineWidth:[x]}})],te=new a.Deck({parent:i,width:m,height:r,controller:!0,deviceProps:{type:f},views:[{"@@type":`OrthographicView`,id:`v`,flipY:!0}],viewState:{target:[m/2,r/2,0],zoom:0},layers:ee(),onHover:({object:e,layer:t})=>{let n=null;e&&t?.id===`service-nodes`?n=e.id:e&&t?.id===`service-edges`&&(n=e.source),n!==x&&(x=n,te.setProps({layers:ee()}))},onClick:({object:e,layer:t})=>{!e||!t||(t.id===`service-nodes`&&o?o(e):t.id===`service-edges`&&s&&s(e))}});p.current=te})().catch(e=>{console.warn(`[@ossrandom/design-system] ServiceMap WebGL init failed; falling back to canvas:`,e),_(`canvas`)}),()=>{e=!0,p.current?.destroy(),p.current=null,i.innerHTML=``}},[g,m,r,t,n,o,s]),C.useEffect(()=>Ke(()=>{_(e=>e)}),[]),(0,S.jsx)(`div`,{ref:d,id:u,className:y(`rcs-service-map`,`rcs-service-map--${g}`,c),style:{position:`relative`,width:`100%`,height:r,...l},"data-engine":g,role:`img`,"aria-label":e[`aria-label`]??`Service map with ${t.length} services`,children:(0,S.jsx)(`div`,{className:`rcs-service-map-engine-badge`,"aria-hidden":`true`,children:g})})}function lt(e){return[{selector:`node`,style:{shape:`ellipse`,width:`data(diameter)`,height:`data(diameter)`,"background-color":e.fg3,"border-color":e.bg1,"border-width":1,label:`data(label)`,color:e.fg3,"font-family":e.fontSans,"font-size":11,"font-weight":400,"text-valign":`bottom`,"text-halign":`center`,"text-margin-y":4,"text-events":`no`,"min-zoomed-font-size":9,"z-index":10,"transition-property":`background-color, border-color, border-width, color, opacity`,"transition-duration":`120ms`}},{selector:`node[status = 'healthy']`,style:{"background-color":e.success}},{selector:`node[status = 'degraded']`,style:{"background-color":e.warning}},{selector:`node[status = 'failing']`,style:{"background-color":e.danger}},{selector:`edge`,style:{width:1,"line-color":e.border2,"target-arrow-color":e.border2,"target-arrow-shape":`triangle`,"arrow-scale":.9,"curve-style":`bezier`,label:`data(label)`,color:e.fg4,"font-family":e.fontMono,"font-size":9,"text-rotation":`autorotate`,"text-margin-y":-4,"text-opacity":0,"text-events":`no`,"z-index":1,"transition-property":`line-color, width, target-arrow-color, opacity, text-opacity`,"transition-duration":`120ms`}},{selector:`edge[status = 'failing']`,style:{"line-color":e.danger,"target-arrow-color":e.danger,width:1.5}},{selector:`.rcs-dim`,style:{opacity:.18}},{selector:`node.rcs-focus`,style:{opacity:1,"border-color":e.accent,"border-width":2,color:e.fg1,"font-weight":500,"z-index":30}},{selector:`node.rcs-neighbor`,style:{opacity:1,color:e.fg1,"z-index":20}},{selector:`edge.rcs-focus-edge`,style:{opacity:1,"line-color":e.accent,"target-arrow-color":e.accent,width:2,"text-opacity":1,color:e.fg1,"z-index":25}},{selector:`node:selected`,style:{"border-color":e.accent,"border-width":2}}]}function ut(e){return typeof CSS<`u`&&typeof CSS.escape==`function`?CSS.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,e=>`\\${e}`)}function dt(e){return e===`healthy`?`info`:e===`degraded`?`warning`:e===`critical`||e===`failing`?`danger`:`neutral`}var ft=C.memo(({node:e,edges:t,onClose:n,onSelectService:r})=>{let i=t.filter(t=>t.target===e.id),a=t.filter(t=>t.source===e.id),o=e.metrics.error_rate*100;return(0,S.jsxs)(T,{direction:`vertical`,size:`md`,children:[(0,S.jsx)(ce,{bordered:!0,padding:`md`,radius:`md`,title:(0,S.jsxs)(T,{size:`xs`,align:`center`,children:[(0,S.jsx)(`code`,{children:e.id}),(0,S.jsx)(ne,{tone:dt(e.status),size:`sm`,children:e.status})]}),extra:(0,S.jsx)(ee,{icon:(0,S.jsx)(Be,{size:13}),"aria-label":`Close`,variant:`ghost`,size:`sm`,onClick:n}),children:(0,S.jsxs)(ue,{columns:2,gap:`sm`,children:[(0,S.jsx)(ue.Col,{span:1,children:(0,S.jsx)(Se,{label:`RPS`,value:Math.round(e.metrics.request_rate_rps)})}),(0,S.jsx)(ue.Col,{span:1,children:(0,S.jsx)(Se,{label:`Error Rate`,value:o.toFixed(2),unit:`%`})}),(0,S.jsx)(ue.Col,{span:1,children:(0,S.jsx)(Se,{label:`Avg Latency`,value:e.metrics.avg_latency_ms,unit:`ms`})}),(0,S.jsx)(ue.Col,{span:1,children:(0,S.jsx)(Se,{label:`P99`,value:e.metrics.p99_latency_ms,unit:`ms`})})]})}),(0,S.jsx)(ce,{bordered:!0,padding:`md`,radius:`md`,title:`Health Score`,extra:(0,S.jsx)(ne,{tone:`subtle`,size:`sm`,children:e.health_score.toFixed(2)}),children:(0,S.jsx)(he,{value:e.health_score*100,tone:e.health_score<.4?`danger`:e.health_score<.7?`warning`:`neutral`})}),i.length>0&&(0,S.jsx)(ce,{bordered:!0,padding:`md`,radius:`md`,title:`Upstream`,children:(0,S.jsx)(T,{direction:`vertical`,size:`xs`,children:i.map(e=>(0,S.jsx)(w,{variant:`ghost`,size:`sm`,block:!0,onClick:()=>r(e.source),children:(0,S.jsxs)(T,{justify:`between`,align:`center`,children:[(0,S.jsx)(`code`,{children:e.source}),(0,S.jsxs)(ne,{tone:`subtle`,size:`sm`,children:[e.call_count,` calls`]})]})},e.source))})}),a.length>0&&(0,S.jsx)(ce,{bordered:!0,padding:`md`,radius:`md`,title:`Downstream`,children:(0,S.jsx)(T,{direction:`vertical`,size:`xs`,children:a.map(e=>(0,S.jsx)(w,{variant:`ghost`,size:`sm`,block:!0,onClick:()=>r(e.target),children:(0,S.jsxs)(T,{justify:`between`,align:`center`,children:[(0,S.jsx)(`code`,{children:e.target}),(0,S.jsxs)(ne,{tone:`subtle`,size:`sm`,children:[e.call_count,` calls`]})]})},e.target))})}),e.alerts.length>0&&(0,S.jsx)(T,{direction:`vertical`,size:`xs`,children:e.alerts.map((e,t)=>(0,S.jsx)(O,{severity:`danger`,children:e},t))})]})}),pt=C.memo(({items:e})=>(0,S.jsx)(ce,{bordered:!0,padding:`md`,radius:`md`,children:(0,S.jsx)(T,{size:`lg`,wrap:!0,children:e.map((e,t)=>(0,S.jsxs)(C.Fragment,{children:[t>0&&(0,S.jsx)(le,{direction:`vertical`}),(0,S.jsx)(Se,{...e})]},`${t}-${String(e.label)}`))})}));function mt(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:String(Math.round(e*10)/10)}function ht(e=800){let[t,n]=(0,C.useState)(()=>typeof window>`u`?e:window.innerHeight);return(0,C.useEffect)(()=>{if(typeof window>`u`)return;let e=()=>n(window.innerHeight);return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),t}function gt(e){return e===`healthy`||e===`degraded`?e:e===`critical`||e===`failing`?`failing`:`unknown`}function _t(e){return e===`critical`||e===`failing`?`failing`:`healthy`}var vt=C.memo(({graph:e,loading:t,error:n,dashboard:r,stats:i})=>{let[a,o]=(0,C.useState)(null),[s,c]=(0,C.useState)(``),l=Ue(`(max-width: 760px)`),u=ht(),d=l?460:Math.max(460,u-320),f=e?.nodes??[],p=e?.edges??[],m=(0,C.useMemo)(()=>{let e=s.trim().toLowerCase();return f.filter(t=>!e||t.id.toLowerCase().includes(e)).map(e=>({id:e.id,label:e.id,status:gt(e.status)}))},[f,s]),h=(0,C.useMemo)(()=>{if(m.length===0)return[];let e=new Set(m.map(e=>e.id));return p.filter(t=>e.has(t.source)&&e.has(t.target)).slice(0,500).map(e=>({source:e.source,target:e.target,status:_t(e.status)}))},[p,m]),g=r?.active_services??f.length,_=r?.error_rate??0,v=i,y=e=>{if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``&&Number.isFinite(Number(e)))return Number(e)},b=y(v?.TraceCount)??y(v?.traceCount)??r?.total_traces??0,x=y(v?.LogCount)??y(v?.logCount)??r?.total_logs??0,w=y(v?.DBSizeMB)??y(v?.db_size_mb),ee=e=>{o(f.find(t=>t.id===e.id)??null)},ne=e=>{let t=f.find(t=>t.id===e);t&&o(t)};return(0,S.jsxs)(T,{direction:`vertical`,size:`md`,style:{display:`flex`,width:`100%`},children:[(0,S.jsx)(we,{size:`sm`,title:`Service Topology`,subtitle:`Live dependency map · click a node for details`,inlineSubtitle:!0}),(0,S.jsx)(pt,{items:[{label:`Services`,value:g},{label:`Error rate`,value:_.toFixed(2),unit:`%`},{label:`Traces`,value:mt(b)},{label:`Logs`,value:mt(x)},...w!=null&&Number.isFinite(w)?[{label:`DB`,value:w.toFixed(0),unit:`MB`}]:[]]}),(0,S.jsxs)(ce,{bordered:!0,padding:`sm`,radius:`md`,extra:(0,S.jsx)(te,{value:s,onChange:e=>c(e),placeholder:`Filter services`,size:`sm`,prefix:(0,S.jsx)(Re,{size:12})}),children:[t&&(0,S.jsx)(ge,{label:`Loading service map`}),n&&(0,S.jsx)(O,{severity:`danger`,title:`Service map failed to load`,children:n}),!t&&!n&&f.length===0&&(0,S.jsx)(O,{severity:`info`,children:`No services discovered yet.`}),!t&&!n&&m.length===0&&f.length>0&&(0,S.jsx)(O,{severity:`info`,children:`No services match the filter.`}),!t&&!n&&m.length>0&&(0,S.jsx)(ct,{nodes:m,edges:h,layout:`cose-bilkent`,height:d,onNodeClick:ee})]}),(0,S.jsx)(me,{open:a!==null,onClose:()=>o(null),placement:`right`,width:l?`92vw`:420,title:a?(0,S.jsx)(`code`,{children:a.id}):void 0,description:`Service detail · upstream, downstream, alerts`,children:a&&(0,S.jsx)(ft,{node:a,edges:p,onClose:()=>o(null),onSelectService:ne})})]})});function yt(e=6e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(``),[a,o]=(0,C.useState)(!0),[s,c]=(0,C.useState)(null),l=(0,C.useRef)(void 0),u=(0,C.useCallback)(async()=>{try{let e=await fetch(`/api/system/graph`);if(!e.ok)throw Error(`HTTP ${e.status}`);i(e.headers.get(`X-Cache`)??``),n(await e.json()),c(null)}catch(e){c(e instanceof Error?e.message:`fetch failed`)}finally{o(!1)}},[]);return(0,C.useEffect)(()=>(u(),l.current=setInterval(u,e),()=>clearInterval(l.current)),[u,e]),{graph:t,cache:r,loading:a,error:s,reload:u}}function bt(e=3e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(null),[a,o]=(0,C.useState)(!0),[s,c]=(0,C.useState)(null),l=(0,C.useRef)(void 0),u=(0,C.useCallback)(async()=>{try{let[e,t]=await Promise.all([fetch(`/api/metrics/dashboard`),fetch(`/api/stats`)]);if(!e.ok||!t.ok)throw Error(`fetch failed`);n(await e.json()),i(await t.json()),c(null)}catch(e){c(e instanceof Error?e.message:`fetch failed`)}finally{o(!1)}},[]);return(0,C.useEffect)(()=>(u(),l.current=setInterval(u,e),()=>clearInterval(l.current)),[u,e]),{dashboard:t,stats:r,loading:a,error:s,reload:u}}var xt=100,St=1e4,Ct=3e4,wt=35e3;function Tt(e){let t=(0,C.useRef)(null),n=(0,C.useRef)(e),[r,i]=(0,C.useState)(`connecting`);t.status=r;let a=(0,C.useRef)(0),o=(0,C.useRef)(null),s=(0,C.useRef)(null),c=(0,C.useRef)(null),l=(0,C.useRef)(!1),u=(0,C.useRef)(()=>{});(0,C.useEffect)(()=>{n.current=e},[e]);let d=(0,C.useCallback)(()=>{o.current!==null&&(window.clearTimeout(o.current),o.current=null)},[]),f=(0,C.useCallback)(()=>{s.current!==null&&(window.clearInterval(s.current),s.current=null),c.current!==null&&(window.clearTimeout(c.current),c.current=null)},[]),p=(0,C.useCallback)(()=>{if(l.current)return;d();let e=a.current,t=Math.min(xt*2**e,St);a.current=e+1,i(`reconnecting`),o.current=window.setTimeout(()=>{o.current=null,u.current()},t)},[d]),m=(0,C.useCallback)(()=>{f(),s.current=window.setInterval(()=>{let e=t.current;if(!(!e||e.readyState!==WebSocket.OPEN)){try{e.send(JSON.stringify({type:`ping`}))}catch{return}c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>{c.current=null;let e=t.current;if(e)try{e.close()}catch{}},wt)}},Ct)},[f]),h=(0,C.useCallback)(()=>{if(l.current)return;d(),f();let e=t.current;if(e){e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null;try{e.close()}catch{}t.current=null}i(a.current===0?`connecting`:`reconnecting`);let r=window.location.protocol===`https:`?`wss:`:`ws:`,o;try{o=new WebSocket(`${r}//${window.location.host}/ws`)}catch{p();return}t.current=o,o.onopen=()=>{l.current||(a.current=0,i(`connected`),m())},o.onmessage=e=>{c.current!==null&&(window.clearTimeout(c.current),c.current=null);try{let t=JSON.parse(e.data);t.type===`logs`&&Array.isArray(t.data)&&n.current(t.data)}catch{}},o.onerror=()=>{},o.onclose=()=>{l.current||(t.current===o&&(t.current=null),f(),i(`disconnected`),p())}},[f,d,p,m]);return(0,C.useEffect)(()=>{u.current=h},[h]),(0,C.useEffect)(()=>{l.current=!1,u.current=h,h();let e=()=>{if(document.visibilityState!==`visible`)return;let e=t.current;(!e||e.readyState===WebSocket.CLOSED||e.readyState===WebSocket.CLOSING)&&(a.current=0,d(),u.current())},n=()=>{a.current=0,d(),u.current()};return document.addEventListener(`visibilitychange`,e),window.addEventListener(`online`,n),()=>{l.current=!0,document.removeEventListener(`visibilitychange`,e),window.removeEventListener(`online`,n),d(),f();let r=t.current;if(r){r.onopen=null,r.onmessage=null,r.onerror=null,r.onclose=null;try{r.close()}catch{}t.current=null}}},[]),t}function Et(){let[e,t]=(0,C.useState)(`services`),n=yt(),r=bt();return(0,S.jsx)(Te,{header:(0,S.jsx)(We,{view:e,onNavigate:t,wsConnected:!!Tt(()=>void 0).current}),children:(0,S.jsx)(vt,{graph:n.graph,loading:n.loading,error:n.error,dashboard:r.dashboard,stats:r.stats})})}(0,ke.createRoot)(document.getElementById(`root`)).render((0,S.jsx)(C.StrictMode,{children:(0,S.jsxs)(Oe,{mode:`dark`,children:[(0,S.jsx)(Et,{}),(0,S.jsx)(xe,{})]})}));export{o as t}; \ No newline at end of file diff --git a/internal/ui/dist/assets/index-D7nwP4LR.js b/internal/ui/dist/assets/index-D7nwP4LR.js new file mode 100644 index 0000000..32c9ba7 --- /dev/null +++ b/internal/ui/dist/assets/index-D7nwP4LR.js @@ -0,0 +1,10 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ServicesView-n3l2yFxx.js","assets/useMediaQuery-D3Mg-H7H.js","assets/inputs-DxVBbFvb.js","assets/MCPConsoleView-BXQJGMyT.js"])))=>i.map(i=>d[i]); +import{C as e,M as t,N as n,O as r,P as i,S as a,T as o,a as s,b as c,c as l,g as u,h as d,i as f,j as p,k as m,l as h,m as g,n as _,o as v,r as y,s as b,t as x,u as ee,w as te,x as ne,y as re}from"./useMediaQuery-D3Mg-H7H.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var ie=n((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,ee||(ee=!0,oe());else{var t=n(l);t!==null&&le(x,t.startTime-e)}}var ee=!1,te=-1,ne=5,re=-1;function ie(){return g?!0:!(e.unstable_now()-ret&&ie());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&le(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?oe():ee=!1}}}var oe;if(typeof y==`function`)oe=function(){y(ae)};else if(typeof MessageChannel<`u`){var se=new MessageChannel,ce=se.port2;se.port1.onmessage=ae,oe=function(){ce.postMessage(null)}}else oe=function(){_(ae,0)};function le(t,n){te=_(function(){t(e.unstable_now())},n)}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(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(te),te=-1):h=!0,le(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,oe()))),r},e.unstable_shouldYield=ie,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),ae=n(((e,t)=>{t.exports=ie()})),oe=n((e=>{var n=t();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=oe()})),ce=n((e=>{var n=ae(),r=t(),i=se();function a(e){var t=`https://react.dev/errors/`+e;if(1me||(e.current=pe[me],pe[me]=null,me--)}function D(e,t){me++,pe[me]=e.current,e.current=t}var ge=he(null),_e=he(null),ve=he(null),ye=he(null);function be(e,t){switch(D(ve,t),D(_e,e),D(ge,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}E(ge),D(ge,e)}function xe(){E(ge),E(_e),E(ve)}function Se(e){e.memoizedState!==null&&D(ye,e);var t=ge.current,n=Hd(t,e.type);t!==n&&(D(_e,e),D(ge,n))}function Ce(e){_e.current===e&&(E(ge),E(_e)),ye.current===e&&(E(ye),Qf._currentValue=fe)}var we,Te;function Ee(e){if(we===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);we=t&&t[1]||``,Te=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{De=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Ee(n):``}function ke(e,t){switch(e.tag){case 26:case 27:case 5:return Ee(e.type);case 16:return Ee(`Lazy`);case 13:return e.child!==t&&t!==null?Ee(`Suspense Fallback`):Ee(`Suspense`);case 19:return Ee(`SuspenseList`);case 0:case 15:return Oe(e.type,!1);case 11:return Oe(e.type.render,!1);case 1:return Oe(e.type,!0);case 31:return Ee(`Activity`);default:return``}}function Ae(e){try{var t=``,n=null;do t+=ke(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var je=Object.prototype.hasOwnProperty,Me=n.unstable_scheduleCallback,Ne=n.unstable_cancelCallback,Pe=n.unstable_shouldYield,Fe=n.unstable_requestPaint,Ie=n.unstable_now,Le=n.unstable_getCurrentPriorityLevel,Re=n.unstable_ImmediatePriority,ze=n.unstable_UserBlockingPriority,Be=n.unstable_NormalPriority,Ve=n.unstable_LowPriority,He=n.unstable_IdlePriority,Ue=n.log,We=n.unstable_setDisableYieldValue,Ge=null,Ke=null;function qe(e){if(typeof Ue==`function`&&We(e),Ke&&typeof Ke.setStrictMode==`function`)try{Ke.setStrictMode(Ge,e)}catch{}}var Je=Math.clz32?Math.clz32:Ze,Ye=Math.log,Xe=Math.LN2;function Ze(e){return e>>>=0,e===0?32:31-(Ye(e)/Xe|0)|0}var Qe=256,$e=262144,et=4194304;function tt(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function nt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=tt(n))):i=tt(o):i=tt(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=tt(n))):i=tt(o)):i=tt(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function rt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function it(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function at(){var e=et;return et<<=1,!(et&62914560)&&(et=4194304),e}function ot(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function st(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function ct(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),bn=!1;if(yn)try{var xn={};Object.defineProperty(xn,`passive`,{get:function(){bn=!0}}),window.addEventListener(`test`,xn,xn),window.removeEventListener(`test`,xn,xn)}catch{bn=!1}var Sn=null,Cn=null,wn=null;function Tn(){if(wn)return wn;var e,t=Cn,n=t.length,r,i=`value`in Sn?Sn.value:Sn.textContent,a=i.length;for(e=0;e=rr),or=` `,sr=!1;function cr(e,t){switch(e){case`keyup`:return tr.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function lr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var ur=!1;function dr(e,t){switch(e){case`compositionend`:return lr(t);case`keypress`:return t.which===32?(sr=!0,or):null;case`textInput`:return e=t.data,e===or&&sr?null:e;default:return null}}function fr(e,t){if(ur)return e===`compositionend`||!nr&&cr(e,t)?(e=Tn(),wn=Cn=Sn=null,ur=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Pr(n)}}function Ir(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Ir(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Lr(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Kt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Kt(e.document)}return t}function Rr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var zr=yn&&`documentMode`in document&&11>=document.documentMode,Br=null,Vr=null,Hr=null,Ur=!1;function Wr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Ur||Br==null||Br!==Kt(r)||(r=Br,`selectionStart`in r&&Rr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Hr&&Nr(Hr,r)||(Hr=r,r=Ed(Vr,`onSelect`),0>=o,i-=o,Ii=1<<32-Je(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),A&&Ri(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),A&&Ri(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return A&&Ri(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),A&&Ri(i,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===_&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case h:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===_){if(r.tag===7){n(e,r.sibling),c=i(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===ie&&Ia(l)===r.type){n(e,r.sibling),c=i(r,o.props),Ua(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===_?(c=Ci(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=Si(o.type,o.key,o.props,null,e.mode,c),Ua(c,o),c.return=e,e=c)}return s(e);case g:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=i(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=Ei(o,e.mode,c),c.return=e,e=c}return s(e);case ie:return o=Ia(o),b(e,r,o,c)}if(de(o))return v(e,r,o,c);if(S(o)){if(l=S(o),typeof l!=`function`)throw Error(a(150));return o=l.call(o),y(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,Ha(o),c);if(o.$$typeof===x)return b(e,r,da(e,o),c);Wa(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,o),c.return=e,e=c):(n(e,r),c=wi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Va=0;var i=b(e,t,n,r);return Ba=null,i}catch(t){if(t===Aa||t===Ma)throw t;var a=vi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ka=Ga(!0),qa=Ga(!1),Ja=!1;function Ya(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Xa(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Za(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Qa(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=hi(e),mi(e,null,n),t}return di(e,r,t,n),hi(e)}function $a(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ut(e,n)}}function eo(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var to=!1;function no(){if(to){var e=xa;if(e!==null)throw e}}function ro(e,t,n,r){to=!1;var i=e.updateQueue;Ja=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,m=f!==s.lane;if(m?(q&f)===f:(r&f)===f){f!==0&&f===ba&&(to=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,f);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,f=typeof h==`function`?h.call(_,d,f):h,f==null)break a;d=p({},d,f);break a;case 2:Ja=!0}}f=s.callback,f!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[f]:m.push(f))}else m={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function io(e,t){if(typeof e!=`function`)throw Error(a(191,e));e.call(t)}function ao(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=w.T,s={};w.T=s,Bs(e,!1,t,n);try{var c=i(),l=w.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?zs(e,t,wa(c,r),pu(e)):zs(e,t,r,pu(e))}catch(n){zs(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{T.p=a,o!==null&&s.types!==null&&(o.types=s.types),w.T=o}}function ks(){}function As(e,t,n,r){if(e.tag!==5)throw Error(a(476));var i=js(e).queue;Os(e,i,t,fe,n===null?ks:function(){return Ms(e),n(r)})}function js(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:fe,baseState:fe,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vo,lastRenderedState:fe},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Ms(e){var t=js(e);t.next===null&&(t=e.alternate.memoizedState),zs(e,t.next.queue,{},pu())}function Ns(){return ua(Qf)}function Ps(){return L().memoizedState}function Fs(){return L().memoizedState}function Is(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Za(n);var r=Qa(t,e,n);r!==null&&(hu(r,t,n),$a(r,t,n)),t={cache:ga()},e.payload=t;return}t=t.return}}function Ls(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Vs(e)?Hs(t,n):(n=fi(e,t,n,r),n!==null&&(hu(n,e,r),Us(n,t,r)))}function Rs(e,t,n){zs(e,t,n,pu())}function zs(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Vs(e))Hs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Mr(s,o))return di(e,t,i,0),G===null&&ui(),!1}catch{}if(n=fi(e,t,i,r),n!==null)return hu(n,e,r),Us(n,t,r),!0}return!1}function Bs(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Vs(e)){if(t)throw Error(a(479))}else t=fi(e,n,r,2),t!==null&&hu(t,e,2)}function Vs(e){var t=e.alternate;return e===N||t!==null&&t===N}function Hs(e,t){So=xo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Us(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ut(e,n)}}var Ws={readContext:ua,use:zo,useCallback:I,useContext:I,useEffect:I,useImperativeHandle:I,useLayoutEffect:I,useInsertionEffect:I,useMemo:I,useReducer:I,useRef:I,useState:I,useDebugValue:I,useDeferredValue:I,useTransition:I,useSyncExternalStore:I,useId:I,useHostTransitionStatus:I,useFormState:I,useActionState:I,useOptimistic:I,useMemoCache:I,useCacheRefresh:I};Ws.useEffectEvent=I;var Gs={readContext:ua,use:zo,useCallback:function(e,t){return Io().memoizedState=[e,t===void 0?null:t],e},useContext:ua,useEffect:hs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ps(4194308,4,xs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ps(4194308,4,e,t)},useInsertionEffect:function(e,t){ps(4,2,e,t)},useMemo:function(e,t){var n=Io();t=t===void 0?null:t;var r=e();if(Co){qe(!0);try{e()}finally{qe(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Io();if(n!==void 0){var i=n(t);if(Co){qe(!0);try{n(t)}finally{qe(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ls.bind(null,N,e),[r.memoizedState,e]},useRef:function(e){var t=Io();return e={current:e},t.memoizedState=e},useState:function(e){e=Zo(e);var t=e.queue,n=Rs.bind(null,N,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Cs,useDeferredValue:function(e,t){return Es(Io(),e,t)},useTransition:function(){var e=Zo(!1);return e=Os.bind(null,N,e.queue,!0,!1),Io().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=N,i=Io();if(A){if(n===void 0)throw Error(a(407));n=n()}else{if(n=t(),G===null)throw Error(a(349));q&127||Ko(r,t,n)}i.memoizedState=n;var o={value:n,getSnapshot:t};return i.queue=o,hs(Jo.bind(null,r,o,e),[e]),r.flags|=2048,ds(9,{destroy:void 0},qo.bind(null,r,o,n,t),null),n},useId:function(){var e=Io(),t=G.identifierPrefix;if(A){var n=Li,r=Ii;n=(r&~(1<<32-Je(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=wo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(i,{is:r.is}):s.createElement(i)}}o[_t]=t,o[vt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Pd(o,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Lc(t)}}return B(t),Rc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Lc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(a(166));if(e=ve.current,Xi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Ui,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[_t]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||qi(t,!0)}else e=Bd(e).createTextNode(r),e[_t]=t,t.stateNode=e}return B(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Xi(t),n!==null){if(e===null){if(!r)throw Error(a(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(a(557));e[_t]=t}else Zi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),e=!1}else n=Qi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(vo(t),t):(vo(t),null);if(t.flags&128)throw Error(a(558))}return B(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Xi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(a(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(a(317));i[_t]=t}else Zi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),i=!1}else i=Qi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(vo(t),t):(vo(t),null)}return vo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Bc(t,t.updateQueue),B(t),null);case 4:return xe(),e===null&&Sd(t.stateNode.containerInfo),B(t),null;case 10:return ia(t.type),B(t),null;case 19:if(E(M),r=t.memoizedState,r===null)return B(t),null;if(i=(t.flags&128)!=0,o=r.rendering,o===null)if(i)Vc(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=yo(e),o!==null){for(t.flags|=128,Vc(r,!1),e=o.updateQueue,t.updateQueue=e,Bc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)xi(n,e),n=n.sibling;return D(M,M.current&1|2),A&&Ri(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Ie()>nu&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}else{if(!i)if(e=yo(o),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Bc(t,e),Vc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!A)return B(t),null}else 2*Ie()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(B(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Ie(),e.sibling=null,n=M.current,D(M,i?n&1|2:n&1),A&&Ri(t,r.treeForkCount),e);case 22:case 23:return vo(t),uo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(B(t),t.subtreeFlags&6&&(t.flags|=8192)):B(t),n=t.updateQueue,n!==null&&Bc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&E(Ea),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ia(j),B(t),null;case 25:return null;case 30:return null}throw Error(a(156,t.tag))}function Uc(e,t){switch(Vi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ia(j),xe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Ce(t),null;case 31:if(t.memoizedState!==null){if(vo(t),t.alternate===null)throw Error(a(340));Zi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(vo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(a(340));Zi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return E(M),null;case 4:return xe(),null;case 10:return ia(t.type),null;case 22:case 23:return vo(t),uo(),e!==null&&E(Ea),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ia(j),null;case 25:return null;default:return null}}function Wc(e,t){switch(Vi(t),t.tag){case 3:ia(j),xe();break;case 26:case 27:case 5:Ce(t);break;case 4:xe();break;case 31:t.memoizedState!==null&&vo(t);break;case 13:vo(t);break;case 19:E(M);break;case 10:ia(t.type);break;case 22:case 23:vo(t),uo(),e!==null&&E(Ea);break;case 24:ia(j)}}function Gc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Kc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function qc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{ao(t,n)}catch(t){Z(e,e.return,t)}}}function Jc(e,t,n){n.props=Qs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Yc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Xc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}function Zc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[vt]=t}catch(t){Z(e,e.return,t)}}function $c(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function el(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||$c(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=un));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(tl(e,t,n),e=e.sibling;e!==null;)tl(e,t,n),e=e.sibling}function nl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(nl(e,t,n),e=e.sibling;e!==null;)nl(e,t,n),e=e.sibling}function rl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[_t]=e,t[vt]=n}catch(t){Z(e,e.return,t)}}var il=!1,V=!1,al=!1,ol=typeof WeakSet==`function`?WeakSet:Set,H=null;function sl(e,t){if(e=e.containerInfo,Rd=sp,e=Lr(e),Rr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||i!==0&&f.nodeType!==3||(c=s+i),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===i&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,H=t;H!==null;)if(t=H,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,H=e;else for(;H!==null;){switch(t=H,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(o,r,n),o[_t]=e,O(o),r=o;break a;case`link`:var s=Vf(`link`,`href`,i).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=Fr(s,h),v=Fr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,w.T=null,n=lu,lu=null;var o=au,s=su;if(X=0,ou=au=null,su=0,W&6)throw Error(a(331));var c=W;if(W|=4,Il(o.current),Ol(o,o.current,s,n),W=c,id(0,!1),Ke&&typeof Ke.onPostCommitFiberRoot==`function`)try{Ke.onPostCommitFiberRoot(Ge,o)}catch{}return!0}finally{T.p=i,w.T=r,Vu(e,t)}}function Wu(e,t,n){t=Oi(n,t),t=ic(e.stateNode,t,2),e=Qa(e,t,2),e!==null&&(st(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=Oi(n,e),n=ac(2),r=Qa(t,n,2),r!==null&&(oc(n,r,t,e),st(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>Ie()-eu?!(W&2)&&Su(e,0):Jl|=n,Xl===q&&(Xl=0)),rd(e)}function qu(e,t){t===0&&(t=at()),e=pi(e,t),e!==null&&(st(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(a(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return Me(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Je(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=q,a=nt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||rt(r,a)||(n=!0,ld(r,a));r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Ie(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}X!==0&&X!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Jt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),O(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Jt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Jt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Jt(n.imageSizes)+`"]`)):i+=`[href="`+Jt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=p({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),O(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Jt(r)+`"][href="`+Jt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=p({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),O(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=kt(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=p({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);O(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=kt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=p({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),O(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=kt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=p({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),O(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var i=(i=ve.current)?gf(i):null;if(!i)throw Error(a(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=kt(i).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var o=kt(i).hoistableStyles,s=o.get(e);if(s||(i=i.ownerDocument||i,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=i.querySelector(jf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Nf(i,e,n,s.state))),t&&r===null)throw Error(a(528,``));return s}if(t&&r!==null)throw Error(a(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=kt(i).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(a(444,e))}}function Af(e){return`href="`+Jt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return p({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),O(t),e.head.appendChild(t))}function Pf(e){return`[src="`+Jt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Jt(n.href)+`"]`);if(r)return t.instance=r,O(r),r;var i=p({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),O(r),Pd(r,`style`,i),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Af(n.href);var o=e.querySelector(jf(i));if(o)return t.state.loading|=4,t.instance=o,O(o),o;r=Mf(n),(i=mf.get(i))&&Rf(r,i),o=(e.ownerDocument||e).createElement(`link`),O(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Pd(o,`link`,r),t.state.loading|=4,Lf(o,n.precedence,e),t.instance=o;case`script`:return o=Pf(n.src),(i=e.querySelector(Ff(o)))?(t.instance=i,O(i),i):(r=n,(i=mf.get(o))&&(r=p({},n),zf(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),O(i),Pd(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(a(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,O(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),O(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=ce()})),S=p(),C=i(t(),1),ue=C.createContext(null),de={"signal-red":`#E60000`,"signal-red-700":`#9E0000`,"signal-red-900":`#520000`,"cod-gray":`#1C1C1C`,"cod-gray-700":`#2B2B2B`,"cod-gray-500":`#5A5A5A`,"cod-gray-300":`#A6A6A6`,"cod-gray-100":`#F5F5F5`,"cod-gray-050":`#FAFAFA`,white:`#FFFFFF`};function w(e){let{mode:t,accent:n,fontFamily:r,children:i}=e,[a,o]=C.useState(t??`light`),s=t??a;C.useEffect(()=>{typeof document>`u`||document.documentElement.setAttribute(`data-theme`,s)},[s]),C.useEffect(()=>{typeof document>`u`||!n||document.documentElement.style.setProperty(`--accent`,de[n])},[n]),C.useEffect(()=>{typeof document>`u`||!r||(r.sans&&document.documentElement.style.setProperty(`--font-sans`,r.sans),r.mono&&document.documentElement.style.setProperty(`--font-mono`,r.mono))},[r]);let c=C.useMemo(()=>({mode:s,setMode:e=>o(e),toggle:()=>o(e=>e===`light`?`dark`:`light`)}),[s]);return(0,S.jsx)(ue.Provider,{value:c,children:i})}var T=le(),fe=f(`Moon`,[[`path`,{d:`M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z`,key:`a7tn18`}]]),pe=f(`Sun`,[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]),me=[{key:`dashboard`,label:`Dashboard`},{key:`services`,label:`Service Map`},{key:`mcp`,label:`MCP Trial`}];function he({view:t,onNavigate:n,wsConnected:i,theme:a,onToggleTheme:o}){return(0,S.jsxs)(e,{justify:`between`,align:`center`,style:{display:`flex`,width:`100%`},children:[(0,S.jsx)(`strong`,{style:{whiteSpace:`nowrap`},children:`OtelContext`}),(0,S.jsx)(`div`,{style:{flex:1,minWidth:0,display:`flex`,justifyContent:`center`},children:(0,S.jsx)(re,{items:me,value:t,onChange:n,variant:`segment`,size:`sm`,scrollable:!0})}),(0,S.jsxs)(e,{size:`sm`,align:`center`,children:[(0,S.jsx)(te,{tone:i?`info`:`danger`,size:`sm`,children:i?`live`:`offline`}),(0,S.jsx)(r,{icon:a===`dark`?(0,S.jsx)(pe,{size:15}):(0,S.jsx)(fe,{size:15}),"aria-label":`Toggle theme`,variant:`ghost`,size:`sm`,shape:`circle`,onClick:o})]})]})}var E={fg1:`#1C1C1C`,fg2:`#3D3D3D`,fg3:`#5A5A5A`,fg4:`#A6A6A6`,bg1:`#FFFFFF`,bg2:`#FAFAFA`,bg3:`#F5F5F5`,border1:`#E5E5E5`,border2:`#D4D4D4`,accent:`#E60000`,accentSoft:`rgba(230,0,0,0.08)`,success:`#1F9E5C`,warning:`#D98E2B`,danger:`#E60000`,info:`#2D73D9`,series:[`#E60000`,`#1C1C1C`,`#5A5A5A`,`#2D73D9`,`#1F9E5C`,`#D98E2B`,`#9E0000`,`#A6A6A6`],fontSans:`Inter, system-ui, sans-serif`,fontMono:`'JetBrains Mono', monospace`,mode:`light`};function D(e,t){return typeof window>`u`?t:getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function ge(){if(typeof window>`u`)return E;let e=document.documentElement.getAttribute(`data-theme`)??`light`,t=D(`--fg-1`,E.fg1),n=D(`--fg-2`,E.fg2),r=D(`--fg-3`,E.fg3),i=D(`--fg-4`,E.fg4),a=D(`--bg-1`,E.bg1),o=D(`--bg-2`,E.bg2),s=D(`--bg-3`,E.bg3),c=D(`--border-1`,E.border1),l=D(`--border-2`,E.border2),u=D(`--accent`,E.accent);return{fg1:t,fg2:n,fg3:r,fg4:i,bg1:a,bg2:o,bg3:s,border1:c,border2:l,accent:u,accentSoft:D(`--accent-soft`,E.accentSoft),success:D(`--success`,E.success),warning:D(`--warning`,E.warning),danger:D(`--danger`,E.danger),info:D(`--info`,E.info),series:e===`dark`?[u,`#F5F5F5`,`#A6A6A6`,`#5BA0F2`,`#3FBE83`,`#E5A65A`,`#FF6464`,`#7A7A7A`]:[u,`#1C1C1C`,`#5A5A5A`,`#2D73D9`,`#1F9E5C`,`#D98E2B`,`#9E0000`,`#A6A6A6`],fontSans:D(`--font-sans`,E.fontSans),fontMono:D(`--font-mono`,E.fontMono),mode:e}}function _e(e){if(typeof window>`u`)return()=>{};let t=new MutationObserver(e);return t.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),()=>t.disconnect()}var ve=`modulepreload`,ye=function(e){return`/`+e},be={},xe=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=ye(t,n),t in be)return;be[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:ve,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function Se(e,t,n,r,i,a){let o=e+n*Math.cos(i),s=t+n*Math.sin(i),c=e+n*Math.cos(a),l=t+n*Math.sin(a),u=e+r*Math.cos(a),d=t+r*Math.sin(a),f=e+r*Math.cos(i),p=t+r*Math.sin(i),m=+(a-i>Math.PI);return`M${o},${s} A${n},${n} 0 ${m} 1 ${c},${l} L${u},${d} A${r},${r} 0 ${m} 0 ${f},${p} Z`}function Ce(e){let{value:t,max:n=100,size:r=120,thickness:i=12,label:a,tone:o=`neutral`,className:s,style:c,id:l}=e,u=ge(),d=Math.max(0,Math.min(1,t/n)),f=r/2,p=f-i,h=-Math.PI*.75,g=h+Math.PI*1.5*d,_=h+Math.PI*1.5,v=o===`good`?u.success:o===`warning`?u.warning:o===`bad`?u.danger:u.accent;return(0,S.jsxs)(`div`,{id:l,className:m(`rcs-gauge`,s),style:{display:`inline-flex`,flexDirection:`column`,alignItems:`center`,...c},children:[(0,S.jsxs)(`svg`,{width:r,height:r,viewBox:`0 0 ${r} ${r}`,role:`img`,"aria-label":e[`aria-label`]??`${t} of ${n}`,children:[(0,S.jsx)(`path`,{d:Se(f,f,f,p,h,_),fill:u.bg3}),d>0&&(0,S.jsx)(`path`,{d:Se(f,f,f,p,h,g),fill:v}),(0,S.jsxs)(`text`,{x:f,y:f,textAnchor:`middle`,dominantBaseline:`middle`,style:{font:`600 ${r/5}px ${u.fontSans}`,fill:u.fg1,fontVariantNumeric:`tabular-nums`},children:[Math.round(d*100),`%`]})]}),a&&(0,S.jsx)(`div`,{style:{font:`400 12px ${u.fontSans}`,color:u.fg3,marginTop:4},children:a})]})}function we(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:String(Math.round(e*10)/10)}function Te(e=6e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(``),[a,o]=(0,C.useState)(!0),[s,c]=(0,C.useState)(null),l=(0,C.useRef)(void 0),u=(0,C.useCallback)(async()=>{try{let e=await fetch(`/api/system/graph`);if(!e.ok)throw Error(`HTTP ${e.status}`);i(e.headers.get(`X-Cache`)??``),n(await e.json()),c(null)}catch(e){c(e instanceof Error?e.message:`fetch failed`)}finally{o(!1)}},[]);return(0,C.useEffect)(()=>(u(),l.current=setInterval(u,e),()=>clearInterval(l.current)),[u,e]),{graph:t,cache:r,loading:a,error:s,reload:u}}function Ee(e=3e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(null),[a,o]=(0,C.useState)(!0),[s,c]=(0,C.useState)(null),l=(0,C.useRef)(void 0),u=(0,C.useCallback)(async()=>{try{let[e,t]=await Promise.all([fetch(`/api/metrics/dashboard`),fetch(`/api/stats`)]);if(!e.ok||!t.ok)throw Error(`fetch failed`);n(await e.json()),i(await t.json()),c(null)}catch(e){c(e instanceof Error?e.message:`fetch failed`)}finally{o(!1)}},[]);return(0,C.useEffect)(()=>(u(),l.current=setInterval(u,e),()=>clearInterval(l.current)),[u,e]),{dashboard:t,stats:r,loading:a,error:s,reload:u}}function De(e=3e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(!0),[a,o]=(0,C.useState)(null),s=(0,C.useRef)(void 0),c=(0,C.useCallback)(async()=>{try{let e=await fetch(`/api/metrics/traffic`);if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();n(Array.isArray(t)?t:[]),o(null)}catch(e){o(e instanceof Error?e.message:`fetch failed`)}finally{i(!1)}},[]);return(0,C.useEffect)(()=>(c(),s.current=setInterval(c,e),()=>clearInterval(s.current)),[c,e]),{points:t,loading:r,error:a,reload:c}}function Oe(e=3e4){let[t,n]=(0,C.useState)(null),[r,i]=(0,C.useState)(!0),[a,o]=(0,C.useState)(null),s=(0,C.useRef)(void 0),c=(0,C.useCallback)(async()=>{try{let e=await(await fetch(`/ready`)).json();n({ready:!!e?.ready,checks:e?.checks??{}}),o(null)}catch(e){o(e instanceof Error?e.message:`fetch failed`)}finally{i(!1)}},[]);return(0,C.useEffect)(()=>(c(),s.current=setInterval(c,e),()=>clearInterval(s.current)),[c,e]),{ready:t,loading:r,error:a,reload:c}}var ke=class extends Error{code;constructor(e,t){super(t),this.name=`McpError`,this.code=e}},Ae=0;function je(e){let t={"Content-Type":`application/json`};return e?.apiKey&&(t.Authorization=`Bearer ${e.apiKey}`),e?.tenant&&(t[`X-Tenant-ID`]=e.tenant),t}async function Me(e,t,n){let r=++Ae,i=await fetch(`/mcp`,{method:`POST`,headers:je(n),body:JSON.stringify({jsonrpc:`2.0`,id:r,method:e,params:t}),signal:n?.signal});if(!i.ok)throw new ke(i.status,`HTTP ${i.status}`);let a=await i.json();if(a.error)throw new ke(a.error.code??-1,a.error.message??`MCP error`);return a.result}async function Ne(e){return(await Me(`tools/list`,{},e)).tools??[]}async function Pe(e,t,n){return Me(`tools/call`,{name:e,arguments:t},n)}function Fe(e){if(!e)return[];let t=e.anomalies;if(Array.isArray(t))return t;let n=e.content?.find(e=>e.type===`text`)?.text;if(!n)return[];try{let e=JSON.parse(n);return Array.isArray(e)?e:[]}catch{return[]}}var Ie=15,Le=20;function Re(e){let t=new Map;for(let n of e){let e=`${n.service}|${n.type}`,r=t.get(e);(!r||n.timestamp>r.timestamp)&&t.set(e,n)}return Array.from(t.values()).sort((e,t)=>e.timestamp{try{let e=await Pe(`get_anomaly_timeline`,{since:new Date(Date.now()-Ie*6e4).toISOString()});if(e.isError){let t=e.content?.find(e=>e.type===`text`)?.text;throw Error(t??`anomaly tool error`)}n(Re(Fe(e))),o(null)}catch(e){o(e instanceof Error?e.message:`fetch failed`)}finally{i(!1)}},[]);return(0,C.useEffect)(()=>(c(),s.current=setInterval(c,e),()=>clearInterval(s.current)),[c,e]),{anomalies:t,loading:r,error:a,reload:c}}function Be(e){switch(e){case`critical`:return`danger`;case`warning`:return`warning`;default:return`neutral`}}function Ve(e){if(!e)return`idle`;let t=e.toLowerCase();return t===`ok`?`running`:t===`skipped`?`idle`:t.startsWith(`saturated`)?`degraded`:`failed`}function He(e){return e.count?e.error_count/e.count*100:0}function Ue(e){if(typeof e!=`number`||Number.isNaN(e))return 0;let t=e<=1?e*100:e;return Math.max(0,Math.min(100,t))}function We(e){if(typeof e!=`number`||!Number.isFinite(e)||e<0)return`—`;let t=Math.floor(e);if(t<60)return`${t}s`;if(t<3600)return`${Math.floor(t/60)}m`;if(t<86400){let e=Math.floor(t/3600),n=Math.floor(t%3600/60);return`${e}h ${String(n).padStart(2,`0`)}m`}let n=Math.floor(t/86400),r=Math.floor(t%86400/3600);return`${n}d ${String(r).padStart(2,`0`)}h`}function Ge(e){if(typeof e==`number`&&Number.isFinite(e))return e;if(typeof e==`string`){let t=Number.parseFloat(e);return Number.isFinite(t)?t:null}return null}var Ke={database:`Database`,graphrag:`GraphRAG`,dlq_disk:`DLQ disk`,pipeline:`Ingest pipeline`};function qe(e){return e>=90?`good`:e>=70?`warning`:`bad`}function Je({onNavigate:t}){let{graph:n,loading:r,error:i}=Te(),{dashboard:s,stats:u,loading:d,error:f}=Ee(),{points:p,error:m}=De(),{ready:re,error:ie}=Oe(),{anomalies:ae,error:oe}=ze(),se=n?.system??null,ce=x(_.coarse),le=x(_.tablet),ue=x(_.wide),de=(0,C.useMemo)(()=>ce?{hero:12,traffic:12,failing:12,anomalies:12,platform:12}:le?{hero:12,traffic:12,failing:12,anomalies:6,platform:6}:{hero:12,traffic:12,failing:8,anomalies:4,platform:12},[ce,le]),w=r&&!n||d&&!s||!se||se.total_services===0,T=i||f||m||ie,fe=Ue(se?.overall_health_score),pe=(0,C.useMemo)(()=>(p??[]).map(e=>e.count),[p]),me=(0,C.useMemo)(()=>(p??[]).map(He),[p]),he=(0,C.useMemo)(()=>pe.reduce((e,t)=>e+t,0),[pe]),E=(0,C.useMemo)(()=>{let e=(p??[]).reduce((e,t)=>e+t.error_count,0);return he>0?e/he*100:0},[p,he]),D=Ge(u?.db_size_mb),ge=ue?{maxWidth:1280,margin:`0 auto`,width:`100%`}:{width:`100%`},_e=[{key:`service_name`,title:`Service`,dataKey:`service_name`,render:(e,t)=>(0,S.jsx)(y,{text:t.service_name})},{key:`error_count`,title:`Errors`,dataKey:`error_count`,width:90,align:`right`,render:(e,t)=>we(t.error_count)},{key:`total_count`,title:`Total`,dataKey:`total_count`,width:90,align:`right`,render:(e,t)=>we(t.total_count)},{key:`error_rate`,title:`Error rate`,dataKey:`error_rate`,width:110,align:`right`,render:(e,t)=>{let n=t.error_rate<=1?t.error_rate*100:t.error_rate;return(0,S.jsxs)(te,{tone:n>=5?`danger`:`neutral`,size:`sm`,children:[n.toFixed(1),`%`]})}}],ve=s?.top_failing_services??[],ye=(ae??[]).map(e=>({key:e.id,title:e.service||e.type,description:e.evidence,time:new Date(e.timestamp).toLocaleTimeString(),tone:Be(e.severity)}));return w?(0,S.jsxs)(e,{direction:`vertical`,size:`md`,style:{display:`flex`,...ge,padding:`0.75rem`},children:[(0,S.jsx)(v,{title:`Dashboard`,subtitle:`Warming up — building service graph…`}),(0,S.jsxs)(a,{columns:12,gap:`md`,children:[(0,S.jsx)(a.Col,{span:12,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,children:(0,S.jsx)(g,{variant:`rect`,height:96})})}),(0,S.jsx)(a.Col,{span:ce?12:8,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,children:(0,S.jsx)(g,{variant:`text`,lines:6})})}),(0,S.jsx)(a.Col,{span:ce?12:4,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,children:(0,S.jsx)(g,{variant:`text`,lines:6})})})]})]}):(0,S.jsxs)(e,{direction:`vertical`,size:`md`,style:{display:`flex`,...ge,padding:`0.75rem`},children:[(0,S.jsx)(v,{title:`Dashboard`,subtitle:`System health at a glance`}),T&&(0,S.jsx)(ee,{severity:`warning`,title:`Some panels failed to load`,children:T}),(0,S.jsxs)(a,{columns:12,gap:`md`,children:[(0,S.jsx)(a.Col,{span:de.hero,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`System health`,children:(0,S.jsxs)(e,{size:`lg`,align:`center`,wrap:!0,style:{display:`flex`},children:[(0,S.jsx)(Ce,{value:fe,max:100,size:120,label:`${Math.round(fe)}%`,tone:qe(fe)}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Healthy`,value:se?.healthy??0}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Degraded`,value:se?.degraded??0}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Critical`,value:se?.critical??0}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Avg latency`,value:Math.round(s?.avg_latency_ms??0),unit:`ms`}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`p99 latency`,value:Math.round(s?.p99_latency??0),unit:`ms`})]})})}),(0,S.jsx)(a.Col,{span:de.traffic,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Traffic`,children:(0,S.jsxs)(e,{size:`lg`,align:`center`,wrap:!0,style:{display:`flex`},children:[(0,S.jsx)(b,{label:`Requests (30m)`,value:we(he),sparkline:pe.length?pe:void 0}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Error rate (30m)`,value:`${E.toFixed(1)}%`,sparkline:me.length?me:void 0}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Total traces`,value:we(s?.total_traces??0)}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Total logs`,value:we(s?.total_logs??0)}),(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(`div`,{style:{alignSelf:`center`},children:(0,S.jsx)(te,{tone:E>=5?`danger`:`neutral`,size:`sm`,children:E>=5?`elevated errors`:`nominal`})})]})})}),(0,S.jsx)(a.Col,{span:de.failing,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Top failing services`,children:(0,S.jsx)(l,{columns:_e,data:ve,rowKey:`service_name`,density:`compact`,onRowClick:()=>t(`services`),empty:(0,S.jsxs)(e,{size:`xs`,align:`center`,style:{display:`flex`},children:[(0,S.jsx)(o,{status:`running`}),(0,S.jsx)(`span`,{children:`No failing services — all clear.`})]})})})}),(0,S.jsx)(a.Col,{span:de.anomalies,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Recent anomalies`,children:oe?(0,S.jsx)(ee,{severity:`warning`,title:`Anomaly feed unavailable`,children:oe}):ye.length?(0,S.jsx)(h,{items:ye}):(0,S.jsxs)(e,{size:`xs`,align:`center`,style:{display:`flex`},children:[(0,S.jsx)(o,{status:`running`}),(0,S.jsx)(`span`,{children:`No anomalies in the last hour.`})]})})}),(0,S.jsx)(a.Col,{span:de.platform,children:(0,S.jsx)(c,{bordered:!0,padding:`md`,radius:`md`,title:`Platform health`,children:(0,S.jsxs)(e,{size:`lg`,align:`center`,wrap:!0,style:{display:`flex`},children:[(0,S.jsx)(b,{label:`Uptime`,value:We(se?.uptime_seconds)}),(0,S.jsx)(ne,{direction:`vertical`}),re?Object.entries(re.checks).map(([e,t])=>(0,S.jsx)(o,{status:Ve(t),label:`${Ke[e]??e}: ${t}`},e)):ie&&(0,S.jsx)(`span`,{style:{minWidth:0},children:`Readiness probe unavailable.`}),D!==null&&(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(ne,{direction:`vertical`}),(0,S.jsx)(b,{label:`Database size`,value:D.toFixed(1),unit:`MB`})]})]})})})]})]})}var Ye=100,Xe=1e4,Ze=3e4,Qe=35e3;function $e(e){let t=(0,C.useRef)(null),n=(0,C.useRef)(e),[r,i]=(0,C.useState)(`connecting`);t.status=r;let a=(0,C.useRef)(0),o=(0,C.useRef)(null),s=(0,C.useRef)(null),c=(0,C.useRef)(null),l=(0,C.useRef)(!1),u=(0,C.useRef)(()=>{});(0,C.useEffect)(()=>{n.current=e},[e]);let d=(0,C.useCallback)(()=>{o.current!==null&&(window.clearTimeout(o.current),o.current=null)},[]),f=(0,C.useCallback)(()=>{s.current!==null&&(window.clearInterval(s.current),s.current=null),c.current!==null&&(window.clearTimeout(c.current),c.current=null)},[]),p=(0,C.useCallback)(()=>{if(l.current)return;d();let e=a.current,t=Math.min(Ye*2**e,Xe);a.current=e+1,i(`reconnecting`),o.current=window.setTimeout(()=>{o.current=null,u.current()},t)},[d]),m=(0,C.useCallback)(()=>{f(),s.current=window.setInterval(()=>{let e=t.current;if(!(!e||e.readyState!==WebSocket.OPEN)){try{e.send(JSON.stringify({type:`ping`}))}catch{return}c.current!==null&&window.clearTimeout(c.current),c.current=window.setTimeout(()=>{c.current=null;let e=t.current;if(e)try{e.close()}catch{}},Qe)}},Ze)},[f]),h=(0,C.useCallback)(()=>{if(l.current)return;d(),f();let e=t.current;if(e){e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null;try{e.close()}catch{}t.current=null}i(a.current===0?`connecting`:`reconnecting`);let r=window.location.protocol===`https:`?`wss:`:`ws:`,o;try{o=new WebSocket(`${r}//${window.location.host}/ws`)}catch{p();return}t.current=o,o.onopen=()=>{l.current||(a.current=0,i(`connected`),m())},o.onmessage=e=>{c.current!==null&&(window.clearTimeout(c.current),c.current=null);try{let t=JSON.parse(e.data);t.type===`logs`&&Array.isArray(t.data)&&n.current(t.data)}catch{}},o.onerror=()=>{},o.onclose=()=>{l.current||(t.current===o&&(t.current=null),f(),i(`disconnected`),p())}},[f,d,p,m]);return(0,C.useEffect)(()=>{u.current=h},[h]),(0,C.useEffect)(()=>{l.current=!1,u.current=h,h();let e=()=>{if(document.visibilityState!==`visible`)return;let e=t.current;(!e||e.readyState===WebSocket.CLOSED||e.readyState===WebSocket.CLOSING)&&(a.current=0,d(),u.current())},n=()=>{a.current=0,d(),u.current()};return document.addEventListener(`visibilitychange`,e),window.addEventListener(`online`,n),()=>{l.current=!0,document.removeEventListener(`visibilitychange`,e),window.removeEventListener(`online`,n),d(),f();let r=t.current;if(r){r.onopen=null,r.onmessage=null,r.onerror=null,r.onclose=null;try{r.close()}catch{}t.current=null}}},[]),t}var et=(0,C.lazy)(()=>xe(()=>import(`./ServicesView-n3l2yFxx.js`),__vite__mapDeps([0,1,2]))),tt=(0,C.lazy)(()=>xe(()=>import(`./MCPConsoleView-BXQJGMyT.js`),__vite__mapDeps([3,1,2])));function nt({theme:e,onToggleTheme:t}){let[n,r]=(0,C.useState)(`dashboard`);return(0,S.jsx)(s,{header:(0,S.jsx)(he,{view:n,onNavigate:r,wsConnected:$e(()=>void 0).status===`connected`,theme:e,onToggleTheme:t}),children:(0,S.jsxs)(C.Suspense,{fallback:(0,S.jsx)(d,{label:`Loading…`}),children:[n===`dashboard`&&(0,S.jsx)(Je,{onNavigate:r}),n===`services`&&(0,S.jsx)(et,{}),n===`mcp`&&(0,S.jsx)(tt,{})]})})}var rt=class extends C.Component{state={error:null,info:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){this.setState({info:t}),console.error(`[ErrorBoundary] Uncaught error in React tree`,{message:e.message,name:e.name,stack:e.stack,componentStack:t.componentStack,url:typeof window>`u`?void 0:window.location.href,userAgent:typeof navigator>`u`?void 0:navigator.userAgent,timestamp:new Date().toISOString()})}reset=()=>{this.setState({error:null,info:null})};reload=()=>{typeof window<`u`&&window.location.reload()};render(){let{error:e,info:t}=this.state;if(!e)return this.props.children;let n=`var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)`;return(0,S.jsx)(`div`,{role:`alert`,"aria-live":`assertive`,style:{position:`fixed`,inset:0,display:`flex`,alignItems:`center`,justifyContent:`center`,padding:`24px`,background:`var(--bg-0, #0a0a0a)`,color:`var(--fg-1, #fff)`,fontFamily:`var(--font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)`,zIndex:9999,overflow:`auto`},children:(0,S.jsxs)(`div`,{style:{width:`100%`,maxWidth:`640px`,background:`var(--bg-1, #111)`,border:`1px solid var(--border-1, #27272a)`,borderRadius:`var(--radius-lg, 12px)`,padding:`32px`,boxShadow:`var(--shadow-lg, 0 10px 40px rgba(0, 0, 0, 0.5))`},children:[(0,S.jsx)(`div`,{style:{fontSize:`12px`,fontWeight:700,letterSpacing:`0.14em`,textTransform:`uppercase`,color:`var(--brand-red-500, #ef4444)`,marginBottom:`12px`},children:`Application error`}),(0,S.jsx)(`h1`,{style:{fontSize:`24px`,fontWeight:700,margin:`0 0 12px 0`,color:`var(--fg-1, #fff)`},children:`Something went wrong`}),(0,S.jsx)(`p`,{style:{fontSize:`14px`,lineHeight:1.6,color:`var(--fg-2, #d4d4d8)`,margin:`0 0 20px 0`},children:`The UI encountered an unexpected error and could not continue rendering. You can try recovering without a full reload, or refresh the page if that fails.`}),(0,S.jsxs)(`div`,{style:{background:`var(--bg-3, #050505)`,border:`1px solid var(--border-1, #27272a)`,borderRadius:`var(--radius-md, 8px)`,padding:`12px 14px`,marginBottom:`20px`,fontFamily:n,fontSize:`13px`,color:`var(--fg-2, #d4d4d8)`,wordBreak:`break-word`},children:[(0,S.jsx)(`span`,{style:{color:`var(--brand-red-500, #ef4444)`},children:e.name||`Error`}),`: `,e.message||`(no message)`]}),t?.componentStack&&(0,S.jsxs)(`details`,{style:{marginBottom:`24px`,fontSize:`12px`,color:`var(--fg-3, #71717a)`},children:[(0,S.jsx)(`summary`,{style:{cursor:`pointer`,userSelect:`none`,padding:`4px 0`,color:`var(--fg-2, #d4d4d8)`},children:`Component stack`}),(0,S.jsx)(`pre`,{style:{marginTop:`8px`,padding:`12px`,background:`var(--bg-3, #050505)`,border:`1px solid var(--border-1, #27272a)`,borderRadius:`var(--radius-md, 8px)`,fontFamily:n,fontSize:`11px`,lineHeight:1.5,color:`var(--fg-2, #d4d4d8)`,whiteSpace:`pre-wrap`,wordBreak:`break-word`,maxHeight:`240px`,overflow:`auto`},children:t.componentStack})]}),(0,S.jsxs)(`div`,{style:{display:`flex`,gap:`12px`,flexWrap:`wrap`},children:[(0,S.jsx)(`button`,{type:`button`,onClick:this.reset,style:{appearance:`none`,border:`1px solid var(--accent-fg, #ef4444)`,background:`var(--accent-fg, #ef4444)`,color:`var(--accent-on, #fff)`,padding:`10px 18px`,borderRadius:`var(--radius-md, 8px)`,fontSize:`14px`,fontWeight:600,cursor:`pointer`,transition:`background 120ms ease`},children:`Try again`}),(0,S.jsx)(`button`,{type:`button`,onClick:this.reload,style:{appearance:`none`,border:`1px solid var(--border-2, #3f3f46)`,background:`transparent`,color:`var(--fg-1, #fff)`,padding:`10px 18px`,borderRadius:`var(--radius-md, 8px)`,fontSize:`14px`,fontWeight:500,cursor:`pointer`,transition:`border-color 120ms ease`},children:`Reload page`})]})]})})}},it=`oc-theme`;function at(){if(typeof window>`u`)return`dark`;try{let e=window.localStorage.getItem(it);return e===`light`||e===`dark`?e:`dark`}catch{return`dark`}}function ot(){let[e,t]=(0,C.useState)(at);return(0,C.useEffect)(()=>{document.documentElement.setAttribute(`data-theme`,e);try{window.localStorage.setItem(it,e)}catch{}},[e]),{theme:e,toggle:()=>t(e=>e===`dark`?`light`:`dark`)}}function st(){let{theme:e,toggle:t}=ot();return(0,S.jsxs)(w,{mode:e,children:[(0,S.jsx)(rt,{children:(0,S.jsx)(nt,{theme:e,onToggleTheme:t})}),(0,S.jsx)(u,{})]})}(0,T.createRoot)(document.getElementById(`root`)).render((0,S.jsx)(C.StrictMode,{children:(0,S.jsx)(st,{})}));export{Te as a,ge as c,Ee as i,Pe as n,we as o,Ne as r,_e as s,ke as t}; \ No newline at end of file diff --git a/internal/ui/dist/assets/inputs-DxVBbFvb.js b/internal/ui/dist/assets/inputs-DxVBbFvb.js new file mode 100644 index 0000000..308bef7 --- /dev/null +++ b/internal/ui/dist/assets/inputs-DxVBbFvb.js @@ -0,0 +1 @@ +import{M as e,P as t,j as n,k as r}from"./useMediaQuery-D3Mg-H7H.js";var i=n(),a=t(e(),1),o=a.forwardRef(function(e,t){let{value:n,defaultValue:o,placeholder:s,size:c=`md`,status:l=`default`,disabled:u=!1,readOnly:d=!1,invalid:f=!1,prefix:p,suffix:m,clearable:h=!1,type:g=`text`,autoFocus:_=!1,onChange:v,onFocus:y,onBlur:b,onKeyDown:x,className:S,style:C,id:w,"data-testid":T,"aria-label":E,"aria-labelledby":D,"aria-describedby":O}=e,k=n!==void 0,[A,j]=a.useState(o??``),M=k?n:A,N=a.useRef(null);a.useImperativeHandle(t,()=>N.current);let P=f?`error`:l;return(0,i.jsxs)(`span`,{className:r(`rcs-input-wrap`,`rcs-input-wrap--${c}`,S),style:C,"data-status":P,"data-disabled":u||void 0,children:[p&&(0,i.jsx)(`span`,{className:`rcs-input-affix rcs-input-affix--left`,children:p}),(0,i.jsx)(`input`,{ref:N,id:w,"data-testid":T,className:`rcs-input`,type:g,value:M,placeholder:s,disabled:u,readOnly:d,autoFocus:_,"aria-invalid":P===`error`||void 0,"aria-label":E,"aria-labelledby":D,"aria-describedby":O,onChange:e=>{k||j(e.target.value),v?.(e.target.value,e)},onFocus:y,onBlur:b,onKeyDown:x}),h&&M&&!u&&!d&&(0,i.jsx)(`button`,{type:`button`,className:`rcs-input-clear`,"aria-label":`Clear`,onClick:e=>{let t=N.current;k||j(``),t&&((Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,`value`)?.set)?.call(t,``),t.dispatchEvent(new Event(`input`,{bubbles:!0}))),v?.(``,e)},children:`×`}),m&&(0,i.jsx)(`span`,{className:`rcs-input-affix rcs-input-affix--right`,children:m})]})});function s(e){let{value:t,defaultValue:n,min:r,max:s,step:c=1,precision:l,onChange:u,...d}=e,f=t!==void 0,[p,m]=a.useState(n??``),h=f?t:p,g=h===``?``:l===void 0?String(h):Number(h).toFixed(l),_=e=>{if(e===``){f||m(``);return}let t=e;r!==void 0&&(t=Math.max(r,t)),s!==void 0&&(t=Math.min(s,t)),f||m(t),u?.(t)};return(0,i.jsx)(o,{...d,type:`text`,value:g,onChange:e=>{if(e===``||e===`-`)return _(``);let t=Number(e);Number.isNaN(t)||_(t)},onKeyDown:e=>{e.key===`ArrowUp`?(e.preventDefault(),_((typeof h==`number`?h:0)+c)):e.key===`ArrowDown`&&(e.preventDefault(),_((typeof h==`number`?h:0)-c)),d.onKeyDown?.(e)}})}var c=a.forwardRef(function(e,t){let{value:n,defaultValue:o,placeholder:s,rows:c=4,autoResize:l=!1,maxLength:u,showCount:d=!1,size:f=`md`,status:p=`default`,disabled:m=!1,readOnly:h=!1,invalid:g=!1,onChange:_,onFocus:v,onBlur:y,onKeyDown:b,autoFocus:x,className:S,style:C,id:w,"data-testid":T,"aria-label":E,"aria-labelledby":D,"aria-describedby":O}=e,k=n!==void 0,[A,j]=a.useState(o??``),M=k?n:A,N=a.useRef(null);a.useImperativeHandle(t,()=>N.current),a.useLayoutEffect(()=>{if(!l)return;let e=N.current;e&&(e.style.height=`auto`,e.style.height=e.scrollHeight+`px`)},[M,l]);let P=g?`error`:p;return(0,i.jsxs)(`span`,{style:{display:`block`,width:`100%`,...C},children:[(0,i.jsx)(`textarea`,{ref:N,id:w,"data-testid":T,className:r(`rcs-textarea`,`rcs-textarea--${f}`,S),rows:c,value:M,placeholder:s,maxLength:u,disabled:m,readOnly:h,autoFocus:x,"aria-invalid":P===`error`||void 0,"aria-label":E,"aria-labelledby":D,"aria-describedby":O,"data-status":P,onChange:e=>{k||j(e.target.value),_?.(e.target.value,e)},onFocus:v,onBlur:y,onKeyDown:b}),d&&(0,i.jsxs)(`span`,{className:`rcs-textarea-count`,children:[M.length,u?` / ${u}`:``]})]})});export{s as n,c as r,o as t}; \ No newline at end of file diff --git a/internal/ui/dist/assets/useMediaQuery-D3Mg-H7H.js b/internal/ui/dist/assets/useMediaQuery-D3Mg-H7H.js new file mode 100644 index 0000000..c33ce21 --- /dev/null +++ b/internal/ui/dist/assets/useMediaQuery-D3Mg-H7H.js @@ -0,0 +1 @@ +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=l()})),d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),f=o(((e,t)=>{t.exports=d()})),p=c(u(),1),m=f();function h(...e){let t=``;for(let n of e)n&&(t+=t?` `+n:n);return t}var g=0;function _(e=`rcs`){return g+=1,`${e}-${g}`}var v=p.forwardRef(function(e,t){let{variant:n=`secondary`,size:r=`md`,shape:i=`rect`,loading:a=!1,disabled:o=!1,block:s=!1,iconLeft:c,iconRight:l,type:u=`button`,children:d,onClick:f,className:p,style:g,id:_,"data-testid":v,"aria-label":y,"aria-labelledby":b,"aria-describedby":x}=e;return(0,m.jsxs)(`button`,{ref:t,id:_,"data-testid":v,type:u,className:h(`rcs-button`,`rcs-button--${n}`,`rcs-button--${r}`,i!==`rect`&&`rcs-button--${i}`,s&&`rcs-button--block`,p),style:g,disabled:o||a,"aria-disabled":o||a||void 0,"aria-busy":a||void 0,"aria-label":y,"aria-labelledby":b,"aria-describedby":x,onClick:f,children:[a?(0,m.jsx)(`span`,{className:`rcs-button-spinner`,"aria-hidden":!0}):c,d,l]})}),y=p.forwardRef(function(e,t){let{icon:n,round:r=!1,"aria-label":i,...a}=e;return(0,m.jsx)(v,{ref:t,...a,shape:r?`circle`:`square`,"aria-label":i,children:n})});function b(e){let{children:t,size:n,direction:r=`horizontal`,attached:i=!0,className:a,style:o,id:s}=e;return(0,m.jsx)(`div`,{id:s,style:o,role:`group`,className:h(`rcs-button-group`,r===`vertical`&&`rcs-button-group--vertical`,i&&`rcs-button-group--attached`,a),children:p.Children.map(t,e=>p.isValidElement(e)&&n&&(e.type===v||e.props?.className?.includes?.(`rcs-button`))?p.cloneElement(e,{size:n}):e)})}function x(e){let{tone:t=`neutral`,size:n=`md`,icon:r,closable:i=!1,onClose:a,children:o,className:s,style:c,id:l}=e;return(0,m.jsxs)(`span`,{id:l,className:h(`rcs-badge`,`rcs-badge--${t}`,n!==`md`&&`rcs-badge--${n}`,s),style:c,children:[r&&(0,m.jsx)(`span`,{"aria-hidden":!0,children:r}),o,i&&(0,m.jsx)(`button`,{type:`button`,className:`rcs-badge-x`,"aria-label":`Remove`,onClick:a,children:`×`})]})}function S(e){let{status:t,label:n,pulse:r=!1,className:i,style:a,id:o}=e;return(0,m.jsxs)(`span`,{id:o,className:h(`rcs-status-dot`,i),style:a,"data-status":t,"data-pulse":r||void 0,children:[(0,m.jsx)(`span`,{className:`rcs-status-dot-glyph`,"aria-hidden":!0}),n&&(0,m.jsx)(`span`,{children:n})]})}var C={xs:4,sm:8,md:12,lg:16,xl:24};function w(e){return e===void 0?12:typeof e==`number`?e:C[e]}var T={none:`0`,sm:`4px`,md:`6px`,lg:`8px`,pill:`9999px`,circle:`50%`};function E(e){return e===void 0?`var(--radius-md)`:typeof e==`number`?`${e}px`:T[e]}var D={none:`none`,sm:`var(--shadow-sm)`,md:`var(--shadow-md)`,lg:`var(--shadow-lg)`,overlay:`var(--shadow-lg)`};function O(e){let{title:t,subtitle:n,extra:r,footer:i,bordered:a=!0,hoverable:o=!1,padding:s,radius:c,shadow:l=`none`,children:u,className:d,style:f,id:p}=e,g={borderRadius:E(c),boxShadow:D[l],border:a?void 0:`0`,...f};return(0,m.jsxs)(`div`,{id:p,className:h(`rcs-card`,d),style:g,"data-hoverable":o||void 0,children:[(t||r)&&(0,m.jsxs)(`div`,{className:`rcs-card-header`,children:[(0,m.jsxs)(`div`,{children:[t&&(0,m.jsx)(`div`,{className:`rcs-card-title`,children:t}),n&&(0,m.jsx)(`div`,{className:`rcs-card-subtitle`,children:n})]}),r&&(0,m.jsx)(`div`,{className:`rcs-card-extra`,children:r})]}),(0,m.jsx)(`div`,{className:`rcs-card-body`,style:s===void 0?void 0:{padding:w(s)},children:u}),i&&(0,m.jsx)(`div`,{className:`rcs-card-footer`,children:i})]})}function k(e){let{direction:t=`horizontal`,size:n=`sm`,align:r,justify:i,wrap:a=!1,split:o,children:s,className:c,style:l,id:u}=e,d=w(n),f=p.Children.toArray(s);return(0,m.jsx)(`div`,{id:u,className:h(`rcs-space`,t===`vertical`&&`rcs-space--vertical`,a&&`rcs-space--wrap`,c),style:{gap:d,alignItems:r,justifyContent:i,flexDirection:t===`vertical`?`column`:`row`,...l},children:f.map((e,t)=>(0,m.jsxs)(p.Fragment,{children:[e,o&&te.key===_),y=(e,t)=>{t||(d||g(e),o?.(e))};return(0,m.jsxs)(`div`,{id:u,"data-scrollable":s||void 0,className:h(`rcs-tabs`,`rcs-tabs--${i}`,`rcs-tabs--${a}`,c),style:l,children:[(0,m.jsx)(`div`,{className:`rcs-tabs-nav`,"data-scrollable":s||void 0,role:`tablist`,children:t.map(e=>(0,m.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":e.key===_,disabled:e.disabled,"data-active":e.key===_||void 0,className:`rcs-tabs-tab`,onClick:()=>y(e.key,e.disabled),children:[e.icon&&(0,m.jsx)(`span`,{"aria-hidden":!0,children:e.icon}),(0,m.jsx)(`span`,{children:e.label}),e.badge&&(0,m.jsx)(`span`,{style:{marginLeft:4},children:e.badge})]},e.key))}),v?.content&&(0,m.jsx)(`div`,{className:`rcs-tabs-content`,role:`tabpanel`,children:v.content})]})}function F(e){let{items:t,selectedKeys:n,defaultSelectedKeys:r,mode:i=`vertical`,onSelect:a,className:o,style:s,id:c}=e,l=n!==void 0,[u,d]=p.useState(r??[]),f=l?n:u;return(0,m.jsx)(`div`,{id:c,role:`menu`,className:h(`rcs-menu`,i===`horizontal`&&`rcs-menu--horizontal`,o),style:s,children:t.map((e,t)=>{if(`type`in e&&e.type===`separator`)return(0,m.jsx)(`div`,{className:`rcs-menu-separator`,role:`separator`},`sep-${t}`);if(`type`in e&&e.type===`label`)return(0,m.jsx)(`div`,{className:`rcs-menu-label`,children:e.label},`lbl-${t}`);let n=e;return(0,m.jsxs)(`div`,{role:`menuitem`,className:`rcs-menu-item`,"data-selected":f.includes(n.key)||void 0,"data-destructive":n.destructive||void 0,"data-disabled":n.disabled||void 0,"aria-disabled":n.disabled||void 0,onClick:()=>{n.disabled||(l||d([n.key]),a?.(n.key))},children:[n.icon&&(0,m.jsx)(`span`,{"aria-hidden":!0,children:n.icon}),(0,m.jsx)(`span`,{children:n.label}),n.badge&&(0,m.jsx)(`span`,{style:{marginLeft:`auto`},children:n.badge}),n.shortcut&&(0,m.jsx)(`span`,{className:`rcs-menu-item-shortcut`,children:n.shortcut})]},n.key)})})}function I(e){let{items:t,separator:n=`/`,maxItems:r,className:i,style:a,id:o}=e,s=t;return r&&t.length>r&&(s=[t[0],{label:`…`},...t.slice(t.length-(r-2))]),(0,m.jsx)(`nav`,{id:o,"aria-label":`Breadcrumb`,className:h(`rcs-breadcrumb`,i),style:a,children:s.map((e,t)=>{let r=t===s.length-1,i=e.href?(0,m.jsxs)(`a`,{href:e.href,onClick:e.onClick,children:[e.icon&&(0,m.jsx)(`span`,{"aria-hidden":!0,style:{marginRight:4},children:e.icon}),e.label]}):e.onClick?(0,m.jsx)(`button`,{type:`button`,onClick:e.onClick,style:{background:`none`,border:0,padding:0,color:`inherit`,cursor:`pointer`,font:`inherit`},children:e.label}):(0,m.jsx)(`span`,{children:e.label});return(0,m.jsxs)(p.Fragment,{children:[(0,m.jsx)(`span`,{className:r?`rcs-breadcrumb-item--last`:void 0,children:i}),!r&&(0,m.jsx)(`span`,{className:`rcs-breadcrumb-sep`,"aria-hidden":!0,children:n})]},t)})})}var L={info:`ⓘ`,success:`✓`,warning:`⚠`,danger:`✕`};function R(e){let{severity:t,title:n,children:r,closable:i=!1,icon:a,action:o,onClose:s,className:c,style:l,id:u}=e;return(0,m.jsxs)(`div`,{id:u,role:`alert`,className:h(`rcs-alert`,`rcs-alert--${t}`,c),style:l,children:[a!==!1&&(0,m.jsx)(`span`,{className:`rcs-alert-icon`,"aria-hidden":!0,children:a??L[t]}),(0,m.jsxs)(`div`,{className:`rcs-alert-body`,children:[n&&(0,m.jsx)(`div`,{className:`rcs-alert-title`,children:n}),r&&(0,m.jsx)(`div`,{className:`rcs-alert-content`,children:r}),o&&(0,m.jsx)(`div`,{className:`rcs-alert-action`,children:o})]}),i&&(0,m.jsx)(`button`,{type:`button`,className:`rcs-alert-close`,"aria-label":`Dismiss`,onClick:s,children:`×`})]})}function z(e,t){p.useEffect(()=>{if(!e)return;let n=e=>{e.key===`Escape`&&t()};return window.addEventListener(`keydown`,n),()=>window.removeEventListener(`keydown`,n)},[e,t])}function B(e){let{open:t,title:n,description:r,size:i=`md`,closeOnEsc:a=!0,closeOnBackdrop:o=!0,footer:s,children:c,onClose:l,className:u,style:d,id:f}=e;return z(t&&a,l),t?(0,m.jsx)(`div`,{className:`rcs-modal-backdrop`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":n?`${f??`modal`}-title`:void 0,onClick:e=>{o&&e.target===e.currentTarget&&l()},children:(0,m.jsxs)(`div`,{id:f,className:h(`rcs-modal`,`rcs-modal--${i}`,u),style:d,children:[(n||r)&&(0,m.jsxs)(`div`,{className:`rcs-modal-header`,children:[n&&(0,m.jsx)(`h2`,{id:`${f??`modal`}-title`,className:`rcs-modal-title`,children:n}),r&&(0,m.jsx)(`div`,{className:`rcs-modal-desc`,children:r})]}),(0,m.jsx)(`div`,{className:`rcs-modal-body`,children:c}),s&&(0,m.jsx)(`div`,{className:`rcs-modal-footer`,children:s})]})}):null}function V(e){let{open:t,title:n,description:r,placement:i=`right`,width:a=360,closeOnEsc:o=!0,closeOnBackdrop:s=!0,footer:c,children:l,onClose:u,className:d,style:f,id:p}=e;if(z(t&&o,u),!t)return null;let g=typeof a==`number`?`${a}px`:a,_={...f};return i===`left`||i===`right`?_.width=g:_.height=g,(0,m.jsx)(`div`,{className:`rcs-modal-backdrop`,role:`dialog`,"aria-modal":`true`,style:{alignItems:i===`top`?`flex-start`:i===`bottom`?`flex-end`:`stretch`,justifyItems:i===`left`?`flex-start`:i===`right`?`flex-end`:`stretch`,padding:0},onClick:e=>{s&&e.target===e.currentTarget&&u()},children:(0,m.jsxs)(`div`,{id:p,className:h(`rcs-drawer`,`rcs-drawer--${i}`,d),style:_,children:[(n||r)&&(0,m.jsxs)(`div`,{className:`rcs-modal-header`,children:[n&&(0,m.jsx)(`h2`,{className:`rcs-modal-title`,children:n}),r&&(0,m.jsx)(`div`,{className:`rcs-modal-desc`,children:r})]}),(0,m.jsx)(`div`,{className:`rcs-modal-body`,style:{flex:1,overflow:`auto`},children:l}),c&&(0,m.jsx)(`div`,{className:`rcs-modal-footer`,children:c})]})})}function H(e){let{value:t,indeterminate:n=!1,variant:r=`linear`,size:i=`md`,tone:a=`neutral`,showValue:o=!1,className:s,style:c,id:l}=e,u=Math.max(0,Math.min(100,t));if(r===`circular`){let e=i===`lg`?24:i===`sm`?14:18,t=i===`lg`?3:2,n=2*Math.PI*e,r=u/100*n;return(0,m.jsx)(`span`,{id:l,className:h(`rcs-progress`,s),style:c,role:`progressbar`,"aria-valuenow":u,children:(0,m.jsxs)(`svg`,{width:e*2+t*2,height:e*2+t*2,children:[(0,m.jsx)(`circle`,{cx:e+t,cy:e+t,r:e,stroke:`var(--bg-3)`,strokeWidth:t,fill:`none`}),(0,m.jsx)(`circle`,{cx:e+t,cy:e+t,r:e,stroke:a===`danger`?`var(--danger)`:a===`warning`?`var(--warning)`:`var(--bg-inverse)`,strokeWidth:t,fill:`none`,strokeDasharray:`${r} ${n}`,strokeLinecap:`round`,transform:`rotate(-90 ${e+t} ${e+t})`,style:{transition:`stroke-dasharray 0.3s var(--ease-out-quart)`}})]})})}return(0,m.jsxs)(`div`,{id:l,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n?void 0:u,className:h(`rcs-progress`,`rcs-progress--${i}`,s),style:c,"data-tone":a,"data-indeterminate":n||void 0,children:[(0,m.jsx)(`div`,{className:`rcs-progress-track`,children:(0,m.jsx)(`div`,{className:`rcs-progress-fill`,style:{width:`${u}%`}})}),o&&(0,m.jsxs)(`div`,{className:`rcs-progress-value`,children:[Math.round(u),`%`]})]})}function U(e){let{variant:t=`rect`,width:n,height:r,lines:i,animated:a=!0,className:o,style:s,id:c}=e;return t===`text`&&i&&i>1?(0,m.jsx)(`span`,{id:c,className:o,style:{display:`block`,...s},children:Array.from({length:i},(e,t)=>(0,m.jsx)(`span`,{className:h(`rcs-skeleton`,`rcs-skeleton--text`),"data-animated":a||void 0,style:{width:t===i-1?`60%`:`100%`,marginBottom:6,height:12}},t))}):(0,m.jsx)(`span`,{id:c,className:h(`rcs-skeleton`,`rcs-skeleton--${t}`,o),"data-animated":a||void 0,style:{width:n??(t===`circle`?32:`100%`),height:r??(t===`circle`?32:t===`text`?12:60),...s}})}function W(e){let{size:t=`md`,tone:n=`neutral`,label:r,className:i,style:a,id:o}=e;return(0,m.jsxs)(`span`,{id:o,className:h(`rcs-spin`,`rcs-spin--${t}`,i),style:a,"data-tone":n,role:`status`,children:[(0,m.jsx)(`span`,{className:`rcs-spin-glyph`,"aria-hidden":!0}),r&&(0,m.jsx)(`span`,{children:r})]})}function G(e){let{content:t,placement:n=`top`,delay:r=100,children:i,className:a,style:o,id:s}=e,[c,l]=p.useState(!1),u=p.useRef(null),d=()=>{u.current&&window.clearTimeout(u.current),u.current=window.setTimeout(()=>l(!0),r)},f=()=>{u.current&&window.clearTimeout(u.current),l(!1)};return(0,m.jsxs)(`span`,{id:s,className:h(`rcs-tooltip`,a),style:o,onMouseEnter:d,onMouseLeave:f,onFocus:d,onBlur:f,children:[i,c&&(0,m.jsx)(`span`,{className:`rcs-tooltip-bubble`,"data-placement":n,role:`tooltip`,children:t})]})}var K=[],q=new Set;function J(){for(let e of q)e([...K])}var Y={show(e){let t=e.id??_(`toast`),n={...e,id:t};K.push(n),J();let r=e.duration??4e3;return r>0&&window.setTimeout(()=>Y.dismiss(t),r),t},dismiss(e){let t=K.findIndex(t=>t.id===e);t>=0&&(K.splice(t,1)[0].onDismiss?.(),J())},async promise(e,t){let n=Y.show({severity:`info`,title:t.loading,duration:0});try{let r=await e;return Y.dismiss(n),Y.show({severity:`success`,title:t.success}),r}catch(e){throw Y.dismiss(n),Y.show({severity:`danger`,title:t.error}),e}}};function X(){let[e,t]=p.useState([]);return p.useEffect(()=>(q.add(t),()=>{q.delete(t)}),[]),(0,m.jsx)(`div`,{className:`rcs-toast-region`,"aria-live":`polite`,"aria-atomic":`false`,children:e.map(e=>(0,m.jsxs)(`div`,{className:h(`rcs-toast`,`rcs-toast--${e.severity??`info`}`),role:`status`,children:[(0,m.jsx)(`span`,{className:`rcs-toast-icon`,"aria-hidden":!0,children:L[e.severity??`info`]}),(0,m.jsxs)(`div`,{style:{flex:1},children:[(0,m.jsx)(`div`,{className:`rcs-toast-title`,children:e.title}),e.description&&(0,m.jsx)(`div`,{className:`rcs-toast-desc`,children:e.description})]}),e.action&&(0,m.jsx)(`button`,{className:`rcs-toast-action`,onClick:()=>{e.action.onClick(),Y.dismiss(e.id)},children:e.action.label}),(0,m.jsx)(`button`,{className:`rcs-input-clear`,"aria-label":`Dismiss`,onClick:()=>Y.dismiss(e.id),children:`×`})]},e.id))})}function Z(e){let{columns:t,data:n,rowKey:r,density:i=`default`,bordered:a=!1,striped:o=!1,stickyHeader:s=!1,loading:c=!1,empty:l=`No data`,selection:u=`none`,selectedKeys:d,onSelectionChange:f,onSort:g,onRowClick:_,className:v,style:y,id:b,"data-testid":x}=e,[S,C]=p.useState(null),[w,T]=p.useState(`asc`),E=e=>typeof r==`function`?r(e):e[r],D=e=>{if(!e.sortable)return;let t=`asc`;S===e.key&&(t=w===`asc`?`desc`:`asc`),C(e.key),T(t),g?.(e.key,t)},O=e=>{if(!(!f||u===`none`))if(u===`single`)f([e]);else{let t=new Set(d??[]);t.has(e)?t.delete(e):t.add(e),f(Array.from(t))}};return(0,m.jsx)(`div`,{id:b,"data-testid":x,className:h(`rcs-table-wrap`,v),style:y,children:(0,m.jsxs)(`table`,{className:`rcs-table`,"data-density":i,"data-bordered":a||void 0,"data-striped":o||void 0,"data-sticky-header":s||void 0,children:[(0,m.jsx)(`thead`,{children:(0,m.jsxs)(`tr`,{children:[u!==`none`&&(0,m.jsx)(`th`,{style:{width:36},children:u===`multi`&&(0,m.jsx)(`input`,{type:`checkbox`,checked:!!d?.length&&d.length===n.length,onChange:e=>f?.(e.target.checked?n.map(E):[])})}),t.map(e=>(0,m.jsx)(`th`,{className:h(e.sortable&&`rcs-table-sortable`,e.align===`right`&&`rcs-table-align-right`,e.align===`center`&&`rcs-table-align-center`),style:{width:e.width},"data-sort":S===e.key?w:void 0,onClick:()=>D(e),children:e.title},e.key))]})}),(0,m.jsx)(`tbody`,{children:c?(0,m.jsx)(`tr`,{children:(0,m.jsx)(`td`,{colSpan:t.length+(u===`none`?0:1),className:`rcs-table-empty`,children:`Loading…`})}):n.length===0?(0,m.jsx)(`tr`,{children:(0,m.jsx)(`td`,{colSpan:t.length+(u===`none`?0:1),className:`rcs-table-empty`,children:l})}):n.map((e,n)=>{let r=E(e),i=d?.includes(r);return(0,m.jsxs)(`tr`,{"data-selected":i||void 0,onClick:()=>_?.(e,n),children:[u!==`none`&&(0,m.jsx)(`td`,{onClick:e=>e.stopPropagation(),children:(0,m.jsx)(`input`,{type:u===`multi`?`checkbox`:`radio`,checked:!!i,onChange:()=>O(r)})}),t.map(t=>{let r=t.dataKey?e[t.dataKey]:void 0,i=t.render?t.render(r,e,n):r;return(0,m.jsx)(`td`,{className:h(t.align===`right`&&`rcs-table-align-right`,t.align===`center`&&`rcs-table-align-center`),children:i},t.key)})]},r)})})]})})}function Q(e){let{label:t,value:n,unit:r,delta:i,sparkline:a,className:o,style:s,id:c}=e;return(0,m.jsxs)(`div`,{id:c,className:h(`rcs-stat`,o),style:s,children:[(0,m.jsx)(`div`,{className:`rcs-stat-label`,children:t}),(0,m.jsxs)(`div`,{className:`rcs-stat-value`,children:[(0,m.jsx)(`span`,{children:n}),r&&(0,m.jsx)(`span`,{className:`rcs-stat-unit`,children:r})]}),i&&(0,m.jsxs)(`span`,{className:`rcs-stat-delta`,"data-tone":i.tone??`neutral`,children:[i.direction===`up`?`↑`:`↓`,i.value,`%`]}),a&&a.length>1&&(0,m.jsx)(ee,{data:a})]})}function ee({data:e}){let t=Math.min(...e),n=Math.max(...e)-t||1;return(0,m.jsx)(`svg`,{viewBox:`0 0 80 24`,className:`rcs-stat-spark`,preserveAspectRatio:`none`,children:(0,m.jsx)(`polyline`,{points:e.map((r,i)=>`${i/(e.length-1)*80},${24-(r-t)/n*24}`).join(` `),fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`})})}function te(e){let{items:t,mode:n=`left`,className:r,style:i,id:a}=e;return(0,m.jsx)(`div`,{id:a,className:h(`rcs-timeline`,r),style:i,"data-mode":n,children:t.map(e=>(0,m.jsxs)(`div`,{className:`rcs-timeline-item`,"data-tone":e.tone??`neutral`,children:[(0,m.jsx)(`div`,{className:`rcs-timeline-marker`,"aria-hidden":!0}),(0,m.jsxs)(`div`,{className:`rcs-timeline-content`,children:[(0,m.jsx)(`div`,{className:`rcs-timeline-title`,children:e.title}),e.description&&(0,m.jsx)(`div`,{className:`rcs-timeline-desc`,children:e.description}),e.time&&(0,m.jsx)(`span`,{className:`rcs-timeline-time`,children:e.time})]})]},e.key))})}function ne(e){let{title:t,subtitle:n,breadcrumbs:r,tabs:i,actions:a,badge:o,avatar:s,back:c,size:l=`md`,inlineSubtitle:u,backInline:d,className:f,style:p,id:g}=e,_=c&&!d,v=c&&d;return(0,m.jsxs)(`div`,{id:g,className:h(`rcs-page-header`,`rcs-page-header--${l}`,f),"data-inline-subtitle":u||void 0,"data-back-inline":d||void 0,style:p,children:[_&&(0,m.jsxs)(`button`,{type:`button`,className:`rcs-page-header-back`,onClick:c.onClick,children:[`← `,c.label??`Back`]}),r&&r.length>0&&(0,m.jsx)(`div`,{style:{marginBottom:8},children:(0,m.jsx)(I,{items:r})}),(0,m.jsxs)(`div`,{className:`rcs-page-header-row`,children:[(0,m.jsxs)(`div`,{className:`rcs-page-header-title`,children:[v&&(0,m.jsx)(`button`,{type:`button`,"aria-label":c.label??`Back`,className:`rcs-page-header-back-inline`,onClick:c.onClick,children:`←`}),s,(0,m.jsxs)(`div`,{className:`rcs-page-header-title-text`,children:[(0,m.jsxs)(`h1`,{children:[t,o&&(0,m.jsx)(`span`,{style:{marginLeft:8},children:o})]}),n&&(0,m.jsx)(`div`,{className:`rcs-page-header-subtitle`,children:n})]})]}),a&&(0,m.jsx)(`div`,{className:`rcs-page-header-actions`,children:a})]}),i&&i.length>0&&(0,m.jsx)(`div`,{className:`rcs-page-header-tabs`,children:(0,m.jsx)(P,{items:i,variant:`line`})})]})}function re(e){let{header:t,sidebar:n,footer:r,sidebarWidth:i=240,sidebarCollapsible:a,children:o,className:s,style:c,id:l}=e;return(0,m.jsxs)(`div`,{id:l,className:h(`rcs-app-shell`,s),style:{"--rcs-sidebar-w":`${i}px`,...c},children:[t&&(0,m.jsx)(`header`,{className:`rcs-app-shell-header`,children:t}),(0,m.jsxs)(`div`,{className:`rcs-app-shell-body`,"data-has-sidebar":!!n||void 0,children:[n&&(0,m.jsx)(`aside`,{className:`rcs-app-shell-sidebar`,children:n}),(0,m.jsx)(`main`,{className:`rcs-app-shell-main`,children:o})]}),r&&(0,m.jsx)(`footer`,{className:`rcs-app-shell-footer`,children:r})]})}var ie=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),$=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),ae={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},oe=(0,p.forwardRef)(({color:e=`currentColor`,size:t=24,strokeWidth:n=2,absoluteStrokeWidth:r,className:i=``,children:a,iconNode:o,...s},c)=>(0,p.createElement)(`svg`,{ref:c,...ae,width:t,height:t,stroke:e,strokeWidth:r?Number(n)*24/Number(t):n,className:$(`lucide`,i),...s},[...o.map(([e,t])=>(0,p.createElement)(e,t)),...Array.isArray(a)?a:[a]])),se=(e,t)=>{let n=(0,p.forwardRef)(({className:n,...r},i)=>(0,p.createElement)(oe,{ref:i,iconNode:t,className:$(`lucide-${ie(e)}`,n),...r}));return n.displayName=`${e}`,n},ce={overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`,minWidth:0,display:`block`};function le({text:e,style:t}){return(0,m.jsx)(`span`,{title:e,style:{...ce,...t},children:e})}var ue={coarse:`(max-width: 768px), (pointer: coarse)`,tablet:`(max-width: 960px)`,desktop:`(min-width: 961px)`,wide:`(min-width: 1281px)`};function de(e){let[t,n]=(0,p.useState)(()=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(e).matches);return(0,p.useEffect)(()=>{if(typeof window>`u`||typeof window.matchMedia!=`function`)return;let t=window.matchMedia(e),r=()=>n(t.matches);return r(),t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}export{_ as A,k as C,b as D,v as E,u as M,o as N,y as O,c as P,N as S,S as T,G as _,re as a,O as b,Z as c,V as d,B as f,X as g,W as h,se as i,f as j,h as k,te as l,U as m,ue as n,ne as o,H as p,le as r,Q as s,de as t,R as u,F as v,x as w,A as x,P as y}; \ No newline at end of file diff --git a/internal/ui/dist/index.html b/internal/ui/dist/index.html index 68d8839..52b315f 100644 --- a/internal/ui/dist/index.html +++ b/internal/ui/dist/index.html @@ -4,7 +4,8 @@ OtelContext - + + diff --git a/ui/eslint.config.js b/ui/eslint.config.js new file mode 100644 index 0000000..c8eb9fd --- /dev/null +++ b/ui/eslint.config.js @@ -0,0 +1,40 @@ +import js from '@eslint/js' +import globals from 'globals' +import tseslint from 'typescript-eslint' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' + +export default tseslint.config( + { ignores: ['dist', 'node_modules'] }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2022, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + // The two react-compiler-era rules below fire on legitimate, codebase-wide + // patterns rather than real defects, so they are warnings (visible) not + // errors: + // - set-state-in-effect: the async data-fetch hooks setState AFTER an + // await (the pre-existing useSystemGraph/useDashboard do the same); the + // rule can't follow the await boundary. + // - refs: the intentional state->ref mirror in useWebSocket and the + // imperative cytoscape hover-overlay positioning in ServiceGraph. + // rules-of-hooks and exhaustive-deps stay at their recommended levels. + 'react-hooks/set-state-in-effect': 'warn', + 'react-hooks/refs': 'warn', + }, + }, +) diff --git a/ui/src/App.tsx b/ui/src/App.tsx index fdcae01..47898ff 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,35 +1,46 @@ -import { useState } from 'react' -import { AppShell } from '@ossrandom/design-system' +import { lazy, Suspense, useState } from 'react' +import { AppShell, Spin } from '@ossrandom/design-system' import TopNav, { type OtelView } from './components/nav/TopNav' -import ServicesView from './components/observability/ServicesView' -import { useSystemGraph } from './hooks/useSystemGraph' -import { useDashboard } from './hooks/useDashboard' +import DashboardView from './components/dashboard/DashboardView' import { useWebSocket } from './hooks/useWebSocket' +import type { Theme } from './hooks/useTheme' -export default function App() { - const [view, setView] = useState('services') +// Dashboard is the default view and loads eagerly. The Service Map pulls in +// cytoscape (~434 KB) and the MCP console is a large secondary surface — both +// are code-split so they don't weigh down the initial dashboard-first load. +const ServicesView = lazy(() => import('./components/observability/ServicesView')) +const MCPConsoleView = lazy(() => import('./components/mcp/MCPConsoleView')) - const graph = useSystemGraph() - const dash = useDashboard() +interface AppProps { + theme: Theme + onToggleTheme: () => void +} + +export default function App({ theme, onToggleTheme }: Readonly) { + const [view, setView] = useState('dashboard') - // WebSocket retained as the live/offline source for the header indicator; - // log batches it pushes are intentionally discarded. + // WebSocket retained purely as the live/offline source for the header badge; + // the pushed log batches are intentionally discarded. const ws = useWebSocket(() => undefined) - const wsConnected = !!ws.current + const wsConnected = ws.status === 'connected' return ( + } > - + }> + {view === 'dashboard' && } + {view === 'services' && } + {view === 'mcp' && } + ) } diff --git a/ui/src/components/common/Truncate.tsx b/ui/src/components/common/Truncate.tsx new file mode 100644 index 0000000..40a87ea --- /dev/null +++ b/ui/src/components/common/Truncate.tsx @@ -0,0 +1,28 @@ +import type { CSSProperties } from 'react' + +interface TruncateProps { + readonly text: string + readonly style?: CSSProperties +} + +// Layout-only inline styles (sanctioned escape hatch). `minWidth: 0` is the +// flex/grid fix that lets a shrinkable child ellipsize instead of overflowing. +const baseStyle: CSSProperties = { + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + minWidth: 0, + display: 'block', +} + +/** + * Single-line ellipsis with a native title tooltip on hover. Use for service + * names, log bodies, trace ids, operation names — anything that can overflow. + */ +export default function Truncate({ text, style }: TruncateProps) { + return ( + + {text} + + ) +} diff --git a/ui/src/components/dashboard/DashboardView.tsx b/ui/src/components/dashboard/DashboardView.tsx new file mode 100644 index 0000000..c851288 --- /dev/null +++ b/ui/src/components/dashboard/DashboardView.tsx @@ -0,0 +1,370 @@ +import { useMemo } from 'react' +import { + Alert, + Badge, + Card, + Divider, + Grid, + PageHeader, + Skeleton, + Space, + Stat, + StatusDot, + Table, + Timeline, +} from '@ossrandom/design-system' +import type { TableColumn, TimelineItem } from '@ossrandom/design-system' +import { RadialGauge } from '@ossrandom/design-system/charts' +import Truncate from '../common/Truncate' +import type { OtelView } from '../nav/TopNav' +import type { ServiceError } from '../../types/api' +import { fmt } from '../../lib/utils' +import { BP } from '../../lib/breakpoints' +import { useMediaQuery } from '../../hooks/useMediaQuery' +import { useSystemGraph } from '../../hooks/useSystemGraph' +import { useDashboard } from '../../hooks/useDashboard' +import { useTraffic } from '../../hooks/useTraffic' +import { useReady } from '../../hooks/useReady' +import { useAnomalies } from '../../hooks/useAnomalies' +import { + bucketErrorRatePct, + coerceDbSizeMb, + formatUptime, + healthPct, + readyCheckToStatus, + severityToTone, +} from './dashTypes' + +interface DashboardViewProps { + onNavigate: (view: OtelView) => void +} + +// Friendly labels for the /ready probe keys. +const READY_LABELS: Record = { + database: 'Database', + graphrag: 'GraphRAG', + dlq_disk: 'DLQ disk', + pipeline: 'Ingest pipeline', +} + +// Health hue for the gauge: green when mostly healthy, amber mid, red low. +function healthTone(pct: number): 'good' | 'warning' | 'bad' { + if (pct >= 90) return 'good' + if (pct >= 70) return 'warning' + return 'bad' +} + +export default function DashboardView({ + onNavigate, +}: Readonly) { + const { graph, loading: graphLoading, error: graphError } = useSystemGraph() + const { + dashboard, + stats, + loading: dashLoading, + error: dashError, + } = useDashboard() + const { points, error: trafficError } = useTraffic() + const { ready, error: readyError } = useReady() + const { anomalies, error: anomalyError } = useAnomalies() + + const summary = graph?.system ?? null + + // Responsive tiers. The DS Grid has no per-breakpoint Col prop, so spans are + // computed here and passed to . + const isCoarse = useMediaQuery(BP.coarse) + const isTablet = useMediaQuery(BP.tablet) + const isWide = useMediaQuery(BP.wide) + + // 12-col band spans per tier (coarse = stack, tablet = halves, desktop = bento). + const span = useMemo(() => { + if (isCoarse) { + return { hero: 12, traffic: 12, failing: 12, anomalies: 12, platform: 12 } + } + if (isTablet) { + return { hero: 12, traffic: 12, failing: 12, anomalies: 6, platform: 6 } + } + return { hero: 12, traffic: 12, failing: 8, anomalies: 4, platform: 12 } + }, [isCoarse, isTablet]) + + // Cold-start gate: GraphRAG rebuilds topology from the DB on a ~60s loop, so + // total_services stays 0 for up to a minute after a fresh boot. Show skeletons + // (not a bare Spin) until first data resolves AND the graph is warm. + const warming = + (graphLoading && !graph) || + (dashLoading && !dashboard) || + !summary || + summary.total_services === 0 + + const fetchError = graphError || dashError || trafficError || readyError + + // ---- Derived display values ------------------------------------------------ + const pct = healthPct(summary?.overall_health_score) + + const trafficCounts = useMemo( + () => (points ?? []).map((p) => p.count), + [points], + ) + const errorRateSeries = useMemo( + () => (points ?? []).map(bucketErrorRatePct), + [points], + ) + const totalRequests = useMemo( + () => trafficCounts.reduce((a, b) => a + b, 0), + [trafficCounts], + ) + // Window-aggregate error rate — steadier than any single bucket for the badge. + const windowErrorPct = useMemo(() => { + const totalErr = (points ?? []).reduce((a, p) => a + p.error_count, 0) + return totalRequests > 0 ? (totalErr / totalRequests) * 100 : 0 + }, [points, totalRequests]) + + const dbSizeMb = coerceDbSizeMb(stats?.db_size_mb) + + const containerStyle = isWide + ? { maxWidth: 1280, margin: '0 auto', width: '100%' } + : { width: '100%' } + + // ---- Top failing services table ------------------------------------------- + const failingColumns: readonly TableColumn[] = [ + { + key: 'service_name', + title: 'Service', + dataKey: 'service_name', + render: (_v, row) => , + }, + { + key: 'error_count', + title: 'Errors', + dataKey: 'error_count', + width: 90, + align: 'right', + render: (_v, row) => fmt(row.error_count), + }, + { + key: 'total_count', + title: 'Total', + dataKey: 'total_count', + width: 90, + align: 'right', + render: (_v, row) => fmt(row.total_count), + }, + { + key: 'error_rate', + title: 'Error rate', + dataKey: 'error_rate', + width: 110, + align: 'right', + render: (_v, row) => { + const ratePct = + row.error_rate <= 1 ? row.error_rate * 100 : row.error_rate + return ( + = 5 ? 'danger' : 'neutral'} size="sm"> + {ratePct.toFixed(1)}% + + ) + }, + }, + ] + + const failing = dashboard?.top_failing_services ?? [] + + // ---- Anomaly timeline items ----------------------------------------------- + const anomalyItems: readonly TimelineItem[] = (anomalies ?? []).map((a) => ({ + key: a.id, + title: a.service || a.type, + description: a.evidence, + time: new Date(a.timestamp).toLocaleTimeString(), + tone: severityToTone(a.severity), + })) + + // ---- Loading state --------------------------------------------------------- + if (warming) { + return ( + + + + + + + + + + + + + + + + + + + + + ) + } + + // ---- Main view ------------------------------------------------------------- + return ( + + + + {fetchError && ( + + {fetchError} + + )} + + + {/* Band 1 — Hero health */} + + + + + + + + + + + + + + + + + + + {/* Band 2 — Traffic + Errors */} + + + + + + + + + + + +
+ = 5 ? 'danger' : 'neutral'} + size="sm" + > + {windowErrorPct >= 5 ? 'elevated errors' : 'nominal'} + +
+
+
+
+ + {/* Band 3 — Top failing services */} + + + + columns={failingColumns} + data={failing} + rowKey="service_name" + density="compact" + onRowClick={() => onNavigate('services')} + empty={ + + + No failing services — all clear. + + } + /> + + + + {/* Band 4 — Recent anomalies */} + + + {anomalyError ? ( + + {anomalyError} + + ) : anomalyItems.length ? ( + + ) : ( + + + No anomalies in the last hour. + + )} + + + + {/* Band 5 — Platform health */} + + + + + + {ready + ? Object.entries(ready.checks).map(([key, value]) => ( + + )) + : readyError && ( + + Readiness probe unavailable. + + )} + {dbSizeMb !== null && ( + <> + + + + )} + + + +
+
+ ) +} diff --git a/ui/src/components/dashboard/dashTypes.test.ts b/ui/src/components/dashboard/dashTypes.test.ts new file mode 100644 index 0000000..5cc2c79 --- /dev/null +++ b/ui/src/components/dashboard/dashTypes.test.ts @@ -0,0 +1,73 @@ +import { describe, expect, it } from 'vitest' +import type { TrafficPoint } from '../../types/api' +import { + bucketErrorRatePct, + coerceDbSizeMb, + healthPct, + readyCheckToStatus, + severityToTone, +} from './dashTypes' + +describe('severityToTone', () => { + it('maps critical -> danger, warning -> warning, info -> neutral', () => { + expect(severityToTone('critical')).toBe('danger') + expect(severityToTone('warning')).toBe('warning') + expect(severityToTone('info')).toBe('neutral') + }) +}) + +describe('readyCheckToStatus', () => { + it('maps /ready check strings to StatusDot statuses', () => { + expect(readyCheckToStatus('ok')).toBe('running') + expect(readyCheckToStatus('skipped')).toBe('idle') + expect(readyCheckToStatus('saturated 96%')).toBe('degraded') + expect(readyCheckToStatus('not running')).toBe('failed') + expect(readyCheckToStatus('ping failed: timeout')).toBe('failed') + expect(readyCheckToStatus(undefined)).toBe('idle') + }) +}) + +describe('bucketErrorRatePct', () => { + it('returns percentage and guards divide-by-zero', () => { + const p = (count: number, error_count: number): TrafficPoint => ({ + timestamp: '2026-06-05T00:00:00Z', + count, + error_count, + }) + expect(bucketErrorRatePct(p(100, 5))).toBe(5) + expect(bucketErrorRatePct(p(0, 0))).toBe(0) + }) +}) + +describe('healthPct', () => { + it('normalises 0-1 and 0-100 inputs and clamps', () => { + expect(healthPct(0.92)).toBeCloseTo(92) + expect(healthPct(87)).toBe(87) + expect(healthPct(1)).toBe(100) + expect(healthPct(150)).toBe(100) + expect(healthPct(-5)).toBe(0) + expect(healthPct(undefined)).toBe(0) + expect(healthPct(Number.NaN)).toBe(0) + }) +}) + +describe('coerceDbSizeMb', () => { + it('coerces number / numeric string / absent values', () => { + expect(coerceDbSizeMb(42.5)).toBe(42.5) + expect(coerceDbSizeMb('128.0')).toBe(128) + expect(coerceDbSizeMb(undefined)).toBeNull() + expect(coerceDbSizeMb('not-a-number')).toBeNull() + expect(coerceDbSizeMb(Number.NaN)).toBeNull() + }) +}) + +describe('dashboard hooks are importable', () => { + it('exposes useTraffic / useReady / useAnomalies as functions', async () => { + const traffic = await import('../../hooks/useTraffic') + const ready = await import('../../hooks/useReady') + const anomalies = await import('../../hooks/useAnomalies') + expect(traffic.useTraffic).toBeTypeOf('function') + expect(ready.useReady).toBeTypeOf('function') + expect(anomalies.useAnomalies).toBeTypeOf('function') + }) +}) diff --git a/ui/src/components/dashboard/dashTypes.ts b/ui/src/components/dashboard/dashTypes.ts new file mode 100644 index 0000000..632f195 --- /dev/null +++ b/ui/src/components/dashboard/dashTypes.ts @@ -0,0 +1,78 @@ +import type { AnomalySeverity, TrafficPoint } from '../../types/api' + +// Map a GraphRAG anomaly severity to a design-system Timeline tone. The +// Timeline component has no 'info' tone, so info collapses to 'neutral'. +export function severityToTone( + sev: AnomalySeverity, +): 'neutral' | 'success' | 'warning' | 'danger' { + switch (sev) { + case 'critical': + return 'danger' + case 'warning': + return 'warning' + default: + return 'neutral' // 'info' -> neutral (no Timeline 'info' tone) + } +} + +// Map a /ready check string ("ok" | "skipped" | "not running" | "saturated +// NN%" | error text) to a design-system StatusDot status. StatusDot has no +// generic "ok"; "running" is the healthy green, "failed" the red, "idle" the +// muted grey for skipped/unknown probes. +export function readyCheckToStatus( + value: string | undefined, +): 'running' | 'degraded' | 'failed' | 'idle' { + if (!value) return 'idle' + const v = value.toLowerCase() + if (v === 'ok') return 'running' + if (v === 'skipped') return 'idle' + if (v.startsWith('saturated')) return 'degraded' + return 'failed' // "not running", ping/connection errors, etc. +} + +// Error-rate percentage for a single traffic bucket (0–100). Guards the +// divide-by-zero on idle minutes. +export function bucketErrorRatePct(p: TrafficPoint): number { + if (!p.count) return 0 + return (p.error_count / p.count) * 100 +} + +// Health score (0–1 from the backend, occasionally 0–100) clamped to a 0–100 +// percentage for display and gauge input. +export function healthPct(score: number | undefined): number { + if (typeof score !== 'number' || Number.isNaN(score)) return 0 + const pct = score <= 1 ? score * 100 : score + return Math.max(0, Math.min(100, pct)) +} + +// Format server uptime (system.uptime_seconds from /api/system/graph) to a +// compact human string: "45s", "12m", "3h 04m", "5d 02h". Returns "—" when +// absent/invalid. +export function formatUptime(seconds: number | undefined): string { + if (typeof seconds !== 'number' || !Number.isFinite(seconds) || seconds < 0) { + return '—' + } + const s = Math.floor(seconds) + if (s < 60) return `${s}s` + if (s < 3600) return `${Math.floor(s / 60)}m` + if (s < 86400) { + const h = Math.floor(s / 3600) + const m = Math.floor((s % 3600) / 60) + return `${h}h ${String(m).padStart(2, '0')}m` + } + const d = Math.floor(s / 86400) + const h = Math.floor((s % 86400) / 3600) + return `${d}d ${String(h).padStart(2, '0')}h` +} + +// Coerce RepoStats.db_size_mb (loosely typed via the index signature — may be a +// number, a numeric string, or absent on non-SQLite drivers) to a number or +// null. +export function coerceDbSizeMb(value: unknown): number | null { + if (typeof value === 'number' && Number.isFinite(value)) return value + if (typeof value === 'string') { + const n = Number.parseFloat(value) + return Number.isFinite(n) ? n : null + } + return null +} diff --git a/ui/src/components/mcp/LiveStream.tsx b/ui/src/components/mcp/LiveStream.tsx new file mode 100644 index 0000000..74323c8 --- /dev/null +++ b/ui/src/components/mcp/LiveStream.tsx @@ -0,0 +1,72 @@ +import { useEffect, useRef, useState } from 'react'; +import { Terminal, Switch, Tooltip, Space } from '@ossrandom/design-system'; +import type { TerminalLine } from '@ossrandom/design-system'; + +interface LiveStreamProps { + /** When an API key is set the toggle is disabled — EventSource can't send + * an Authorization header, so the SSE GET would 401. */ + readonly apiKey: string; +} + +const MAX_LINES = 200; + +/** + * Optional SSE viewer for the `/mcp` GET stream. The backend emits a + * `: keep-alive` comment every 25s; EventSource swallows comments, so we also + * surface the open/error lifecycle to make the heartbeat observable. + */ +export default function LiveStream({ apiKey }: LiveStreamProps) { + const [on, setOn] = useState(false); + const [lines, setLines] = useState([]); + const esRef = useRef(null); + + const disabled = apiKey.length > 0; + + useEffect(() => { + if (!on || disabled) { + esRef.current?.close(); + esRef.current = null; + return; + } + const push = (line: TerminalLine) => + setLines((prev) => [...prev, line].slice(-MAX_LINES)); + + const es = new EventSource('/mcp'); + esRef.current = es; + push({ type: 'info', text: 'opening /mcp SSE stream…', timestamp: new Date() }); + es.onopen = () => push({ type: 'info', text: 'stream open — waiting for events', timestamp: new Date() }); + es.onmessage = (ev) => + push({ type: 'stdout', text: ev.data || '(empty event)', timestamp: new Date() }); + es.onerror = () => + push({ type: 'warn', text: 'stream error / reconnecting (keep-alive every 25s)', timestamp: new Date() }); + + return () => { + es.close(); + esRef.current = null; + }; + }, [on, disabled]); + + return ( + +
+ {disabled ? ( + + + + + + ) : ( + + )} +
+ {on && !disabled && ( + 0 ? lines : [{ type: 'info', text: 'connecting…' }]} + streaming + height={220} + /> + )} +
+ ); +} diff --git a/ui/src/components/mcp/MCPConsole.tsx b/ui/src/components/mcp/MCPConsole.tsx deleted file mode 100644 index c510523..0000000 --- a/ui/src/components/mcp/MCPConsole.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Note: MCPConsole is no longer mounted in App.tsx — the MCP endpoint URL -// + Copy button now live in the TopNav header. This file is kept temporarily -// as orphaned source pending a follow-up cleanup pass; it is tree-shaken out -// of the production bundle. -import { useState } from 'react' -import { Badge, Button, Card, Input, Space } from '@ossrandom/design-system' -import { Check, Copy, Terminal } from 'lucide-react' - -export default function MCPConsole() { - const url = `${window.location.origin}/mcp` - const [copied, setCopied] = useState(false) - - const copyUrl = async () => { - await navigator.clipboard.writeText(url) - setCopied(true) - window.setTimeout(() => setCopied(false), 1500) - } - - return ( - - - - - - MCP Endpoint - live - - -
- -
- -
-
-
-
- ) -} diff --git a/ui/src/components/mcp/MCPConsoleView.tsx b/ui/src/components/mcp/MCPConsoleView.tsx new file mode 100644 index 0000000..74b743c --- /dev/null +++ b/ui/src/components/mcp/MCPConsoleView.tsx @@ -0,0 +1,278 @@ +import { useMemo, useState } from 'react'; +import { + Menu, + Select, + PageHeader, + Tabs, + Button, + IconButton, + Alert, + Skeleton, + Badge, + CodeBlock, + Space, +} from '@ossrandom/design-system'; +import { Settings } from 'lucide-react'; +import { useMediaQuery } from '../../hooks/useMediaQuery'; +import { BP } from '../../lib/breakpoints'; +import { useMcpTools } from '../../hooks/useMcpTools'; +import { useMcpCall, type HistoryEntry } from '../../hooks/useMcpCall'; +import type { McpTool } from '../../lib/mcpClient'; +import ToolForm from './ToolForm'; +import ToolResult from './ToolResult'; +import ToolHistory from './ToolHistory'; +import LiveStream from './LiveStream'; +import SettingsDrawer, { useMcpSettings } from './SettingsDrawer'; + +// Tools are grouped by data source per the design spec: instant in-memory +// GraphRAG tools vs DB / fallback tools. Order within each group is fixed; any +// tool the live catalog returns that isn't listed here lands under "Other". +const INSTANT_TOOLS = [ + 'get_anomaly_timeline', + 'get_service_map', + 'get_service_health', + 'root_cause_analysis', + 'impact_analysis', +]; +const DB_TOOLS = ['trace_graph', 'search_logs']; + +type WorkbenchTab = 'run' | 'definition' | 'history'; + +// Layout-only escape hatches (sanctioned): the list-detail split + scroll. +const layout: React.CSSProperties = { display: 'flex', height: '100%', minHeight: 0 }; +const rail: React.CSSProperties = { + width: 280, + flex: '0 0 280px', + borderRight: '1px solid var(--rcs-color-border, rgba(127,127,127,0.18))', + overflowY: 'auto', + padding: 12, +}; +const pane: React.CSSProperties = { + flex: 1, + minWidth: 0, + display: 'flex', + flexDirection: 'column', + overflow: 'hidden', +}; +const paneBody: React.CSSProperties = { flex: 1, minHeight: 0, overflowY: 'auto', padding: 16 }; + +function groupTools(tools: McpTool[]) { + const byName = new Map(tools.map((t) => [t.name, t])); + const instant = INSTANT_TOOLS.filter((n) => byName.has(n)).map((n) => byName.get(n)!); + const db = DB_TOOLS.filter((n) => byName.has(n)).map((n) => byName.get(n)!); + const known = new Set([...INSTANT_TOOLS, ...DB_TOOLS]); + const other = tools.filter((t) => !known.has(t.name)); + return { instant, db, other }; +} + +export default function MCPConsoleView() { + const isMobile = useMediaQuery(BP.coarse); + const { settings, save } = useMcpSettings(); + const callOpts = useMemo( + () => ({ apiKey: settings.apiKey || undefined, tenant: settings.tenant || undefined }), + [settings.apiKey, settings.tenant], + ); + + const { tools, loading, error, reload } = useMcpTools(callOpts); + const { state, call, reset, history, clearHistory } = useMcpCall(callOpts); + + const [selected, setSelected] = useState(null); + const [tab, setTab] = useState('run'); + const [settingsOpen, setSettingsOpen] = useState(false); + const [rerunSeed, setRerunSeed] = useState | undefined>(undefined); + // Bumped on each re-run so the keyed ToolForm re-mounts and re-seeds even + // when the same tool is re-run with identical arguments. + const [formNonce, setFormNonce] = useState(0); + + const groups = useMemo(() => groupTools(tools), [tools]); + + // Effective selection: the user's pick if it's still in the catalog, + // otherwise the first advertised tool. Derived — no effect/setState needed, + // so a volatile catalog never leaves a dangling selection. + const effectiveSelected = + selected && tools.some((t) => t.name === selected) + ? selected + : (tools[0]?.name ?? null); + + const activeTool = tools.find((t) => t.name === effectiveSelected) ?? null; + + const selectTool = (name: string) => { + setSelected(name); + setTab('run'); + setRerunSeed(undefined); + setFormNonce((n) => n + 1); + reset(); + }; + + const handleRerun = (entry: HistoryEntry) => { + const seed: Record = {}; + for (const [k, v] of Object.entries(entry.args)) { + seed[k] = typeof v === 'string' ? v : String(v); + } + setSelected(entry.tool); + setRerunSeed(seed); + setTab('run'); + setFormNonce((n) => n + 1); + reset(); + }; + + const menuItems = useMemo(() => { + type MenuEntry = Parameters[0]['items'][number]; + const items: MenuEntry[] = []; + if (groups.instant.length > 0) { + items.push({ type: 'label', label: 'In-memory (instant)' }); + for (const t of groups.instant) items.push({ key: t.name, label: t.name }); + } + if (groups.db.length > 0) { + items.push({ type: 'label', label: 'DB / fallback' }); + for (const t of groups.db) items.push({ key: t.name, label: t.name }); + } + if (groups.other.length > 0) { + items.push({ type: 'label', label: 'Other' }); + for (const t of groups.other) items.push({ key: t.name, label: t.name }); + } + return items; + }, [groups]); + + const selectOptions = useMemo( + () => tools.map((t) => ({ label: t.name, value: t.name })), + [tools], + ); + + // --- Rail (desktop) / Select (mobile) --- + const railContent = loading ? ( + + + + ) : ( + + ); + + const headerActions = ( + + {settings.apiKey && auth on} + {settings.tenant && tenant: {settings.tenant}} + } + onClick={() => setSettingsOpen(true)} + /> + + ); + + return ( +
+ {!isMobile &&
{railContent}
} + +
+ + +
+ {error && ( + + Retry + + } + style={{ marginBottom: 16 }} + > + {error} — POST /mcp failed. Check the server is up and your API key + under settings. + + )} + + {isMobile && !loading && tools.length > 0 && ( +
+ setApiKey(v)} + /> + + + setTenant(v)} /> + + + + ); +} diff --git a/ui/src/components/mcp/ToolForm.tsx b/ui/src/components/mcp/ToolForm.tsx new file mode 100644 index 0000000..4bb206e --- /dev/null +++ b/ui/src/components/mcp/ToolForm.tsx @@ -0,0 +1,282 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { + Button, + ButtonGroup, + FormField, + Input, + NumberInput, + Select, + DatePicker, + Textarea, + Space, + Alert, +} from '@ossrandom/design-system'; +import type { McpTool } from '../../lib/mcpClient'; +import { + fieldsForTool, + toArguments, + SEVERITY_OPTIONS, + DATE_PRESETS, + type ToolField, +} from './toolFields'; + +interface ToolFormProps { + readonly tool: McpTool; + readonly running: boolean; + readonly onRun: (args: Record) => void; + /** Pre-fill values (e.g. re-run from History). */ + readonly initialValues?: Record; +} + +// Layout-only escape hatches (sanctioned): grid + spacing for the field rows. +const fieldGrid: React.CSSProperties = { + display: 'grid', + gap: 12, + gridTemplateColumns: 'minmax(0, 1fr)', +}; +const presetRow: React.CSSProperties = { display: 'flex', gap: 8, marginTop: 6 }; + +function toRfc3339(d: Date | null): string { + return d ? d.toISOString() : ''; +} + +/** Fetches the service catalog once for service / service_name pickers. */ +function useServiceOptions() { + const [services, setServices] = useState([]); + useEffect(() => { + const ctrl = new AbortController(); + fetch('/api/metadata/services', { signal: ctrl.signal }) + .then((r) => (r.ok ? r.json() : [])) + .then((list: unknown) => { + if (Array.isArray(list)) setServices(list.filter((s): s is string => typeof s === 'string')); + }) + .catch(() => { + /* non-fatal — the field falls back to free-text guidance below */ + }); + return () => ctrl.abort(); + }, []); + return services; +} + +export default function ToolForm({ tool, running, onRun, initialValues }: ToolFormProps) { + const fields = useMemo(() => fieldsForTool(tool), [tool]); + const services = useServiceOptions(); + // Field state seeds from initialValues. The parent re-mounts this component + // (via `key`) whenever the tool or the re-run seed changes, so there is no + // prop-sync effect to fall out of date. + const [values, setValues] = useState>(initialValues ?? {}); + const [rawOpen, setRawOpen] = useState(false); + const [rawText, setRawText] = useState(''); + const [rawError, setRawError] = useState(null); + + const setField = useCallback((name: string, value: string) => { + setValues((prev) => ({ ...prev, [name]: value })); + }, []); + + const args = useMemo(() => toArguments(fields, values), [fields, values]); + + // Keep the raw-JSON editor in sync with the form while it's open & untouched. + useEffect(() => { + if (rawOpen) setRawText(JSON.stringify(args, null, 2)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [rawOpen]); + + const applyRaw = useCallback( + (text: string) => { + setRawText(text); + try { + const parsed = text.trim() ? JSON.parse(text) : {}; + if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) { + setRawError('Arguments must be a JSON object.'); + return; + } + const next: Record = {}; + for (const [k, v] of Object.entries(parsed as Record)) { + next[k] = typeof v === 'string' ? v : String(v); + } + setValues(next); + setRawError(null); + } catch { + setRawError('Invalid JSON.'); + } + }, + [], + ); + + const missingRequired = fields + .filter((f) => f.required && !values[f.name]) + .map((f) => f.name); + + const handleRun = () => { + if (missingRequired.length > 0) return; + onRun(args); + }; + + return ( + +
+ {fields.length === 0 && ( + + This tool takes no arguments — run it directly. + + )} + {fields.map((field) => ( + setField(field.name, v)} + /> + ))} +
+ +
+ + {rawOpen && ( +
+